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>
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index c8d7ce8..dda2721 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -648,17 +648,29 @@
 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;
+
+	ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode);
 	if (ret < 0)
 		return ret;
 
-	ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10);
-	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 @@
 {
 	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 @@
 	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);
 }