From 12ff91264ce3e2f24013d667d44ba786f947506c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 17 Jul 2008 10:30:56 -0300 Subject: [PATCH] V4L/DVB (8373): gspca: Hue, saturation and contrast controls added for sn9c10x ovxxxx. (does not work with ov6650) Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixb.c | 177 ++++++++++++++++++++++++++++- 1 file changed, 175 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index d34d582e5f59..5b3490ad661a 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -45,6 +45,9 @@ struct sd { unsigned char autogain; unsigned char autogain_ignore_frames; unsigned char freq; /* light freq filter setting */ + unsigned char saturation; + unsigned char hue; + unsigned char contrast; unsigned char fr_h_sz; /* size of frame header */ char sensor; /* Type of image sensor chip */ @@ -89,6 +92,12 @@ 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_setfreq(struct gspca_dev *gspca_dev, __s32 val); static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); +static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { { @@ -165,6 +174,48 @@ static struct ctrl sd_ctrls[] = { .set = sd_setfreq, .get = sd_getfreq, }, + { + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 255, + .step = 1, +#define SATURATION_DEF 127 + .default_value = SATURATION_DEF, + }, + .set = sd_setsaturation, + .get = sd_getsaturation, + }, + { + { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = 0, + .maximum = 255, + .step = 1, +#define HUE_DEF 127 + .default_value = HUE_DEF, + }, + .set = sd_sethue, + .get = sd_gethue, + }, + { + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 1, +#define CONTRAST_DEF 127 + .default_value = CONTRAST_DEF, + }, + .set = sd_setcontrast, + .get = sd_getcontrast, + }, }; static struct v4l2_pix_format vga_mode[] = { @@ -735,6 +786,68 @@ static void setfreq(struct gspca_dev *gspca_dev) } } +static void setsaturation(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + switch (sd->sensor) { +/* case SENSOR_OV6650: */ + case SENSOR_OV7630_3: + case SENSOR_OV7630: { + __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}; + i2c[1] = sd->sensor_addr; + i2c[3] = sd->saturation & 0xf0; + if (i2c_w(gspca_dev, i2c) < 0) + PDEBUG(D_ERR, "i2c error setsaturation"); + else + PDEBUG(D_CONF, "saturation set to: %d", + (int)sd->saturation); + break; + } + } +} + +static void sethue(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + switch (sd->sensor) { +/* case SENSOR_OV6650: */ + case SENSOR_OV7630_3: + case SENSOR_OV7630: { + __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10}; + i2c[1] = sd->sensor_addr; + i2c[3] = 0x20 | (sd->hue >> 3); + if (i2c_w(gspca_dev, i2c) < 0) + PDEBUG(D_ERR, "i2c error setsaturation"); + else + PDEBUG(D_CONF, "hue set to: %d", (int)sd->hue); + break; + } + } +} + +static void setcontrast(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + switch (sd->sensor) { +/* case SENSOR_OV6650: */ + case SENSOR_OV7630_3: + case SENSOR_OV7630: { + __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10}; + i2c[1] = sd->sensor_addr; + i2c[3] = 0x20 | (sd->contrast >> 3); + if (i2c_w(gspca_dev, i2c) < 0) + PDEBUG(D_ERR, "i2c error setcontrast"); + else + PDEBUG(D_CONF, "contrast set to: %d", + (int)sd->contrast); + break; + } + } +} + static void do_autogain(struct gspca_dev *gspca_dev) { @@ -771,7 +884,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->fr_h_sz = 12; /* default size of the frame header */ sd->sd_desc.nctrls = 2; /* default nb of ctrls */ sd->autogain = AUTOGAIN_DEF; /* default is autogain active */ - sd->freq = FREQ_DEF; product = id->idProduct; /* switch (id->idVendor) { */ @@ -811,7 +923,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor_addr = 0x21; sd->fr_h_sz = 18; /* size of frame header */ sd->sensor_has_gain = 1; - sd->sd_desc.nctrls = 5; + sd->sd_desc.nctrls = 8; sd->sd_desc.dq_callback = do_autogain; sd->autogain = 0; break; @@ -851,6 +963,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; + sd->freq = FREQ_DEF; + sd->contrast = CONTRAST_DEF; + sd->saturation = SATURATION_DEF; + sd->hue = HUE_DEF; if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */ reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630); return 0; @@ -1033,6 +1149,9 @@ static void sd_start(struct gspca_dev *gspca_dev) setbrightness(gspca_dev); setexposure(gspca_dev); setfreq(gspca_dev); + setsaturation(gspca_dev); + sethue(gspca_dev); + setcontrast(gspca_dev); sd->autogain_ignore_frames = 0; atomic_set(&sd->avg_lum, -1); @@ -1208,6 +1327,60 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->saturation = val; + if (gspca_dev->streaming) + setsaturation(gspca_dev); + return 0; +} + +static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->saturation; + return 0; +} + +static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->hue = val; + if (gspca_dev->streaming) + sethue(gspca_dev); + return 0; +} + +static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->hue; + return 0; +} + +static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->contrast = val; + if (gspca_dev->streaming) + setcontrast(gspca_dev); + return 0; +} + +static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->contrast; + return 0; +} + static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu) { -- 2.34.1