summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sn9c20x.c
diff options
context:
space:
mode:
authorJean-François Moine <moinejf@free.fr>2012-03-19 08:35:34 +0100
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-03-20 02:30:20 +0100
commit4c632e4e51e5d89af75ecf3e958988658c01294f (patch)
tree47d8cd9aeb262e3038c517ebe816353f7a847b9a /drivers/media/video/gspca/sn9c20x.c
parent[media] gspca - sn9c20x: Add a delay after Omnivision sensor reset (diff)
downloadlinux-4c632e4e51e5d89af75ecf3e958988658c01294f.tar.xz
linux-4c632e4e51e5d89af75ecf3e958988658c01294f.zip
[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 <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/sn9c20x.c')
-rw-r--r--drivers/media/video/gspca/sn9c20x.c41
1 files changed, 37 insertions, 4 deletions
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: