diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-29 10:35:05 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-07-05 13:30:05 -0400 |
commit | 02e7804b2135ff941b8846f5820cf48fbfdadd54 (patch) | |
tree | 58d3e596946d4c6b1bae23465f5d9b80e893d300 /drivers | |
parent | 6934e6fface7b7d5fe7e578c3f43cbe8f23af2d4 (diff) |
V4L/DVB (12138): em28xx: add support for Silvercrest Webcam
This webcam uses a em2710 chipset, that identifies itself as em2820,
plus a mt9v011 sensor, and a DY-301P lens.
It needs a few different initializations than a normal em28xx device.
Thanks to Hans de Goede <hdegoede@redhat.com> and Douglas Landgraf
<dougsland@redhat.com> for providing the acces for the webcam during
this weekend, I could make a patch for it while returning back from
FISL/Fudcom LATAM 2009.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/em28xx/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 37 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 33 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 3 |
4 files changed, 68 insertions, 7 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..bd9b637c7ea5 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -191,6 +191,13 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { | |||
191 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, | 191 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, |
192 | { -1, -1, -1, -1}, | 192 | { -1, -1, -1, -1}, |
193 | }; | 193 | }; |
194 | |||
195 | static struct em28xx_reg_seq silvercrest_reg_seq[] = { | ||
196 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, | ||
197 | {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, | ||
198 | { -1, -1, -1, -1}, | ||
199 | }; | ||
200 | |||
194 | /* | 201 | /* |
195 | * Board definitions | 202 | * Board definitions |
196 | */ | 203 | */ |
@@ -438,6 +445,18 @@ struct em28xx_board em28xx_boards[] = { | |||
438 | .amux = EM28XX_AMUX_VIDEO, | 445 | .amux = EM28XX_AMUX_VIDEO, |
439 | } }, | 446 | } }, |
440 | }, | 447 | }, |
448 | [EM2820_BOARD_SILVERCREST_WEBCAM] = { | ||
449 | .name = "Silvercrest Webcam 1.3mpix", | ||
450 | .tuner_type = TUNER_ABSENT, | ||
451 | .is_27xx = 1, | ||
452 | .decoder = EM28XX_MT9V011, | ||
453 | .input = { { | ||
454 | .type = EM28XX_VMUX_COMPOSITE1, | ||
455 | .vmux = 0, | ||
456 | .amux = EM28XX_AMUX_VIDEO, | ||
457 | .gpio = silvercrest_reg_seq, | ||
458 | } }, | ||
459 | }, | ||
441 | [EM2821_BOARD_SUPERCOMP_USB_2] = { | 460 | [EM2821_BOARD_SUPERCOMP_USB_2] = { |
442 | .name = "Supercomp USB 2.0 TV", | 461 | .name = "Supercomp USB 2.0 TV", |
443 | .valid = EM28XX_BOARD_NOT_VALIDATED, | 462 | .valid = EM28XX_BOARD_NOT_VALIDATED, |
@@ -1639,6 +1658,11 @@ static unsigned short tvp5150_addrs[] = { | |||
1639 | I2C_CLIENT_END | 1658 | I2C_CLIENT_END |
1640 | }; | 1659 | }; |
1641 | 1660 | ||
1661 | static unsigned short mt9v011_addrs[] = { | ||
1662 | 0xba >> 1, | ||
1663 | I2C_CLIENT_END | ||
1664 | }; | ||
1665 | |||
1642 | static unsigned short msp3400_addrs[] = { | 1666 | static unsigned short msp3400_addrs[] = { |
1643 | 0x80 >> 1, | 1667 | 0x80 >> 1, |
1644 | 0x88 >> 1, | 1668 | 0x88 >> 1, |
@@ -1706,7 +1730,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) | |||
1706 | em28xx_info("chip ID is em2750\n"); | 1730 | em28xx_info("chip ID is em2750\n"); |
1707 | break; | 1731 | break; |
1708 | case CHIP_ID_EM2820: | 1732 | case CHIP_ID_EM2820: |
1709 | em28xx_info("chip ID is em2820\n"); | 1733 | if (dev->board.is_27xx) |
1734 | em28xx_info("chip is em2710\n"); | ||
1735 | else | ||
1736 | em28xx_info("chip ID is em2820\n"); | ||
1710 | break; | 1737 | break; |
1711 | case CHIP_ID_EM2840: | 1738 | case CHIP_ID_EM2840: |
1712 | em28xx_info("chip ID is em2840\n"); | 1739 | em28xx_info("chip ID is em2840\n"); |
@@ -2158,6 +2185,10 @@ void em28xx_card_setup(struct em28xx *dev) | |||
2158 | before probing the i2c bus. */ | 2185 | before probing the i2c bus. */ |
2159 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 2186 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
2160 | break; | 2187 | break; |
2188 | case EM2820_BOARD_SILVERCREST_WEBCAM: | ||
2189 | /* FIXME: need to document the registers bellow */ | ||
2190 | em28xx_write_reg(dev, 0x0d, 0x42); | ||
2191 | em28xx_write_reg(dev, 0x13, 0x08); | ||
2161 | } | 2192 | } |
2162 | 2193 | ||
2163 | if (dev->board.has_snapshot_button) | 2194 | if (dev->board.has_snapshot_button) |
@@ -2189,6 +2220,10 @@ void em28xx_card_setup(struct em28xx *dev) | |||
2189 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, | 2220 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
2190 | "tvp5150", "tvp5150", tvp5150_addrs); | 2221 | "tvp5150", "tvp5150", tvp5150_addrs); |
2191 | 2222 | ||
2223 | if (dev->board.decoder == EM28XX_MT9V011) | ||
2224 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, | ||
2225 | "mt9v011", "mt9v011", mt9v011_addrs); | ||
2226 | |||
2192 | if (dev->board.adecoder == EM28XX_TVAUDIO) | 2227 | if (dev->board.adecoder == EM28XX_TVAUDIO) |
2193 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, | 2228 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
2194 | "tvaudio", "tvaudio", dev->board.tvaudio_addr); | 2229 | "tvaudio", "tvaudio", dev->board.tvaudio_addr); |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index c8d7ce8fbd36..dda2721ee5b0 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -648,17 +648,29 @@ int em28xx_capture_start(struct em28xx *dev, int start) | |||
648 | int em28xx_set_outfmt(struct em28xx *dev) | 648 | int em28xx_set_outfmt(struct em28xx *dev) |
649 | { | 649 | { |
650 | int ret; | 650 | 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 | outfmt = 0x24; | ||
659 | } else { | ||
660 | vinmode = 0x10; | ||
661 | vinctl = 0x11; | ||
662 | } | ||
651 | 663 | ||
652 | ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, | 664 | ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, |
653 | dev->format->reg | 0x20, 0x3f); | 665 | outfmt | 0x20, 0xff); |
654 | if (ret < 0) | 666 | if (ret < 0) |
655 | return ret; | 667 | return ret; |
656 | 668 | ||
657 | ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); | 669 | ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); |
658 | if (ret < 0) | 670 | if (ret < 0) |
659 | return ret; | 671 | return ret; |
660 | 672 | ||
661 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); | 673 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); |
662 | } | 674 | } |
663 | 675 | ||
664 | static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, | 676 | static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, |
@@ -695,13 +707,19 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) | |||
695 | { | 707 | { |
696 | u8 mode; | 708 | u8 mode; |
697 | /* the em2800 scaler only supports scaling down to 50% */ | 709 | /* the em2800 scaler only supports scaling down to 50% */ |
698 | if (dev->board.is_em2800) | 710 | |
711 | if (dev->board.is_27xx) { | ||
712 | /* FIXME: Don't use the scaler yet */ | ||
713 | mode = 0; | ||
714 | } else if (dev->board.is_em2800) { | ||
699 | mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); | 715 | mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); |
700 | else { | 716 | } else { |
701 | u8 buf[2]; | 717 | u8 buf[2]; |
718 | |||
702 | buf[0] = h; | 719 | buf[0] = h; |
703 | buf[1] = h >> 8; | 720 | buf[1] = h >> 8; |
704 | em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); | 721 | em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); |
722 | |||
705 | buf[0] = v; | 723 | buf[0] = v; |
706 | buf[1] = v >> 8; | 724 | buf[1] = v >> 8; |
707 | em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); | 725 | em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); |
@@ -720,8 +738,11 @@ int em28xx_resolution_set(struct em28xx *dev) | |||
720 | height = norm_maxh(dev) >> 1; | 738 | height = norm_maxh(dev) >> 1; |
721 | 739 | ||
722 | em28xx_set_outfmt(dev); | 740 | em28xx_set_outfmt(dev); |
741 | |||
742 | |||
723 | em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); | 743 | em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); |
724 | em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); | 744 | em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); |
745 | |||
725 | return em28xx_scaler_set(dev, dev->hscale, dev->vscale); | 746 | return em28xx_scaler_set(dev, dev->hscale, dev->vscale); |
726 | } | 747 | } |
727 | 748 | ||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 813ce45c2f99..d90fef463764 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 |
@@ -360,6 +361,7 @@ enum em28xx_decoder { | |||
360 | EM28XX_NODECODER, | 361 | EM28XX_NODECODER, |
361 | EM28XX_TVP5150, | 362 | EM28XX_TVP5150, |
362 | EM28XX_SAA711X, | 363 | EM28XX_SAA711X, |
364 | EM28XX_MT9V011, | ||
363 | }; | 365 | }; |
364 | 366 | ||
365 | enum em28xx_adecoder { | 367 | enum em28xx_adecoder { |
@@ -388,6 +390,7 @@ struct em28xx_board { | |||
388 | unsigned int max_range_640_480:1; | 390 | unsigned int max_range_640_480:1; |
389 | unsigned int has_dvb:1; | 391 | unsigned int has_dvb:1; |
390 | unsigned int has_snapshot_button:1; | 392 | unsigned int has_snapshot_button:1; |
393 | unsigned int is_27xx:1; | ||
391 | unsigned int valid:1; | 394 | unsigned int valid:1; |
392 | 395 | ||
393 | unsigned char xclk, i2c_speed; | 396 | unsigned char xclk, i2c_speed; |