From 7ddaac7fcb01eed38692f1bfa81f5f4348d848d7 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Tue, 16 Mar 2010 13:58:27 -0300 Subject: [PATCH] V4L/DVB: gspca - sn9c20x: Add upside down detection Add support for detecting webcams that are mounted upside down in laptops. Currently the only two known are two MSI modesl using the 0c45:624f. Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 50 +++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 825d5b8dfd6f..06c75dbecaee 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -27,6 +27,7 @@ #include "jpeg.h" #include +#include MODULE_AUTHOR("Brian Johnson , " "microdia project "); @@ -55,6 +56,7 @@ MODULE_LICENSE("GPL"); /* camera flags */ #define HAS_BUTTON 0x1 #define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ +#define FLIP_DETECT 0x4 /* specific webcam descriptor */ struct sd { @@ -127,6 +129,25 @@ static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val); static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); +static const struct dmi_system_id flip_dmi_table[] = { + { + .ident = "MSI MS-1034", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0341") + } + }, + { + .ident = "MSI MS-1632", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), + DMI_MATCH(DMI_BOARD_NAME, "MS-1632") + } + }, + {} +}; + static const struct ctrl sd_ctrls[] = { { #define BRIGHTNESS_IDX 0 @@ -1496,17 +1517,26 @@ static int set_redblue(struct gspca_dev *gspca_dev) static int set_hvflip(struct gspca_dev *gspca_dev) { - u8 value, tslb; + u8 value, tslb, hflip, vflip; u16 value2; struct sd *sd = (struct sd *) gspca_dev; + + if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { + hflip = !sd->hflip; + vflip = !sd->vflip; + } else { + hflip = sd->hflip; + vflip = sd->vflip; + } + switch (sd->sensor) { case SENSOR_OV9650: i2c_r1(gspca_dev, 0x1e, &value); value &= ~0x30; tslb = 0x01; - if (sd->hflip) + if (hflip) value |= 0x20; - if (sd->vflip) { + if (vflip) { value |= 0x10; tslb = 0x49; } @@ -1517,9 +1547,9 @@ static int set_hvflip(struct gspca_dev *gspca_dev) case SENSOR_MT9V011: i2c_r2(gspca_dev, 0x20, &value2); value2 &= ~0xc0a0; - if (sd->hflip) + if (hflip) value2 |= 0x8080; - if (sd->vflip) + if (vflip) value2 |= 0x4020; i2c_w2(gspca_dev, 0x20, value2); break; @@ -1527,18 +1557,18 @@ static int set_hvflip(struct gspca_dev *gspca_dev) case SENSOR_MT9V112: i2c_r2(gspca_dev, 0x20, &value2); value2 &= ~0x0003; - if (sd->hflip) + if (hflip) value2 |= 0x0002; - if (sd->vflip) + if (vflip) value2 |= 0x0001; i2c_w2(gspca_dev, 0x20, value2); break; case SENSOR_HV7131R: i2c_r1(gspca_dev, 0x01, &value); value &= ~0x03; - if (sd->vflip) + if (vflip) value |= 0x01; - if (sd->hflip) + if (hflip) value |= 0x02; i2c_w1(gspca_dev, 0x01, value); break; @@ -2371,7 +2401,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, (HAS_BUTTON | LED_REVERSE))}, - {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, FLIP_DETECT)}, {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, -- 2.30.2