1 /* 2 * Driver for the Auvitek USB bridge 3 * 4 * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #include "au0828.h" 23 #include "au0828-cards.h" 24 #include "au8522.h" 25 #include "media/tuner.h" 26 #include "media/v4l2-common.h" 27 28 static void hvr950q_cs5340_audio(void *priv, int enable) 29 { 30 /* Because the HVR-950q shares an i2s bus between the cs5340 and the 31 au8522, we need to hold cs5340 in reset when using the au8522 */ 32 struct au0828_dev *dev = priv; 33 if (enable == 1) 34 au0828_set(dev, REG_000, 0x10); 35 else 36 au0828_clear(dev, REG_000, 0x10); 37 } 38 39 /* 40 * WARNING: There's a quirks table at sound/usb/quirks-table.h 41 * that should also be updated every time a new device with V4L2 support 42 * is added here. 43 */ 44 struct au0828_board au0828_boards[] = { 45 [AU0828_BOARD_UNKNOWN] = { 46 .name = "Unknown board", 47 .tuner_type = -1U, 48 .tuner_addr = ADDR_UNSET, 49 }, 50 [AU0828_BOARD_HAUPPAUGE_HVR850] = { 51 .name = "Hauppauge HVR850", 52 .tuner_type = TUNER_XC5000, 53 .tuner_addr = 0x61, 54 .has_ir_i2c = 1, 55 .has_analog = 1, 56 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, 57 .input = { 58 { 59 .type = AU0828_VMUX_TELEVISION, 60 .vmux = AU8522_COMPOSITE_CH4_SIF, 61 .amux = AU8522_AUDIO_SIF, 62 }, 63 { 64 .type = AU0828_VMUX_COMPOSITE, 65 .vmux = AU8522_COMPOSITE_CH1, 66 .amux = AU8522_AUDIO_NONE, 67 .audio_setup = hvr950q_cs5340_audio, 68 }, 69 { 70 .type = AU0828_VMUX_SVIDEO, 71 .vmux = AU8522_SVIDEO_CH13, 72 .amux = AU8522_AUDIO_NONE, 73 .audio_setup = hvr950q_cs5340_audio, 74 }, 75 }, 76 }, 77 [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { 78 .name = "Hauppauge HVR950Q", 79 .tuner_type = TUNER_XC5000, 80 .tuner_addr = 0x61, 81 .has_ir_i2c = 1, 82 .has_analog = 1, 83 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, 84 .input = { 85 { 86 .type = AU0828_VMUX_TELEVISION, 87 .vmux = AU8522_COMPOSITE_CH4_SIF, 88 .amux = AU8522_AUDIO_SIF, 89 }, 90 { 91 .type = AU0828_VMUX_COMPOSITE, 92 .vmux = AU8522_COMPOSITE_CH1, 93 .amux = AU8522_AUDIO_NONE, 94 .audio_setup = hvr950q_cs5340_audio, 95 }, 96 { 97 .type = AU0828_VMUX_SVIDEO, 98 .vmux = AU8522_SVIDEO_CH13, 99 .amux = AU8522_AUDIO_NONE, 100 .audio_setup = hvr950q_cs5340_audio, 101 }, 102 }, 103 }, 104 [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { 105 .name = "Hauppauge HVR950Q rev xxF8", 106 .tuner_type = TUNER_XC5000, 107 .tuner_addr = 0x61, 108 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, 109 }, 110 [AU0828_BOARD_DVICO_FUSIONHDTV7] = { 111 .name = "DViCO FusionHDTV USB", 112 .tuner_type = TUNER_XC5000, 113 .tuner_addr = 0x61, 114 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, 115 }, 116 [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { 117 .name = "Hauppauge Woodbury", 118 .tuner_type = TUNER_NXP_TDA18271, 119 .tuner_addr = 0x60, 120 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, 121 }, 122 }; 123 124 /* Tuner callback function for au0828 boards. Currently only needed 125 * for HVR1500Q, which has an xc5000 tuner. 126 */ 127 int au0828_tuner_callback(void *priv, int component, int command, int arg) 128 { 129 struct au0828_dev *dev = priv; 130 131 dprintk(1, "%s()\n", __func__); 132 133 switch (dev->boardnr) { 134 case AU0828_BOARD_HAUPPAUGE_HVR850: 135 case AU0828_BOARD_HAUPPAUGE_HVR950Q: 136 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: 137 case AU0828_BOARD_DVICO_FUSIONHDTV7: 138 if (command == 0) { 139 /* Tuner Reset Command from xc5000 */ 140 /* Drive the tuner into reset and out */ 141 au0828_clear(dev, REG_001, 2); 142 mdelay(10); 143 au0828_set(dev, REG_001, 2); 144 mdelay(10); 145 return 0; 146 } else { 147 pr_err("%s(): Unknown command.\n", __func__); 148 return -EINVAL; 149 } 150 break; 151 } 152 153 return 0; /* Should never be here */ 154 } 155 156 static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) 157 { 158 struct tveeprom tv; 159 160 tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); 161 dev->board.tuner_type = tv.tuner_type; 162 163 /* Make sure we support the board model */ 164 switch (tv.model) { 165 case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */ 166 case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ 167 case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ 168 case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ 169 case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ 170 case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ 171 case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ 172 case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ 173 case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ 174 case 72261: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ 175 case 72271: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ 176 case 72281: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ 177 case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */ 178 case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ 179 break; 180 default: 181 pr_warn("%s: warning: unknown hauppauge model #%d\n", 182 __func__, tv.model); 183 break; 184 } 185 186 pr_info("%s: hauppauge eeprom: model=%d\n", 187 __func__, tv.model); 188 } 189 190 void au0828_card_analog_fe_setup(struct au0828_dev *dev); 191 192 void au0828_card_setup(struct au0828_dev *dev) 193 { 194 static u8 eeprom[256]; 195 196 dprintk(1, "%s()\n", __func__); 197 198 if (dev->i2c_rc == 0) { 199 dev->i2c_client.addr = 0xa0 >> 1; 200 tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); 201 } 202 203 switch (dev->boardnr) { 204 case AU0828_BOARD_HAUPPAUGE_HVR850: 205 case AU0828_BOARD_HAUPPAUGE_HVR950Q: 206 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: 207 case AU0828_BOARD_HAUPPAUGE_WOODBURY: 208 if (dev->i2c_rc == 0) 209 hauppauge_eeprom(dev, eeprom+0xa0); 210 break; 211 } 212 213 au0828_card_analog_fe_setup(dev); 214 } 215 216 void au0828_card_analog_fe_setup(struct au0828_dev *dev) 217 { 218 #ifdef CONFIG_VIDEO_AU0828_V4L2 219 struct tuner_setup tun_setup; 220 struct v4l2_subdev *sd; 221 unsigned int mode_mask = T_ANALOG_TV; 222 223 if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { 224 /* Load the analog demodulator driver (note this would need to 225 be abstracted out if we ever need to support a different 226 demod) */ 227 sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, 228 "au8522", 0x8e >> 1, NULL); 229 if (sd == NULL) 230 pr_err("analog subdev registration failed\n"); 231 #ifdef CONFIG_MEDIA_CONTROLLER 232 if (sd) 233 dev->decoder = &sd->entity; 234 #endif 235 } 236 237 /* Setup tuners */ 238 if (dev->board.tuner_type != TUNER_ABSENT && dev->board.has_analog) { 239 /* Load the tuner module, which does the attach */ 240 sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, 241 "tuner", dev->board.tuner_addr, NULL); 242 if (sd == NULL) 243 pr_err("tuner subdev registration fail\n"); 244 245 tun_setup.mode_mask = mode_mask; 246 tun_setup.type = dev->board.tuner_type; 247 tun_setup.addr = dev->board.tuner_addr; 248 tun_setup.tuner_callback = au0828_tuner_callback; 249 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, 250 &tun_setup); 251 } 252 #endif 253 } 254 255 /* 256 * The bridge has between 8 and 12 gpios. 257 * Regs 1 and 0 deal with output enables. 258 * Regs 3 and 2 deal with direction. 259 */ 260 void au0828_gpio_setup(struct au0828_dev *dev) 261 { 262 dprintk(1, "%s()\n", __func__); 263 264 switch (dev->boardnr) { 265 case AU0828_BOARD_HAUPPAUGE_HVR850: 266 case AU0828_BOARD_HAUPPAUGE_HVR950Q: 267 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: 268 case AU0828_BOARD_HAUPPAUGE_WOODBURY: 269 /* GPIO's 270 * 4 - CS5340 271 * 5 - AU8522 Demodulator 272 * 6 - eeprom W/P 273 * 7 - power supply 274 * 9 - XC5000 Tuner 275 */ 276 277 /* Set relevant GPIOs as outputs (leave the EEPROM W/P 278 as an input since we will never touch it and it has 279 a pullup) */ 280 au0828_write(dev, REG_003, 0x02); 281 au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); 282 283 /* Into reset */ 284 au0828_write(dev, REG_001, 0x0); 285 au0828_write(dev, REG_000, 0x0); 286 msleep(50); 287 288 /* Bring power supply out of reset */ 289 au0828_write(dev, REG_000, 0x80); 290 msleep(50); 291 292 /* Bring xc5000 and au8522 out of reset (leave the 293 cs5340 in reset until needed) */ 294 au0828_write(dev, REG_001, 0x02); /* xc5000 */ 295 au0828_write(dev, REG_000, 0x80 | 0x20); /* PS + au8522 */ 296 297 msleep(250); 298 break; 299 case AU0828_BOARD_DVICO_FUSIONHDTV7: 300 /* GPIO's 301 * 6 - ? 302 * 8 - AU8522 Demodulator 303 * 9 - XC5000 Tuner 304 */ 305 306 /* Into reset */ 307 au0828_write(dev, REG_003, 0x02); 308 au0828_write(dev, REG_002, 0xa0); 309 au0828_write(dev, REG_001, 0x0); 310 au0828_write(dev, REG_000, 0x0); 311 msleep(100); 312 313 /* Out of reset */ 314 au0828_write(dev, REG_003, 0x02); 315 au0828_write(dev, REG_002, 0xa0); 316 au0828_write(dev, REG_001, 0x02); 317 au0828_write(dev, REG_000, 0xa0); 318 msleep(250); 319 break; 320 } 321 } 322 323 /* table of devices that work with this driver */ 324 struct usb_device_id au0828_usb_id_table[] = { 325 { USB_DEVICE(0x2040, 0x7200), 326 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 327 { USB_DEVICE(0x2040, 0x7240), 328 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 }, 329 { USB_DEVICE(0x0fe9, 0xd620), 330 .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 }, 331 { USB_DEVICE(0x2040, 0x7210), 332 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 333 { USB_DEVICE(0x2040, 0x7217), 334 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 335 { USB_DEVICE(0x2040, 0x721b), 336 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 337 { USB_DEVICE(0x2040, 0x721e), 338 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 339 { USB_DEVICE(0x2040, 0x721f), 340 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 341 { USB_DEVICE(0x2040, 0x7280), 342 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 343 { USB_DEVICE(0x0fd9, 0x0008), 344 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 345 { USB_DEVICE(0x2040, 0x7201), 346 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, 347 { USB_DEVICE(0x2040, 0x7211), 348 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, 349 { USB_DEVICE(0x2040, 0x7281), 350 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, 351 { USB_DEVICE(0x05e1, 0x0480), 352 .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, 353 { USB_DEVICE(0x2040, 0x8200), 354 .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, 355 { USB_DEVICE(0x2040, 0x7260), 356 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 357 { USB_DEVICE(0x2040, 0x7213), 358 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 359 { USB_DEVICE(0x2040, 0x7270), 360 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, 361 { }, 362 }; 363 364 MODULE_DEVICE_TABLE(usb, au0828_usb_id_table); 365