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