summaryrefslogtreecommitdiff
path: root/drivers/media/video/gspca/ov519.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/ov519.c')
-rw-r--r--drivers/media/video/gspca/ov519.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index ef88e244df17..a63cb75aa7f1 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -80,6 +80,10 @@ struct sd {
__u8 vflip;
__u8 autobrightness;
__u8 freq;
+ __u8 quality;
+#define QUALITY_MIN 50
+#define QUALITY_MAX 70
+#define QUALITY_DEF 50
__u8 stopped; /* Streaming is temporarily paused */
@@ -104,6 +108,8 @@ struct sd {
int sensor_width;
int sensor_height;
int sensor_reg_cache[256];
+
+ u8 *jpeg_hdr;
};
/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
@@ -2303,8 +2309,6 @@ static int i2c_w_mask(struct sd *sd,
* registers while the camera is streaming */
static inline int ov51x_stop(struct sd *sd)
{
- int ret;
-
PDEBUG(D_STREAM, "stopping");
sd->stopped = 1;
switch (sd->bridge) {
@@ -2319,10 +2323,7 @@ static inline int ov51x_stop(struct sd *sd)
case BRIDGE_OVFX2:
return reg_w_mask(sd, 0x0f, 0x00, 0x02);
case BRIDGE_W9968CF:
- ret = reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
- ret += reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
- ret += reg_w(sd, 0x16, 0x0000); /* stop video capture */
- return ret;
+ return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
}
return 0;
@@ -3088,8 +3089,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
case BRIDGE_W9968CF:
cam->cam_mode = w9968cf_vga_mode;
cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
- /* if (sd->sif)
- cam->nmodes--; */
+ if (sd->sif)
+ cam->nmodes--;
/* w9968cf needs initialisation once the sensor is known */
if (w9968cf_init(sd) < 0)
@@ -3113,6 +3114,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) |
(1 << OV7670_FREQ_IDX);
}
+ sd->quality = QUALITY_DEF;
if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX;
/* OV8610 Frequency filter control should work but needs testing */
@@ -3909,6 +3911,14 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
ov51x_led_control(sd, 0);
}
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->bridge == BRIDGE_W9968CF)
+ w9968cf_stop0(sd);
+}
+
static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *in, /* isoc packet */
@@ -4421,6 +4431,45 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
return -EINVAL;
}
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+ struct v4l2_jpegcompression *jcomp)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->bridge != BRIDGE_W9968CF)
+ return -EINVAL;
+
+ memset(jcomp, 0, sizeof *jcomp);
+ jcomp->quality = sd->quality;
+ jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT |
+ V4L2_JPEG_MARKER_DRI;
+ return 0;
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+ struct v4l2_jpegcompression *jcomp)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->bridge != BRIDGE_W9968CF)
+ return -EINVAL;
+
+ if (gspca_dev->streaming)
+ return -EBUSY;
+
+ if (jcomp->quality < QUALITY_MIN)
+ sd->quality = QUALITY_MIN;
+ else if (jcomp->quality > QUALITY_MAX)
+ sd->quality = QUALITY_MAX;
+ else
+ sd->quality = jcomp->quality;
+
+ /* Return resulting jcomp params to app */
+ sd_get_jcomp(gspca_dev, jcomp);
+
+ return 0;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -4430,8 +4479,11 @@ static const struct sd_desc sd_desc = {
.init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
+ .stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
.querymenu = sd_querymenu,
+ .get_jcomp = sd_get_jcomp,
+ .set_jcomp = sd_set_jcomp,
};
/* -- module initialisation -- */