aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-08-10 09:29:27 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-08-13 19:39:10 -0400
commit3d3215c4e4cfca74e5805a8506d50a6752172e81 (patch)
tree281fee715a781ba21a86eca9a2a4d7256d3cf1d1
parentfcd20e3c369caf7a3fec300c9c183b25a06e21b2 (diff)
V4L/DVB (12411): em28xx: Fix artifacts with Silvercrest webcam
Silvercrest mt9v011 sensor produces a 640x480 image. However, previously, the code were getting only half of the lines and merging two consecutive frames to "produce" a 640x480 image. With the addition of progressive mode, now em28xx is working with a full image. However, when the number of lines is bigger than 240, the beginning of some odd lines are filled with blank. After lots of testing, and physically checking the device for a Xtal, it was noticed experimentally that mt9v011 is using em28xx XCLK as its clock. Due to that, changing XCLK value changes the maximum speed of the stream. At the tests, it were possible to produce up to 32 fps, using a 30 MHz XCLK. However, at that rate, the artifacts happen even at 320x240. Lower values of XCLK produces artifacts only at 640x480. At some values of xclk (for example XCLKK = 6 MHz, 640x480), it is possible to see an invalid sucession of artifacts with this pattern: .xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx .xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (where the dots represent the blanked pixels) So, it seems that a waveform in the format of a ramp is interferring at the image. The cause of this interference is currently unknown. Some possibilities are: - electrical interference (maybe this device is broken?); - some issue at mt9v011 programming; - some bug at em28xx chip. So, for now, let's be conservative and use a value of XCLK that we know for sure that it won't cause artifacts. As I'm waiting for more of such devices with different em28xx chipset revisions, I'll have the opportunity to double check the issue with other pieces of hardware. Later patches can vary XCLK depending on the vertical resolutions, if a proper fix is not discovered. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 6b2b5d3e2fad..54429b629b2d 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -218,7 +218,7 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = {
218struct em28xx_board em28xx_boards[] = { 218struct em28xx_board em28xx_boards[] = {
219 [EM2750_BOARD_UNKNOWN] = { 219 [EM2750_BOARD_UNKNOWN] = {
220 .name = "EM2710/EM2750/EM2751 webcam grabber", 220 .name = "EM2710/EM2750/EM2751 webcam grabber",
221 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, 221 .xclk = EM28XX_XCLK_FREQUENCY_20MHZ,
222 .tuner_type = TUNER_ABSENT, 222 .tuner_type = TUNER_ABSENT,
223 .is_webcam = 1, 223 .is_webcam = 1,
224 .input = { { 224 .input = { {
@@ -1768,6 +1768,7 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1768 __be16 version_be; 1768 __be16 version_be;
1769 u16 version; 1769 u16 version;
1770 1770
1771 /* Micron sensor detection */
1771 dev->i2c_client.addr = 0xba >> 1; 1772 dev->i2c_client.addr = 0xba >> 1;
1772 cmd = 0; 1773 cmd = 0;
1773 i2c_master_send(&dev->i2c_client, &cmd, 1); 1774 i2c_master_send(&dev->i2c_client, &cmd, 1);
@@ -1776,16 +1777,27 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1776 return -EINVAL; 1777 return -EINVAL;
1777 1778
1778 version = be16_to_cpu(version_be); 1779 version = be16_to_cpu(version_be);
1779
1780 switch (version) { 1780 switch (version) {
1781 case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */ 1781 case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */
1782 case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */ 1782 case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */
1783 dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; 1783 dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
1784 em28xx_set_model(dev);
1785
1784 sensor_name = "mt9v011"; 1786 sensor_name = "mt9v011";
1785 dev->em28xx_sensor = EM28XX_MT9V011; 1787 dev->em28xx_sensor = EM28XX_MT9V011;
1786 dev->sensor_xres = 640; 1788 dev->sensor_xres = 640;
1787 dev->sensor_yres = 480; 1789 dev->sensor_yres = 480;
1788 dev->sensor_xtal = 12150000; 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;
1789 1801
1790 /* probably means GRGB 16 bit bayer */ 1802 /* probably means GRGB 16 bit bayer */
1791 dev->vinmode = 0x0d; 1803 dev->vinmode = 0x0d;
@@ -1794,6 +1806,8 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1794 break; 1806 break;
1795 case 0x8431: 1807 case 0x8431:
1796 dev->model = EM2750_BOARD_UNKNOWN; 1808 dev->model = EM2750_BOARD_UNKNOWN;
1809 em28xx_set_model(dev);
1810
1797 sensor_name = "mt9m001"; 1811 sensor_name = "mt9m001";
1798 dev->em28xx_sensor = EM28XX_MT9M001; 1812 dev->em28xx_sensor = EM28XX_MT9M001;
1799 em28xx_initialize_mt9m001(dev); 1813 em28xx_initialize_mt9m001(dev);
@@ -1810,6 +1824,9 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1810 return -EINVAL; 1824 return -EINVAL;
1811 } 1825 }
1812 1826
1827 /* Setup webcam defaults */
1828 em28xx_pre_card_setup(dev);
1829
1813 em28xx_errdev("Sensor is %s, using model %s entry.\n", 1830 em28xx_errdev("Sensor is %s, using model %s entry.\n",
1814 sensor_name, em28xx_boards[dev->model].name); 1831 sensor_name, em28xx_boards[dev->model].name);
1815 1832
@@ -2169,7 +2186,20 @@ void em28xx_register_i2c_ir(struct em28xx *dev)
2169 2186
2170void em28xx_card_setup(struct em28xx *dev) 2187void em28xx_card_setup(struct em28xx *dev)
2171{ 2188{
2172 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);
2173 2203
2174 dev->tuner_type = em28xx_boards[dev->model].tuner_type; 2204 dev->tuner_type = em28xx_boards[dev->model].tuner_type;
2175 if (em28xx_boards[dev->model].tuner_addr) 2205 if (em28xx_boards[dev->model].tuner_addr)
@@ -2489,18 +2519,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
2489 dev->vinmode = 0x10; 2519 dev->vinmode = 0x10;
2490 dev->vinctl = 0x11; 2520 dev->vinctl = 0x11;
2491 2521
2492 /*
2493 * If the device can be a webcam, seek for a sensor.
2494 * If sensor is not found, then it isn't a webcam.
2495 */
2496 if (dev->board.is_webcam)
2497 if (em28xx_hint_sensor(dev) < 0)
2498 dev->board.is_webcam = 0;
2499
2500 /* It makes no sense to use de-interlacing mode on webcams */
2501 if (dev->board.is_webcam)
2502 dev->progressive = 1;
2503
2504 /* Do board specific init and eeprom reading */ 2522 /* Do board specific init and eeprom reading */
2505 em28xx_card_setup(dev); 2523 em28xx_card_setup(dev);
2506 2524