aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-cards.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-cards.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c182
1 files changed, 171 insertions, 11 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index c43fdb9bc888..320f1f60276e 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -157,6 +157,20 @@ static struct em28xx_reg_seq evga_indtube_digital[] = {
157 { -1, -1, -1, -1}, 157 { -1, -1, -1, -1},
158}; 158};
159 159
160/* Pinnacle Hybrid Pro eb1a:2881 */
161static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
162 {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10},
163 { -1, -1, -1, -1},
164};
165
166static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
167 {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10},
168 {EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */
169 {EM2880_R04_GPO, 0x0c, 0xff, 1},
170 { -1, -1, -1, -1},
171};
172
173
160/* Callback for the most boards */ 174/* Callback for the most boards */
161static struct em28xx_reg_seq default_tuner_gpio[] = { 175static struct em28xx_reg_seq default_tuner_gpio[] = {
162 {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, 176 {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
@@ -191,18 +205,27 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = {
191 {EM28XX_R08_GPIO, 0xff, 0xff, 10}, 205 {EM28XX_R08_GPIO, 0xff, 0xff, 10},
192 { -1, -1, -1, -1}, 206 { -1, -1, -1, -1},
193}; 207};
208
209static struct em28xx_reg_seq silvercrest_reg_seq[] = {
210 {EM28XX_R08_GPIO, 0xff, 0xff, 10},
211 {EM28XX_R08_GPIO, 0x01, 0xf7, 10},
212 { -1, -1, -1, -1},
213};
214
194/* 215/*
195 * Board definitions 216 * Board definitions
196 */ 217 */
197struct em28xx_board em28xx_boards[] = { 218struct em28xx_board em28xx_boards[] = {
198 [EM2750_BOARD_UNKNOWN] = { 219 [EM2750_BOARD_UNKNOWN] = {
199 .name = "Unknown EM2750/EM2751 webcam grabber", 220 .name = "EM2710/EM2750/EM2751 webcam grabber",
200 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, 221 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ,
201 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 222 .tuner_type = TUNER_ABSENT,
223 .is_webcam = 1,
202 .input = { { 224 .input = { {
203 .type = EM28XX_VMUX_COMPOSITE1, 225 .type = EM28XX_VMUX_COMPOSITE1,
204 .vmux = 0, 226 .vmux = 0,
205 .amux = EM28XX_AMUX_VIDEO, 227 .amux = EM28XX_AMUX_VIDEO,
228 .gpio = silvercrest_reg_seq,
206 } }, 229 } },
207 }, 230 },
208 [EM2800_BOARD_UNKNOWN] = { 231 [EM2800_BOARD_UNKNOWN] = {
@@ -224,13 +247,15 @@ struct em28xx_board em28xx_boards[] = {
224 [EM2820_BOARD_UNKNOWN] = { 247 [EM2820_BOARD_UNKNOWN] = {
225 .name = "Unknown EM2750/28xx video grabber", 248 .name = "Unknown EM2750/28xx video grabber",
226 .tuner_type = TUNER_ABSENT, 249 .tuner_type = TUNER_ABSENT,
250 .is_webcam = 1, /* To enable sensor probe */
227 }, 251 },
228 [EM2750_BOARD_DLCW_130] = { 252 [EM2750_BOARD_DLCW_130] = {
229 /* Beijing Huaqi Information Digital Technology Co., Ltd */ 253 /* Beijing Huaqi Information Digital Technology Co., Ltd */
230 .name = "Huaqi DLCW-130", 254 .name = "Huaqi DLCW-130",
231 .valid = EM28XX_BOARD_NOT_VALIDATED, 255 .valid = EM28XX_BOARD_NOT_VALIDATED,
232 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, 256 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ,
233 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 257 .tuner_type = TUNER_ABSENT,
258 .is_webcam = 1,
234 .input = { { 259 .input = { {
235 .type = EM28XX_VMUX_COMPOSITE1, 260 .type = EM28XX_VMUX_COMPOSITE1,
236 .vmux = 0, 261 .vmux = 0,
@@ -431,13 +456,25 @@ struct em28xx_board em28xx_boards[] = {
431 [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { 456 [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
432 .name = "Videology 20K14XUSB USB2.0", 457 .name = "Videology 20K14XUSB USB2.0",
433 .valid = EM28XX_BOARD_NOT_VALIDATED, 458 .valid = EM28XX_BOARD_NOT_VALIDATED,
434 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 459 .tuner_type = TUNER_ABSENT,
460 .is_webcam = 1,
435 .input = { { 461 .input = { {
436 .type = EM28XX_VMUX_COMPOSITE1, 462 .type = EM28XX_VMUX_COMPOSITE1,
437 .vmux = 0, 463 .vmux = 0,
438 .amux = EM28XX_AMUX_VIDEO, 464 .amux = EM28XX_AMUX_VIDEO,
439 } }, 465 } },
440 }, 466 },
467 [EM2820_BOARD_SILVERCREST_WEBCAM] = {
468 .name = "Silvercrest Webcam 1.3mpix",
469 .tuner_type = TUNER_ABSENT,
470 .is_webcam = 1,
471 .input = { {
472 .type = EM28XX_VMUX_COMPOSITE1,
473 .vmux = 0,
474 .amux = EM28XX_AMUX_VIDEO,
475 .gpio = silvercrest_reg_seq,
476 } },
477 },
441 [EM2821_BOARD_SUPERCOMP_USB_2] = { 478 [EM2821_BOARD_SUPERCOMP_USB_2] = {
442 .name = "Supercomp USB 2.0 TV", 479 .name = "Supercomp USB 2.0 TV",
443 .valid = EM28XX_BOARD_NOT_VALIDATED, 480 .valid = EM28XX_BOARD_NOT_VALIDATED,
@@ -479,7 +516,8 @@ struct em28xx_board em28xx_boards[] = {
479 /* Beijing Huaqi Information Digital Technology Co., Ltd */ 516 /* Beijing Huaqi Information Digital Technology Co., Ltd */
480 .name = "NetGMBH Cam", 517 .name = "NetGMBH Cam",
481 .valid = EM28XX_BOARD_NOT_VALIDATED, 518 .valid = EM28XX_BOARD_NOT_VALIDATED,
482 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 519 .tuner_type = TUNER_ABSENT,
520 .is_webcam = 1,
483 .input = { { 521 .input = { {
484 .type = EM28XX_VMUX_COMPOSITE1, 522 .type = EM28XX_VMUX_COMPOSITE1,
485 .vmux = 0, 523 .vmux = 0,
@@ -826,7 +864,7 @@ struct em28xx_board em28xx_boards[] = {
826 .tuner_gpio = default_tuner_gpio, 864 .tuner_gpio = default_tuner_gpio,
827 .decoder = EM28XX_TVP5150, 865 .decoder = EM28XX_TVP5150,
828 .has_dvb = 1, 866 .has_dvb = 1,
829 .dvb_gpio = default_analog, 867 .dvb_gpio = default_digital,
830 .input = { { 868 .input = { {
831 .type = EM28XX_VMUX_TELEVISION, 869 .type = EM28XX_VMUX_TELEVISION,
832 .vmux = TVP5150_COMPOSITE0, 870 .vmux = TVP5150_COMPOSITE0,
@@ -1229,25 +1267,26 @@ struct em28xx_board em28xx_boards[] = {
1229 }, 1267 },
1230 [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { 1268 [EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
1231 .name = "Pinnacle Hybrid Pro", 1269 .name = "Pinnacle Hybrid Pro",
1232 .valid = EM28XX_BOARD_NOT_VALIDATED,
1233 .tuner_type = TUNER_XC2028, 1270 .tuner_type = TUNER_XC2028,
1234 .tuner_gpio = default_tuner_gpio, 1271 .tuner_gpio = default_tuner_gpio,
1235 .decoder = EM28XX_TVP5150, 1272 .decoder = EM28XX_TVP5150,
1273 .has_dvb = 1,
1274 .dvb_gpio = pinnacle_hybrid_pro_digital,
1236 .input = { { 1275 .input = { {
1237 .type = EM28XX_VMUX_TELEVISION, 1276 .type = EM28XX_VMUX_TELEVISION,
1238 .vmux = TVP5150_COMPOSITE0, 1277 .vmux = TVP5150_COMPOSITE0,
1239 .amux = EM28XX_AMUX_VIDEO, 1278 .amux = EM28XX_AMUX_VIDEO,
1240 .gpio = default_analog, 1279 .gpio = pinnacle_hybrid_pro_analog,
1241 }, { 1280 }, {
1242 .type = EM28XX_VMUX_COMPOSITE1, 1281 .type = EM28XX_VMUX_COMPOSITE1,
1243 .vmux = TVP5150_COMPOSITE1, 1282 .vmux = TVP5150_COMPOSITE1,
1244 .amux = EM28XX_AMUX_LINE_IN, 1283 .amux = EM28XX_AMUX_LINE_IN,
1245 .gpio = default_analog, 1284 .gpio = pinnacle_hybrid_pro_analog,
1246 }, { 1285 }, {
1247 .type = EM28XX_VMUX_SVIDEO, 1286 .type = EM28XX_VMUX_SVIDEO,
1248 .vmux = TVP5150_SVIDEO, 1287 .vmux = TVP5150_SVIDEO,
1249 .amux = EM28XX_AMUX_LINE_IN, 1288 .amux = EM28XX_AMUX_LINE_IN,
1250 .gpio = default_analog, 1289 .gpio = pinnacle_hybrid_pro_analog,
1251 } }, 1290 } },
1252 }, 1291 },
1253 [EM2882_BOARD_PINNACLE_HYBRID_PRO] = { 1292 [EM2882_BOARD_PINNACLE_HYBRID_PRO] = {
@@ -1617,6 +1656,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = {
1617 {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, 1656 {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
1618 {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, 1657 {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
1619 {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, 1658 {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
1659 {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028},
1620}; 1660};
1621 1661
1622/* I2C devicelist hash table for devices with generic USB IDs */ 1662/* I2C devicelist hash table for devices with generic USB IDs */
@@ -1639,6 +1679,11 @@ static unsigned short tvp5150_addrs[] = {
1639 I2C_CLIENT_END 1679 I2C_CLIENT_END
1640}; 1680};
1641 1681
1682static unsigned short mt9v011_addrs[] = {
1683 0xba >> 1,
1684 I2C_CLIENT_END
1685};
1686
1642static unsigned short msp3400_addrs[] = { 1687static unsigned short msp3400_addrs[] = {
1643 0x80 >> 1, 1688 0x80 >> 1,
1644 0x88 >> 1, 1689 0x88 >> 1,
@@ -1678,6 +1723,91 @@ static inline void em28xx_set_model(struct em28xx *dev)
1678 EM28XX_I2C_FREQ_100_KHZ; 1723 EM28XX_I2C_FREQ_100_KHZ;
1679} 1724}
1680 1725
1726/* FIXME: Should be replaced by a proper mt9m001 driver */
1727static int em28xx_initialize_mt9m001(struct em28xx *dev)
1728{
1729 int i;
1730 unsigned char regs[][3] = {
1731 { 0x0d, 0x00, 0x01, },
1732 { 0x0d, 0x00, 0x00, },
1733 { 0x04, 0x05, 0x00, }, /* hres = 1280 */
1734 { 0x03, 0x04, 0x00, }, /* vres = 1024 */
1735 { 0x20, 0x11, 0x00, },
1736 { 0x06, 0x00, 0x10, },
1737 { 0x2b, 0x00, 0x24, },
1738 { 0x2e, 0x00, 0x24, },
1739 { 0x35, 0x00, 0x24, },
1740 { 0x2d, 0x00, 0x20, },
1741 { 0x2c, 0x00, 0x20, },
1742 { 0x09, 0x0a, 0xd4, },
1743 { 0x35, 0x00, 0x57, },
1744 };
1745
1746 for (i = 0; i < ARRAY_SIZE(regs); i++)
1747 i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
1748
1749 return 0;
1750}
1751
1752/* HINT method: webcam I2C chips
1753 *
1754 * This method work for webcams with Micron sensors
1755 */
1756static int em28xx_hint_sensor(struct em28xx *dev)
1757{
1758 int rc;
1759 char *sensor_name;
1760 unsigned char cmd;
1761 __be16 version_be;
1762 u16 version;
1763
1764 dev->i2c_client.addr = 0xba >> 1;
1765 cmd = 0;
1766 i2c_master_send(&dev->i2c_client, &cmd, 1);
1767 rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2);
1768 if (rc != 2)
1769 return -EINVAL;
1770
1771 version = be16_to_cpu(version_be);
1772
1773 switch (version) {
1774 case 0x8243: /* mt9v011 640x480 1.3 Mpix sensor */
1775 dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
1776 sensor_name = "mt9v011";
1777 dev->em28xx_sensor = EM28XX_MT9V011;
1778 dev->sensor_xres = 640;
1779 dev->sensor_yres = 480;
1780 dev->sensor_xtal = 6300000;
1781
1782 /* probably means GRGB 16 bit bayer */
1783 dev->vinmode = 0x0d;
1784 dev->vinctl = 0x00;
1785
1786 break;
1787 case 0x8431:
1788 dev->model = EM2750_BOARD_UNKNOWN;
1789 sensor_name = "mt9m001";
1790 dev->em28xx_sensor = EM28XX_MT9M001;
1791 em28xx_initialize_mt9m001(dev);
1792 dev->sensor_xres = 1280;
1793 dev->sensor_yres = 1024;
1794
1795 /* probably means BGGR 16 bit bayer */
1796 dev->vinmode = 0x0c;
1797 dev->vinctl = 0x00;
1798
1799 break;
1800 default:
1801 printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version));
1802 return -EINVAL;
1803 }
1804
1805 em28xx_errdev("Sensor is %s, using model %s entry.\n",
1806 sensor_name, em28xx_boards[dev->model].name);
1807
1808 return 0;
1809}
1810
1681/* Since em28xx_pre_card_setup() requires a proper dev->model, 1811/* Since em28xx_pre_card_setup() requires a proper dev->model,
1682 * this won't work for boards with generic PCI IDs 1812 * this won't work for boards with generic PCI IDs
1683 */ 1813 */
@@ -1706,7 +1836,7 @@ void em28xx_pre_card_setup(struct em28xx *dev)
1706 em28xx_info("chip ID is em2750\n"); 1836 em28xx_info("chip ID is em2750\n");
1707 break; 1837 break;
1708 case CHIP_ID_EM2820: 1838 case CHIP_ID_EM2820:
1709 em28xx_info("chip ID is em2820\n"); 1839 em28xx_info("chip ID is em2710 or em2820\n");
1710 break; 1840 break;
1711 case CHIP_ID_EM2840: 1841 case CHIP_ID_EM2840:
1712 em28xx_info("chip ID is em2840\n"); 1842 em28xx_info("chip ID is em2840\n");
@@ -1860,6 +1990,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
1860 ctl->demod = XC3028_FE_ZARLINK456; 1990 ctl->demod = XC3028_FE_ZARLINK456;
1861 break; 1991 break;
1862 case EM2880_BOARD_TERRATEC_HYBRID_XS: 1992 case EM2880_BOARD_TERRATEC_HYBRID_XS:
1993 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
1863 ctl->demod = XC3028_FE_ZARLINK456; 1994 ctl->demod = XC3028_FE_ZARLINK456;
1864 break; 1995 break;
1865 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 1996 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
@@ -2156,8 +2287,13 @@ void em28xx_card_setup(struct em28xx *dev)
2156 em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, 2287 em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
2157 so make the call now so the analog GPIOs are set properly 2288 so make the call now so the analog GPIOs are set properly
2158 before probing the i2c bus. */ 2289 before probing the i2c bus. */
2290 em28xx_gpio_set(dev, dev->board.tuner_gpio);
2159 em28xx_set_mode(dev, EM28XX_ANALOG_MODE); 2291 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
2160 break; 2292 break;
2293 case EM2820_BOARD_SILVERCREST_WEBCAM:
2294 /* FIXME: need to document the registers bellow */
2295 em28xx_write_reg(dev, 0x0d, 0x42);
2296 em28xx_write_reg(dev, 0x13, 0x08);
2161 } 2297 }
2162 2298
2163 if (dev->board.has_snapshot_button) 2299 if (dev->board.has_snapshot_button)
@@ -2189,6 +2325,15 @@ void em28xx_card_setup(struct em28xx *dev)
2189 v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, 2325 v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
2190 "tvp5150", "tvp5150", tvp5150_addrs); 2326 "tvp5150", "tvp5150", tvp5150_addrs);
2191 2327
2328 if (dev->em28xx_sensor == EM28XX_MT9V011) {
2329 struct v4l2_subdev *sd;
2330
2331 sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev,
2332 &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs);
2333 v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal);
2334 }
2335
2336
2192 if (dev->board.adecoder == EM28XX_TVAUDIO) 2337 if (dev->board.adecoder == EM28XX_TVAUDIO)
2193 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, 2338 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
2194 "tvaudio", "tvaudio", dev->board.tvaudio_addr); 2339 "tvaudio", "tvaudio", dev->board.tvaudio_addr);
@@ -2333,6 +2478,20 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
2333 return errCode; 2478 return errCode;
2334 } 2479 }
2335 2480
2481 /*
2482 * Default format, used for tvp5150 or saa711x output formats
2483 */
2484 dev->vinmode = 0x10;
2485 dev->vinctl = 0x11;
2486
2487 /*
2488 * If the device can be a webcam, seek for a sensor.
2489 * If sensor is not found, then it isn't a webcam.
2490 */
2491 if (dev->board.is_webcam)
2492 if (em28xx_hint_sensor(dev) < 0)
2493 dev->board.is_webcam = 0;
2494
2336 /* Do board specific init and eeprom reading */ 2495 /* Do board specific init and eeprom reading */
2337 em28xx_card_setup(dev); 2496 em28xx_card_setup(dev);
2338 2497
@@ -2573,6 +2732,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
2573 retval = em28xx_init_dev(&dev, udev, interface, nr); 2732 retval = em28xx_init_dev(&dev, udev, interface, nr);
2574 if (retval) { 2733 if (retval) {
2575 em28xx_devused &= ~(1<<dev->devno); 2734 em28xx_devused &= ~(1<<dev->devno);
2735 mutex_unlock(&dev->lock);
2576 kfree(dev); 2736 kfree(dev);
2577 goto err; 2737 goto err;
2578 } 2738 }