1 /* 2 * Driver for the NXP SAA7164 PCIe bridge 3 * 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com> 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 <linux/init.h> 23 #include <linux/module.h> 24 #include <linux/pci.h> 25 #include <linux/delay.h> 26 27 #include "saa7164.h" 28 29 /* The Bridge API needs to understand register widths (in bytes) for the 30 * attached I2C devices, so we can simplify the virtual i2c mechansms 31 * and keep the -i2c.c implementation clean. 32 */ 33 #define REGLEN_8bit 1 34 #define REGLEN_16bit 2 35 36 struct saa7164_board saa7164_boards[] = { 37 [SAA7164_BOARD_UNKNOWN] = { 38 /* Bridge will not load any firmware, without knowing 39 * the rev this would be fatal. */ 40 .name = "Unknown", 41 }, 42 [SAA7164_BOARD_UNKNOWN_REV2] = { 43 /* Bridge will load the v2 f/w and dump descriptors */ 44 /* Required during new board bringup */ 45 .name = "Generic Rev2", 46 .chiprev = SAA7164_CHIP_REV2, 47 }, 48 [SAA7164_BOARD_UNKNOWN_REV3] = { 49 /* Bridge will load the v2 f/w and dump descriptors */ 50 /* Required during new board bringup */ 51 .name = "Generic Rev3", 52 .chiprev = SAA7164_CHIP_REV3, 53 }, 54 [SAA7164_BOARD_HAUPPAUGE_HVR2200] = { 55 .name = "Hauppauge WinTV-HVR2200", 56 .porta = SAA7164_MPEG_DVB, 57 .portb = SAA7164_MPEG_DVB, 58 .portc = SAA7164_MPEG_ENCODER, 59 .portd = SAA7164_MPEG_ENCODER, 60 .porte = SAA7164_MPEG_VBI, 61 .portf = SAA7164_MPEG_VBI, 62 .chiprev = SAA7164_CHIP_REV3, 63 .unit = {{ 64 .id = 0x1d, 65 .type = SAA7164_UNIT_EEPROM, 66 .name = "4K EEPROM", 67 .i2c_bus_nr = SAA7164_I2C_BUS_0, 68 .i2c_bus_addr = 0xa0 >> 1, 69 .i2c_reg_len = REGLEN_8bit, 70 }, { 71 .id = 0x04, 72 .type = SAA7164_UNIT_TUNER, 73 .name = "TDA18271-1", 74 .i2c_bus_nr = SAA7164_I2C_BUS_1, 75 .i2c_bus_addr = 0xc0 >> 1, 76 .i2c_reg_len = REGLEN_8bit, 77 }, { 78 .id = 0x1b, 79 .type = SAA7164_UNIT_TUNER, 80 .name = "TDA18271-2", 81 .i2c_bus_nr = SAA7164_I2C_BUS_2, 82 .i2c_bus_addr = 0xc0 >> 1, 83 .i2c_reg_len = REGLEN_8bit, 84 }, { 85 .id = 0x1e, 86 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 87 .name = "TDA10048-1", 88 .i2c_bus_nr = SAA7164_I2C_BUS_1, 89 .i2c_bus_addr = 0x10 >> 1, 90 .i2c_reg_len = REGLEN_8bit, 91 }, { 92 .id = 0x1f, 93 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 94 .name = "TDA10048-2", 95 .i2c_bus_nr = SAA7164_I2C_BUS_2, 96 .i2c_bus_addr = 0x12 >> 1, 97 .i2c_reg_len = REGLEN_8bit, 98 } }, 99 }, 100 [SAA7164_BOARD_HAUPPAUGE_HVR2200_2] = { 101 .name = "Hauppauge WinTV-HVR2200", 102 .porta = SAA7164_MPEG_DVB, 103 .portb = SAA7164_MPEG_DVB, 104 .portc = SAA7164_MPEG_ENCODER, 105 .portd = SAA7164_MPEG_ENCODER, 106 .porte = SAA7164_MPEG_VBI, 107 .portf = SAA7164_MPEG_VBI, 108 .chiprev = SAA7164_CHIP_REV2, 109 .unit = {{ 110 .id = 0x06, 111 .type = SAA7164_UNIT_EEPROM, 112 .name = "4K EEPROM", 113 .i2c_bus_nr = SAA7164_I2C_BUS_0, 114 .i2c_bus_addr = 0xa0 >> 1, 115 .i2c_reg_len = REGLEN_8bit, 116 }, { 117 .id = 0x04, 118 .type = SAA7164_UNIT_TUNER, 119 .name = "TDA18271-1", 120 .i2c_bus_nr = SAA7164_I2C_BUS_1, 121 .i2c_bus_addr = 0xc0 >> 1, 122 .i2c_reg_len = REGLEN_8bit, 123 }, { 124 .id = 0x05, 125 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 126 .name = "TDA10048-1", 127 .i2c_bus_nr = SAA7164_I2C_BUS_1, 128 .i2c_bus_addr = 0x10 >> 1, 129 .i2c_reg_len = REGLEN_8bit, 130 }, { 131 .id = 0x1e, 132 .type = SAA7164_UNIT_TUNER, 133 .name = "TDA18271-2", 134 .i2c_bus_nr = SAA7164_I2C_BUS_2, 135 .i2c_bus_addr = 0xc0 >> 1, 136 .i2c_reg_len = REGLEN_8bit, 137 }, { 138 .id = 0x1f, 139 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 140 .name = "TDA10048-2", 141 .i2c_bus_nr = SAA7164_I2C_BUS_2, 142 .i2c_bus_addr = 0x12 >> 1, 143 .i2c_reg_len = REGLEN_8bit, 144 } }, 145 }, 146 [SAA7164_BOARD_HAUPPAUGE_HVR2200_3] = { 147 .name = "Hauppauge WinTV-HVR2200", 148 .porta = SAA7164_MPEG_DVB, 149 .portb = SAA7164_MPEG_DVB, 150 .portc = SAA7164_MPEG_ENCODER, 151 .portd = SAA7164_MPEG_ENCODER, 152 .porte = SAA7164_MPEG_VBI, 153 .portf = SAA7164_MPEG_VBI, 154 .chiprev = SAA7164_CHIP_REV2, 155 .unit = {{ 156 .id = 0x1d, 157 .type = SAA7164_UNIT_EEPROM, 158 .name = "4K EEPROM", 159 .i2c_bus_nr = SAA7164_I2C_BUS_0, 160 .i2c_bus_addr = 0xa0 >> 1, 161 .i2c_reg_len = REGLEN_8bit, 162 }, { 163 .id = 0x04, 164 .type = SAA7164_UNIT_TUNER, 165 .name = "TDA18271-1", 166 .i2c_bus_nr = SAA7164_I2C_BUS_1, 167 .i2c_bus_addr = 0xc0 >> 1, 168 .i2c_reg_len = REGLEN_8bit, 169 }, { 170 .id = 0x05, 171 .type = SAA7164_UNIT_ANALOG_DEMODULATOR, 172 .name = "TDA8290-1", 173 .i2c_bus_nr = SAA7164_I2C_BUS_1, 174 .i2c_bus_addr = 0x84 >> 1, 175 .i2c_reg_len = REGLEN_8bit, 176 }, { 177 .id = 0x1b, 178 .type = SAA7164_UNIT_TUNER, 179 .name = "TDA18271-2", 180 .i2c_bus_nr = SAA7164_I2C_BUS_2, 181 .i2c_bus_addr = 0xc0 >> 1, 182 .i2c_reg_len = REGLEN_8bit, 183 }, { 184 .id = 0x1c, 185 .type = SAA7164_UNIT_ANALOG_DEMODULATOR, 186 .name = "TDA8290-2", 187 .i2c_bus_nr = SAA7164_I2C_BUS_2, 188 .i2c_bus_addr = 0x84 >> 1, 189 .i2c_reg_len = REGLEN_8bit, 190 }, { 191 .id = 0x1e, 192 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 193 .name = "TDA10048-1", 194 .i2c_bus_nr = SAA7164_I2C_BUS_1, 195 .i2c_bus_addr = 0x10 >> 1, 196 .i2c_reg_len = REGLEN_8bit, 197 }, { 198 .id = 0x1f, 199 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 200 .name = "TDA10048-2", 201 .i2c_bus_nr = SAA7164_I2C_BUS_2, 202 .i2c_bus_addr = 0x12 >> 1, 203 .i2c_reg_len = REGLEN_8bit, 204 } }, 205 }, 206 [SAA7164_BOARD_HAUPPAUGE_HVR2200_4] = { 207 .name = "Hauppauge WinTV-HVR2200", 208 .porta = SAA7164_MPEG_DVB, 209 .portb = SAA7164_MPEG_DVB, 210 .portc = SAA7164_MPEG_ENCODER, 211 .portd = SAA7164_MPEG_ENCODER, 212 .porte = SAA7164_MPEG_VBI, 213 .portf = SAA7164_MPEG_VBI, 214 .chiprev = SAA7164_CHIP_REV3, 215 .unit = {{ 216 .id = 0x1d, 217 .type = SAA7164_UNIT_EEPROM, 218 .name = "4K EEPROM", 219 .i2c_bus_nr = SAA7164_I2C_BUS_0, 220 .i2c_bus_addr = 0xa0 >> 1, 221 .i2c_reg_len = REGLEN_8bit, 222 }, { 223 .id = 0x04, 224 .type = SAA7164_UNIT_TUNER, 225 .name = "TDA18271-1", 226 .i2c_bus_nr = SAA7164_I2C_BUS_1, 227 .i2c_bus_addr = 0xc0 >> 1, 228 .i2c_reg_len = REGLEN_8bit, 229 }, { 230 .id = 0x05, 231 .type = SAA7164_UNIT_ANALOG_DEMODULATOR, 232 .name = "TDA8290-1", 233 .i2c_bus_nr = SAA7164_I2C_BUS_1, 234 .i2c_bus_addr = 0x84 >> 1, 235 .i2c_reg_len = REGLEN_8bit, 236 }, { 237 .id = 0x1b, 238 .type = SAA7164_UNIT_TUNER, 239 .name = "TDA18271-2", 240 .i2c_bus_nr = SAA7164_I2C_BUS_2, 241 .i2c_bus_addr = 0xc0 >> 1, 242 .i2c_reg_len = REGLEN_8bit, 243 }, { 244 .id = 0x1c, 245 .type = SAA7164_UNIT_ANALOG_DEMODULATOR, 246 .name = "TDA8290-2", 247 .i2c_bus_nr = SAA7164_I2C_BUS_2, 248 .i2c_bus_addr = 0x84 >> 1, 249 .i2c_reg_len = REGLEN_8bit, 250 }, { 251 .id = 0x1e, 252 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 253 .name = "TDA10048-1", 254 .i2c_bus_nr = SAA7164_I2C_BUS_1, 255 .i2c_bus_addr = 0x10 >> 1, 256 .i2c_reg_len = REGLEN_8bit, 257 }, { 258 .id = 0x1f, 259 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 260 .name = "TDA10048-2", 261 .i2c_bus_nr = SAA7164_I2C_BUS_2, 262 .i2c_bus_addr = 0x12 >> 1, 263 .i2c_reg_len = REGLEN_8bit, 264 } }, 265 }, 266 [SAA7164_BOARD_HAUPPAUGE_HVR2250] = { 267 .name = "Hauppauge WinTV-HVR2250", 268 .porta = SAA7164_MPEG_DVB, 269 .portb = SAA7164_MPEG_DVB, 270 .portc = SAA7164_MPEG_ENCODER, 271 .portd = SAA7164_MPEG_ENCODER, 272 .porte = SAA7164_MPEG_VBI, 273 .portf = SAA7164_MPEG_VBI, 274 .chiprev = SAA7164_CHIP_REV3, 275 .unit = {{ 276 .id = 0x22, 277 .type = SAA7164_UNIT_EEPROM, 278 .name = "4K EEPROM", 279 .i2c_bus_nr = SAA7164_I2C_BUS_0, 280 .i2c_bus_addr = 0xa0 >> 1, 281 .i2c_reg_len = REGLEN_8bit, 282 }, { 283 .id = 0x04, 284 .type = SAA7164_UNIT_TUNER, 285 .name = "TDA18271-1", 286 .i2c_bus_nr = SAA7164_I2C_BUS_1, 287 .i2c_bus_addr = 0xc0 >> 1, 288 .i2c_reg_len = REGLEN_8bit, 289 }, { 290 .id = 0x07, 291 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 292 .name = "CX24228/S5H1411-1 (TOP)", 293 .i2c_bus_nr = SAA7164_I2C_BUS_1, 294 .i2c_bus_addr = 0x32 >> 1, 295 .i2c_reg_len = REGLEN_8bit, 296 }, { 297 .id = 0x08, 298 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 299 .name = "CX24228/S5H1411-1 (QAM)", 300 .i2c_bus_nr = SAA7164_I2C_BUS_1, 301 .i2c_bus_addr = 0x34 >> 1, 302 .i2c_reg_len = REGLEN_8bit, 303 }, { 304 .id = 0x1e, 305 .type = SAA7164_UNIT_TUNER, 306 .name = "TDA18271-2", 307 .i2c_bus_nr = SAA7164_I2C_BUS_2, 308 .i2c_bus_addr = 0xc0 >> 1, 309 .i2c_reg_len = REGLEN_8bit, 310 }, { 311 .id = 0x20, 312 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 313 .name = "CX24228/S5H1411-2 (TOP)", 314 .i2c_bus_nr = SAA7164_I2C_BUS_2, 315 .i2c_bus_addr = 0x32 >> 1, 316 .i2c_reg_len = REGLEN_8bit, 317 }, { 318 .id = 0x23, 319 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 320 .name = "CX24228/S5H1411-2 (QAM)", 321 .i2c_bus_nr = SAA7164_I2C_BUS_2, 322 .i2c_bus_addr = 0x34 >> 1, 323 .i2c_reg_len = REGLEN_8bit, 324 } }, 325 }, 326 [SAA7164_BOARD_HAUPPAUGE_HVR2250_2] = { 327 .name = "Hauppauge WinTV-HVR2250", 328 .porta = SAA7164_MPEG_DVB, 329 .portb = SAA7164_MPEG_DVB, 330 .portc = SAA7164_MPEG_ENCODER, 331 .portd = SAA7164_MPEG_ENCODER, 332 .porte = SAA7164_MPEG_VBI, 333 .portf = SAA7164_MPEG_VBI, 334 .chiprev = SAA7164_CHIP_REV3, 335 .unit = {{ 336 .id = 0x28, 337 .type = SAA7164_UNIT_EEPROM, 338 .name = "4K EEPROM", 339 .i2c_bus_nr = SAA7164_I2C_BUS_0, 340 .i2c_bus_addr = 0xa0 >> 1, 341 .i2c_reg_len = REGLEN_8bit, 342 }, { 343 .id = 0x04, 344 .type = SAA7164_UNIT_TUNER, 345 .name = "TDA18271-1", 346 .i2c_bus_nr = SAA7164_I2C_BUS_1, 347 .i2c_bus_addr = 0xc0 >> 1, 348 .i2c_reg_len = REGLEN_8bit, 349 }, { 350 .id = 0x07, 351 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 352 .name = "CX24228/S5H1411-1 (TOP)", 353 .i2c_bus_nr = SAA7164_I2C_BUS_1, 354 .i2c_bus_addr = 0x32 >> 1, 355 .i2c_reg_len = REGLEN_8bit, 356 }, { 357 .id = 0x08, 358 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 359 .name = "CX24228/S5H1411-1 (QAM)", 360 .i2c_bus_nr = SAA7164_I2C_BUS_1, 361 .i2c_bus_addr = 0x34 >> 1, 362 .i2c_reg_len = REGLEN_8bit, 363 }, { 364 .id = 0x24, 365 .type = SAA7164_UNIT_TUNER, 366 .name = "TDA18271-2", 367 .i2c_bus_nr = SAA7164_I2C_BUS_2, 368 .i2c_bus_addr = 0xc0 >> 1, 369 .i2c_reg_len = REGLEN_8bit, 370 }, { 371 .id = 0x26, 372 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 373 .name = "CX24228/S5H1411-2 (TOP)", 374 .i2c_bus_nr = SAA7164_I2C_BUS_2, 375 .i2c_bus_addr = 0x32 >> 1, 376 .i2c_reg_len = REGLEN_8bit, 377 }, { 378 .id = 0x29, 379 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 380 .name = "CX24228/S5H1411-2 (QAM)", 381 .i2c_bus_nr = SAA7164_I2C_BUS_2, 382 .i2c_bus_addr = 0x34 >> 1, 383 .i2c_reg_len = REGLEN_8bit, 384 } }, 385 }, 386 [SAA7164_BOARD_HAUPPAUGE_HVR2250_3] = { 387 .name = "Hauppauge WinTV-HVR2250", 388 .porta = SAA7164_MPEG_DVB, 389 .portb = SAA7164_MPEG_DVB, 390 .portc = SAA7164_MPEG_ENCODER, 391 .portd = SAA7164_MPEG_ENCODER, 392 .porte = SAA7164_MPEG_VBI, 393 .portf = SAA7164_MPEG_VBI, 394 .chiprev = SAA7164_CHIP_REV3, 395 .unit = {{ 396 .id = 0x26, 397 .type = SAA7164_UNIT_EEPROM, 398 .name = "4K EEPROM", 399 .i2c_bus_nr = SAA7164_I2C_BUS_0, 400 .i2c_bus_addr = 0xa0 >> 1, 401 .i2c_reg_len = REGLEN_8bit, 402 }, { 403 .id = 0x04, 404 .type = SAA7164_UNIT_TUNER, 405 .name = "TDA18271-1", 406 .i2c_bus_nr = SAA7164_I2C_BUS_1, 407 .i2c_bus_addr = 0xc0 >> 1, 408 .i2c_reg_len = REGLEN_8bit, 409 }, { 410 .id = 0x07, 411 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 412 .name = "CX24228/S5H1411-1 (TOP)", 413 .i2c_bus_nr = SAA7164_I2C_BUS_1, 414 .i2c_bus_addr = 0x32 >> 1, 415 .i2c_reg_len = REGLEN_8bit, 416 }, { 417 .id = 0x08, 418 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 419 .name = "CX24228/S5H1411-1 (QAM)", 420 .i2c_bus_nr = SAA7164_I2C_BUS_1, 421 .i2c_bus_addr = 0x34 >> 1, 422 .i2c_reg_len = REGLEN_8bit, 423 }, { 424 .id = 0x22, 425 .type = SAA7164_UNIT_TUNER, 426 .name = "TDA18271-2", 427 .i2c_bus_nr = SAA7164_I2C_BUS_2, 428 .i2c_bus_addr = 0xc0 >> 1, 429 .i2c_reg_len = REGLEN_8bit, 430 }, { 431 .id = 0x24, 432 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 433 .name = "CX24228/S5H1411-2 (TOP)", 434 .i2c_bus_nr = SAA7164_I2C_BUS_2, 435 .i2c_bus_addr = 0x32 >> 1, 436 .i2c_reg_len = REGLEN_8bit, 437 }, { 438 .id = 0x27, 439 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 440 .name = "CX24228/S5H1411-2 (QAM)", 441 .i2c_bus_nr = SAA7164_I2C_BUS_2, 442 .i2c_bus_addr = 0x34 >> 1, 443 .i2c_reg_len = REGLEN_8bit, 444 } }, 445 }, 446 [SAA7164_BOARD_HAUPPAUGE_HVR2200_5] = { 447 .name = "Hauppauge WinTV-HVR2200", 448 .porta = SAA7164_MPEG_DVB, 449 .portb = SAA7164_MPEG_DVB, 450 .chiprev = SAA7164_CHIP_REV3, 451 .unit = {{ 452 .id = 0x23, 453 .type = SAA7164_UNIT_EEPROM, 454 .name = "4K EEPROM", 455 .i2c_bus_nr = SAA7164_I2C_BUS_0, 456 .i2c_bus_addr = 0xa0 >> 1, 457 .i2c_reg_len = REGLEN_8bit, 458 }, { 459 .id = 0x04, 460 .type = SAA7164_UNIT_TUNER, 461 .name = "TDA18271-1", 462 .i2c_bus_nr = SAA7164_I2C_BUS_1, 463 .i2c_bus_addr = 0xc0 >> 1, 464 .i2c_reg_len = REGLEN_8bit, 465 }, { 466 .id = 0x05, 467 .type = SAA7164_UNIT_ANALOG_DEMODULATOR, 468 .name = "TDA8290-1", 469 .i2c_bus_nr = SAA7164_I2C_BUS_1, 470 .i2c_bus_addr = 0x84 >> 1, 471 .i2c_reg_len = REGLEN_8bit, 472 }, { 473 .id = 0x21, 474 .type = SAA7164_UNIT_TUNER, 475 .name = "TDA18271-2", 476 .i2c_bus_nr = SAA7164_I2C_BUS_2, 477 .i2c_bus_addr = 0xc0 >> 1, 478 .i2c_reg_len = REGLEN_8bit, 479 }, { 480 .id = 0x22, 481 .type = SAA7164_UNIT_ANALOG_DEMODULATOR, 482 .name = "TDA8290-2", 483 .i2c_bus_nr = SAA7164_I2C_BUS_2, 484 .i2c_bus_addr = 0x84 >> 1, 485 .i2c_reg_len = REGLEN_8bit, 486 }, { 487 .id = 0x24, 488 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 489 .name = "TDA10048-1", 490 .i2c_bus_nr = SAA7164_I2C_BUS_1, 491 .i2c_bus_addr = 0x10 >> 1, 492 .i2c_reg_len = REGLEN_8bit, 493 }, { 494 .id = 0x25, 495 .type = SAA7164_UNIT_DIGITAL_DEMODULATOR, 496 .name = "TDA10048-2", 497 .i2c_bus_nr = SAA7164_I2C_BUS_2, 498 .i2c_bus_addr = 0x12 >> 1, 499 .i2c_reg_len = REGLEN_8bit, 500 } }, 501 }, 502 }; 503 const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards); 504 505 /* ------------------------------------------------------------------ */ 506 /* PCI subsystem IDs */ 507 508 struct saa7164_subid saa7164_subids[] = { 509 { 510 .subvendor = 0x0070, 511 .subdevice = 0x8880, 512 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250, 513 }, { 514 .subvendor = 0x0070, 515 .subdevice = 0x8810, 516 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250, 517 }, { 518 .subvendor = 0x0070, 519 .subdevice = 0x8980, 520 .card = SAA7164_BOARD_HAUPPAUGE_HVR2200, 521 }, { 522 .subvendor = 0x0070, 523 .subdevice = 0x8900, 524 .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_2, 525 }, { 526 .subvendor = 0x0070, 527 .subdevice = 0x8901, 528 .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_3, 529 }, { 530 .subvendor = 0x0070, 531 .subdevice = 0x88A1, 532 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250_3, 533 }, { 534 .subvendor = 0x0070, 535 .subdevice = 0x8891, 536 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250_2, 537 }, { 538 .subvendor = 0x0070, 539 .subdevice = 0x8851, 540 .card = SAA7164_BOARD_HAUPPAUGE_HVR2250_2, 541 }, { 542 .subvendor = 0x0070, 543 .subdevice = 0x8940, 544 .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_4, 545 }, { 546 .subvendor = 0x0070, 547 .subdevice = 0x8953, 548 .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_5, 549 }, 550 }; 551 const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids); 552 553 void saa7164_card_list(struct saa7164_dev *dev) 554 { 555 int i; 556 557 if (0 == dev->pci->subsystem_vendor && 558 0 == dev->pci->subsystem_device) { 559 printk(KERN_ERR 560 "%s: Board has no valid PCIe Subsystem ID and can't\n" 561 "%s: be autodetected. Pass card=<n> insmod option to\n" 562 "%s: workaround that. Send complaints to the vendor\n" 563 "%s: of the TV card. Best regards,\n" 564 "%s: -- tux\n", 565 dev->name, dev->name, dev->name, dev->name, dev->name); 566 } else { 567 printk(KERN_ERR 568 "%s: Your board isn't known (yet) to the driver.\n" 569 "%s: Try to pick one of the existing card configs via\n" 570 "%s: card=<n> insmod option. Updating to the latest\n" 571 "%s: version might help as well.\n", 572 dev->name, dev->name, dev->name, dev->name); 573 } 574 575 printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod " 576 "option:\n", dev->name); 577 578 for (i = 0; i < saa7164_bcount; i++) 579 printk(KERN_ERR "%s: card=%d -> %s\n", 580 dev->name, i, saa7164_boards[i].name); 581 } 582 583 /* TODO: clean this define up into the -cards.c structs */ 584 #define PCIEBRIDGE_UNITID 2 585 586 void saa7164_gpio_setup(struct saa7164_dev *dev) 587 { 588 switch (dev->board) { 589 case SAA7164_BOARD_HAUPPAUGE_HVR2200: 590 case SAA7164_BOARD_HAUPPAUGE_HVR2200_2: 591 case SAA7164_BOARD_HAUPPAUGE_HVR2200_3: 592 case SAA7164_BOARD_HAUPPAUGE_HVR2200_4: 593 case SAA7164_BOARD_HAUPPAUGE_HVR2200_5: 594 case SAA7164_BOARD_HAUPPAUGE_HVR2250: 595 case SAA7164_BOARD_HAUPPAUGE_HVR2250_2: 596 case SAA7164_BOARD_HAUPPAUGE_HVR2250_3: 597 /* 598 GPIO 2: s5h1411 / tda10048-1 demod reset 599 GPIO 3: s5h1411 / tda10048-2 demod reset 600 GPIO 7: IRBlaster Zilog reset 601 */ 602 603 /* Reset parts by going in and out of reset */ 604 saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2); 605 saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3); 606 607 msleep(20); 608 609 saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2); 610 saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3); 611 break; 612 } 613 } 614 615 static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data) 616 { 617 struct tveeprom tv; 618 619 /* TODO: Assumption: eeprom on bus 0 */ 620 tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv, 621 eeprom_data); 622 623 /* Make sure we support the board model */ 624 switch (tv.model) { 625 case 88001: 626 /* Development board - Limit circulation */ 627 /* WinTV-HVR2250 (PCIe, Retail, full-height bracket) 628 * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */ 629 case 88021: 630 /* WinTV-HVR2250 (PCIe, Retail, full-height bracket) 631 * ATSC/QAM (TDA18271/S5H1411) and basic analog, MCE CIR, FM */ 632 break; 633 case 88041: 634 /* WinTV-HVR2250 (PCIe, Retail, full-height bracket) 635 * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */ 636 break; 637 case 88061: 638 /* WinTV-HVR2250 (PCIe, Retail, full-height bracket) 639 * ATSC/QAM (TDA18271/S5H1411) and basic analog, FM */ 640 break; 641 case 89519: 642 case 89609: 643 /* WinTV-HVR2200 (PCIe, Retail, full-height) 644 * DVB-T (TDA18271/TDA10048) and basic analog, no IR */ 645 break; 646 case 89619: 647 /* WinTV-HVR2200 (PCIe, Retail, half-height) 648 * DVB-T (TDA18271/TDA10048) and basic analog, no IR */ 649 break; 650 default: 651 printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n", 652 dev->name, tv.model); 653 break; 654 } 655 656 printk(KERN_INFO "%s: Hauppauge eeprom: model=%d\n", dev->name, 657 tv.model); 658 } 659 660 void saa7164_card_setup(struct saa7164_dev *dev) 661 { 662 static u8 eeprom[256]; 663 664 if (dev->i2c_bus[0].i2c_rc == 0) { 665 if (saa7164_api_read_eeprom(dev, &eeprom[0], 666 sizeof(eeprom)) < 0) 667 return; 668 } 669 670 switch (dev->board) { 671 case SAA7164_BOARD_HAUPPAUGE_HVR2200: 672 case SAA7164_BOARD_HAUPPAUGE_HVR2200_2: 673 case SAA7164_BOARD_HAUPPAUGE_HVR2200_3: 674 case SAA7164_BOARD_HAUPPAUGE_HVR2200_4: 675 case SAA7164_BOARD_HAUPPAUGE_HVR2200_5: 676 case SAA7164_BOARD_HAUPPAUGE_HVR2250: 677 case SAA7164_BOARD_HAUPPAUGE_HVR2250_2: 678 case SAA7164_BOARD_HAUPPAUGE_HVR2250_3: 679 hauppauge_eeprom(dev, &eeprom[0]); 680 break; 681 } 682 } 683 684 /* With most other drivers, the kernel expects to communicate with subdrivers 685 * through i2c. This bridge does not allow that, it does not expose any direct 686 * access to I2C. Instead we have to communicate through the device f/w for 687 * register access to 'processing units'. Each unit has a unique 688 * id, regardless of how the physical implementation occurs across 689 * the three physical i2c busses. The being said if we want leverge of 690 * the existing kernel drivers for tuners and demods we have to 'speak i2c', 691 * to this bridge implements 3 virtual i2c buses. This is a helper function 692 * for those. 693 * 694 * Description: Translate the kernels notion of an i2c address and bus into 695 * the appropriate unitid. 696 */ 697 int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr) 698 { 699 /* For a given bus and i2c device address, return the saa7164 unique 700 * unitid. < 0 on error */ 701 702 struct saa7164_dev *dev = bus->dev; 703 struct saa7164_unit *unit; 704 int i; 705 706 for (i = 0; i < SAA7164_MAX_UNITS; i++) { 707 unit = &saa7164_boards[dev->board].unit[i]; 708 709 if (unit->type == SAA7164_UNIT_UNDEFINED) 710 continue; 711 if ((bus->nr == unit->i2c_bus_nr) && 712 (addr == unit->i2c_bus_addr)) 713 return unit->id; 714 } 715 716 return -1; 717 } 718 719 /* The 7164 API needs to know the i2c register length in advance. 720 * this is a helper function. Based on a specific chip addr and bus return the 721 * reg length. 722 */ 723 int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr) 724 { 725 /* For a given bus and i2c device address, return the 726 * saa7164 registry address width. < 0 on error 727 */ 728 729 struct saa7164_dev *dev = bus->dev; 730 struct saa7164_unit *unit; 731 int i; 732 733 for (i = 0; i < SAA7164_MAX_UNITS; i++) { 734 unit = &saa7164_boards[dev->board].unit[i]; 735 736 if (unit->type == SAA7164_UNIT_UNDEFINED) 737 continue; 738 739 if ((bus->nr == unit->i2c_bus_nr) && 740 (addr == unit->i2c_bus_addr)) 741 return unit->i2c_reg_len; 742 } 743 744 return -1; 745 } 746 /* TODO: implement a 'findeeprom' functio like the above and fix any other 747 * eeprom related todo's in -api.c. 748 */ 749 750 /* Translate a unitid into a x readable device name, for display purposes. */ 751 char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid) 752 { 753 char *undefed = "UNDEFINED"; 754 char *bridge = "BRIDGE"; 755 struct saa7164_unit *unit; 756 int i; 757 758 if (unitid == 0) 759 return bridge; 760 761 for (i = 0; i < SAA7164_MAX_UNITS; i++) { 762 unit = &saa7164_boards[dev->board].unit[i]; 763 764 if (unit->type == SAA7164_UNIT_UNDEFINED) 765 continue; 766 767 if (unitid == unit->id) 768 return unit->name; 769 } 770 771 return undefed; 772 } 773 774