summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/gspca/sunplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/gspca/sunplus.c')
-rw-r--r--linux/drivers/media/video/gspca/sunplus.c55
1 files changed, 53 insertions, 2 deletions
diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c
index fba6f98d1..428b1e2b7 100644
--- a/linux/drivers/media/video/gspca/sunplus.c
+++ b/linux/drivers/media/video/gspca/sunplus.c
@@ -22,7 +22,6 @@
#define MODULE_NAME "sunplus"
#include "gspca.h"
-#define QUANT_VAL 5 /* quantization table */
#include "jpeg.h"
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
@@ -40,6 +39,10 @@ struct sd {
unsigned char contrast;
unsigned char colors;
unsigned char autogain;
+ u8 quality;
+#define QUALITY_MIN 70
+#define QUALITY_MAX 95
+#define QUALITY_DEF 85
char bridge;
#define BRIDGE_SPCA504 0
@@ -52,6 +55,8 @@ struct sd {
#define LogitechClickSmart420 2
#define LogitechClickSmart820 3
#define MegapixV4 4
+
+ u8 *jpeg_hdr;
};
/* V4L2 controls supported by the driver */
@@ -883,6 +888,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
+ sd->quality = QUALITY_DEF;
return 0;
}
@@ -999,6 +1005,12 @@ static int sd_start(struct gspca_dev *gspca_dev)
__u8 i;
__u8 info[6];
+ /* create the JPEG header */
+ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+ jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ 0x22); /* JPEG 411 */
+ jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
if (sd->bridge == BRIDGE_SPCA504B)
spca504B_setQtable(gspca_dev);
spca504B_SetSizeType(gspca_dev);
@@ -1108,6 +1120,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
}
}
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ kfree(sd->jpeg_hdr);
+}
+
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
@@ -1184,7 +1203,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
ffd9, 2);
/* put the JPEG header in the new frame */
- jpeg_put_header(gspca_dev, frame, 0x22);
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+ sd->jpeg_hdr, JPEG_HDR_SZ);
}
/* add 0x00 after 0xff */
@@ -1333,6 +1353,34 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+ struct v4l2_jpegcompression *jcomp)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (jcomp->quality < QUALITY_MIN)
+ sd->quality = QUALITY_MIN;
+ else if (jcomp->quality > QUALITY_MAX)
+ sd->quality = QUALITY_MAX;
+ else
+ sd->quality = jcomp->quality;
+ if (gspca_dev->streaming)
+ jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+ return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+ struct v4l2_jpegcompression *jcomp)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ memset(jcomp, 0, sizeof *jcomp);
+ jcomp->quality = sd->quality;
+ jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+ | V4L2_JPEG_MARKER_DQT;
+ return 0;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -1342,7 +1390,10 @@ static const struct sd_desc sd_desc = {
.init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
+ .stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
+ .get_jcomp = sd_get_jcomp,
+ .set_jcomp = sd_set_jcomp,
};
/* -- module initialisation -- */