summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/em28xx
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-06-30 16:36:08 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-30 16:36:08 -0300
commit2fbea57afdd3fb8da843ee44c1859b54d08433ad (patch)
tree4140c56526d11596b0c2d5c8176c7ff31eedec50 /linux/drivers/media/video/em28xx
parent2e3dbe38af11659dad7ec398a503f64125c2617e (diff)
parentb0b50913254709734afb1bcc907788c1beb15e62 (diff)
downloadmediapointer-dvb-s2-2fbea57afdd3fb8da843ee44c1859b54d08433ad.tar.gz
mediapointer-dvb-s2-2fbea57afdd3fb8da843ee44c1859b54d08433ad.tar.bz2
merge: http://www.kernellabs.com/hg/~dheitmueller/em28xx-terratec-zl10353/
From: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers/media/video/em28xx')
-rw-r--r--linux/drivers/media/video/em28xx/Kconfig2
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-cards.c37
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-core.c33
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-i2c.c2
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-video.c57
-rw-r--r--linux/drivers/media/video/em28xx/em28xx.h3
6 files changed, 125 insertions, 9 deletions
diff --git a/linux/drivers/media/video/em28xx/Kconfig b/linux/drivers/media/video/em28xx/Kconfig
index 16a5af30e..6524b493e 100644
--- a/linux/drivers/media/video/em28xx/Kconfig
+++ b/linux/drivers/media/video/em28xx/Kconfig
@@ -8,6 +8,8 @@ config VIDEO_EM28XX
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO
+
---help---
This is a video4linux driver for Empia 28xx based TV cards.
diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c
index 46ce91afc..e63c2e64e 100644
--- a/linux/drivers/media/video/em28xx/em28xx-cards.c
+++ b/linux/drivers/media/video/em28xx/em28xx-cards.c
@@ -204,6 +204,13 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = {
{EM28XX_R08_GPIO, 0xff, 0xff, 10},
{ -1, -1, -1, -1},
};
+
+static struct em28xx_reg_seq silvercrest_reg_seq[] = {
+ {EM28XX_R08_GPIO, 0xff, 0xff, 10},
+ {EM28XX_R08_GPIO, 0x01, 0xf7, 10},
+ { -1, -1, -1, -1},
+};
+
/*
* Board definitions
*/
@@ -451,6 +458,18 @@ struct em28xx_board em28xx_boards[] = {
.amux = EM28XX_AMUX_VIDEO,
} },
},
+ [EM2820_BOARD_SILVERCREST_WEBCAM] = {
+ .name = "Silvercrest Webcam 1.3mpix",
+ .tuner_type = TUNER_ABSENT,
+ .is_27xx = 1,
+ .decoder = EM28XX_MT9V011,
+ .input = { {
+ .type = EM28XX_VMUX_COMPOSITE1,
+ .vmux = 0,
+ .amux = EM28XX_AMUX_VIDEO,
+ .gpio = silvercrest_reg_seq,
+ } },
+ },
[EM2821_BOARD_SUPERCOMP_USB_2] = {
.name = "Supercomp USB 2.0 TV",
.valid = EM28XX_BOARD_NOT_VALIDATED,
@@ -1708,6 +1727,11 @@ static unsigned short tvp5150_addrs[] = {
I2C_CLIENT_END
};
+static unsigned short mt9v011_addrs[] = {
+ 0xba >> 1,
+ I2C_CLIENT_END
+};
+
static unsigned short msp3400_addrs[] = {
0x80 >> 1,
0x88 >> 1,
@@ -1775,7 +1799,10 @@ void em28xx_pre_card_setup(struct em28xx *dev)
em28xx_info("chip ID is em2750\n");
break;
case CHIP_ID_EM2820:
- em28xx_info("chip ID is em2820\n");
+ if (dev->board.is_27xx)
+ em28xx_info("chip is em2710\n");
+ else
+ em28xx_info("chip ID is em2820\n");
break;
case CHIP_ID_EM2840:
em28xx_info("chip ID is em2840\n");
@@ -2261,6 +2288,10 @@ void em28xx_card_setup(struct em28xx *dev)
before probing the i2c bus. */
em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
break;
+ case EM2820_BOARD_SILVERCREST_WEBCAM:
+ /* FIXME: need to document the registers bellow */
+ em28xx_write_reg(dev, 0x0d, 0x42);
+ em28xx_write_reg(dev, 0x13, 0x08);
}
if (dev->board.has_snapshot_button)
@@ -2292,6 +2323,10 @@ void em28xx_card_setup(struct em28xx *dev)
v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
"tvp5150", "tvp5150", tvp5150_addrs);
+ if (dev->board.decoder == EM28XX_MT9V011)
+ v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+ "mt9v011", "mt9v011", mt9v011_addrs);
+
if (dev->board.adecoder == EM28XX_TVAUDIO)
v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
"tvaudio", "tvaudio", dev->board.tvaudio_addr);
diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c
index 2bce72e4f..7ad8edff2 100644
--- a/linux/drivers/media/video/em28xx/em28xx-core.c
+++ b/linux/drivers/media/video/em28xx/em28xx-core.c
@@ -648,17 +648,29 @@ int em28xx_capture_start(struct em28xx *dev, int start)
int em28xx_set_outfmt(struct em28xx *dev)
{
int ret;
+ int vinmode, vinctl, outfmt;
+
+ outfmt = dev->format->reg;
+
+ if (dev->board.is_27xx) {
+ vinmode = 0x0d;
+ vinctl = 0x00;
+ outfmt = 0x24;
+ } else {
+ vinmode = 0x10;
+ vinctl = 0x11;
+ }
ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
- dev->format->reg | 0x20, 0x3f);
+ outfmt | 0x20, 0xff);
if (ret < 0)
- return ret;
+ return ret;
- ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10);
+ ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode);
if (ret < 0)
return ret;
- return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11);
+ return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl);
}
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)
{
u8 mode;
/* the em2800 scaler only supports scaling down to 50% */
- if (dev->board.is_em2800)
+
+ if (dev->board.is_27xx) {
+ /* FIXME: Don't use the scaler yet */
+ mode = 0;
+ } else if (dev->board.is_em2800) {
mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
- else {
+ } else {
u8 buf[2];
+
buf[0] = h;
buf[1] = h >> 8;
em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
+
buf[0] = v;
buf[1] = v >> 8;
em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
@@ -720,8 +738,11 @@ int em28xx_resolution_set(struct em28xx *dev)
height = norm_maxh(dev) >> 1;
em28xx_set_outfmt(dev);
+
+
em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
+
return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
}
diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c
index 1cdd88361..24eebd4a3 100644
--- a/linux/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c
@@ -461,7 +461,7 @@ static struct i2c_algorithm em28xx_algo = {
static struct i2c_adapter em28xx_adap_template = {
.owner = THIS_MODULE,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
.class = I2C_CLASS_TV_ANALOG,
#endif
.name = "em28xx",
diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c
index 63d21698c..3c47acee3 100644
--- a/linux/drivers/media/video/em28xx/em28xx-video.c
+++ b/linux/drivers/media/video/em28xx/em28xx-video.c
@@ -94,6 +94,49 @@ static struct em28xx_fmt format[] = {
.fourcc = V4L2_PIX_FMT_YUYV,
.depth = 16,
.reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
+ }, {
+ .name = "16 bpp RGB, le",
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .depth = 16,
+ .reg = EM28XX_OUTFMT_YUV211,
+#if 0
+ /* TODO: need tests and newer definitions */
+ }, {
+ .name = "Y1-U-Y0-V, 16 bpp",
+ .fourcc = 0,
+ .depth = 16,
+ .reg = EM28XX_OUTFMT_YUV422_Y1UY0V
+ }, {
+ .name = "YUV211, 8 bpp",
+ .fourcc = 0,
+ .depth = 8,
+ .reg = EM28XX_OUTFMT_YUV211,
+ }, {
+ .name = "YUV411, 12 bpp",
+ .fourcc = 0,
+ .depth = 12,
+ .reg = EM28XX_OUTFMT_YUV411,
+ }, {
+ .name = "RGB, 8bit RGRG",
+ .fourcc = 0,
+ .depth = 8,
+ .reg = EM28XX_OUTFMT_YUV211,
+ }, {
+ .name = "RGB, 8bit GRGR",
+ .fourcc = 0,
+ .depth = 8,
+ .reg = EM28XX_OUTFMT_YUV211,
+ }, {
+ .name = "RGB, 8bit GBGB",
+ .fourcc = 0,
+ .depth = 8,
+ .reg = EM28XX_OUTFMT_YUV211,
+ }, {
+ .name = "RGB, 8bit BGBG",
+ .fourcc = 0,
+ .depth = 8,
+ .reg = EM28XX_OUTFMT_RGB_8_BGBG,
+#endif
},
};
@@ -698,6 +741,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
unsigned int hscale, vscale;
struct em28xx_fmt *fmt;
+ /* FIXME: This is the only supported fmt */
+ if (dev->board.is_27xx)
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
+
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
if (!fmt) {
em28xx_videodbg("Fourcc format (%08x) invalid.\n",
@@ -705,7 +752,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
}
- if (dev->board.is_em2800) {
+ if (dev->board.is_27xx) {
+ /* FIXME: This is the only supported fmt */
+ width = 640;
+ height = 480;
+ } else if (dev->board.is_em2800) {
/* the em2800 can only scale down to 50% */
height = height > (3 * maxh / 4) ? maxh : maxh / 2;
width = width > (3 * maxw / 4) ? maxw : maxw / 2;
@@ -751,6 +802,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
mutex_lock(&dev->lock);
+ /* FIXME: This is the only supported fmt */
+ if (dev->board.is_27xx)
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
+
vidioc_try_fmt_vid_cap(file, priv, f);
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h
index 6fb890efa..2eedfef53 100644
--- a/linux/drivers/media/video/em28xx/em28xx.h
+++ b/linux/drivers/media/video/em28xx/em28xx.h
@@ -108,6 +108,7 @@
#define EM2860_BOARD_TERRATEC_AV350 68
#define EM2882_BOARD_KWORLD_ATSC_315U 69
#define EM2882_BOARD_EVGA_INDTUBE 70
+#define EM2820_BOARD_SILVERCREST_WEBCAM 71
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
@@ -361,6 +362,7 @@ enum em28xx_decoder {
EM28XX_NODECODER,
EM28XX_TVP5150,
EM28XX_SAA711X,
+ EM28XX_MT9V011,
};
enum em28xx_adecoder {
@@ -389,6 +391,7 @@ struct em28xx_board {
unsigned int max_range_640_480:1;
unsigned int has_dvb:1;
unsigned int has_snapshot_button:1;
+ unsigned int is_27xx:1;
unsigned int valid:1;
unsigned char xclk, i2c_speed;