1*7955f03dSHans Verkuil /* 2*7955f03dSHans Verkuil * Copyright (C) 2005-2006 Micronas USA Inc. 3*7955f03dSHans Verkuil * 4*7955f03dSHans Verkuil * This program is free software; you can redistribute it and/or modify 5*7955f03dSHans Verkuil * it under the terms of the GNU General Public License (Version 2) as 6*7955f03dSHans Verkuil * published by the Free Software Foundation. 7*7955f03dSHans Verkuil * 8*7955f03dSHans Verkuil * This program is distributed in the hope that it will be useful, 9*7955f03dSHans Verkuil * but WITHOUT ANY WARRANTY; without even the implied warranty of 10*7955f03dSHans Verkuil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11*7955f03dSHans Verkuil * GNU General Public License for more details. 12*7955f03dSHans Verkuil */ 13*7955f03dSHans Verkuil 14*7955f03dSHans Verkuil #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15*7955f03dSHans Verkuil 16*7955f03dSHans Verkuil #include <linux/module.h> 17*7955f03dSHans Verkuil #include <linux/kernel.h> 18*7955f03dSHans Verkuil #include <linux/wait.h> 19*7955f03dSHans Verkuil #include <linux/list.h> 20*7955f03dSHans Verkuil #include <linux/slab.h> 21*7955f03dSHans Verkuil #include <linux/time.h> 22*7955f03dSHans Verkuil #include <linux/mm.h> 23*7955f03dSHans Verkuil #include <linux/usb.h> 24*7955f03dSHans Verkuil #include <linux/i2c.h> 25*7955f03dSHans Verkuil #include <asm/byteorder.h> 26*7955f03dSHans Verkuil #include <media/saa7115.h> 27*7955f03dSHans Verkuil #include <media/tuner.h> 28*7955f03dSHans Verkuil #include <media/uda1342.h> 29*7955f03dSHans Verkuil 30*7955f03dSHans Verkuil #include "go7007-priv.h" 31*7955f03dSHans Verkuil 32*7955f03dSHans Verkuil static unsigned int assume_endura; 33*7955f03dSHans Verkuil module_param(assume_endura, int, 0644); 34*7955f03dSHans Verkuil MODULE_PARM_DESC(assume_endura, 35*7955f03dSHans Verkuil "when probing fails, hardware is a Pelco Endura"); 36*7955f03dSHans Verkuil 37*7955f03dSHans Verkuil /* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */ 38*7955f03dSHans Verkuil 39*7955f03dSHans Verkuil #define HPI_STATUS_ADDR 0xFFF4 40*7955f03dSHans Verkuil #define INT_PARAM_ADDR 0xFFF6 41*7955f03dSHans Verkuil #define INT_INDEX_ADDR 0xFFF8 42*7955f03dSHans Verkuil 43*7955f03dSHans Verkuil /* 44*7955f03dSHans Verkuil * Pipes on EZ-USB interface: 45*7955f03dSHans Verkuil * 0 snd - Control 46*7955f03dSHans Verkuil * 0 rcv - Control 47*7955f03dSHans Verkuil * 2 snd - Download firmware (control) 48*7955f03dSHans Verkuil * 4 rcv - Read Interrupt (interrupt) 49*7955f03dSHans Verkuil * 6 rcv - Read Video (bulk) 50*7955f03dSHans Verkuil * 8 rcv - Read Audio (bulk) 51*7955f03dSHans Verkuil */ 52*7955f03dSHans Verkuil 53*7955f03dSHans Verkuil #define GO7007_USB_EZUSB (1<<0) 54*7955f03dSHans Verkuil #define GO7007_USB_EZUSB_I2C (1<<1) 55*7955f03dSHans Verkuil 56*7955f03dSHans Verkuil struct go7007_usb_board { 57*7955f03dSHans Verkuil unsigned int flags; 58*7955f03dSHans Verkuil struct go7007_board_info main_info; 59*7955f03dSHans Verkuil }; 60*7955f03dSHans Verkuil 61*7955f03dSHans Verkuil struct go7007_usb { 62*7955f03dSHans Verkuil const struct go7007_usb_board *board; 63*7955f03dSHans Verkuil struct mutex i2c_lock; 64*7955f03dSHans Verkuil struct usb_device *usbdev; 65*7955f03dSHans Verkuil struct urb *video_urbs[8]; 66*7955f03dSHans Verkuil struct urb *audio_urbs[8]; 67*7955f03dSHans Verkuil struct urb *intr_urb; 68*7955f03dSHans Verkuil }; 69*7955f03dSHans Verkuil 70*7955f03dSHans Verkuil /*********************** Product specification data ***********************/ 71*7955f03dSHans Verkuil 72*7955f03dSHans Verkuil static const struct go7007_usb_board board_matrix_ii = { 73*7955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 74*7955f03dSHans Verkuil .main_info = { 75*7955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 76*7955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 77*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 78*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 79*7955f03dSHans Verkuil .audio_rate = 48000, 80*7955f03dSHans Verkuil .audio_bclk_div = 8, 81*7955f03dSHans Verkuil .audio_main_div = 2, 82*7955f03dSHans Verkuil .hpi_buffer_cap = 7, 83*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 84*7955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 85*7955f03dSHans Verkuil GO7007_SENSOR_TV | 86*7955f03dSHans Verkuil GO7007_SENSOR_SAA7115 | 87*7955f03dSHans Verkuil GO7007_SENSOR_VBI | 88*7955f03dSHans Verkuil GO7007_SENSOR_SCALING, 89*7955f03dSHans Verkuil .num_i2c_devs = 1, 90*7955f03dSHans Verkuil .i2c_devs = { 91*7955f03dSHans Verkuil { 92*7955f03dSHans Verkuil .type = "saa7115", 93*7955f03dSHans Verkuil .addr = 0x20, 94*7955f03dSHans Verkuil .is_video = 1, 95*7955f03dSHans Verkuil }, 96*7955f03dSHans Verkuil }, 97*7955f03dSHans Verkuil .num_inputs = 2, 98*7955f03dSHans Verkuil .inputs = { 99*7955f03dSHans Verkuil { 100*7955f03dSHans Verkuil .video_input = 0, 101*7955f03dSHans Verkuil .name = "Composite", 102*7955f03dSHans Verkuil }, 103*7955f03dSHans Verkuil { 104*7955f03dSHans Verkuil .video_input = 9, 105*7955f03dSHans Verkuil .name = "S-Video", 106*7955f03dSHans Verkuil }, 107*7955f03dSHans Verkuil }, 108*7955f03dSHans Verkuil .video_config = SAA7115_IDQ_IS_DEFAULT, 109*7955f03dSHans Verkuil }, 110*7955f03dSHans Verkuil }; 111*7955f03dSHans Verkuil 112*7955f03dSHans Verkuil static const struct go7007_usb_board board_matrix_reload = { 113*7955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 114*7955f03dSHans Verkuil .main_info = { 115*7955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 116*7955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 117*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 118*7955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 119*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 120*7955f03dSHans Verkuil .audio_rate = 48000, 121*7955f03dSHans Verkuil .audio_bclk_div = 8, 122*7955f03dSHans Verkuil .audio_main_div = 2, 123*7955f03dSHans Verkuil .hpi_buffer_cap = 7, 124*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 125*7955f03dSHans Verkuil GO7007_SENSOR_TV, 126*7955f03dSHans Verkuil .num_i2c_devs = 1, 127*7955f03dSHans Verkuil .i2c_devs = { 128*7955f03dSHans Verkuil { 129*7955f03dSHans Verkuil .type = "saa7113", 130*7955f03dSHans Verkuil .addr = 0x25, 131*7955f03dSHans Verkuil .is_video = 1, 132*7955f03dSHans Verkuil }, 133*7955f03dSHans Verkuil }, 134*7955f03dSHans Verkuil .num_inputs = 2, 135*7955f03dSHans Verkuil .inputs = { 136*7955f03dSHans Verkuil { 137*7955f03dSHans Verkuil .video_input = 0, 138*7955f03dSHans Verkuil .name = "Composite", 139*7955f03dSHans Verkuil }, 140*7955f03dSHans Verkuil { 141*7955f03dSHans Verkuil .video_input = 9, 142*7955f03dSHans Verkuil .name = "S-Video", 143*7955f03dSHans Verkuil }, 144*7955f03dSHans Verkuil }, 145*7955f03dSHans Verkuil .video_config = SAA7115_IDQ_IS_DEFAULT, 146*7955f03dSHans Verkuil }, 147*7955f03dSHans Verkuil }; 148*7955f03dSHans Verkuil 149*7955f03dSHans Verkuil static const struct go7007_usb_board board_star_trek = { 150*7955f03dSHans Verkuil .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, 151*7955f03dSHans Verkuil .main_info = { 152*7955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO, /* | 153*7955f03dSHans Verkuil GO7007_BOARD_HAS_TUNER, */ 154*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 155*7955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 156*7955f03dSHans Verkuil GO7007_SENSOR_TV | 157*7955f03dSHans Verkuil GO7007_SENSOR_SAA7115 | 158*7955f03dSHans Verkuil GO7007_SENSOR_VBI | 159*7955f03dSHans Verkuil GO7007_SENSOR_SCALING, 160*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 161*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 162*7955f03dSHans Verkuil .audio_bclk_div = 8, 163*7955f03dSHans Verkuil .audio_main_div = 2, 164*7955f03dSHans Verkuil .hpi_buffer_cap = 7, 165*7955f03dSHans Verkuil .num_i2c_devs = 1, 166*7955f03dSHans Verkuil .i2c_devs = { 167*7955f03dSHans Verkuil { 168*7955f03dSHans Verkuil .type = "saa7115", 169*7955f03dSHans Verkuil .addr = 0x20, 170*7955f03dSHans Verkuil .is_video = 1, 171*7955f03dSHans Verkuil }, 172*7955f03dSHans Verkuil }, 173*7955f03dSHans Verkuil .num_inputs = 2, 174*7955f03dSHans Verkuil .inputs = { 175*7955f03dSHans Verkuil /* { 176*7955f03dSHans Verkuil * .video_input = 3, 177*7955f03dSHans Verkuil * .audio_index = AUDIO_TUNER, 178*7955f03dSHans Verkuil * .name = "Tuner", 179*7955f03dSHans Verkuil * }, 180*7955f03dSHans Verkuil */ 181*7955f03dSHans Verkuil { 182*7955f03dSHans Verkuil .video_input = 1, 183*7955f03dSHans Verkuil /* .audio_index = AUDIO_EXTERN, */ 184*7955f03dSHans Verkuil .name = "Composite", 185*7955f03dSHans Verkuil }, 186*7955f03dSHans Verkuil { 187*7955f03dSHans Verkuil .video_input = 8, 188*7955f03dSHans Verkuil /* .audio_index = AUDIO_EXTERN, */ 189*7955f03dSHans Verkuil .name = "S-Video", 190*7955f03dSHans Verkuil }, 191*7955f03dSHans Verkuil }, 192*7955f03dSHans Verkuil .video_config = SAA7115_IDQ_IS_DEFAULT, 193*7955f03dSHans Verkuil }, 194*7955f03dSHans Verkuil }; 195*7955f03dSHans Verkuil 196*7955f03dSHans Verkuil static const struct go7007_usb_board board_px_tv402u = { 197*7955f03dSHans Verkuil .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, 198*7955f03dSHans Verkuil .main_info = { 199*7955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 200*7955f03dSHans Verkuil GO7007_BOARD_HAS_TUNER, 201*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 202*7955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 203*7955f03dSHans Verkuil GO7007_SENSOR_TV | 204*7955f03dSHans Verkuil GO7007_SENSOR_SAA7115 | 205*7955f03dSHans Verkuil GO7007_SENSOR_VBI | 206*7955f03dSHans Verkuil GO7007_SENSOR_SCALING, 207*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 208*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 209*7955f03dSHans Verkuil .audio_bclk_div = 8, 210*7955f03dSHans Verkuil .audio_main_div = 2, 211*7955f03dSHans Verkuil .hpi_buffer_cap = 7, 212*7955f03dSHans Verkuil .num_i2c_devs = 5, 213*7955f03dSHans Verkuil .i2c_devs = { 214*7955f03dSHans Verkuil { 215*7955f03dSHans Verkuil .type = "saa7115", 216*7955f03dSHans Verkuil .addr = 0x20, 217*7955f03dSHans Verkuil .is_video = 1, 218*7955f03dSHans Verkuil }, 219*7955f03dSHans Verkuil { 220*7955f03dSHans Verkuil .type = "uda1342", 221*7955f03dSHans Verkuil .addr = 0x1a, 222*7955f03dSHans Verkuil .is_audio = 1, 223*7955f03dSHans Verkuil }, 224*7955f03dSHans Verkuil { 225*7955f03dSHans Verkuil .type = "tuner", 226*7955f03dSHans Verkuil .addr = 0x60, 227*7955f03dSHans Verkuil }, 228*7955f03dSHans Verkuil { 229*7955f03dSHans Verkuil .type = "tuner", 230*7955f03dSHans Verkuil .addr = 0x43, 231*7955f03dSHans Verkuil }, 232*7955f03dSHans Verkuil { 233*7955f03dSHans Verkuil .type = "sony-btf-mpx", 234*7955f03dSHans Verkuil .addr = 0x44, 235*7955f03dSHans Verkuil }, 236*7955f03dSHans Verkuil }, 237*7955f03dSHans Verkuil .num_inputs = 3, 238*7955f03dSHans Verkuil .inputs = { 239*7955f03dSHans Verkuil { 240*7955f03dSHans Verkuil .video_input = 3, 241*7955f03dSHans Verkuil .audio_index = 0, 242*7955f03dSHans Verkuil .name = "Tuner", 243*7955f03dSHans Verkuil }, 244*7955f03dSHans Verkuil { 245*7955f03dSHans Verkuil .video_input = 1, 246*7955f03dSHans Verkuil .audio_index = 1, 247*7955f03dSHans Verkuil .name = "Composite", 248*7955f03dSHans Verkuil }, 249*7955f03dSHans Verkuil { 250*7955f03dSHans Verkuil .video_input = 8, 251*7955f03dSHans Verkuil .audio_index = 1, 252*7955f03dSHans Verkuil .name = "S-Video", 253*7955f03dSHans Verkuil }, 254*7955f03dSHans Verkuil }, 255*7955f03dSHans Verkuil .video_config = SAA7115_IDQ_IS_DEFAULT, 256*7955f03dSHans Verkuil .num_aud_inputs = 2, 257*7955f03dSHans Verkuil .aud_inputs = { 258*7955f03dSHans Verkuil { 259*7955f03dSHans Verkuil .audio_input = UDA1342_IN2, 260*7955f03dSHans Verkuil .name = "Tuner", 261*7955f03dSHans Verkuil }, 262*7955f03dSHans Verkuil { 263*7955f03dSHans Verkuil .audio_input = UDA1342_IN1, 264*7955f03dSHans Verkuil .name = "Line In", 265*7955f03dSHans Verkuil }, 266*7955f03dSHans Verkuil }, 267*7955f03dSHans Verkuil }, 268*7955f03dSHans Verkuil }; 269*7955f03dSHans Verkuil 270*7955f03dSHans Verkuil static const struct go7007_usb_board board_xmen = { 271*7955f03dSHans Verkuil .flags = 0, 272*7955f03dSHans Verkuil .main_info = { 273*7955f03dSHans Verkuil .flags = GO7007_BOARD_USE_ONBOARD_I2C, 274*7955f03dSHans Verkuil .hpi_buffer_cap = 0, 275*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_VREF_POLAR, 276*7955f03dSHans Verkuil .sensor_width = 320, 277*7955f03dSHans Verkuil .sensor_height = 240, 278*7955f03dSHans Verkuil .sensor_framerate = 30030, 279*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_ONE_CHANNEL | 280*7955f03dSHans Verkuil GO7007_AUDIO_I2S_MODE_3 | 281*7955f03dSHans Verkuil GO7007_AUDIO_WORD_14 | 282*7955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 283*7955f03dSHans Verkuil GO7007_AUDIO_BCLK_POLAR | 284*7955f03dSHans Verkuil GO7007_AUDIO_OKI_MODE, 285*7955f03dSHans Verkuil .audio_rate = 8000, 286*7955f03dSHans Verkuil .audio_bclk_div = 48, 287*7955f03dSHans Verkuil .audio_main_div = 1, 288*7955f03dSHans Verkuil .num_i2c_devs = 1, 289*7955f03dSHans Verkuil .i2c_devs = { 290*7955f03dSHans Verkuil { 291*7955f03dSHans Verkuil .type = "ov7640", 292*7955f03dSHans Verkuil .addr = 0x21, 293*7955f03dSHans Verkuil }, 294*7955f03dSHans Verkuil }, 295*7955f03dSHans Verkuil .num_inputs = 1, 296*7955f03dSHans Verkuil .inputs = { 297*7955f03dSHans Verkuil { 298*7955f03dSHans Verkuil .name = "Camera", 299*7955f03dSHans Verkuil }, 300*7955f03dSHans Verkuil }, 301*7955f03dSHans Verkuil }, 302*7955f03dSHans Verkuil }; 303*7955f03dSHans Verkuil 304*7955f03dSHans Verkuil static const struct go7007_usb_board board_matrix_revolution = { 305*7955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 306*7955f03dSHans Verkuil .main_info = { 307*7955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 308*7955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 309*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 310*7955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 311*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 312*7955f03dSHans Verkuil .audio_rate = 48000, 313*7955f03dSHans Verkuil .audio_bclk_div = 8, 314*7955f03dSHans Verkuil .audio_main_div = 2, 315*7955f03dSHans Verkuil .hpi_buffer_cap = 7, 316*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 317*7955f03dSHans Verkuil GO7007_SENSOR_TV | 318*7955f03dSHans Verkuil GO7007_SENSOR_VBI, 319*7955f03dSHans Verkuil .num_i2c_devs = 1, 320*7955f03dSHans Verkuil .i2c_devs = { 321*7955f03dSHans Verkuil { 322*7955f03dSHans Verkuil .type = "tw9903", 323*7955f03dSHans Verkuil .is_video = 1, 324*7955f03dSHans Verkuil .addr = 0x44, 325*7955f03dSHans Verkuil }, 326*7955f03dSHans Verkuil }, 327*7955f03dSHans Verkuil .num_inputs = 2, 328*7955f03dSHans Verkuil .inputs = { 329*7955f03dSHans Verkuil { 330*7955f03dSHans Verkuil .video_input = 2, 331*7955f03dSHans Verkuil .name = "Composite", 332*7955f03dSHans Verkuil }, 333*7955f03dSHans Verkuil { 334*7955f03dSHans Verkuil .video_input = 8, 335*7955f03dSHans Verkuil .name = "S-Video", 336*7955f03dSHans Verkuil }, 337*7955f03dSHans Verkuil }, 338*7955f03dSHans Verkuil }, 339*7955f03dSHans Verkuil }; 340*7955f03dSHans Verkuil 341*7955f03dSHans Verkuil static const struct go7007_usb_board board_lifeview_lr192 = { 342*7955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 343*7955f03dSHans Verkuil .main_info = { 344*7955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 345*7955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 346*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 347*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 348*7955f03dSHans Verkuil .audio_rate = 48000, 349*7955f03dSHans Verkuil .audio_bclk_div = 8, 350*7955f03dSHans Verkuil .audio_main_div = 2, 351*7955f03dSHans Verkuil .hpi_buffer_cap = 7, 352*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 353*7955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 354*7955f03dSHans Verkuil GO7007_SENSOR_TV | 355*7955f03dSHans Verkuil GO7007_SENSOR_VBI | 356*7955f03dSHans Verkuil GO7007_SENSOR_SCALING, 357*7955f03dSHans Verkuil .num_i2c_devs = 0, 358*7955f03dSHans Verkuil .num_inputs = 1, 359*7955f03dSHans Verkuil .inputs = { 360*7955f03dSHans Verkuil { 361*7955f03dSHans Verkuil .video_input = 0, 362*7955f03dSHans Verkuil .name = "Composite", 363*7955f03dSHans Verkuil }, 364*7955f03dSHans Verkuil }, 365*7955f03dSHans Verkuil }, 366*7955f03dSHans Verkuil }; 367*7955f03dSHans Verkuil 368*7955f03dSHans Verkuil static const struct go7007_usb_board board_endura = { 369*7955f03dSHans Verkuil .flags = 0, 370*7955f03dSHans Verkuil .main_info = { 371*7955f03dSHans Verkuil .flags = 0, 372*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 373*7955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 374*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 375*7955f03dSHans Verkuil .audio_rate = 8000, 376*7955f03dSHans Verkuil .audio_bclk_div = 48, 377*7955f03dSHans Verkuil .audio_main_div = 8, 378*7955f03dSHans Verkuil .hpi_buffer_cap = 0, 379*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 380*7955f03dSHans Verkuil GO7007_SENSOR_TV, 381*7955f03dSHans Verkuil .sensor_h_offset = 8, 382*7955f03dSHans Verkuil .num_i2c_devs = 0, 383*7955f03dSHans Verkuil .num_inputs = 1, 384*7955f03dSHans Verkuil .inputs = { 385*7955f03dSHans Verkuil { 386*7955f03dSHans Verkuil .name = "Camera", 387*7955f03dSHans Verkuil }, 388*7955f03dSHans Verkuil }, 389*7955f03dSHans Verkuil }, 390*7955f03dSHans Verkuil }; 391*7955f03dSHans Verkuil 392*7955f03dSHans Verkuil static const struct go7007_usb_board board_adlink_mpg24 = { 393*7955f03dSHans Verkuil .flags = 0, 394*7955f03dSHans Verkuil .main_info = { 395*7955f03dSHans Verkuil .flags = GO7007_BOARD_USE_ONBOARD_I2C, 396*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 397*7955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 398*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 399*7955f03dSHans Verkuil .audio_rate = 48000, 400*7955f03dSHans Verkuil .audio_bclk_div = 8, 401*7955f03dSHans Verkuil .audio_main_div = 2, 402*7955f03dSHans Verkuil .hpi_buffer_cap = 0, 403*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 404*7955f03dSHans Verkuil GO7007_SENSOR_TV | 405*7955f03dSHans Verkuil GO7007_SENSOR_VBI, 406*7955f03dSHans Verkuil .num_i2c_devs = 1, 407*7955f03dSHans Verkuil .i2c_devs = { 408*7955f03dSHans Verkuil { 409*7955f03dSHans Verkuil .type = "tw2804", 410*7955f03dSHans Verkuil .addr = 0x00, /* yes, really */ 411*7955f03dSHans Verkuil .flags = I2C_CLIENT_TEN, 412*7955f03dSHans Verkuil .is_video = 1, 413*7955f03dSHans Verkuil }, 414*7955f03dSHans Verkuil }, 415*7955f03dSHans Verkuil .num_inputs = 1, 416*7955f03dSHans Verkuil .inputs = { 417*7955f03dSHans Verkuil { 418*7955f03dSHans Verkuil .name = "Composite", 419*7955f03dSHans Verkuil }, 420*7955f03dSHans Verkuil }, 421*7955f03dSHans Verkuil }, 422*7955f03dSHans Verkuil }; 423*7955f03dSHans Verkuil 424*7955f03dSHans Verkuil static const struct go7007_usb_board board_sensoray_2250 = { 425*7955f03dSHans Verkuil .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, 426*7955f03dSHans Verkuil .main_info = { 427*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 428*7955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 429*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 430*7955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO, 431*7955f03dSHans Verkuil .audio_rate = 48000, 432*7955f03dSHans Verkuil .audio_bclk_div = 8, 433*7955f03dSHans Verkuil .audio_main_div = 2, 434*7955f03dSHans Verkuil .hpi_buffer_cap = 7, 435*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 436*7955f03dSHans Verkuil GO7007_SENSOR_TV, 437*7955f03dSHans Verkuil .num_i2c_devs = 1, 438*7955f03dSHans Verkuil .i2c_devs = { 439*7955f03dSHans Verkuil { 440*7955f03dSHans Verkuil .type = "s2250", 441*7955f03dSHans Verkuil .addr = 0x43, 442*7955f03dSHans Verkuil .is_video = 1, 443*7955f03dSHans Verkuil .is_audio = 1, 444*7955f03dSHans Verkuil }, 445*7955f03dSHans Verkuil }, 446*7955f03dSHans Verkuil .num_inputs = 2, 447*7955f03dSHans Verkuil .inputs = { 448*7955f03dSHans Verkuil { 449*7955f03dSHans Verkuil .video_input = 0, 450*7955f03dSHans Verkuil .name = "Composite", 451*7955f03dSHans Verkuil }, 452*7955f03dSHans Verkuil { 453*7955f03dSHans Verkuil .video_input = 1, 454*7955f03dSHans Verkuil .name = "S-Video", 455*7955f03dSHans Verkuil }, 456*7955f03dSHans Verkuil }, 457*7955f03dSHans Verkuil .num_aud_inputs = 3, 458*7955f03dSHans Verkuil .aud_inputs = { 459*7955f03dSHans Verkuil { 460*7955f03dSHans Verkuil .audio_input = 0, 461*7955f03dSHans Verkuil .name = "Line In", 462*7955f03dSHans Verkuil }, 463*7955f03dSHans Verkuil { 464*7955f03dSHans Verkuil .audio_input = 1, 465*7955f03dSHans Verkuil .name = "Mic", 466*7955f03dSHans Verkuil }, 467*7955f03dSHans Verkuil { 468*7955f03dSHans Verkuil .audio_input = 2, 469*7955f03dSHans Verkuil .name = "Mic Boost", 470*7955f03dSHans Verkuil }, 471*7955f03dSHans Verkuil }, 472*7955f03dSHans Verkuil }, 473*7955f03dSHans Verkuil }; 474*7955f03dSHans Verkuil 475*7955f03dSHans Verkuil static const struct go7007_usb_board board_ads_usbav_709 = { 476*7955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 477*7955f03dSHans Verkuil .main_info = { 478*7955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 479*7955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 480*7955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 481*7955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 482*7955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 483*7955f03dSHans Verkuil .audio_rate = 48000, 484*7955f03dSHans Verkuil .audio_bclk_div = 8, 485*7955f03dSHans Verkuil .audio_main_div = 2, 486*7955f03dSHans Verkuil .hpi_buffer_cap = 7, 487*7955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 488*7955f03dSHans Verkuil GO7007_SENSOR_TV | 489*7955f03dSHans Verkuil GO7007_SENSOR_VBI, 490*7955f03dSHans Verkuil .num_i2c_devs = 1, 491*7955f03dSHans Verkuil .i2c_devs = { 492*7955f03dSHans Verkuil { 493*7955f03dSHans Verkuil .type = "tw9906", 494*7955f03dSHans Verkuil .is_video = 1, 495*7955f03dSHans Verkuil .addr = 0x44, 496*7955f03dSHans Verkuil }, 497*7955f03dSHans Verkuil }, 498*7955f03dSHans Verkuil .num_inputs = 2, 499*7955f03dSHans Verkuil .inputs = { 500*7955f03dSHans Verkuil { 501*7955f03dSHans Verkuil .video_input = 0, 502*7955f03dSHans Verkuil .name = "Composite", 503*7955f03dSHans Verkuil }, 504*7955f03dSHans Verkuil { 505*7955f03dSHans Verkuil .video_input = 10, 506*7955f03dSHans Verkuil .name = "S-Video", 507*7955f03dSHans Verkuil }, 508*7955f03dSHans Verkuil }, 509*7955f03dSHans Verkuil }, 510*7955f03dSHans Verkuil }; 511*7955f03dSHans Verkuil 512*7955f03dSHans Verkuil static const struct usb_device_id go7007_usb_id_table[] = { 513*7955f03dSHans Verkuil { 514*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 515*7955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 516*7955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 517*7955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 518*7955f03dSHans Verkuil .bcdDevice_lo = 0x200, /* Revision number of XMen */ 519*7955f03dSHans Verkuil .bcdDevice_hi = 0x200, 520*7955f03dSHans Verkuil .bInterfaceClass = 255, 521*7955f03dSHans Verkuil .bInterfaceSubClass = 0, 522*7955f03dSHans Verkuil .bInterfaceProtocol = 255, 523*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN, 524*7955f03dSHans Verkuil }, 525*7955f03dSHans Verkuil { 526*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 527*7955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 528*7955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 529*7955f03dSHans Verkuil .bcdDevice_lo = 0x202, /* Revision number of Matrix II */ 530*7955f03dSHans Verkuil .bcdDevice_hi = 0x202, 531*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_II, 532*7955f03dSHans Verkuil }, 533*7955f03dSHans Verkuil { 534*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 535*7955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 536*7955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 537*7955f03dSHans Verkuil .bcdDevice_lo = 0x204, /* Revision number of Matrix */ 538*7955f03dSHans Verkuil .bcdDevice_hi = 0x204, /* Reloaded */ 539*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD, 540*7955f03dSHans Verkuil }, 541*7955f03dSHans Verkuil { 542*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 543*7955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 544*7955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 545*7955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 546*7955f03dSHans Verkuil .bcdDevice_lo = 0x205, /* Revision number of XMen-II */ 547*7955f03dSHans Verkuil .bcdDevice_hi = 0x205, 548*7955f03dSHans Verkuil .bInterfaceClass = 255, 549*7955f03dSHans Verkuil .bInterfaceSubClass = 0, 550*7955f03dSHans Verkuil .bInterfaceProtocol = 255, 551*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_II, 552*7955f03dSHans Verkuil }, 553*7955f03dSHans Verkuil { 554*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 555*7955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 556*7955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 557*7955f03dSHans Verkuil .bcdDevice_lo = 0x208, /* Revision number of Star Trek */ 558*7955f03dSHans Verkuil .bcdDevice_hi = 0x208, 559*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_STAR_TREK, 560*7955f03dSHans Verkuil }, 561*7955f03dSHans Verkuil { 562*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 563*7955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 564*7955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 565*7955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 566*7955f03dSHans Verkuil .bcdDevice_lo = 0x209, /* Revision number of XMen-III */ 567*7955f03dSHans Verkuil .bcdDevice_hi = 0x209, 568*7955f03dSHans Verkuil .bInterfaceClass = 255, 569*7955f03dSHans Verkuil .bInterfaceSubClass = 0, 570*7955f03dSHans Verkuil .bInterfaceProtocol = 255, 571*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_III, 572*7955f03dSHans Verkuil }, 573*7955f03dSHans Verkuil { 574*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 575*7955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 576*7955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 577*7955f03dSHans Verkuil .bcdDevice_lo = 0x210, /* Revision number of Matrix */ 578*7955f03dSHans Verkuil .bcdDevice_hi = 0x210, /* Revolution */ 579*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV, 580*7955f03dSHans Verkuil }, 581*7955f03dSHans Verkuil { 582*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 583*7955f03dSHans Verkuil .idVendor = 0x093b, /* Vendor ID of Plextor */ 584*7955f03dSHans Verkuil .idProduct = 0xa102, /* Product ID of M402U */ 585*7955f03dSHans Verkuil .bcdDevice_lo = 0x1, /* revision number of Blueberry */ 586*7955f03dSHans Verkuil .bcdDevice_hi = 0x1, 587*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_M402U, 588*7955f03dSHans Verkuil }, 589*7955f03dSHans Verkuil { 590*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 591*7955f03dSHans Verkuil .idVendor = 0x093b, /* Vendor ID of Plextor */ 592*7955f03dSHans Verkuil .idProduct = 0xa104, /* Product ID of TV402U */ 593*7955f03dSHans Verkuil .bcdDevice_lo = 0x1, 594*7955f03dSHans Verkuil .bcdDevice_hi = 0x1, 595*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_TV402U, 596*7955f03dSHans Verkuil }, 597*7955f03dSHans Verkuil { 598*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 599*7955f03dSHans Verkuil .idVendor = 0x10fd, /* Vendor ID of Anubis Electronics */ 600*7955f03dSHans Verkuil .idProduct = 0xde00, /* Product ID of Lifeview LR192 */ 601*7955f03dSHans Verkuil .bcdDevice_lo = 0x1, 602*7955f03dSHans Verkuil .bcdDevice_hi = 0x1, 603*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192, 604*7955f03dSHans Verkuil }, 605*7955f03dSHans Verkuil { 606*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 607*7955f03dSHans Verkuil .idVendor = 0x1943, /* Vendor ID Sensoray */ 608*7955f03dSHans Verkuil .idProduct = 0x2250, /* Product ID of 2250/2251 */ 609*7955f03dSHans Verkuil .bcdDevice_lo = 0x1, 610*7955f03dSHans Verkuil .bcdDevice_hi = 0x1, 611*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250, 612*7955f03dSHans Verkuil }, 613*7955f03dSHans Verkuil { 614*7955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 615*7955f03dSHans Verkuil .idVendor = 0x06e1, /* Vendor ID of ADS Technologies */ 616*7955f03dSHans Verkuil .idProduct = 0x0709, /* Product ID of DVD Xpress DX2 */ 617*7955f03dSHans Verkuil .bcdDevice_lo = 0x204, 618*7955f03dSHans Verkuil .bcdDevice_hi = 0x204, 619*7955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709, 620*7955f03dSHans Verkuil }, 621*7955f03dSHans Verkuil { } /* Terminating entry */ 622*7955f03dSHans Verkuil }; 623*7955f03dSHans Verkuil 624*7955f03dSHans Verkuil MODULE_DEVICE_TABLE(usb, go7007_usb_id_table); 625*7955f03dSHans Verkuil 626*7955f03dSHans Verkuil /********************* Driver for EZ-USB HPI interface *********************/ 627*7955f03dSHans Verkuil 628*7955f03dSHans Verkuil static int go7007_usb_vendor_request(struct go7007 *go, int request, 629*7955f03dSHans Verkuil int value, int index, void *transfer_buffer, int length, int in) 630*7955f03dSHans Verkuil { 631*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 632*7955f03dSHans Verkuil int timeout = 5000; 633*7955f03dSHans Verkuil 634*7955f03dSHans Verkuil if (in) { 635*7955f03dSHans Verkuil return usb_control_msg(usb->usbdev, 636*7955f03dSHans Verkuil usb_rcvctrlpipe(usb->usbdev, 0), request, 637*7955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 638*7955f03dSHans Verkuil value, index, transfer_buffer, length, timeout); 639*7955f03dSHans Verkuil } else { 640*7955f03dSHans Verkuil return usb_control_msg(usb->usbdev, 641*7955f03dSHans Verkuil usb_sndctrlpipe(usb->usbdev, 0), request, 642*7955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE, 643*7955f03dSHans Verkuil value, index, transfer_buffer, length, timeout); 644*7955f03dSHans Verkuil } 645*7955f03dSHans Verkuil } 646*7955f03dSHans Verkuil 647*7955f03dSHans Verkuil static int go7007_usb_interface_reset(struct go7007 *go) 648*7955f03dSHans Verkuil { 649*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 650*7955f03dSHans Verkuil u16 intr_val, intr_data; 651*7955f03dSHans Verkuil 652*7955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 653*7955f03dSHans Verkuil return -1; 654*7955f03dSHans Verkuil /* Reset encoder */ 655*7955f03dSHans Verkuil if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) 656*7955f03dSHans Verkuil return -1; 657*7955f03dSHans Verkuil msleep(100); 658*7955f03dSHans Verkuil 659*7955f03dSHans Verkuil if (usb->board->flags & GO7007_USB_EZUSB) { 660*7955f03dSHans Verkuil /* Reset buffer in EZ-USB */ 661*7955f03dSHans Verkuil pr_debug("resetting EZ-USB buffers\n"); 662*7955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 || 663*7955f03dSHans Verkuil go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0) 664*7955f03dSHans Verkuil return -1; 665*7955f03dSHans Verkuil 666*7955f03dSHans Verkuil /* Reset encoder again */ 667*7955f03dSHans Verkuil if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) 668*7955f03dSHans Verkuil return -1; 669*7955f03dSHans Verkuil msleep(100); 670*7955f03dSHans Verkuil } 671*7955f03dSHans Verkuil 672*7955f03dSHans Verkuil /* Wait for an interrupt to indicate successful hardware reset */ 673*7955f03dSHans Verkuil if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || 674*7955f03dSHans Verkuil (intr_val & ~0x1) != 0x55aa) { 675*7955f03dSHans Verkuil dev_err(go->dev, "unable to reset the USB interface\n"); 676*7955f03dSHans Verkuil return -1; 677*7955f03dSHans Verkuil } 678*7955f03dSHans Verkuil return 0; 679*7955f03dSHans Verkuil } 680*7955f03dSHans Verkuil 681*7955f03dSHans Verkuil static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, 682*7955f03dSHans Verkuil int addr, int data) 683*7955f03dSHans Verkuil { 684*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 685*7955f03dSHans Verkuil int i, r; 686*7955f03dSHans Verkuil u16 status_reg = 0; 687*7955f03dSHans Verkuil int timeout = 500; 688*7955f03dSHans Verkuil 689*7955f03dSHans Verkuil pr_debug("WriteInterrupt: %04x %04x\n", addr, data); 690*7955f03dSHans Verkuil 691*7955f03dSHans Verkuil for (i = 0; i < 100; ++i) { 692*7955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, 693*7955f03dSHans Verkuil usb_rcvctrlpipe(usb->usbdev, 0), 0x14, 694*7955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 695*7955f03dSHans Verkuil 0, HPI_STATUS_ADDR, go->usb_buf, 696*7955f03dSHans Verkuil sizeof(status_reg), timeout); 697*7955f03dSHans Verkuil if (r < 0) 698*7955f03dSHans Verkuil break; 699*7955f03dSHans Verkuil status_reg = le16_to_cpu(*((u16 *)go->usb_buf)); 700*7955f03dSHans Verkuil if (!(status_reg & 0x0010)) 701*7955f03dSHans Verkuil break; 702*7955f03dSHans Verkuil msleep(10); 703*7955f03dSHans Verkuil } 704*7955f03dSHans Verkuil if (r < 0) 705*7955f03dSHans Verkuil goto write_int_error; 706*7955f03dSHans Verkuil if (i == 100) { 707*7955f03dSHans Verkuil dev_err(go->dev, "device is hung, status reg = 0x%04x\n", status_reg); 708*7955f03dSHans Verkuil return -1; 709*7955f03dSHans Verkuil } 710*7955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12, 711*7955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE, data, 712*7955f03dSHans Verkuil INT_PARAM_ADDR, NULL, 0, timeout); 713*7955f03dSHans Verkuil if (r < 0) 714*7955f03dSHans Verkuil goto write_int_error; 715*7955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 716*7955f03dSHans Verkuil 0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr, 717*7955f03dSHans Verkuil INT_INDEX_ADDR, NULL, 0, timeout); 718*7955f03dSHans Verkuil if (r < 0) 719*7955f03dSHans Verkuil goto write_int_error; 720*7955f03dSHans Verkuil return 0; 721*7955f03dSHans Verkuil 722*7955f03dSHans Verkuil write_int_error: 723*7955f03dSHans Verkuil dev_err(go->dev, "error in WriteInterrupt: %d\n", r); 724*7955f03dSHans Verkuil return r; 725*7955f03dSHans Verkuil } 726*7955f03dSHans Verkuil 727*7955f03dSHans Verkuil static int go7007_usb_onboard_write_interrupt(struct go7007 *go, 728*7955f03dSHans Verkuil int addr, int data) 729*7955f03dSHans Verkuil { 730*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 731*7955f03dSHans Verkuil int r; 732*7955f03dSHans Verkuil int timeout = 500; 733*7955f03dSHans Verkuil 734*7955f03dSHans Verkuil pr_debug("WriteInterrupt: %04x %04x\n", addr, data); 735*7955f03dSHans Verkuil 736*7955f03dSHans Verkuil go->usb_buf[0] = data & 0xff; 737*7955f03dSHans Verkuil go->usb_buf[1] = data >> 8; 738*7955f03dSHans Verkuil go->usb_buf[2] = addr & 0xff; 739*7955f03dSHans Verkuil go->usb_buf[3] = addr >> 8; 740*7955f03dSHans Verkuil go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0; 741*7955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00, 742*7955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa, 743*7955f03dSHans Verkuil 0xf0f0, go->usb_buf, 8, timeout); 744*7955f03dSHans Verkuil if (r < 0) { 745*7955f03dSHans Verkuil dev_err(go->dev, "error in WriteInterrupt: %d\n", r); 746*7955f03dSHans Verkuil return r; 747*7955f03dSHans Verkuil } 748*7955f03dSHans Verkuil return 0; 749*7955f03dSHans Verkuil } 750*7955f03dSHans Verkuil 751*7955f03dSHans Verkuil static void go7007_usb_readinterrupt_complete(struct urb *urb) 752*7955f03dSHans Verkuil { 753*7955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 754*7955f03dSHans Verkuil u16 *regs = (u16 *)urb->transfer_buffer; 755*7955f03dSHans Verkuil int status = urb->status; 756*7955f03dSHans Verkuil 757*7955f03dSHans Verkuil if (status) { 758*7955f03dSHans Verkuil if (status != -ESHUTDOWN && 759*7955f03dSHans Verkuil go->status != STATUS_SHUTDOWN) { 760*7955f03dSHans Verkuil dev_err(go->dev, "error in read interrupt: %d\n", urb->status); 761*7955f03dSHans Verkuil } else { 762*7955f03dSHans Verkuil wake_up(&go->interrupt_waitq); 763*7955f03dSHans Verkuil return; 764*7955f03dSHans Verkuil } 765*7955f03dSHans Verkuil } else if (urb->actual_length != urb->transfer_buffer_length) { 766*7955f03dSHans Verkuil dev_err(go->dev, "short read in interrupt pipe!\n"); 767*7955f03dSHans Verkuil } else { 768*7955f03dSHans Verkuil go->interrupt_available = 1; 769*7955f03dSHans Verkuil go->interrupt_data = __le16_to_cpu(regs[0]); 770*7955f03dSHans Verkuil go->interrupt_value = __le16_to_cpu(regs[1]); 771*7955f03dSHans Verkuil pr_debug("ReadInterrupt: %04x %04x\n", 772*7955f03dSHans Verkuil go->interrupt_value, go->interrupt_data); 773*7955f03dSHans Verkuil } 774*7955f03dSHans Verkuil 775*7955f03dSHans Verkuil wake_up(&go->interrupt_waitq); 776*7955f03dSHans Verkuil } 777*7955f03dSHans Verkuil 778*7955f03dSHans Verkuil static int go7007_usb_read_interrupt(struct go7007 *go) 779*7955f03dSHans Verkuil { 780*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 781*7955f03dSHans Verkuil int r; 782*7955f03dSHans Verkuil 783*7955f03dSHans Verkuil r = usb_submit_urb(usb->intr_urb, GFP_KERNEL); 784*7955f03dSHans Verkuil if (r < 0) { 785*7955f03dSHans Verkuil dev_err(go->dev, "unable to submit interrupt urb: %d\n", r); 786*7955f03dSHans Verkuil return r; 787*7955f03dSHans Verkuil } 788*7955f03dSHans Verkuil return 0; 789*7955f03dSHans Verkuil } 790*7955f03dSHans Verkuil 791*7955f03dSHans Verkuil static void go7007_usb_read_video_pipe_complete(struct urb *urb) 792*7955f03dSHans Verkuil { 793*7955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 794*7955f03dSHans Verkuil int r, status = urb->status; 795*7955f03dSHans Verkuil 796*7955f03dSHans Verkuil if (!vb2_is_streaming(&go->vidq)) { 797*7955f03dSHans Verkuil wake_up_interruptible(&go->frame_waitq); 798*7955f03dSHans Verkuil return; 799*7955f03dSHans Verkuil } 800*7955f03dSHans Verkuil if (status) { 801*7955f03dSHans Verkuil dev_err(go->dev, "error in video pipe: %d\n", status); 802*7955f03dSHans Verkuil return; 803*7955f03dSHans Verkuil } 804*7955f03dSHans Verkuil if (urb->actual_length != urb->transfer_buffer_length) { 805*7955f03dSHans Verkuil dev_err(go->dev, "short read in video pipe!\n"); 806*7955f03dSHans Verkuil return; 807*7955f03dSHans Verkuil } 808*7955f03dSHans Verkuil go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length); 809*7955f03dSHans Verkuil r = usb_submit_urb(urb, GFP_ATOMIC); 810*7955f03dSHans Verkuil if (r < 0) 811*7955f03dSHans Verkuil dev_err(go->dev, "error in video pipe: %d\n", r); 812*7955f03dSHans Verkuil } 813*7955f03dSHans Verkuil 814*7955f03dSHans Verkuil static void go7007_usb_read_audio_pipe_complete(struct urb *urb) 815*7955f03dSHans Verkuil { 816*7955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 817*7955f03dSHans Verkuil int r, status = urb->status; 818*7955f03dSHans Verkuil 819*7955f03dSHans Verkuil if (!vb2_is_streaming(&go->vidq)) 820*7955f03dSHans Verkuil return; 821*7955f03dSHans Verkuil if (status) { 822*7955f03dSHans Verkuil dev_err(go->dev, "error in audio pipe: %d\n", 823*7955f03dSHans Verkuil status); 824*7955f03dSHans Verkuil return; 825*7955f03dSHans Verkuil } 826*7955f03dSHans Verkuil if (urb->actual_length != urb->transfer_buffer_length) { 827*7955f03dSHans Verkuil dev_err(go->dev, "short read in audio pipe!\n"); 828*7955f03dSHans Verkuil return; 829*7955f03dSHans Verkuil } 830*7955f03dSHans Verkuil if (go->audio_deliver != NULL) 831*7955f03dSHans Verkuil go->audio_deliver(go, urb->transfer_buffer, urb->actual_length); 832*7955f03dSHans Verkuil r = usb_submit_urb(urb, GFP_ATOMIC); 833*7955f03dSHans Verkuil if (r < 0) 834*7955f03dSHans Verkuil dev_err(go->dev, "error in audio pipe: %d\n", r); 835*7955f03dSHans Verkuil } 836*7955f03dSHans Verkuil 837*7955f03dSHans Verkuil static int go7007_usb_stream_start(struct go7007 *go) 838*7955f03dSHans Verkuil { 839*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 840*7955f03dSHans Verkuil int i, r; 841*7955f03dSHans Verkuil 842*7955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 843*7955f03dSHans Verkuil r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL); 844*7955f03dSHans Verkuil if (r < 0) { 845*7955f03dSHans Verkuil dev_err(go->dev, "error submitting video urb %d: %d\n", i, r); 846*7955f03dSHans Verkuil goto video_submit_failed; 847*7955f03dSHans Verkuil } 848*7955f03dSHans Verkuil } 849*7955f03dSHans Verkuil if (!go->audio_enabled) 850*7955f03dSHans Verkuil return 0; 851*7955f03dSHans Verkuil 852*7955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 853*7955f03dSHans Verkuil r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL); 854*7955f03dSHans Verkuil if (r < 0) { 855*7955f03dSHans Verkuil dev_err(go->dev, "error submitting audio urb %d: %d\n", i, r); 856*7955f03dSHans Verkuil goto audio_submit_failed; 857*7955f03dSHans Verkuil } 858*7955f03dSHans Verkuil } 859*7955f03dSHans Verkuil return 0; 860*7955f03dSHans Verkuil 861*7955f03dSHans Verkuil audio_submit_failed: 862*7955f03dSHans Verkuil for (i = 0; i < 7; ++i) 863*7955f03dSHans Verkuil usb_kill_urb(usb->audio_urbs[i]); 864*7955f03dSHans Verkuil video_submit_failed: 865*7955f03dSHans Verkuil for (i = 0; i < 8; ++i) 866*7955f03dSHans Verkuil usb_kill_urb(usb->video_urbs[i]); 867*7955f03dSHans Verkuil return -1; 868*7955f03dSHans Verkuil } 869*7955f03dSHans Verkuil 870*7955f03dSHans Verkuil static int go7007_usb_stream_stop(struct go7007 *go) 871*7955f03dSHans Verkuil { 872*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 873*7955f03dSHans Verkuil int i; 874*7955f03dSHans Verkuil 875*7955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 876*7955f03dSHans Verkuil return 0; 877*7955f03dSHans Verkuil for (i = 0; i < 8; ++i) 878*7955f03dSHans Verkuil usb_kill_urb(usb->video_urbs[i]); 879*7955f03dSHans Verkuil if (go->audio_enabled) 880*7955f03dSHans Verkuil for (i = 0; i < 8; ++i) 881*7955f03dSHans Verkuil usb_kill_urb(usb->audio_urbs[i]); 882*7955f03dSHans Verkuil return 0; 883*7955f03dSHans Verkuil } 884*7955f03dSHans Verkuil 885*7955f03dSHans Verkuil static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len) 886*7955f03dSHans Verkuil { 887*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 888*7955f03dSHans Verkuil int transferred, pipe; 889*7955f03dSHans Verkuil int timeout = 500; 890*7955f03dSHans Verkuil 891*7955f03dSHans Verkuil pr_debug("DownloadBuffer sending %d bytes\n", len); 892*7955f03dSHans Verkuil 893*7955f03dSHans Verkuil if (usb->board->flags & GO7007_USB_EZUSB) 894*7955f03dSHans Verkuil pipe = usb_sndbulkpipe(usb->usbdev, 2); 895*7955f03dSHans Verkuil else 896*7955f03dSHans Verkuil pipe = usb_sndbulkpipe(usb->usbdev, 3); 897*7955f03dSHans Verkuil 898*7955f03dSHans Verkuil return usb_bulk_msg(usb->usbdev, pipe, data, len, 899*7955f03dSHans Verkuil &transferred, timeout); 900*7955f03dSHans Verkuil } 901*7955f03dSHans Verkuil 902*7955f03dSHans Verkuil static void go7007_usb_release(struct go7007 *go) 903*7955f03dSHans Verkuil { 904*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 905*7955f03dSHans Verkuil struct urb *vurb, *aurb; 906*7955f03dSHans Verkuil int i; 907*7955f03dSHans Verkuil 908*7955f03dSHans Verkuil if (usb->intr_urb) { 909*7955f03dSHans Verkuil usb_kill_urb(usb->intr_urb); 910*7955f03dSHans Verkuil kfree(usb->intr_urb->transfer_buffer); 911*7955f03dSHans Verkuil usb_free_urb(usb->intr_urb); 912*7955f03dSHans Verkuil } 913*7955f03dSHans Verkuil 914*7955f03dSHans Verkuil /* Free USB-related structs */ 915*7955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 916*7955f03dSHans Verkuil vurb = usb->video_urbs[i]; 917*7955f03dSHans Verkuil if (vurb) { 918*7955f03dSHans Verkuil usb_kill_urb(vurb); 919*7955f03dSHans Verkuil kfree(vurb->transfer_buffer); 920*7955f03dSHans Verkuil usb_free_urb(vurb); 921*7955f03dSHans Verkuil } 922*7955f03dSHans Verkuil aurb = usb->audio_urbs[i]; 923*7955f03dSHans Verkuil if (aurb) { 924*7955f03dSHans Verkuil usb_kill_urb(aurb); 925*7955f03dSHans Verkuil kfree(aurb->transfer_buffer); 926*7955f03dSHans Verkuil usb_free_urb(aurb); 927*7955f03dSHans Verkuil } 928*7955f03dSHans Verkuil } 929*7955f03dSHans Verkuil 930*7955f03dSHans Verkuil kfree(go->hpi_context); 931*7955f03dSHans Verkuil } 932*7955f03dSHans Verkuil 933*7955f03dSHans Verkuil static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { 934*7955f03dSHans Verkuil .interface_reset = go7007_usb_interface_reset, 935*7955f03dSHans Verkuil .write_interrupt = go7007_usb_ezusb_write_interrupt, 936*7955f03dSHans Verkuil .read_interrupt = go7007_usb_read_interrupt, 937*7955f03dSHans Verkuil .stream_start = go7007_usb_stream_start, 938*7955f03dSHans Verkuil .stream_stop = go7007_usb_stream_stop, 939*7955f03dSHans Verkuil .send_firmware = go7007_usb_send_firmware, 940*7955f03dSHans Verkuil .release = go7007_usb_release, 941*7955f03dSHans Verkuil }; 942*7955f03dSHans Verkuil 943*7955f03dSHans Verkuil static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { 944*7955f03dSHans Verkuil .interface_reset = go7007_usb_interface_reset, 945*7955f03dSHans Verkuil .write_interrupt = go7007_usb_onboard_write_interrupt, 946*7955f03dSHans Verkuil .read_interrupt = go7007_usb_read_interrupt, 947*7955f03dSHans Verkuil .stream_start = go7007_usb_stream_start, 948*7955f03dSHans Verkuil .stream_stop = go7007_usb_stream_stop, 949*7955f03dSHans Verkuil .send_firmware = go7007_usb_send_firmware, 950*7955f03dSHans Verkuil .release = go7007_usb_release, 951*7955f03dSHans Verkuil }; 952*7955f03dSHans Verkuil 953*7955f03dSHans Verkuil /********************* Driver for EZ-USB I2C adapter *********************/ 954*7955f03dSHans Verkuil 955*7955f03dSHans Verkuil static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, 956*7955f03dSHans Verkuil struct i2c_msg msgs[], int num) 957*7955f03dSHans Verkuil { 958*7955f03dSHans Verkuil struct go7007 *go = i2c_get_adapdata(adapter); 959*7955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 960*7955f03dSHans Verkuil u8 *buf = go->usb_buf; 961*7955f03dSHans Verkuil int buf_len, i; 962*7955f03dSHans Verkuil int ret = -EIO; 963*7955f03dSHans Verkuil 964*7955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 965*7955f03dSHans Verkuil return -ENODEV; 966*7955f03dSHans Verkuil 967*7955f03dSHans Verkuil mutex_lock(&usb->i2c_lock); 968*7955f03dSHans Verkuil 969*7955f03dSHans Verkuil for (i = 0; i < num; ++i) { 970*7955f03dSHans Verkuil /* The hardware command is "write some bytes then read some 971*7955f03dSHans Verkuil * bytes", so we try to coalesce a write followed by a read 972*7955f03dSHans Verkuil * into a single USB transaction */ 973*7955f03dSHans Verkuil if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr && 974*7955f03dSHans Verkuil !(msgs[i].flags & I2C_M_RD) && 975*7955f03dSHans Verkuil (msgs[i + 1].flags & I2C_M_RD)) { 976*7955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 977*7955f03dSHans Verkuil pr_debug("i2c write/read %d/%d bytes on %02x\n", 978*7955f03dSHans Verkuil msgs[i].len, msgs[i + 1].len, msgs[i].addr); 979*7955f03dSHans Verkuil #endif 980*7955f03dSHans Verkuil buf[0] = 0x01; 981*7955f03dSHans Verkuil buf[1] = msgs[i].len + 1; 982*7955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 983*7955f03dSHans Verkuil memcpy(&buf[3], msgs[i].buf, msgs[i].len); 984*7955f03dSHans Verkuil buf_len = msgs[i].len + 3; 985*7955f03dSHans Verkuil buf[buf_len++] = msgs[++i].len; 986*7955f03dSHans Verkuil } else if (msgs[i].flags & I2C_M_RD) { 987*7955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 988*7955f03dSHans Verkuil pr_debug("i2c read %d bytes on %02x\n", 989*7955f03dSHans Verkuil msgs[i].len, msgs[i].addr); 990*7955f03dSHans Verkuil #endif 991*7955f03dSHans Verkuil buf[0] = 0x01; 992*7955f03dSHans Verkuil buf[1] = 1; 993*7955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 994*7955f03dSHans Verkuil buf[3] = msgs[i].len; 995*7955f03dSHans Verkuil buf_len = 4; 996*7955f03dSHans Verkuil } else { 997*7955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 998*7955f03dSHans Verkuil pr_debug("i2c write %d bytes on %02x\n", 999*7955f03dSHans Verkuil msgs[i].len, msgs[i].addr); 1000*7955f03dSHans Verkuil #endif 1001*7955f03dSHans Verkuil buf[0] = 0x00; 1002*7955f03dSHans Verkuil buf[1] = msgs[i].len + 1; 1003*7955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 1004*7955f03dSHans Verkuil memcpy(&buf[3], msgs[i].buf, msgs[i].len); 1005*7955f03dSHans Verkuil buf_len = msgs[i].len + 3; 1006*7955f03dSHans Verkuil buf[buf_len++] = 0; 1007*7955f03dSHans Verkuil } 1008*7955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x24, 0, 0, 1009*7955f03dSHans Verkuil buf, buf_len, 0) < 0) 1010*7955f03dSHans Verkuil goto i2c_done; 1011*7955f03dSHans Verkuil if (msgs[i].flags & I2C_M_RD) { 1012*7955f03dSHans Verkuil memset(buf, 0, msgs[i].len + 1); 1013*7955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf, 1014*7955f03dSHans Verkuil msgs[i].len + 1, 1) < 0) 1015*7955f03dSHans Verkuil goto i2c_done; 1016*7955f03dSHans Verkuil memcpy(msgs[i].buf, buf + 1, msgs[i].len); 1017*7955f03dSHans Verkuil } 1018*7955f03dSHans Verkuil } 1019*7955f03dSHans Verkuil ret = num; 1020*7955f03dSHans Verkuil 1021*7955f03dSHans Verkuil i2c_done: 1022*7955f03dSHans Verkuil mutex_unlock(&usb->i2c_lock); 1023*7955f03dSHans Verkuil return ret; 1024*7955f03dSHans Verkuil } 1025*7955f03dSHans Verkuil 1026*7955f03dSHans Verkuil static u32 go7007_usb_functionality(struct i2c_adapter *adapter) 1027*7955f03dSHans Verkuil { 1028*7955f03dSHans Verkuil /* No errors are reported by the hardware, so we don't bother 1029*7955f03dSHans Verkuil * supporting quick writes to avoid confusing probing */ 1030*7955f03dSHans Verkuil return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK; 1031*7955f03dSHans Verkuil } 1032*7955f03dSHans Verkuil 1033*7955f03dSHans Verkuil static struct i2c_algorithm go7007_usb_algo = { 1034*7955f03dSHans Verkuil .master_xfer = go7007_usb_i2c_master_xfer, 1035*7955f03dSHans Verkuil .functionality = go7007_usb_functionality, 1036*7955f03dSHans Verkuil }; 1037*7955f03dSHans Verkuil 1038*7955f03dSHans Verkuil static struct i2c_adapter go7007_usb_adap_templ = { 1039*7955f03dSHans Verkuil .owner = THIS_MODULE, 1040*7955f03dSHans Verkuil .name = "WIS GO7007SB EZ-USB", 1041*7955f03dSHans Verkuil .algo = &go7007_usb_algo, 1042*7955f03dSHans Verkuil }; 1043*7955f03dSHans Verkuil 1044*7955f03dSHans Verkuil /********************* USB add/remove functions *********************/ 1045*7955f03dSHans Verkuil 1046*7955f03dSHans Verkuil static int go7007_usb_probe(struct usb_interface *intf, 1047*7955f03dSHans Verkuil const struct usb_device_id *id) 1048*7955f03dSHans Verkuil { 1049*7955f03dSHans Verkuil struct go7007 *go; 1050*7955f03dSHans Verkuil struct go7007_usb *usb; 1051*7955f03dSHans Verkuil const struct go7007_usb_board *board; 1052*7955f03dSHans Verkuil struct usb_device *usbdev = interface_to_usbdev(intf); 1053*7955f03dSHans Verkuil unsigned num_i2c_devs; 1054*7955f03dSHans Verkuil char *name; 1055*7955f03dSHans Verkuil int video_pipe, i, v_urb_len; 1056*7955f03dSHans Verkuil 1057*7955f03dSHans Verkuil pr_debug("probing new GO7007 USB board\n"); 1058*7955f03dSHans Verkuil 1059*7955f03dSHans Verkuil switch (id->driver_info) { 1060*7955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_II: 1061*7955f03dSHans Verkuil name = "WIS Matrix II or compatible"; 1062*7955f03dSHans Verkuil board = &board_matrix_ii; 1063*7955f03dSHans Verkuil break; 1064*7955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_RELOAD: 1065*7955f03dSHans Verkuil name = "WIS Matrix Reloaded or compatible"; 1066*7955f03dSHans Verkuil board = &board_matrix_reload; 1067*7955f03dSHans Verkuil break; 1068*7955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_REV: 1069*7955f03dSHans Verkuil name = "WIS Matrix Revolution or compatible"; 1070*7955f03dSHans Verkuil board = &board_matrix_revolution; 1071*7955f03dSHans Verkuil break; 1072*7955f03dSHans Verkuil case GO7007_BOARDID_STAR_TREK: 1073*7955f03dSHans Verkuil name = "WIS Star Trek or compatible"; 1074*7955f03dSHans Verkuil board = &board_star_trek; 1075*7955f03dSHans Verkuil break; 1076*7955f03dSHans Verkuil case GO7007_BOARDID_XMEN: 1077*7955f03dSHans Verkuil name = "WIS XMen or compatible"; 1078*7955f03dSHans Verkuil board = &board_xmen; 1079*7955f03dSHans Verkuil break; 1080*7955f03dSHans Verkuil case GO7007_BOARDID_XMEN_II: 1081*7955f03dSHans Verkuil name = "WIS XMen II or compatible"; 1082*7955f03dSHans Verkuil board = &board_xmen; 1083*7955f03dSHans Verkuil break; 1084*7955f03dSHans Verkuil case GO7007_BOARDID_XMEN_III: 1085*7955f03dSHans Verkuil name = "WIS XMen III or compatible"; 1086*7955f03dSHans Verkuil board = &board_xmen; 1087*7955f03dSHans Verkuil break; 1088*7955f03dSHans Verkuil case GO7007_BOARDID_PX_M402U: 1089*7955f03dSHans Verkuil name = "Plextor PX-M402U"; 1090*7955f03dSHans Verkuil board = &board_matrix_ii; 1091*7955f03dSHans Verkuil break; 1092*7955f03dSHans Verkuil case GO7007_BOARDID_PX_TV402U: 1093*7955f03dSHans Verkuil name = "Plextor PX-TV402U (unknown tuner)"; 1094*7955f03dSHans Verkuil board = &board_px_tv402u; 1095*7955f03dSHans Verkuil break; 1096*7955f03dSHans Verkuil case GO7007_BOARDID_LIFEVIEW_LR192: 1097*7955f03dSHans Verkuil dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n"); 1098*7955f03dSHans Verkuil return -ENODEV; 1099*7955f03dSHans Verkuil name = "Lifeview TV Walker Ultra"; 1100*7955f03dSHans Verkuil board = &board_lifeview_lr192; 1101*7955f03dSHans Verkuil break; 1102*7955f03dSHans Verkuil case GO7007_BOARDID_SENSORAY_2250: 1103*7955f03dSHans Verkuil dev_info(&intf->dev, "Sensoray 2250 found\n"); 1104*7955f03dSHans Verkuil name = "Sensoray 2250/2251"; 1105*7955f03dSHans Verkuil board = &board_sensoray_2250; 1106*7955f03dSHans Verkuil break; 1107*7955f03dSHans Verkuil case GO7007_BOARDID_ADS_USBAV_709: 1108*7955f03dSHans Verkuil name = "ADS Tech DVD Xpress DX2"; 1109*7955f03dSHans Verkuil board = &board_ads_usbav_709; 1110*7955f03dSHans Verkuil break; 1111*7955f03dSHans Verkuil default: 1112*7955f03dSHans Verkuil dev_err(&intf->dev, "unknown board ID %d!\n", 1113*7955f03dSHans Verkuil (unsigned int)id->driver_info); 1114*7955f03dSHans Verkuil return -ENODEV; 1115*7955f03dSHans Verkuil } 1116*7955f03dSHans Verkuil 1117*7955f03dSHans Verkuil go = go7007_alloc(&board->main_info, &intf->dev); 1118*7955f03dSHans Verkuil if (go == NULL) 1119*7955f03dSHans Verkuil return -ENOMEM; 1120*7955f03dSHans Verkuil 1121*7955f03dSHans Verkuil usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL); 1122*7955f03dSHans Verkuil if (usb == NULL) { 1123*7955f03dSHans Verkuil kfree(go); 1124*7955f03dSHans Verkuil return -ENOMEM; 1125*7955f03dSHans Verkuil } 1126*7955f03dSHans Verkuil 1127*7955f03dSHans Verkuil usb->board = board; 1128*7955f03dSHans Verkuil usb->usbdev = usbdev; 1129*7955f03dSHans Verkuil usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info)); 1130*7955f03dSHans Verkuil go->board_id = id->driver_info; 1131*7955f03dSHans Verkuil strncpy(go->name, name, sizeof(go->name)); 1132*7955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB) 1133*7955f03dSHans Verkuil go->hpi_ops = &go7007_usb_ezusb_hpi_ops; 1134*7955f03dSHans Verkuil else 1135*7955f03dSHans Verkuil go->hpi_ops = &go7007_usb_onboard_hpi_ops; 1136*7955f03dSHans Verkuil go->hpi_context = usb; 1137*7955f03dSHans Verkuil 1138*7955f03dSHans Verkuil /* Allocate the URB and buffer for receiving incoming interrupts */ 1139*7955f03dSHans Verkuil usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL); 1140*7955f03dSHans Verkuil if (usb->intr_urb == NULL) 1141*7955f03dSHans Verkuil goto allocfail; 1142*7955f03dSHans Verkuil usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL); 1143*7955f03dSHans Verkuil if (usb->intr_urb->transfer_buffer == NULL) 1144*7955f03dSHans Verkuil goto allocfail; 1145*7955f03dSHans Verkuil 1146*7955f03dSHans Verkuil if (go->board_id == GO7007_BOARDID_SENSORAY_2250) 1147*7955f03dSHans Verkuil usb_fill_bulk_urb(usb->intr_urb, usb->usbdev, 1148*7955f03dSHans Verkuil usb_rcvbulkpipe(usb->usbdev, 4), 1149*7955f03dSHans Verkuil usb->intr_urb->transfer_buffer, 2*sizeof(u16), 1150*7955f03dSHans Verkuil go7007_usb_readinterrupt_complete, go); 1151*7955f03dSHans Verkuil else 1152*7955f03dSHans Verkuil usb_fill_int_urb(usb->intr_urb, usb->usbdev, 1153*7955f03dSHans Verkuil usb_rcvintpipe(usb->usbdev, 4), 1154*7955f03dSHans Verkuil usb->intr_urb->transfer_buffer, 2*sizeof(u16), 1155*7955f03dSHans Verkuil go7007_usb_readinterrupt_complete, go, 8); 1156*7955f03dSHans Verkuil usb_set_intfdata(intf, &go->v4l2_dev); 1157*7955f03dSHans Verkuil 1158*7955f03dSHans Verkuil /* Boot the GO7007 */ 1159*7955f03dSHans Verkuil if (go7007_boot_encoder(go, go->board_info->flags & 1160*7955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C) < 0) 1161*7955f03dSHans Verkuil goto allocfail; 1162*7955f03dSHans Verkuil 1163*7955f03dSHans Verkuil /* Register the EZ-USB I2C adapter, if we're using it */ 1164*7955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB_I2C) { 1165*7955f03dSHans Verkuil memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, 1166*7955f03dSHans Verkuil sizeof(go7007_usb_adap_templ)); 1167*7955f03dSHans Verkuil mutex_init(&usb->i2c_lock); 1168*7955f03dSHans Verkuil go->i2c_adapter.dev.parent = go->dev; 1169*7955f03dSHans Verkuil i2c_set_adapdata(&go->i2c_adapter, go); 1170*7955f03dSHans Verkuil if (i2c_add_adapter(&go->i2c_adapter) < 0) { 1171*7955f03dSHans Verkuil dev_err(go->dev, "error: i2c_add_adapter failed\n"); 1172*7955f03dSHans Verkuil goto allocfail; 1173*7955f03dSHans Verkuil } 1174*7955f03dSHans Verkuil go->i2c_adapter_online = 1; 1175*7955f03dSHans Verkuil } 1176*7955f03dSHans Verkuil 1177*7955f03dSHans Verkuil /* Pelco and Adlink reused the XMen and XMen-III vendor and product 1178*7955f03dSHans Verkuil * IDs for their own incompatible designs. We can detect XMen boards 1179*7955f03dSHans Verkuil * by probing the sensor, but there is no way to probe the sensors on 1180*7955f03dSHans Verkuil * the Pelco and Adlink designs so we default to the Adlink. If it 1181*7955f03dSHans Verkuil * is actually a Pelco, the user must set the assume_endura module 1182*7955f03dSHans Verkuil * parameter. */ 1183*7955f03dSHans Verkuil if ((go->board_id == GO7007_BOARDID_XMEN || 1184*7955f03dSHans Verkuil go->board_id == GO7007_BOARDID_XMEN_III) && 1185*7955f03dSHans Verkuil go->i2c_adapter_online) { 1186*7955f03dSHans Verkuil union i2c_smbus_data data; 1187*7955f03dSHans Verkuil 1188*7955f03dSHans Verkuil /* Check to see if register 0x0A is 0x76 */ 1189*7955f03dSHans Verkuil i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB, 1190*7955f03dSHans Verkuil I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data); 1191*7955f03dSHans Verkuil if (data.byte != 0x76) { 1192*7955f03dSHans Verkuil if (assume_endura) { 1193*7955f03dSHans Verkuil go->board_id = GO7007_BOARDID_ENDURA; 1194*7955f03dSHans Verkuil usb->board = board = &board_endura; 1195*7955f03dSHans Verkuil go->board_info = &board->main_info; 1196*7955f03dSHans Verkuil strncpy(go->name, "Pelco Endura", 1197*7955f03dSHans Verkuil sizeof(go->name)); 1198*7955f03dSHans Verkuil } else { 1199*7955f03dSHans Verkuil u16 channel; 1200*7955f03dSHans Verkuil 1201*7955f03dSHans Verkuil /* read channel number from GPIO[1:0] */ 1202*7955f03dSHans Verkuil go7007_read_addr(go, 0x3c81, &channel); 1203*7955f03dSHans Verkuil channel &= 0x3; 1204*7955f03dSHans Verkuil go->board_id = GO7007_BOARDID_ADLINK_MPG24; 1205*7955f03dSHans Verkuil usb->board = board = &board_adlink_mpg24; 1206*7955f03dSHans Verkuil go->board_info = &board->main_info; 1207*7955f03dSHans Verkuil go->channel_number = channel; 1208*7955f03dSHans Verkuil snprintf(go->name, sizeof(go->name), 1209*7955f03dSHans Verkuil "Adlink PCI-MPG24, channel #%d", 1210*7955f03dSHans Verkuil channel); 1211*7955f03dSHans Verkuil } 1212*7955f03dSHans Verkuil go7007_update_board(go); 1213*7955f03dSHans Verkuil } 1214*7955f03dSHans Verkuil } 1215*7955f03dSHans Verkuil 1216*7955f03dSHans Verkuil num_i2c_devs = go->board_info->num_i2c_devs; 1217*7955f03dSHans Verkuil 1218*7955f03dSHans Verkuil /* Probe the tuner model on the TV402U */ 1219*7955f03dSHans Verkuil if (go->board_id == GO7007_BOARDID_PX_TV402U) { 1220*7955f03dSHans Verkuil /* Board strapping indicates tuner model */ 1221*7955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, 1222*7955f03dSHans Verkuil 1) < 0) { 1223*7955f03dSHans Verkuil dev_err(go->dev, "GPIO read failed!\n"); 1224*7955f03dSHans Verkuil goto allocfail; 1225*7955f03dSHans Verkuil } 1226*7955f03dSHans Verkuil switch (go->usb_buf[0] >> 6) { 1227*7955f03dSHans Verkuil case 1: 1228*7955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PG472Z; 1229*7955f03dSHans Verkuil go->std = V4L2_STD_PAL; 1230*7955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-EU", 1231*7955f03dSHans Verkuil sizeof(go->name)); 1232*7955f03dSHans Verkuil break; 1233*7955f03dSHans Verkuil case 2: 1234*7955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PK467Z; 1235*7955f03dSHans Verkuil go->std = V4L2_STD_NTSC_M_JP; 1236*7955f03dSHans Verkuil num_i2c_devs -= 2; 1237*7955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-JP", 1238*7955f03dSHans Verkuil sizeof(go->name)); 1239*7955f03dSHans Verkuil break; 1240*7955f03dSHans Verkuil case 3: 1241*7955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PB463Z; 1242*7955f03dSHans Verkuil num_i2c_devs -= 2; 1243*7955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-NA", 1244*7955f03dSHans Verkuil sizeof(go->name)); 1245*7955f03dSHans Verkuil break; 1246*7955f03dSHans Verkuil default: 1247*7955f03dSHans Verkuil pr_debug("unable to detect tuner type!\n"); 1248*7955f03dSHans Verkuil break; 1249*7955f03dSHans Verkuil } 1250*7955f03dSHans Verkuil /* Configure tuner mode selection inputs connected 1251*7955f03dSHans Verkuil * to the EZ-USB GPIO output pins */ 1252*7955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, 1253*7955f03dSHans Verkuil NULL, 0, 0) < 0) { 1254*7955f03dSHans Verkuil dev_err(go->dev, "GPIO write failed!\n"); 1255*7955f03dSHans Verkuil goto allocfail; 1256*7955f03dSHans Verkuil } 1257*7955f03dSHans Verkuil } 1258*7955f03dSHans Verkuil 1259*7955f03dSHans Verkuil /* Print a nasty message if the user attempts to use a USB2.0 device in 1260*7955f03dSHans Verkuil * a USB1.1 port. There will be silent corruption of the stream. */ 1261*7955f03dSHans Verkuil if ((board->flags & GO7007_USB_EZUSB) && 1262*7955f03dSHans Verkuil usbdev->speed != USB_SPEED_HIGH) 1263*7955f03dSHans Verkuil dev_err(go->dev, "*** WARNING *** This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n"); 1264*7955f03dSHans Verkuil 1265*7955f03dSHans Verkuil /* Allocate the URBs and buffers for receiving the video stream */ 1266*7955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB) { 1267*7955f03dSHans Verkuil v_urb_len = 1024; 1268*7955f03dSHans Verkuil video_pipe = usb_rcvbulkpipe(usb->usbdev, 6); 1269*7955f03dSHans Verkuil } else { 1270*7955f03dSHans Verkuil v_urb_len = 512; 1271*7955f03dSHans Verkuil video_pipe = usb_rcvbulkpipe(usb->usbdev, 1); 1272*7955f03dSHans Verkuil } 1273*7955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 1274*7955f03dSHans Verkuil usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); 1275*7955f03dSHans Verkuil if (usb->video_urbs[i] == NULL) 1276*7955f03dSHans Verkuil goto allocfail; 1277*7955f03dSHans Verkuil usb->video_urbs[i]->transfer_buffer = 1278*7955f03dSHans Verkuil kmalloc(v_urb_len, GFP_KERNEL); 1279*7955f03dSHans Verkuil if (usb->video_urbs[i]->transfer_buffer == NULL) 1280*7955f03dSHans Verkuil goto allocfail; 1281*7955f03dSHans Verkuil usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe, 1282*7955f03dSHans Verkuil usb->video_urbs[i]->transfer_buffer, v_urb_len, 1283*7955f03dSHans Verkuil go7007_usb_read_video_pipe_complete, go); 1284*7955f03dSHans Verkuil } 1285*7955f03dSHans Verkuil 1286*7955f03dSHans Verkuil /* Allocate the URBs and buffers for receiving the audio stream */ 1287*7955f03dSHans Verkuil if ((board->flags & GO7007_USB_EZUSB) && 1288*7955f03dSHans Verkuil (board->flags & GO7007_BOARD_HAS_AUDIO)) { 1289*7955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 1290*7955f03dSHans Verkuil usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); 1291*7955f03dSHans Verkuil if (usb->audio_urbs[i] == NULL) 1292*7955f03dSHans Verkuil goto allocfail; 1293*7955f03dSHans Verkuil usb->audio_urbs[i]->transfer_buffer = kmalloc(4096, 1294*7955f03dSHans Verkuil GFP_KERNEL); 1295*7955f03dSHans Verkuil if (usb->audio_urbs[i]->transfer_buffer == NULL) 1296*7955f03dSHans Verkuil goto allocfail; 1297*7955f03dSHans Verkuil usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev, 1298*7955f03dSHans Verkuil usb_rcvbulkpipe(usb->usbdev, 8), 1299*7955f03dSHans Verkuil usb->audio_urbs[i]->transfer_buffer, 4096, 1300*7955f03dSHans Verkuil go7007_usb_read_audio_pipe_complete, go); 1301*7955f03dSHans Verkuil } 1302*7955f03dSHans Verkuil } 1303*7955f03dSHans Verkuil 1304*7955f03dSHans Verkuil /* Do any final GO7007 initialization, then register the 1305*7955f03dSHans Verkuil * V4L2 and ALSA interfaces */ 1306*7955f03dSHans Verkuil if (go7007_register_encoder(go, num_i2c_devs) < 0) 1307*7955f03dSHans Verkuil goto allocfail; 1308*7955f03dSHans Verkuil 1309*7955f03dSHans Verkuil go->status = STATUS_ONLINE; 1310*7955f03dSHans Verkuil return 0; 1311*7955f03dSHans Verkuil 1312*7955f03dSHans Verkuil allocfail: 1313*7955f03dSHans Verkuil go7007_usb_release(go); 1314*7955f03dSHans Verkuil kfree(go); 1315*7955f03dSHans Verkuil return -ENOMEM; 1316*7955f03dSHans Verkuil } 1317*7955f03dSHans Verkuil 1318*7955f03dSHans Verkuil static void go7007_usb_disconnect(struct usb_interface *intf) 1319*7955f03dSHans Verkuil { 1320*7955f03dSHans Verkuil struct go7007 *go = to_go7007(usb_get_intfdata(intf)); 1321*7955f03dSHans Verkuil 1322*7955f03dSHans Verkuil mutex_lock(&go->queue_lock); 1323*7955f03dSHans Verkuil mutex_lock(&go->serialize_lock); 1324*7955f03dSHans Verkuil 1325*7955f03dSHans Verkuil if (go->audio_enabled) 1326*7955f03dSHans Verkuil go7007_snd_remove(go); 1327*7955f03dSHans Verkuil 1328*7955f03dSHans Verkuil go->status = STATUS_SHUTDOWN; 1329*7955f03dSHans Verkuil v4l2_device_disconnect(&go->v4l2_dev); 1330*7955f03dSHans Verkuil video_unregister_device(&go->vdev); 1331*7955f03dSHans Verkuil mutex_unlock(&go->serialize_lock); 1332*7955f03dSHans Verkuil mutex_unlock(&go->queue_lock); 1333*7955f03dSHans Verkuil 1334*7955f03dSHans Verkuil v4l2_device_put(&go->v4l2_dev); 1335*7955f03dSHans Verkuil } 1336*7955f03dSHans Verkuil 1337*7955f03dSHans Verkuil static struct usb_driver go7007_usb_driver = { 1338*7955f03dSHans Verkuil .name = "go7007", 1339*7955f03dSHans Verkuil .probe = go7007_usb_probe, 1340*7955f03dSHans Verkuil .disconnect = go7007_usb_disconnect, 1341*7955f03dSHans Verkuil .id_table = go7007_usb_id_table, 1342*7955f03dSHans Verkuil }; 1343*7955f03dSHans Verkuil 1344*7955f03dSHans Verkuil module_usb_driver(go7007_usb_driver); 1345*7955f03dSHans Verkuil MODULE_LICENSE("GPL v2"); 1346