aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r--drivers/media/video/em28xx/Kconfig2
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c182
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c18
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c74
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c2
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c84
-rw-r--r--drivers/media/video/em28xx/em28xx.h32
7 files changed, 340 insertions, 54 deletions
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 16a5af30e9d1..6524b493e033 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -8,6 +8,8 @@ config VIDEO_EM28XX
8 select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO 8 select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
9 select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO 9 select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
10 select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO 10 select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
11 select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO
12
11 ---help--- 13 ---help---
12 This is a video4linux driver for Empia 28xx based TV cards. 14 This is a video4linux driver for Empia 28xx based TV cards.
13 15
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 }
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index c8d7ce8fbd36..5b78e199abd1 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -650,15 +650,15 @@ int em28xx_set_outfmt(struct em28xx *dev)
650 int ret; 650 int ret;
651 651
652 ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, 652 ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
653 dev->format->reg | 0x20, 0x3f); 653 dev->format->reg | 0x20, 0xff);
654 if (ret < 0) 654 if (ret < 0)
655 return ret; 655 return ret;
656 656
657 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); 657 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
658 if (ret < 0) 658 if (ret < 0)
659 return ret; 659 return ret;
660 660
661 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); 661 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl);
662} 662}
663 663
664static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, 664static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
@@ -695,13 +695,16 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
695{ 695{
696 u8 mode; 696 u8 mode;
697 /* the em2800 scaler only supports scaling down to 50% */ 697 /* the em2800 scaler only supports scaling down to 50% */
698 if (dev->board.is_em2800) 698
699 if (dev->board.is_em2800) {
699 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); 700 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
700 else { 701 } else {
701 u8 buf[2]; 702 u8 buf[2];
703
702 buf[0] = h; 704 buf[0] = h;
703 buf[1] = h >> 8; 705 buf[1] = h >> 8;
704 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); 706 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
707
705 buf[0] = v; 708 buf[0] = v;
706 buf[1] = v >> 8; 709 buf[1] = v >> 8;
707 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); 710 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
@@ -720,8 +723,11 @@ int em28xx_resolution_set(struct em28xx *dev)
720 height = norm_maxh(dev) >> 1; 723 height = norm_maxh(dev) >> 1;
721 724
722 em28xx_set_outfmt(dev); 725 em28xx_set_outfmt(dev);
726
727
723 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); 728 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
724 em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); 729 em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
730
725 return em28xx_scaler_set(dev, dev->hscale, dev->vscale); 731 return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
726} 732}
727 733
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index e7b47c8da8f3..cf0ac7f2a30d 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -31,6 +31,8 @@
31#include "lgdt330x.h" 31#include "lgdt330x.h"
32#include "zl10353.h" 32#include "zl10353.h"
33#include "s5h1409.h" 33#include "s5h1409.h"
34#include "mt352.h"
35#include "mt352_priv.h" /* FIXME */
34 36
35MODULE_DESCRIPTION("driver for em28xx based DVB cards"); 37MODULE_DESCRIPTION("driver for em28xx based DVB cards");
36MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 38MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -243,6 +245,14 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
243 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 245 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
244}; 246};
245 247
248static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
249 .demod_address = (0x1e >> 1),
250 .no_tuner = 1,
251 .disable_i2c_gate_ctrl = 1,
252 .parallel_ts = 1,
253 .if2 = 45600,
254};
255
246#ifdef EM28XX_DRX397XD_SUPPORT 256#ifdef EM28XX_DRX397XD_SUPPORT
247/* [TODO] djh - not sure yet what the device config needs to contain */ 257/* [TODO] djh - not sure yet what the device config needs to contain */
248static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { 258static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
@@ -250,6 +260,41 @@ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
250}; 260};
251#endif 261#endif
252 262
263static int mt352_terratec_xs_init(struct dvb_frontend *fe)
264{
265 /* Values extracted from a USB trace of the Terratec Windows driver */
266 static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c };
267 static u8 reset[] = { RESET, 0x80 };
268 static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 };
269 static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 };
270 static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
271 static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d };
272 static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
273 static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
274 static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
275 static u8 tuner_go[] = { TUNER_GO, 0x01};
276
277 mt352_write(fe, clock_config, sizeof(clock_config));
278 udelay(200);
279 mt352_write(fe, reset, sizeof(reset));
280 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
281 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
282 mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
283 mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg));
284 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
285 mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg));
286 mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg));
287 mt352_write(fe, tuner_go, sizeof(tuner_go));
288 return 0;
289}
290
291static struct mt352_config terratec_xs_mt352_cfg = {
292 .demod_address = (0x1e >> 1),
293 .no_tuner = 1,
294 .if2 = 45600,
295 .demod_init = mt352_terratec_xs_init,
296};
297
253/* ------------------------------------------------------------------ */ 298/* ------------------------------------------------------------------ */
254 299
255static int attach_xc3028(u8 addr, struct em28xx *dev) 300static int attach_xc3028(u8 addr, struct em28xx *dev)
@@ -432,8 +477,6 @@ static int dvb_init(struct em28xx *dev)
432 goto out_free; 477 goto out_free;
433 } 478 }
434 break; 479 break;
435 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
436 case EM2880_BOARD_TERRATEC_HYBRID_XS:
437 case EM2880_BOARD_KWORLD_DVB_310U: 480 case EM2880_BOARD_KWORLD_DVB_310U:
438 case EM2880_BOARD_EMPIRE_DUAL_TV: 481 case EM2880_BOARD_EMPIRE_DUAL_TV:
439 dvb->frontend = dvb_attach(zl10353_attach, 482 dvb->frontend = dvb_attach(zl10353_attach,
@@ -444,6 +487,33 @@ static int dvb_init(struct em28xx *dev)
444 goto out_free; 487 goto out_free;
445 } 488 }
446 break; 489 break;
490 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
491 dvb->frontend = dvb_attach(zl10353_attach,
492 &em28xx_zl10353_xc3028_no_i2c_gate,
493 &dev->i2c_adap);
494 if (attach_xc3028(0x61, dev) < 0) {
495 result = -EINVAL;
496 goto out_free;
497 }
498 break;
499 case EM2880_BOARD_TERRATEC_HYBRID_XS:
500 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
501 dvb->frontend = dvb_attach(zl10353_attach,
502 &em28xx_zl10353_xc3028_no_i2c_gate,
503 &dev->i2c_adap);
504 if (dvb->frontend == NULL) {
505 /* This board could have either a zl10353 or a mt352.
506 If the chip id isn't for zl10353, try mt352 */
507 dvb->frontend = dvb_attach(mt352_attach,
508 &terratec_xs_mt352_cfg,
509 &dev->i2c_adap);
510 }
511
512 if (attach_xc3028(0x61, dev) < 0) {
513 result = -EINVAL;
514 goto out_free;
515 }
516 break;
447 case EM2883_BOARD_KWORLD_HYBRID_330U: 517 case EM2883_BOARD_KWORLD_HYBRID_330U:
448 case EM2882_BOARD_EVGA_INDTUBE: 518 case EM2882_BOARD_EVGA_INDTUBE:
449 dvb->frontend = dvb_attach(s5h1409_attach, 519 dvb->frontend = dvb_attach(s5h1409_attach,
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 2c86fcf089f5..27e33a287dfc 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -483,7 +483,7 @@ static char *i2c_devs[128] = {
483 [0xa0 >> 1] = "eeprom", 483 [0xa0 >> 1] = "eeprom",
484 [0xb0 >> 1] = "tda9874", 484 [0xb0 >> 1] = "tda9874",
485 [0xb8 >> 1] = "tvp5150a", 485 [0xb8 >> 1] = "tvp5150a",
486 [0xba >> 1] = "tvp5150a", 486 [0xba >> 1] = "webcam sensor or tvp5150a",
487 [0xc0 >> 1] = "tuner (analog)", 487 [0xc0 >> 1] = "tuner (analog)",
488 [0xc2 >> 1] = "tuner (analog)", 488 [0xc2 >> 1] = "tuner (analog)",
489 [0xc4 >> 1] = "tuner (analog)", 489 [0xc4 >> 1] = "tuner (analog)",
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 8fe1beecfffa..ff37b4c15f44 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -90,10 +90,35 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
90/* supported video standards */ 90/* supported video standards */
91static struct em28xx_fmt format[] = { 91static struct em28xx_fmt format[] = {
92 { 92 {
93 .name = "16bpp YUY2, 4:2:2, packed", 93 .name = "16 bpp YUY2, 4:2:2, packed",
94 .fourcc = V4L2_PIX_FMT_YUYV, 94 .fourcc = V4L2_PIX_FMT_YUYV,
95 .depth = 16, 95 .depth = 16,
96 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, 96 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
97 }, {
98 .name = "16 bpp RGB 565, LE",
99 .fourcc = V4L2_PIX_FMT_RGB565,
100 .depth = 16,
101 .reg = EM28XX_OUTFMT_RGB_16_656,
102 }, {
103 .name = "8 bpp Bayer BGBG..GRGR",
104 .fourcc = V4L2_PIX_FMT_SBGGR8,
105 .depth = 8,
106 .reg = EM28XX_OUTFMT_RGB_8_BGBG,
107 }, {
108 .name = "8 bpp Bayer GRGR..BGBG",
109 .fourcc = V4L2_PIX_FMT_SGRBG8,
110 .depth = 8,
111 .reg = EM28XX_OUTFMT_RGB_8_GRGR,
112 }, {
113 .name = "8 bpp Bayer GBGB..RGRG",
114 .fourcc = V4L2_PIX_FMT_SGBRG8,
115 .depth = 8,
116 .reg = EM28XX_OUTFMT_RGB_8_GBGB,
117 }, {
118 .name = "12 bpp YUV411",
119 .fourcc = V4L2_PIX_FMT_YUV411P,
120 .depth = 12,
121 .reg = EM28XX_OUTFMT_YUV411,
97 }, 122 },
98}; 123};
99 124
@@ -632,8 +657,8 @@ static void get_scale(struct em28xx *dev,
632 unsigned int width, unsigned int height, 657 unsigned int width, unsigned int height,
633 unsigned int *hscale, unsigned int *vscale) 658 unsigned int *hscale, unsigned int *vscale)
634{ 659{
635 unsigned int maxw = norm_maxw(dev); 660 unsigned int maxw = norm_maxw(dev);
636 unsigned int maxh = norm_maxh(dev); 661 unsigned int maxh = norm_maxh(dev);
637 662
638 *hscale = (((unsigned long)maxw) << 12) / width - 4096L; 663 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
639 if (*hscale >= 0x4000) 664 if (*hscale >= 0x4000)
@@ -733,13 +758,34 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
733 return 0; 758 return 0;
734} 759}
735 760
761static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
762 unsigned width, unsigned height)
763{
764 struct em28xx_fmt *fmt;
765
766 fmt = format_by_fourcc(fourcc);
767 if (!fmt)
768 return -EINVAL;
769
770 dev->format = fmt;
771 dev->width = width;
772 dev->height = height;
773
774 /* set new image size */
775 get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
776
777 em28xx_set_alternate(dev);
778 em28xx_resolution_set(dev);
779
780 return 0;
781}
782
736static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, 783static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
737 struct v4l2_format *f) 784 struct v4l2_format *f)
738{ 785{
739 struct em28xx_fh *fh = priv; 786 struct em28xx_fh *fh = priv;
740 struct em28xx *dev = fh->dev; 787 struct em28xx *dev = fh->dev;
741 int rc; 788 int rc;
742 struct em28xx_fmt *fmt;
743 789
744 rc = check_dev(dev); 790 rc = check_dev(dev);
745 if (rc < 0) 791 if (rc < 0)
@@ -749,12 +795,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
749 795
750 vidioc_try_fmt_vid_cap(file, priv, f); 796 vidioc_try_fmt_vid_cap(file, priv, f);
751 797
752 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
753 if (!fmt) {
754 rc = -EINVAL;
755 goto out;
756 }
757
758 if (videobuf_queue_is_busy(&fh->vb_vidq)) { 798 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
759 em28xx_errdev("%s queue busy\n", __func__); 799 em28xx_errdev("%s queue busy\n", __func__);
760 rc = -EBUSY; 800 rc = -EBUSY;
@@ -767,16 +807,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
767 goto out; 807 goto out;
768 } 808 }
769 809
770 /* set new image size */ 810 rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
771 dev->width = f->fmt.pix.width; 811 f->fmt.pix.width, f->fmt.pix.height);
772 dev->height = f->fmt.pix.height;
773 dev->format = fmt;
774 get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
775
776 em28xx_set_alternate(dev);
777 em28xx_resolution_set(dev);
778
779 rc = 0;
780 812
781out: 813out:
782 mutex_unlock(&dev->lock); 814 mutex_unlock(&dev->lock);
@@ -1616,11 +1648,6 @@ static int em28xx_v4l2_open(struct file *filp)
1616 filp->private_data = fh; 1648 filp->private_data = fh;
1617 1649
1618 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { 1650 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
1619 dev->width = norm_maxw(dev);
1620 dev->height = norm_maxh(dev);
1621 dev->hscale = 0;
1622 dev->vscale = 0;
1623
1624 em28xx_set_mode(dev, EM28XX_ANALOG_MODE); 1651 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
1625 em28xx_set_alternate(dev); 1652 em28xx_set_alternate(dev);
1626 em28xx_resolution_set(dev); 1653 em28xx_resolution_set(dev);
@@ -1962,15 +1989,14 @@ int em28xx_register_analog_devices(struct em28xx *dev)
1962 1989
1963 /* set default norm */ 1990 /* set default norm */
1964 dev->norm = em28xx_video_template.current_norm; 1991 dev->norm = em28xx_video_template.current_norm;
1965 dev->width = norm_maxw(dev);
1966 dev->height = norm_maxh(dev);
1967 dev->interlaced = EM28XX_INTERLACED_DEFAULT; 1992 dev->interlaced = EM28XX_INTERLACED_DEFAULT;
1968 dev->hscale = 0;
1969 dev->vscale = 0;
1970 dev->ctl_input = 0; 1993 dev->ctl_input = 0;
1971 1994
1972 /* Analog specific initialization */ 1995 /* Analog specific initialization */
1973 dev->format = &format[0]; 1996 dev->format = &format[0];
1997 em28xx_set_video_format(dev, format[0].fourcc,
1998 norm_maxw(dev), norm_maxh(dev));
1999
1974 video_mux(dev, dev->ctl_input); 2000 video_mux(dev, dev->ctl_input);
1975 2001
1976 /* Audio defaults */ 2002 /* Audio defaults */
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 813ce45c2f99..45bd513f62dc 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -107,6 +107,7 @@
107#define EM2860_BOARD_TERRATEC_AV350 68 107#define EM2860_BOARD_TERRATEC_AV350 68
108#define EM2882_BOARD_KWORLD_ATSC_315U 69 108#define EM2882_BOARD_KWORLD_ATSC_315U 69
109#define EM2882_BOARD_EVGA_INDTUBE 70 109#define EM2882_BOARD_EVGA_INDTUBE 70
110#define EM2820_BOARD_SILVERCREST_WEBCAM 71
110 111
111/* Limits minimum and default number of buffers */ 112/* Limits minimum and default number of buffers */
112#define EM28XX_MIN_BUF 4 113#define EM28XX_MIN_BUF 4
@@ -357,11 +358,17 @@ struct em28xx_input {
357#define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) 358#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
358 359
359enum em28xx_decoder { 360enum em28xx_decoder {
360 EM28XX_NODECODER, 361 EM28XX_NODECODER = 0,
361 EM28XX_TVP5150, 362 EM28XX_TVP5150,
362 EM28XX_SAA711X, 363 EM28XX_SAA711X,
363}; 364};
364 365
366enum em28xx_sensor {
367 EM28XX_NOSENSOR = 0,
368 EM28XX_MT9V011,
369 EM28XX_MT9M001,
370};
371
365enum em28xx_adecoder { 372enum em28xx_adecoder {
366 EM28XX_NOADECODER = 0, 373 EM28XX_NOADECODER = 0,
367 EM28XX_TVAUDIO, 374 EM28XX_TVAUDIO,
@@ -388,6 +395,7 @@ struct em28xx_board {
388 unsigned int max_range_640_480:1; 395 unsigned int max_range_640_480:1;
389 unsigned int has_dvb:1; 396 unsigned int has_dvb:1;
390 unsigned int has_snapshot_button:1; 397 unsigned int has_snapshot_button:1;
398 unsigned int is_webcam:1;
391 unsigned int valid:1; 399 unsigned int valid:1;
392 400
393 unsigned char xclk, i2c_speed; 401 unsigned char xclk, i2c_speed;
@@ -471,6 +479,14 @@ struct em28xx {
471 struct v4l2_device v4l2_dev; 479 struct v4l2_device v4l2_dev;
472 struct em28xx_board board; 480 struct em28xx_board board;
473 481
482 /* Webcam specific fields */
483 enum em28xx_sensor em28xx_sensor;
484 int sensor_xres, sensor_yres;
485 int sensor_xtal;
486
487 /* Vinmode/Vinctl used at the driver */
488 int vinmode, vinctl;
489
474 unsigned int stream_on:1; /* Locks streams */ 490 unsigned int stream_on:1; /* Locks streams */
475 unsigned int has_audio_class:1; 491 unsigned int has_audio_class:1;
476 unsigned int has_alsa_audio:1; 492 unsigned int has_alsa_audio:1;
@@ -751,17 +767,23 @@ static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
751/*FIXME: maxw should be dependent of alt mode */ 767/*FIXME: maxw should be dependent of alt mode */
752static inline unsigned int norm_maxw(struct em28xx *dev) 768static inline unsigned int norm_maxw(struct em28xx *dev)
753{ 769{
770 if (dev->board.is_webcam)
771 return dev->sensor_xres;
772
754 if (dev->board.max_range_640_480) 773 if (dev->board.max_range_640_480)
755 return 640; 774 return 640;
756 else 775
757 return 720; 776 return 720;
758} 777}
759 778
760static inline unsigned int norm_maxh(struct em28xx *dev) 779static inline unsigned int norm_maxh(struct em28xx *dev)
761{ 780{
781 if (dev->board.is_webcam)
782 return dev->sensor_yres;
783
762 if (dev->board.max_range_640_480) 784 if (dev->board.max_range_640_480)
763 return 480; 785 return 480;
764 else 786
765 return (dev->norm & V4L2_STD_625_50) ? 576 : 480; 787 return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
766} 788}
767#endif 789#endif