diff options
-rw-r--r-- | drivers/media/video/gspca/sonixj.c | 117 |
1 files changed, 99 insertions, 18 deletions
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 83564e09eee..504976960ce 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -41,6 +41,8 @@ struct sd { unsigned char contrast; unsigned char colors; unsigned char autogain; + __u8 blue; + __u8 red; __u8 vflip; /* ov7630 only */ __u8 infrared; /* mi0360 only */ @@ -72,6 +74,10 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); @@ -116,7 +122,7 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Color", .minimum = 0, - .maximum = 64, + .maximum = 40, .step = 1, #define COLOR_DEF 32 .default_value = COLOR_DEF, @@ -124,7 +130,35 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, -#define AUTOGAIN_IDX 3 + { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = 24, + .maximum = 40, + .step = 1, +#define BLUE_BALANCE_DEF 32 + .default_value = BLUE_BALANCE_DEF, + }, + .set = sd_setblue_balance, + .get = sd_getblue_balance, + }, + { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = 24, + .maximum = 40, + .step = 1, +#define RED_BALANCE_DEF 32 + .default_value = RED_BALANCE_DEF, + }, + .set = sd_setred_balance, + .get = sd_getred_balance, + }, +#define AUTOGAIN_IDX 5 { { .id = V4L2_CID_AUTOGAIN, @@ -140,7 +174,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getautogain, }, /* ov7630 only */ -#define VFLIP_IDX 4 +#define VFLIP_IDX 6 { { .id = V4L2_CID_VFLIP, @@ -156,7 +190,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getvflip, }, /* mi0360 only */ -#define INFRARED_IDX 5 +#define INFRARED_IDX 7 { { .id = V4L2_CID_INFRARED, @@ -981,6 +1015,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->blue = BLUE_BALANCE_DEF; + sd->red = RED_BALANCE_DEF; sd->autogain = AUTOGAIN_DEF; sd->ag_cnt = -1; sd->vflip = VFLIP_DEF; @@ -1170,18 +1206,27 @@ static void setcontrast(struct gspca_dev *gspca_dev) static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 blue, red; - - if (sd->colors >= 32) { - red = 32 + (sd->colors - 32) / 2; - blue = 64 - sd->colors; - } else { - red = sd->colors; - blue = 32 + (32 - sd->colors) / 2; + int i, v; + __u8 rega0[12]; /* U & V gains */ + static __s16 uv[6] = { /* same as reg84 in signed decimal */ + -24, -38, 64, /* UR UG UB */ + 62, -51, -9 /* VR VG VB */ + }; + for (i = 0; i < 6; i++) { + v = uv[i] * sd->colors / COLOR_DEF; + rega0[i * 2] = v; + rega0[i * 2 + 1] = (v >> 8) & 0x0f; } - reg_w1(gspca_dev, 0x05, red); + reg_w(gspca_dev, 0x84, rega0, sizeof rega0); +} + +static void setredblue(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + reg_w1(gspca_dev, 0x05, sd->red); /* reg_w1(gspca_dev, 0x07, 32); */ - reg_w1(gspca_dev, 0x06, blue); + reg_w1(gspca_dev, 0x06, sd->blue); } static void setautogain(struct gspca_dev *gspca_dev) @@ -1259,9 +1304,9 @@ static int sd_start(struct gspca_dev *gspca_dev) } reg_w1(gspca_dev, 0x17, reg17); /* set reg1 was here */ - reg_w1(gspca_dev, 0x05, sn9c1xx[5]); - reg_w1(gspca_dev, 0x07, sn9c1xx[7]); - reg_w1(gspca_dev, 0x06, sn9c1xx[6]); + reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */ + reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ + reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def); for (i = 0; i < 8; i++) @@ -1462,7 +1507,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) expotimes = 0; sd->exposure = setexposure(gspca_dev, (unsigned int) expotimes); - setcolors(gspca_dev); + setredblue(gspca_dev); break; } } @@ -1565,6 +1610,42 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->blue = val; + if (gspca_dev->streaming) + setredblue(gspca_dev); + return 0; +} + +static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->blue; + return 0; +} + +static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->red = val; + if (gspca_dev->streaming) + setredblue(gspca_dev); + return 0; +} + +static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->red; + return 0; +} + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; |