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/em28xx-cards.c287
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c30
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c64
-rw-r--r--drivers/media/video/em28xx/em28xx-reg.h3
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c93
-rw-r--r--drivers/media/video/em28xx/em28xx.h34
6 files changed, 361 insertions, 150 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index ebd24a25fb85..ed281f565945 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -58,8 +58,6 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
58module_param_array(card, int, NULL, 0444); 58module_param_array(card, int, NULL, 0444);
59MODULE_PARM_DESC(card, "card type"); 59MODULE_PARM_DESC(card, "card type");
60 60
61#define MT9V011_VERSION 0x8243
62
63/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ 61/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
64static unsigned long em28xx_devused; 62static unsigned long em28xx_devused;
65 63
@@ -159,6 +157,20 @@ static struct em28xx_reg_seq evga_indtube_digital[] = {
159 { -1, -1, -1, -1}, 157 { -1, -1, -1, -1},
160}; 158};
161 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
162/* Callback for the most boards */ 174/* Callback for the most boards */
163static struct em28xx_reg_seq default_tuner_gpio[] = { 175static struct em28xx_reg_seq default_tuner_gpio[] = {
164 {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, 176 {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
@@ -205,13 +217,15 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = {
205 */ 217 */
206struct em28xx_board em28xx_boards[] = { 218struct em28xx_board em28xx_boards[] = {
207 [EM2750_BOARD_UNKNOWN] = { 219 [EM2750_BOARD_UNKNOWN] = {
208 .name = "Unknown EM2750/EM2751 webcam grabber", 220 .name = "EM2710/EM2750/EM2751 webcam grabber",
209 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, 221 .xclk = EM28XX_XCLK_FREQUENCY_20MHZ,
210 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 222 .tuner_type = TUNER_ABSENT,
223 .is_webcam = 1,
211 .input = { { 224 .input = { {
212 .type = EM28XX_VMUX_COMPOSITE1, 225 .type = EM28XX_VMUX_COMPOSITE1,
213 .vmux = 0, 226 .vmux = 0,
214 .amux = EM28XX_AMUX_VIDEO, 227 .amux = EM28XX_AMUX_VIDEO,
228 .gpio = silvercrest_reg_seq,
215 } }, 229 } },
216 }, 230 },
217 [EM2800_BOARD_UNKNOWN] = { 231 [EM2800_BOARD_UNKNOWN] = {
@@ -233,13 +247,15 @@ struct em28xx_board em28xx_boards[] = {
233 [EM2820_BOARD_UNKNOWN] = { 247 [EM2820_BOARD_UNKNOWN] = {
234 .name = "Unknown EM2750/28xx video grabber", 248 .name = "Unknown EM2750/28xx video grabber",
235 .tuner_type = TUNER_ABSENT, 249 .tuner_type = TUNER_ABSENT,
250 .is_webcam = 1, /* To enable sensor probe */
236 }, 251 },
237 [EM2750_BOARD_DLCW_130] = { 252 [EM2750_BOARD_DLCW_130] = {
238 /* Beijing Huaqi Information Digital Technology Co., Ltd */ 253 /* Beijing Huaqi Information Digital Technology Co., Ltd */
239 .name = "Huaqi DLCW-130", 254 .name = "Huaqi DLCW-130",
240 .valid = EM28XX_BOARD_NOT_VALIDATED, 255 .valid = EM28XX_BOARD_NOT_VALIDATED,
241 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, 256 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ,
242 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 257 .tuner_type = TUNER_ABSENT,
258 .is_webcam = 1,
243 .input = { { 259 .input = { {
244 .type = EM28XX_VMUX_COMPOSITE1, 260 .type = EM28XX_VMUX_COMPOSITE1,
245 .vmux = 0, 261 .vmux = 0,
@@ -440,7 +456,8 @@ struct em28xx_board em28xx_boards[] = {
440 [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { 456 [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
441 .name = "Videology 20K14XUSB USB2.0", 457 .name = "Videology 20K14XUSB USB2.0",
442 .valid = EM28XX_BOARD_NOT_VALIDATED, 458 .valid = EM28XX_BOARD_NOT_VALIDATED,
443 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 459 .tuner_type = TUNER_ABSENT,
460 .is_webcam = 1,
444 .input = { { 461 .input = { {
445 .type = EM28XX_VMUX_COMPOSITE1, 462 .type = EM28XX_VMUX_COMPOSITE1,
446 .vmux = 0, 463 .vmux = 0,
@@ -450,8 +467,7 @@ struct em28xx_board em28xx_boards[] = {
450 [EM2820_BOARD_SILVERCREST_WEBCAM] = { 467 [EM2820_BOARD_SILVERCREST_WEBCAM] = {
451 .name = "Silvercrest Webcam 1.3mpix", 468 .name = "Silvercrest Webcam 1.3mpix",
452 .tuner_type = TUNER_ABSENT, 469 .tuner_type = TUNER_ABSENT,
453 .is_27xx = 1, 470 .is_webcam = 1,
454 .decoder = EM28XX_MT9V011,
455 .input = { { 471 .input = { {
456 .type = EM28XX_VMUX_COMPOSITE1, 472 .type = EM28XX_VMUX_COMPOSITE1,
457 .vmux = 0, 473 .vmux = 0,
@@ -500,7 +516,8 @@ struct em28xx_board em28xx_boards[] = {
500 /* Beijing Huaqi Information Digital Technology Co., Ltd */ 516 /* Beijing Huaqi Information Digital Technology Co., Ltd */
501 .name = "NetGMBH Cam", 517 .name = "NetGMBH Cam",
502 .valid = EM28XX_BOARD_NOT_VALIDATED, 518 .valid = EM28XX_BOARD_NOT_VALIDATED,
503 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 519 .tuner_type = TUNER_ABSENT,
520 .is_webcam = 1,
504 .input = { { 521 .input = { {
505 .type = EM28XX_VMUX_COMPOSITE1, 522 .type = EM28XX_VMUX_COMPOSITE1,
506 .vmux = 0, 523 .vmux = 0,
@@ -605,22 +622,27 @@ struct em28xx_board em28xx_boards[] = {
605 }, 622 },
606 [EM2861_BOARD_PLEXTOR_PX_TV100U] = { 623 [EM2861_BOARD_PLEXTOR_PX_TV100U] = {
607 .name = "Plextor ConvertX PX-TV100U", 624 .name = "Plextor ConvertX PX-TV100U",
608 .valid = EM28XX_BOARD_NOT_VALIDATED,
609 .tuner_type = TUNER_TNF_5335MF, 625 .tuner_type = TUNER_TNF_5335MF,
626 .xclk = EM28XX_XCLK_I2S_MSB_TIMING |
627 EM28XX_XCLK_FREQUENCY_12MHZ,
610 .tda9887_conf = TDA9887_PRESENT, 628 .tda9887_conf = TDA9887_PRESENT,
611 .decoder = EM28XX_TVP5150, 629 .decoder = EM28XX_TVP5150,
630 .has_msp34xx = 1,
612 .input = { { 631 .input = { {
613 .type = EM28XX_VMUX_TELEVISION, 632 .type = EM28XX_VMUX_TELEVISION,
614 .vmux = TVP5150_COMPOSITE0, 633 .vmux = TVP5150_COMPOSITE0,
615 .amux = EM28XX_AMUX_LINE_IN, 634 .amux = EM28XX_AMUX_LINE_IN,
635 .gpio = pinnacle_hybrid_pro_analog,
616 }, { 636 }, {
617 .type = EM28XX_VMUX_COMPOSITE1, 637 .type = EM28XX_VMUX_COMPOSITE1,
618 .vmux = TVP5150_COMPOSITE1, 638 .vmux = TVP5150_COMPOSITE1,
619 .amux = EM28XX_AMUX_LINE_IN, 639 .amux = EM28XX_AMUX_LINE_IN,
640 .gpio = pinnacle_hybrid_pro_analog,
620 }, { 641 }, {
621 .type = EM28XX_VMUX_SVIDEO, 642 .type = EM28XX_VMUX_SVIDEO,
622 .vmux = TVP5150_SVIDEO, 643 .vmux = TVP5150_SVIDEO,
623 .amux = EM28XX_AMUX_LINE_IN, 644 .amux = EM28XX_AMUX_LINE_IN,
645 .gpio = pinnacle_hybrid_pro_analog,
624 } }, 646 } },
625 }, 647 },
626 648
@@ -1250,25 +1272,26 @@ struct em28xx_board em28xx_boards[] = {
1250 }, 1272 },
1251 [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { 1273 [EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
1252 .name = "Pinnacle Hybrid Pro", 1274 .name = "Pinnacle Hybrid Pro",
1253 .valid = EM28XX_BOARD_NOT_VALIDATED,
1254 .tuner_type = TUNER_XC2028, 1275 .tuner_type = TUNER_XC2028,
1255 .tuner_gpio = default_tuner_gpio, 1276 .tuner_gpio = default_tuner_gpio,
1256 .decoder = EM28XX_TVP5150, 1277 .decoder = EM28XX_TVP5150,
1278 .has_dvb = 1,
1279 .dvb_gpio = pinnacle_hybrid_pro_digital,
1257 .input = { { 1280 .input = { {
1258 .type = EM28XX_VMUX_TELEVISION, 1281 .type = EM28XX_VMUX_TELEVISION,
1259 .vmux = TVP5150_COMPOSITE0, 1282 .vmux = TVP5150_COMPOSITE0,
1260 .amux = EM28XX_AMUX_VIDEO, 1283 .amux = EM28XX_AMUX_VIDEO,
1261 .gpio = default_analog, 1284 .gpio = pinnacle_hybrid_pro_analog,
1262 }, { 1285 }, {
1263 .type = EM28XX_VMUX_COMPOSITE1, 1286 .type = EM28XX_VMUX_COMPOSITE1,
1264 .vmux = TVP5150_COMPOSITE1, 1287 .vmux = TVP5150_COMPOSITE1,
1265 .amux = EM28XX_AMUX_LINE_IN, 1288 .amux = EM28XX_AMUX_LINE_IN,
1266 .gpio = default_analog, 1289 .gpio = pinnacle_hybrid_pro_analog,
1267 }, { 1290 }, {
1268 .type = EM28XX_VMUX_SVIDEO, 1291 .type = EM28XX_VMUX_SVIDEO,
1269 .vmux = TVP5150_SVIDEO, 1292 .vmux = TVP5150_SVIDEO,
1270 .amux = EM28XX_AMUX_LINE_IN, 1293 .amux = EM28XX_AMUX_LINE_IN,
1271 .gpio = default_analog, 1294 .gpio = pinnacle_hybrid_pro_analog,
1272 } }, 1295 } },
1273 }, 1296 },
1274 [EM2882_BOARD_PINNACLE_HYBRID_PRO] = { 1297 [EM2882_BOARD_PINNACLE_HYBRID_PRO] = {
@@ -1526,6 +1549,8 @@ struct usb_device_id em28xx_id_table[] = {
1526 .driver_info = EM2750_BOARD_UNKNOWN }, 1549 .driver_info = EM2750_BOARD_UNKNOWN },
1527 { USB_DEVICE(0xeb1a, 0x2800), 1550 { USB_DEVICE(0xeb1a, 0x2800),
1528 .driver_info = EM2800_BOARD_UNKNOWN }, 1551 .driver_info = EM2800_BOARD_UNKNOWN },
1552 { USB_DEVICE(0xeb1a, 0x2710),
1553 .driver_info = EM2820_BOARD_UNKNOWN },
1529 { USB_DEVICE(0xeb1a, 0x2820), 1554 { USB_DEVICE(0xeb1a, 0x2820),
1530 .driver_info = EM2820_BOARD_UNKNOWN }, 1555 .driver_info = EM2820_BOARD_UNKNOWN },
1531 { USB_DEVICE(0xeb1a, 0x2821), 1556 { USB_DEVICE(0xeb1a, 0x2821),
@@ -1638,6 +1663,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = {
1638 {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, 1663 {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
1639 {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, 1664 {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
1640 {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, 1665 {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
1666 {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028},
1641}; 1667};
1642 1668
1643/* I2C devicelist hash table for devices with generic USB IDs */ 1669/* I2C devicelist hash table for devices with generic USB IDs */
@@ -1704,6 +1730,32 @@ static inline void em28xx_set_model(struct em28xx *dev)
1704 EM28XX_I2C_FREQ_100_KHZ; 1730 EM28XX_I2C_FREQ_100_KHZ;
1705} 1731}
1706 1732
1733/* FIXME: Should be replaced by a proper mt9m001 driver */
1734static int em28xx_initialize_mt9m001(struct em28xx *dev)
1735{
1736 int i;
1737 unsigned char regs[][3] = {
1738 { 0x0d, 0x00, 0x01, },
1739 { 0x0d, 0x00, 0x00, },
1740 { 0x04, 0x05, 0x00, }, /* hres = 1280 */
1741 { 0x03, 0x04, 0x00, }, /* vres = 1024 */
1742 { 0x20, 0x11, 0x00, },
1743 { 0x06, 0x00, 0x10, },
1744 { 0x2b, 0x00, 0x24, },
1745 { 0x2e, 0x00, 0x24, },
1746 { 0x35, 0x00, 0x24, },
1747 { 0x2d, 0x00, 0x20, },
1748 { 0x2c, 0x00, 0x20, },
1749 { 0x09, 0x0a, 0xd4, },
1750 { 0x35, 0x00, 0x57, },
1751 };
1752
1753 for (i = 0; i < ARRAY_SIZE(regs); i++)
1754 i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
1755
1756 return 0;
1757}
1758
1707/* HINT method: webcam I2C chips 1759/* HINT method: webcam I2C chips
1708 * 1760 *
1709 * This method work for webcams with Micron sensors 1761 * This method work for webcams with Micron sensors
@@ -1716,9 +1768,7 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1716 __be16 version_be; 1768 __be16 version_be;
1717 u16 version; 1769 u16 version;
1718 1770
1719 if (dev->model != EM2820_BOARD_UNKNOWN) 1771 /* Micron sensor detection */
1720 return 0;
1721
1722 dev->i2c_client.addr = 0xba >> 1; 1772 dev->i2c_client.addr = 0xba >> 1;
1723 cmd = 0; 1773 cmd = 0;
1724 i2c_master_send(&dev->i2c_client, &cmd, 1); 1774 i2c_master_send(&dev->i2c_client, &cmd, 1);
@@ -1727,18 +1777,57 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1727 return -EINVAL; 1777 return -EINVAL;
1728 1778
1729 version = be16_to_cpu(version_be); 1779 version = be16_to_cpu(version_be);
1730
1731 switch (version) { 1780 switch (version) {
1732 case MT9V011_VERSION: 1781 case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */
1782 case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */
1733 dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; 1783 dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
1784 em28xx_set_model(dev);
1785
1734 sensor_name = "mt9v011"; 1786 sensor_name = "mt9v011";
1787 dev->em28xx_sensor = EM28XX_MT9V011;
1788 dev->sensor_xres = 640;
1789 dev->sensor_yres = 480;
1790 /*
1791 * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
1792 * the Silvercrest cam I have here for testing - for higher
1793 * resolutions, a high clock cause horizontal artifacts, so we
1794 * need to use a lower xclk frequency.
1795 * Yet, it would be possible to adjust xclk depending on the
1796 * desired resolution, since this affects directly the
1797 * frame rate.
1798 */
1799 dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
1800 dev->sensor_xtal = 4300000;
1801
1802 /* probably means GRGB 16 bit bayer */
1803 dev->vinmode = 0x0d;
1804 dev->vinctl = 0x00;
1805
1806 break;
1807 case 0x8431:
1808 dev->model = EM2750_BOARD_UNKNOWN;
1809 em28xx_set_model(dev);
1810
1811 sensor_name = "mt9m001";
1812 dev->em28xx_sensor = EM28XX_MT9M001;
1813 em28xx_initialize_mt9m001(dev);
1814 dev->sensor_xres = 1280;
1815 dev->sensor_yres = 1024;
1816
1817 /* probably means BGGR 16 bit bayer */
1818 dev->vinmode = 0x0c;
1819 dev->vinctl = 0x00;
1820
1735 break; 1821 break;
1736 default: 1822 default:
1737 printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version)); 1823 printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version));
1738 return -EINVAL; 1824 return -EINVAL;
1739 } 1825 }
1740 1826
1741 em28xx_errdev("Sensor is %s, assuming that webcam is %s\n", 1827 /* Setup webcam defaults */
1828 em28xx_pre_card_setup(dev);
1829
1830 em28xx_errdev("Sensor is %s, using model %s entry.\n",
1742 sensor_name, em28xx_boards[dev->model].name); 1831 sensor_name, em28xx_boards[dev->model].name);
1743 1832
1744 return 0; 1833 return 0;
@@ -1749,63 +1838,6 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1749 */ 1838 */
1750void em28xx_pre_card_setup(struct em28xx *dev) 1839void em28xx_pre_card_setup(struct em28xx *dev)
1751{ 1840{
1752 int rc;
1753
1754 em28xx_set_model(dev);
1755
1756 em28xx_info("Identified as %s (card=%d)\n",
1757 dev->board.name, dev->model);
1758
1759 /* Set the default GPO/GPIO for legacy devices */
1760 dev->reg_gpo_num = EM2880_R04_GPO;
1761 dev->reg_gpio_num = EM28XX_R08_GPIO;
1762
1763 dev->wait_after_write = 5;
1764
1765 /* Based on the Chip ID, set the device configuration */
1766 rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
1767 if (rc > 0) {
1768 dev->chip_id = rc;
1769
1770 switch (dev->chip_id) {
1771 case CHIP_ID_EM2750:
1772 em28xx_info("chip ID is em2750\n");
1773 break;
1774 case CHIP_ID_EM2820:
1775 if (dev->board.is_27xx)
1776 em28xx_info("chip is em2710\n");
1777 else
1778 em28xx_info("chip ID is em2820\n");
1779 break;
1780 case CHIP_ID_EM2840:
1781 em28xx_info("chip ID is em2840\n");
1782 break;
1783 case CHIP_ID_EM2860:
1784 em28xx_info("chip ID is em2860\n");
1785 break;
1786 case CHIP_ID_EM2870:
1787 em28xx_info("chip ID is em2870\n");
1788 dev->wait_after_write = 0;
1789 break;
1790 case CHIP_ID_EM2874:
1791 em28xx_info("chip ID is em2874\n");
1792 dev->reg_gpio_num = EM2874_R80_GPIO;
1793 dev->wait_after_write = 0;
1794 break;
1795 case CHIP_ID_EM2883:
1796 em28xx_info("chip ID is em2882/em2883\n");
1797 dev->wait_after_write = 0;
1798 break;
1799 default:
1800 em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
1801 }
1802 }
1803
1804 /* Prepopulate cached GPO register content */
1805 rc = em28xx_read_reg(dev, dev->reg_gpo_num);
1806 if (rc >= 0)
1807 dev->reg_gpo = rc;
1808
1809 /* Set the initial XCLK and I2C clock values based on the board 1841 /* Set the initial XCLK and I2C clock values based on the board
1810 definition */ 1842 definition */
1811 em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); 1843 em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
@@ -1815,9 +1847,8 @@ void em28xx_pre_card_setup(struct em28xx *dev)
1815 /* request some modules */ 1847 /* request some modules */
1816 switch (dev->model) { 1848 switch (dev->model) {
1817 case EM2861_BOARD_PLEXTOR_PX_TV100U: 1849 case EM2861_BOARD_PLEXTOR_PX_TV100U:
1818 /* FIXME guess */ 1850 /* Sets the msp34xx I2S speed */
1819 /* Turn on analog audio output */ 1851 dev->i2s_speed = 2048000;
1820 em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
1821 break; 1852 break;
1822 case EM2861_BOARD_KWORLD_PVRTV_300U: 1853 case EM2861_BOARD_KWORLD_PVRTV_300U:
1823 case EM2880_BOARD_KWORLD_DVB_305U: 1854 case EM2880_BOARD_KWORLD_DVB_305U:
@@ -1929,6 +1960,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
1929 ctl->demod = XC3028_FE_ZARLINK456; 1960 ctl->demod = XC3028_FE_ZARLINK456;
1930 break; 1961 break;
1931 case EM2880_BOARD_TERRATEC_HYBRID_XS: 1962 case EM2880_BOARD_TERRATEC_HYBRID_XS:
1963 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
1932 ctl->demod = XC3028_FE_ZARLINK456; 1964 ctl->demod = XC3028_FE_ZARLINK456;
1933 break; 1965 break;
1934 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 1966 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
@@ -2154,7 +2186,20 @@ void em28xx_register_i2c_ir(struct em28xx *dev)
2154 2186
2155void em28xx_card_setup(struct em28xx *dev) 2187void em28xx_card_setup(struct em28xx *dev)
2156{ 2188{
2157 em28xx_set_model(dev); 2189 /*
2190 * If the device can be a webcam, seek for a sensor.
2191 * If sensor is not found, then it isn't a webcam.
2192 */
2193 if (dev->board.is_webcam) {
2194 if (em28xx_hint_sensor(dev) < 0)
2195 dev->board.is_webcam = 0;
2196 else
2197 dev->progressive = 1;
2198 } else
2199 em28xx_set_model(dev);
2200
2201 em28xx_info("Identified as %s (card=%d)\n",
2202 dev->board.name, dev->model);
2158 2203
2159 dev->tuner_type = em28xx_boards[dev->model].tuner_type; 2204 dev->tuner_type = em28xx_boards[dev->model].tuner_type;
2160 if (em28xx_boards[dev->model].tuner_addr) 2205 if (em28xx_boards[dev->model].tuner_addr)
@@ -2225,12 +2270,9 @@ void em28xx_card_setup(struct em28xx *dev)
2225 em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, 2270 em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
2226 so make the call now so the analog GPIOs are set properly 2271 so make the call now so the analog GPIOs are set properly
2227 before probing the i2c bus. */ 2272 before probing the i2c bus. */
2273 em28xx_gpio_set(dev, dev->board.tuner_gpio);
2228 em28xx_set_mode(dev, EM28XX_ANALOG_MODE); 2274 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
2229 break; 2275 break;
2230 case EM2820_BOARD_SILVERCREST_WEBCAM:
2231 /* FIXME: need to document the registers bellow */
2232 em28xx_write_reg(dev, 0x0d, 0x42);
2233 em28xx_write_reg(dev, 0x13, 0x08);
2234 } 2276 }
2235 2277
2236 if (dev->board.has_snapshot_button) 2278 if (dev->board.has_snapshot_button)
@@ -2262,9 +2304,14 @@ void em28xx_card_setup(struct em28xx *dev)
2262 v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, 2304 v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
2263 "tvp5150", "tvp5150", tvp5150_addrs); 2305 "tvp5150", "tvp5150", tvp5150_addrs);
2264 2306
2265 if (dev->board.decoder == EM28XX_MT9V011) 2307 if (dev->em28xx_sensor == EM28XX_MT9V011) {
2266 v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, 2308 struct v4l2_subdev *sd;
2267 "mt9v011", "mt9v011", mt9v011_addrs); 2309
2310 sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev,
2311 &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs);
2312 v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal);
2313 }
2314
2268 2315
2269 if (dev->board.adecoder == EM28XX_TVAUDIO) 2316 if (dev->board.adecoder == EM28XX_TVAUDIO)
2270 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, 2317 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
@@ -2365,7 +2412,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
2365 int minor) 2412 int minor)
2366{ 2413{
2367 struct em28xx *dev = *devhandle; 2414 struct em28xx *dev = *devhandle;
2368 int retval = -ENOMEM; 2415 int retval;
2369 int errCode; 2416 int errCode;
2370 2417
2371 dev->udev = udev; 2418 dev->udev = udev;
@@ -2382,6 +2429,58 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
2382 dev->em28xx_read_reg_req = em28xx_read_reg_req; 2429 dev->em28xx_read_reg_req = em28xx_read_reg_req;
2383 dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; 2430 dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800;
2384 2431
2432 em28xx_set_model(dev);
2433
2434 /* Set the default GPO/GPIO for legacy devices */
2435 dev->reg_gpo_num = EM2880_R04_GPO;
2436 dev->reg_gpio_num = EM28XX_R08_GPIO;
2437
2438 dev->wait_after_write = 5;
2439
2440 /* Based on the Chip ID, set the device configuration */
2441 retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
2442 if (retval > 0) {
2443 dev->chip_id = retval;
2444
2445 switch (dev->chip_id) {
2446 case CHIP_ID_EM2710:
2447 em28xx_info("chip ID is em2710\n");
2448 break;
2449 case CHIP_ID_EM2750:
2450 em28xx_info("chip ID is em2750\n");
2451 break;
2452 case CHIP_ID_EM2820:
2453 em28xx_info("chip ID is em2820 (or em2710)\n");
2454 break;
2455 case CHIP_ID_EM2840:
2456 em28xx_info("chip ID is em2840\n");
2457 break;
2458 case CHIP_ID_EM2860:
2459 em28xx_info("chip ID is em2860\n");
2460 break;
2461 case CHIP_ID_EM2870:
2462 em28xx_info("chip ID is em2870\n");
2463 dev->wait_after_write = 0;
2464 break;
2465 case CHIP_ID_EM2874:
2466 em28xx_info("chip ID is em2874\n");
2467 dev->reg_gpio_num = EM2874_R80_GPIO;
2468 dev->wait_after_write = 0;
2469 break;
2470 case CHIP_ID_EM2883:
2471 em28xx_info("chip ID is em2882/em2883\n");
2472 dev->wait_after_write = 0;
2473 break;
2474 default:
2475 em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
2476 }
2477 }
2478
2479 /* Prepopulate cached GPO register content */
2480 retval = em28xx_read_reg(dev, dev->reg_gpo_num);
2481 if (retval >= 0)
2482 dev->reg_gpo = retval;
2483
2385 em28xx_pre_card_setup(dev); 2484 em28xx_pre_card_setup(dev);
2386 2485
2387 if (!dev->board.is_em2800) { 2486 if (!dev->board.is_em2800) {
@@ -2410,7 +2509,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
2410 return errCode; 2509 return errCode;
2411 } 2510 }
2412 2511
2413 em28xx_hint_sensor(dev); 2512 /*
2513 * Default format, used for tvp5150 or saa711x output formats
2514 */
2515 dev->vinmode = 0x10;
2516 dev->vinctl = 0x11;
2414 2517
2415 /* Do board specific init and eeprom reading */ 2518 /* Do board specific init and eeprom reading */
2416 em28xx_card_setup(dev); 2519 em28xx_card_setup(dev);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 079ab4d563a6..98e140b5d95e 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -632,6 +632,9 @@ int em28xx_capture_start(struct em28xx *dev, int start)
632 return rc; 632 return rc;
633 } 633 }
634 634
635 if (dev->board.is_webcam)
636 rc = em28xx_write_reg(dev, 0x13, 0x0c);
637
635 /* enable video capture */ 638 /* enable video capture */
636 rc = em28xx_write_reg(dev, 0x48, 0x00); 639 rc = em28xx_write_reg(dev, 0x48, 0x00);
637 640
@@ -648,28 +651,17 @@ int em28xx_capture_start(struct em28xx *dev, int start)
648int em28xx_set_outfmt(struct em28xx *dev) 651int em28xx_set_outfmt(struct em28xx *dev)
649{ 652{
650 int ret; 653 int ret;
651 int vinmode, vinctl, outfmt;
652
653 outfmt = dev->format->reg;
654
655 if (dev->board.is_27xx) {
656 vinmode = 0x0d;
657 vinctl = 0x00;
658 } else {
659 vinmode = 0x10;
660 vinctl = 0x11;
661 }
662 654
663 ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, 655 ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
664 outfmt | 0x20, 0xff); 656 dev->format->reg | 0x20, 0xff);
665 if (ret < 0) 657 if (ret < 0)
666 return ret; 658 return ret;
667 659
668 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); 660 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
669 if (ret < 0) 661 if (ret < 0)
670 return ret; 662 return ret;
671 663
672 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); 664 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl);
673} 665}
674 666
675static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, 667static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
@@ -707,10 +699,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
707 u8 mode; 699 u8 mode;
708 /* the em2800 scaler only supports scaling down to 50% */ 700 /* the em2800 scaler only supports scaling down to 50% */
709 701
710 if (dev->board.is_27xx) { 702 if (dev->board.is_em2800) {
711 /* FIXME: Don't use the scaler yet */
712 mode = 0;
713 } else if (dev->board.is_em2800) {
714 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); 703 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
715 } else { 704 } else {
716 u8 buf[2]; 705 u8 buf[2];
@@ -734,7 +723,10 @@ int em28xx_resolution_set(struct em28xx *dev)
734{ 723{
735 int width, height; 724 int width, height;
736 width = norm_maxw(dev); 725 width = norm_maxw(dev);
737 height = norm_maxh(dev) >> 1; 726 height = norm_maxh(dev);
727
728 if (!dev->progressive)
729 height >>= norm_maxh(dev);
738 730
739 em28xx_set_outfmt(dev); 731 em28xx_set_outfmt(dev);
740 732
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 3da97c32b8fa..d603575431b4 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,7 +245,7 @@ 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
246static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = { 248static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
247 .demod_address = (0x1e >> 1), 249 .demod_address = (0x1e >> 1),
248 .no_tuner = 1, 250 .no_tuner = 1,
249 .disable_i2c_gate_ctrl = 1, 251 .disable_i2c_gate_ctrl = 1,
@@ -258,6 +260,41 @@ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
258}; 260};
259#endif 261#endif
260 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
261/* ------------------------------------------------------------------ */ 298/* ------------------------------------------------------------------ */
262 299
263static int attach_xc3028(u8 addr, struct em28xx *dev) 300static int attach_xc3028(u8 addr, struct em28xx *dev)
@@ -440,9 +477,7 @@ static int dvb_init(struct em28xx *dev)
440 goto out_free; 477 goto out_free;
441 } 478 }
442 break; 479 break;
443 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
444 case EM2880_BOARD_KWORLD_DVB_310U: 480 case EM2880_BOARD_KWORLD_DVB_310U:
445 case EM2880_BOARD_EMPIRE_DUAL_TV:
446 dvb->frontend = dvb_attach(zl10353_attach, 481 dvb->frontend = dvb_attach(zl10353_attach,
447 &em28xx_zl10353_with_xc3028, 482 &em28xx_zl10353_with_xc3028,
448 &dev->i2c_adap); 483 &dev->i2c_adap);
@@ -451,20 +486,29 @@ static int dvb_init(struct em28xx *dev)
451 goto out_free; 486 goto out_free;
452 } 487 }
453 break; 488 break;
489 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
490 case EM2880_BOARD_EMPIRE_DUAL_TV:
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;
454 case EM2880_BOARD_TERRATEC_HYBRID_XS: 499 case EM2880_BOARD_TERRATEC_HYBRID_XS:
500 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
455 dvb->frontend = dvb_attach(zl10353_attach, 501 dvb->frontend = dvb_attach(zl10353_attach,
456 &em28xx_terratec_xs_zl10353_xc3028, 502 &em28xx_zl10353_xc3028_no_i2c_gate,
457 &dev->i2c_adap); 503 &dev->i2c_adap);
458 if (dvb->frontend == NULL) { 504 if (dvb->frontend == NULL) {
459 /* This board could have either a zl10353 or a mt352. 505 /* This board could have either a zl10353 or a mt352.
460 If the chip id isn't for zl10353, try mt352 */ 506 If the chip id isn't for zl10353, try mt352 */
461 507 dvb->frontend = dvb_attach(mt352_attach,
462 /* FIXME: make support for mt352 work */ 508 &terratec_xs_mt352_cfg,
463 printk(KERN_ERR "version of this board with mt352 not " 509 &dev->i2c_adap);
464 "currently supported\n");
465 result = -EINVAL;
466 goto out_free;
467 } 510 }
511
468 if (attach_xc3028(0x61, dev) < 0) { 512 if (attach_xc3028(0x61, dev) < 0) {
469 result = -EINVAL; 513 result = -EINVAL;
470 goto out_free; 514 goto out_free;
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
index a2676d63cfd0..6bf84bd787df 100644
--- a/drivers/media/video/em28xx/em28xx-reg.h
+++ b/drivers/media/video/em28xx/em28xx-reg.h
@@ -176,7 +176,8 @@
176 176
177/* FIXME: Need to be populated with the other chip ID's */ 177/* FIXME: Need to be populated with the other chip ID's */
178enum em28xx_chip_id { 178enum em28xx_chip_id {
179 CHIP_ID_EM2820 = 18, /* Also used by em2710 */ 179 CHIP_ID_EM2710 = 17,
180 CHIP_ID_EM2820 = 18, /* Also used by some em2710 */
180 CHIP_ID_EM2840 = 20, 181 CHIP_ID_EM2840 = 20,
181 CHIP_ID_EM2750 = 33, 182 CHIP_ID_EM2750 = 33,
182 CHIP_ID_EM2860 = 34, 183 CHIP_ID_EM2860 = 34,
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 14316c912179..ab079d9256c4 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -194,15 +194,24 @@ static void em28xx_copy_video(struct em28xx *dev,
194 startread = p; 194 startread = p;
195 remain = len; 195 remain = len;
196 196
197 /* Interlaces frame */ 197 if (dev->progressive)
198 if (buf->top_field)
199 fieldstart = outp; 198 fieldstart = outp;
200 else 199 else {
201 fieldstart = outp + bytesperline; 200 /* Interlaces two half frames */
201 if (buf->top_field)
202 fieldstart = outp;
203 else
204 fieldstart = outp + bytesperline;
205 }
202 206
203 linesdone = dma_q->pos / bytesperline; 207 linesdone = dma_q->pos / bytesperline;
204 currlinedone = dma_q->pos % bytesperline; 208 currlinedone = dma_q->pos % bytesperline;
205 offset = linesdone * bytesperline * 2 + currlinedone; 209
210 if (dev->progressive)
211 offset = linesdone * bytesperline + currlinedone;
212 else
213 offset = linesdone * bytesperline * 2 + currlinedone;
214
206 startwrite = fieldstart + offset; 215 startwrite = fieldstart + offset;
207 lencopy = bytesperline - currlinedone; 216 lencopy = bytesperline - currlinedone;
208 lencopy = lencopy > remain ? remain : lencopy; 217 lencopy = lencopy > remain ? remain : lencopy;
@@ -376,7 +385,7 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
376 em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], 385 em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
377 len, (p[2] & 1) ? "odd" : "even"); 386 len, (p[2] & 1) ? "odd" : "even");
378 387
379 if (!(p[2] & 1)) { 388 if (dev->progressive || !(p[2] & 1)) {
380 if (buf != NULL) 389 if (buf != NULL)
381 buffer_filled(dev, dma_q, buf); 390 buffer_filled(dev, dma_q, buf);
382 get_next_buf(dma_q, &buf); 391 get_next_buf(dma_q, &buf);
@@ -657,8 +666,8 @@ static void get_scale(struct em28xx *dev,
657 unsigned int width, unsigned int height, 666 unsigned int width, unsigned int height,
658 unsigned int *hscale, unsigned int *vscale) 667 unsigned int *hscale, unsigned int *vscale)
659{ 668{
660 unsigned int maxw = norm_maxw(dev); 669 unsigned int maxw = norm_maxw(dev);
661 unsigned int maxh = norm_maxh(dev); 670 unsigned int maxh = norm_maxh(dev);
662 671
663 *hscale = (((unsigned long)maxw) << 12) / width - 4096L; 672 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
664 if (*hscale >= 0x4000) 673 if (*hscale >= 0x4000)
@@ -689,7 +698,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
689 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 698 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
690 699
691 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ 700 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
692 f->fmt.pix.field = dev->interlaced ? 701 if (dev->progressive)
702 f->fmt.pix.field = V4L2_FIELD_NONE;
703 else
704 f->fmt.pix.field = dev->interlaced ?
693 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; 705 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
694 706
695 mutex_unlock(&dev->lock); 707 mutex_unlock(&dev->lock);
@@ -726,11 +738,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
726 return -EINVAL; 738 return -EINVAL;
727 } 739 }
728 740
729 if (dev->board.is_27xx) { 741 if (dev->board.is_em2800) {
730 /* FIXME: This is the only supported fmt */
731 width = 640;
732 height = 480;
733 } else if (dev->board.is_em2800) {
734 /* the em2800 can only scale down to 50% */ 742 /* the em2800 can only scale down to 50% */
735 height = height > (3 * maxh / 4) ? maxh : maxh / 2; 743 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
736 width = width > (3 * maxw / 4) ? maxw : maxw / 2; 744 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
@@ -757,7 +765,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
757 f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; 765 f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
758 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; 766 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
759 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 767 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
760 f->fmt.pix.field = V4L2_FIELD_INTERLACED; 768 if (dev->progressive)
769 f->fmt.pix.field = V4L2_FIELD_NONE;
770 else
771 f->fmt.pix.field = dev->interlaced ?
772 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
761 773
762 return 0; 774 return 0;
763} 775}
@@ -767,12 +779,6 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
767{ 779{
768 struct em28xx_fmt *fmt; 780 struct em28xx_fmt *fmt;
769 781
770 /* FIXME: This is the only supported fmt */
771 if (dev->board.is_27xx) {
772 width = 640;
773 height = 480;
774 }
775
776 fmt = format_by_fourcc(fourcc); 782 fmt = format_by_fourcc(fourcc);
777 if (!fmt) 783 if (!fmt)
778 return -EINVAL; 784 return -EINVAL;
@@ -856,6 +862,41 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
856 return 0; 862 return 0;
857} 863}
858 864
865static int vidioc_g_parm(struct file *file, void *priv,
866 struct v4l2_streamparm *p)
867{
868 struct em28xx_fh *fh = priv;
869 struct em28xx *dev = fh->dev;
870 int rc = 0;
871
872 if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
873 return -EINVAL;
874
875 if (dev->board.is_webcam)
876 rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
877 video, g_parm, p);
878 else
879 v4l2_video_std_frame_period(dev->norm,
880 &p->parm.capture.timeperframe);
881
882 return rc;
883}
884
885static int vidioc_s_parm(struct file *file, void *priv,
886 struct v4l2_streamparm *p)
887{
888 struct em28xx_fh *fh = priv;
889 struct em28xx *dev = fh->dev;
890
891 if (!dev->board.is_webcam)
892 return -EINVAL;
893
894 if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
895 return -EINVAL;
896
897 return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
898}
899
859static const char *iname[] = { 900static const char *iname[] = {
860 [EM28XX_VMUX_COMPOSITE1] = "Composite1", 901 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
861 [EM28XX_VMUX_COMPOSITE2] = "Composite2", 902 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
@@ -1634,6 +1675,7 @@ static int em28xx_v4l2_open(struct file *filp)
1634 struct em28xx *dev; 1675 struct em28xx *dev;
1635 enum v4l2_buf_type fh_type; 1676 enum v4l2_buf_type fh_type;
1636 struct em28xx_fh *fh; 1677 struct em28xx_fh *fh;
1678 enum v4l2_field field;
1637 1679
1638 dev = em28xx_get_device(minor, &fh_type, &radio); 1680 dev = em28xx_get_device(minor, &fh_type, &radio);
1639 1681
@@ -1675,8 +1717,13 @@ static int em28xx_v4l2_open(struct file *filp)
1675 1717
1676 dev->users++; 1718 dev->users++;
1677 1719
1720 if (dev->progressive)
1721 field = V4L2_FIELD_NONE;
1722 else
1723 field = V4L2_FIELD_INTERLACED;
1724
1678 videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, 1725 videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
1679 NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, 1726 NULL, &dev->slock, fh->type, field,
1680 sizeof(struct em28xx_buffer), fh); 1727 sizeof(struct em28xx_buffer), fh);
1681 1728
1682 mutex_unlock(&dev->lock); 1729 mutex_unlock(&dev->lock);
@@ -1895,6 +1942,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
1895 .vidioc_qbuf = vidioc_qbuf, 1942 .vidioc_qbuf = vidioc_qbuf,
1896 .vidioc_dqbuf = vidioc_dqbuf, 1943 .vidioc_dqbuf = vidioc_dqbuf,
1897 .vidioc_s_std = vidioc_s_std, 1944 .vidioc_s_std = vidioc_s_std,
1945 .vidioc_g_parm = vidioc_g_parm,
1946 .vidioc_s_parm = vidioc_s_parm,
1898 .vidioc_enum_input = vidioc_enum_input, 1947 .vidioc_enum_input = vidioc_enum_input,
1899 .vidioc_g_input = vidioc_g_input, 1948 .vidioc_g_input = vidioc_g_input,
1900 .vidioc_s_input = vidioc_s_input, 1949 .vidioc_s_input = vidioc_s_input,
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index d90fef463764..8c2dc38bca9f 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -358,10 +358,15 @@ struct em28xx_input {
358#define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) 358#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
359 359
360enum em28xx_decoder { 360enum em28xx_decoder {
361 EM28XX_NODECODER, 361 EM28XX_NODECODER = 0,
362 EM28XX_TVP5150, 362 EM28XX_TVP5150,
363 EM28XX_SAA711X, 363 EM28XX_SAA711X,
364};
365
366enum em28xx_sensor {
367 EM28XX_NOSENSOR = 0,
364 EM28XX_MT9V011, 368 EM28XX_MT9V011,
369 EM28XX_MT9M001,
365}; 370};
366 371
367enum em28xx_adecoder { 372enum em28xx_adecoder {
@@ -390,7 +395,7 @@ struct em28xx_board {
390 unsigned int max_range_640_480:1; 395 unsigned int max_range_640_480:1;
391 unsigned int has_dvb:1; 396 unsigned int has_dvb:1;
392 unsigned int has_snapshot_button:1; 397 unsigned int has_snapshot_button:1;
393 unsigned int is_27xx:1; 398 unsigned int is_webcam:1;
394 unsigned int valid:1; 399 unsigned int valid:1;
395 400
396 unsigned char xclk, i2c_speed; 401 unsigned char xclk, i2c_speed;
@@ -474,6 +479,17 @@ struct em28xx {
474 struct v4l2_device v4l2_dev; 479 struct v4l2_device v4l2_dev;
475 struct em28xx_board board; 480 struct em28xx_board board;
476 481
482 /* Webcam specific fields */
483 enum em28xx_sensor em28xx_sensor;
484 int sensor_xres, sensor_yres;
485 int sensor_xtal;
486
487 /* Allows progressive (e. g. non-interlaced) mode */
488 int progressive;
489
490 /* Vinmode/Vinctl used at the driver */
491 int vinmode, vinctl;
492
477 unsigned int stream_on:1; /* Locks streams */ 493 unsigned int stream_on:1; /* Locks streams */
478 unsigned int has_audio_class:1; 494 unsigned int has_audio_class:1;
479 unsigned int has_alsa_audio:1; 495 unsigned int has_alsa_audio:1;
@@ -754,17 +770,23 @@ static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
754/*FIXME: maxw should be dependent of alt mode */ 770/*FIXME: maxw should be dependent of alt mode */
755static inline unsigned int norm_maxw(struct em28xx *dev) 771static inline unsigned int norm_maxw(struct em28xx *dev)
756{ 772{
773 if (dev->board.is_webcam)
774 return dev->sensor_xres;
775
757 if (dev->board.max_range_640_480) 776 if (dev->board.max_range_640_480)
758 return 640; 777 return 640;
759 else 778
760 return 720; 779 return 720;
761} 780}
762 781
763static inline unsigned int norm_maxh(struct em28xx *dev) 782static inline unsigned int norm_maxh(struct em28xx *dev)
764{ 783{
784 if (dev->board.is_webcam)
785 return dev->sensor_yres;
786
765 if (dev->board.max_range_640_480) 787 if (dev->board.max_range_640_480)
766 return 480; 788 return 480;
767 else 789
768 return (dev->norm & V4L2_STD_625_50) ? 576 : 480; 790 return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
769} 791}
770#endif 792#endif