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