From: Jean-François Moine Date: Mon, 19 Mar 2012 07:35:34 +0000 (-0300) Subject: [media] gspca - sn9c20x: Add the JPEG compression quality control X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=4c632e4e51e5d89af75ecf3e958988658c01294f;p=linux-beck.git [media] gspca - sn9c20x: Add the JPEG compression quality control The JPEG compression quality was hardcoded to 95%. This value was too big, raising often buffer overflows. This quality is now 80% by default and is settable. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 97c653f9f983..0894a3d2c336 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -79,6 +79,7 @@ enum e_ctrl { EXPOSURE, GAIN, AUTOGAIN, + QUALITY, NCTRLS /* number of controls */ }; @@ -88,6 +89,8 @@ struct sd { struct gspca_ctrl ctrls[NCTRLS]; + u8 fmt; /* (used for JPEG QTAB update */ + #define MIN_AVG_LUM 80 #define MAX_AVG_LUM 130 atomic_t avg_lum; @@ -101,7 +104,6 @@ struct sd { u8 vstart; u8 jpeg_hdr[JPEG_HDR_SZ]; - u8 quality; u8 flags; }; @@ -162,6 +164,7 @@ static void set_redblue(struct gspca_dev *gspca_dev); static void set_hvflip(struct gspca_dev *gspca_dev); static void set_exposure(struct gspca_dev *gspca_dev); static void set_gain(struct gspca_dev *gspca_dev); +static void set_quality(struct gspca_dev *gspca_dev); static const struct ctrl sd_ctrls[NCTRLS] = { [BRIGHTNESS] = { @@ -307,6 +310,21 @@ static const struct ctrl sd_ctrls[NCTRLS] = { .default_value = 1, }, }, +[QUALITY] = { + { + .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Compression Quality", +#define QUALITY_MIN 50 +#define QUALITY_MAX 90 +#define QUALITY_DEF 80 + .minimum = QUALITY_MIN, + .maximum = QUALITY_MAX, + .step = 1, + .default_value = QUALITY_DEF, + }, + .set_control = set_quality + }, }; static const struct v4l2_pix_format vga_mode[] = { @@ -1732,6 +1750,21 @@ static void set_gain(struct gspca_dev *gspca_dev) i2c_w(gspca_dev, gain); } +static void set_quality(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); + reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ + reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ + reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); + reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); + reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ + reg_w1(gspca_dev, 0x10e0, sd->fmt); + sd->fmt ^= 0x0c; /* invert QTAB use + write */ + reg_w1(gspca_dev, 0x10e0, sd->fmt); +} + #ifdef CONFIG_VIDEO_ADV_DEBUG static int sd_dbg_g_register(struct gspca_dev *gspca_dev, struct v4l2_dbg_register *reg) @@ -1846,7 +1879,6 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->cam.ctrls = sd->ctrls; - sd->quality = 95; return 0; } @@ -2058,14 +2090,15 @@ static int sd_start(struct gspca_dev *gspca_dev) jpeg_define(sd->jpeg_hdr, height, width, 0x21); - jpeg_set_qual(sd->jpeg_hdr, sd->quality); + jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); if (mode & MODE_RAW) fmt = 0x2d; else if (mode & MODE_JPEG) - fmt = 0x2c; + fmt = 0x24; else fmt = 0x2f; /* YUV 420 */ + sd->fmt = fmt; switch (mode & SCALE_MASK) { case SCALE_1280x1024: