diff options
author | Jean-François Moine <moinejf@free.fr> | 2012-03-19 03:35:34 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-19 21:30:20 -0400 |
commit | 4c632e4e51e5d89af75ecf3e958988658c01294f (patch) | |
tree | 47d8cd9aeb262e3038c517ebe816353f7a847b9a /drivers/media | |
parent | 92884f80b7e5f8d0ffd725a251c81dd45e9e6eb0 (diff) |
[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')
-rw-r--r-- | drivers/media/video/gspca/sn9c20x.c | 41 |
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 { | |||
79 | EXPOSURE, | 79 | EXPOSURE, |
80 | GAIN, | 80 | GAIN, |
81 | AUTOGAIN, | 81 | AUTOGAIN, |
82 | QUALITY, | ||
82 | NCTRLS /* number of controls */ | 83 | NCTRLS /* number of controls */ |
83 | }; | 84 | }; |
84 | 85 | ||
@@ -88,6 +89,8 @@ struct sd { | |||
88 | 89 | ||
89 | struct gspca_ctrl ctrls[NCTRLS]; | 90 | struct gspca_ctrl ctrls[NCTRLS]; |
90 | 91 | ||
92 | u8 fmt; /* (used for JPEG QTAB update */ | ||
93 | |||
91 | #define MIN_AVG_LUM 80 | 94 | #define MIN_AVG_LUM 80 |
92 | #define MAX_AVG_LUM 130 | 95 | #define MAX_AVG_LUM 130 |
93 | atomic_t avg_lum; | 96 | atomic_t avg_lum; |
@@ -101,7 +104,6 @@ struct sd { | |||
101 | u8 vstart; | 104 | u8 vstart; |
102 | 105 | ||
103 | u8 jpeg_hdr[JPEG_HDR_SZ]; | 106 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
104 | u8 quality; | ||
105 | 107 | ||
106 | u8 flags; | 108 | u8 flags; |
107 | }; | 109 | }; |
@@ -162,6 +164,7 @@ static void set_redblue(struct gspca_dev *gspca_dev); | |||
162 | static void set_hvflip(struct gspca_dev *gspca_dev); | 164 | static void set_hvflip(struct gspca_dev *gspca_dev); |
163 | static void set_exposure(struct gspca_dev *gspca_dev); | 165 | static void set_exposure(struct gspca_dev *gspca_dev); |
164 | static void set_gain(struct gspca_dev *gspca_dev); | 166 | static void set_gain(struct gspca_dev *gspca_dev); |
167 | static void set_quality(struct gspca_dev *gspca_dev); | ||
165 | 168 | ||
166 | static const struct ctrl sd_ctrls[NCTRLS] = { | 169 | static const struct ctrl sd_ctrls[NCTRLS] = { |
167 | [BRIGHTNESS] = { | 170 | [BRIGHTNESS] = { |
@@ -307,6 +310,21 @@ static const struct ctrl sd_ctrls[NCTRLS] = { | |||
307 | .default_value = 1, | 310 | .default_value = 1, |
308 | }, | 311 | }, |
309 | }, | 312 | }, |
313 | [QUALITY] = { | ||
314 | { | ||
315 | .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, | ||
316 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
317 | .name = "Compression Quality", | ||
318 | #define QUALITY_MIN 50 | ||
319 | #define QUALITY_MAX 90 | ||
320 | #define QUALITY_DEF 80 | ||
321 | .minimum = QUALITY_MIN, | ||
322 | .maximum = QUALITY_MAX, | ||
323 | .step = 1, | ||
324 | .default_value = QUALITY_DEF, | ||
325 | }, | ||
326 | .set_control = set_quality | ||
327 | }, | ||
310 | }; | 328 | }; |
311 | 329 | ||
312 | static const struct v4l2_pix_format vga_mode[] = { | 330 | static const struct v4l2_pix_format vga_mode[] = { |
@@ -1732,6 +1750,21 @@ static void set_gain(struct gspca_dev *gspca_dev) | |||
1732 | i2c_w(gspca_dev, gain); | 1750 | i2c_w(gspca_dev, gain); |
1733 | } | 1751 | } |
1734 | 1752 | ||
1753 | static void set_quality(struct gspca_dev *gspca_dev) | ||
1754 | { | ||
1755 | struct sd *sd = (struct sd *) gspca_dev; | ||
1756 | |||
1757 | jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); | ||
1758 | reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ | ||
1759 | reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ | ||
1760 | reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); | ||
1761 | reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); | ||
1762 | reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ | ||
1763 | reg_w1(gspca_dev, 0x10e0, sd->fmt); | ||
1764 | sd->fmt ^= 0x0c; /* invert QTAB use + write */ | ||
1765 | reg_w1(gspca_dev, 0x10e0, sd->fmt); | ||
1766 | } | ||
1767 | |||
1735 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1768 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1736 | static int sd_dbg_g_register(struct gspca_dev *gspca_dev, | 1769 | static int sd_dbg_g_register(struct gspca_dev *gspca_dev, |
1737 | struct v4l2_dbg_register *reg) | 1770 | struct v4l2_dbg_register *reg) |
@@ -1846,7 +1879,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1846 | 1879 | ||
1847 | gspca_dev->cam.ctrls = sd->ctrls; | 1880 | gspca_dev->cam.ctrls = sd->ctrls; |
1848 | 1881 | ||
1849 | sd->quality = 95; | ||
1850 | 1882 | ||
1851 | return 0; | 1883 | return 0; |
1852 | } | 1884 | } |
@@ -2058,14 +2090,15 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2058 | 2090 | ||
2059 | jpeg_define(sd->jpeg_hdr, height, width, | 2091 | jpeg_define(sd->jpeg_hdr, height, width, |
2060 | 0x21); | 2092 | 0x21); |
2061 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 2093 | jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); |
2062 | 2094 | ||
2063 | if (mode & MODE_RAW) | 2095 | if (mode & MODE_RAW) |
2064 | fmt = 0x2d; | 2096 | fmt = 0x2d; |
2065 | else if (mode & MODE_JPEG) | 2097 | else if (mode & MODE_JPEG) |
2066 | fmt = 0x2c; | 2098 | fmt = 0x24; |
2067 | else | 2099 | else |
2068 | fmt = 0x2f; /* YUV 420 */ | 2100 | fmt = 0x2f; /* YUV 420 */ |
2101 | sd->fmt = fmt; | ||
2069 | 2102 | ||
2070 | switch (mode & SCALE_MASK) { | 2103 | switch (mode & SCALE_MASK) { |
2071 | case SCALE_1280x1024: | 2104 | case SCALE_1280x1024: |