[media] gspca - zc3xx: Adjust the JPEG decompression tables

As the bridge register 08 defines the JPEG compression quality,
it must be changed on JPEG quality change and also, the decompression
tables must be adjusted when the register varies.

[mchehab@redhat.com: replace a // comment by a /* */ one]
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Jean-François Moine 2012-02-27 07:26:30 -03:00 committed by Mauro Carvalho Chehab
parent a7705c093d
commit 30c73d464a
1 changed files with 50 additions and 47 deletions

View File

@ -34,7 +34,7 @@ MODULE_LICENSE("GPL");
static int force_sensor = -1;
#define QUANT_VAL 1 /* quantization table */
#define REG08_DEF 3 /* default JPEG compression (70%) */
#include "zc3xx-reg.h"
/* controls */
@ -57,10 +57,7 @@ struct sd {
struct gspca_ctrl ctrls[NCTRLS];
u8 quality; /* image quality */
#define QUALITY_MIN 50
#define QUALITY_MAX 80
#define QUALITY_DEF 70
u8 reg08; /* webcam compression quality */
u8 bridge;
u8 sensor; /* Type of image sensor chip */
@ -229,6 +226,9 @@ static const struct v4l2_pix_format sif_mode[] = {
.priv = 0},
};
/* bridge reg08 -> JPEG quality conversion table */
static u8 jpeg_qual[] = {40, 50, 60, 70, /*80*/};
/* usb exchanges */
struct usb_action {
u8 req;
@ -5925,32 +5925,17 @@ static void setexposure(struct gspca_dev *gspca_dev)
static void setquality(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 frxt;
s8 reg07;
reg07 = 0;
switch (sd->sensor) {
case SENSOR_ADCM2700:
case SENSOR_GC0305:
case SENSOR_HV7131B:
case SENSOR_HV7131R:
case SENSOR_OV7620:
case SENSOR_PAS202B:
case SENSOR_PO2030:
return;
reg07 = 0x30;
break;
}
/*fixme: is it really 0008 0007 0018 for all other sensors? */
reg_w(gspca_dev, QUANT_VAL, 0x0008);
frxt = 0x30;
reg_w(gspca_dev, frxt, 0x0007);
#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2
frxt = 0xff;
#elif QUANT_VAL == 3
frxt = 0xf0;
#elif QUANT_VAL == 4
frxt = 0xe0;
#else
frxt = 0x20;
#endif
reg_w(gspca_dev, frxt, 0x0018);
reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING);
if (reg07 != 0)
reg_w(gspca_dev, reg07, 0x0007);
}
/* Matches the sensor's internal frame rate to the lighting frequency.
@ -6411,7 +6396,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->sensor = id->driver_info;
gspca_dev->cam.ctrls = sd->ctrls;
sd->quality = QUALITY_DEF;
sd->reg08 = REG08_DEF;
return 0;
}
@ -6464,6 +6449,27 @@ static int sd_init(struct gspca_dev *gspca_dev)
[SENSOR_PO2030] = 1,
[SENSOR_TAS5130C] = 1,
};
static const u8 reg08_tb[SENSOR_MAX] = {
[SENSOR_ADCM2700] = 1,
[SENSOR_CS2102] = 3,
/* [SENSOR_CS2102K] = 3, */
[SENSOR_GC0303] = 2,
[SENSOR_GC0305] = 3,
[SENSOR_HDCS2020] = 1,
[SENSOR_HV7131B] = 3,
[SENSOR_HV7131R] = 3,
[SENSOR_ICM105A] = 3,
[SENSOR_MC501CB] = 3,
[SENSOR_MT9V111_1] = 3,
[SENSOR_MT9V111_3] = 3,
[SENSOR_OV7620] = 1,
[SENSOR_OV7630C] = 3,
[SENSOR_PAS106] = 3,
[SENSOR_PAS202B] = 3,
[SENSOR_PB0330] = 3,
[SENSOR_PO2030] = 2,
[SENSOR_TAS5130C] = 3,
};
sensor = zcxx_probeSensor(gspca_dev);
if (sensor >= 0)
@ -6616,6 +6622,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
}
sd->ctrls[GAMMA].def = gamma[sd->sensor];
sd->reg08 = reg08_tb[sd->sensor];
switch (sd->sensor) {
case SENSOR_HV7131R:
@ -6685,7 +6692,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* create the JPEG header */
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x21); /* JPEG 422 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
switch (sd->sensor) {
@ -6761,10 +6767,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_r(gspca_dev, 0x0180); /* from win */
reg_w(gspca_dev, 0x00, 0x0180);
break;
default:
setquality(gspca_dev);
break;
}
setquality(gspca_dev);
jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08]);
setlightfreq(gspca_dev);
switch (sd->sensor) {
@ -6802,13 +6807,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
}
setautogain(gspca_dev);
switch (sd->sensor) {
case SENSOR_PO2030:
msleep(50);
reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */
reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING);
break;
}
return gspca_dev->usb_err;
}
@ -6897,15 +6895,20 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev,
struct v4l2_jpegcompression *jcomp)
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
if (jcomp->quality < QUALITY_MIN)
sd->quality = QUALITY_MIN;
else if (jcomp->quality > QUALITY_MAX)
sd->quality = QUALITY_MAX;
else
sd->quality = jcomp->quality;
for (i = 0; i < ARRAY_SIZE(jpeg_qual) - 1; i++) {
if (jcomp->quality <= jpeg_qual[i])
break;
}
if (i > 0
&& i == sd->reg08
&& jcomp->quality < jpeg_qual[sd->reg08])
i--;
sd->reg08 = i;
jcomp->quality = jpeg_qual[i];
if (gspca_dev->streaming)
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
jpeg_set_qual(sd->jpeg_hdr, jcomp->quality);
return gspca_dev->usb_err;
}
@ -6915,7 +6918,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
struct sd *sd = (struct sd *) gspca_dev;
memset(jcomp, 0, sizeof *jcomp);
jcomp->quality = sd->quality;
jcomp->quality = jpeg_qual[sd->reg08];
jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
| V4L2_JPEG_MARKER_DQT;
return 0;