Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 241870
b: refs/heads/master
c: b96cfc3
h: refs/heads/master
v: v3
  • Loading branch information
Jean-François Moine authored and Mauro Carvalho Chehab committed Mar 21, 2011
1 parent fb04b21 commit cc60545
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dccdcccdd36bf7570967ff53411c7401b8e645d6
refs/heads/master: b96cfc33e74f5ee5a206b2d43bf0bc3898c5a572
109 changes: 86 additions & 23 deletions trunk/drivers/media/video/gspca/sonixj.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,18 @@ struct sd {
atomic_t avg_lum;
u32 exposure;

struct work_struct work;
struct workqueue_struct *work_thread;

u32 pktsz; /* (used by pkt_scan) */
u16 npkt;
u8 nchg;
s8 short_mark;

u8 quality; /* image quality */
#define QUALITY_MIN 60
#define QUALITY_MAX 95
#define QUALITY_DEF 80
#define QUALITY_MIN 25
#define QUALITY_MAX 90
#define QUALITY_DEF 70

u8 reg01;
u8 reg17;
Expand Down Expand Up @@ -100,6 +106,8 @@ enum sensors {
SENSOR_SP80708,
};

static void qual_upd(struct work_struct *work);

/* device flags */
#define F_PDN_INV 0x01 /* inverse pin S_PWR_DN / sn_xxx tables */
#define F_ILLUM 0x02 /* presence of illuminator */
Expand Down Expand Up @@ -1786,6 +1794,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->ag_cnt = -1;
sd->quality = QUALITY_DEF;

INIT_WORK(&sd->work, qual_upd);

return 0;
}

Expand Down Expand Up @@ -2297,6 +2307,19 @@ static void setjpegqual(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x18, sd->reg18);
}

/* JPEG quality update */
/* This function is executed from a work queue. */
static void qual_upd(struct work_struct *work)
{
struct sd *sd = container_of(work, struct sd, work);
struct gspca_dev *gspca_dev = &sd->gspca_dev;

mutex_lock(&gspca_dev->usb_lock);
PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);
setjpegqual(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock);
}

/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
Expand Down Expand Up @@ -2610,6 +2633,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
setcolors(gspca_dev);
setautogain(gspca_dev);
setfreq(gspca_dev);

sd->pktsz = sd->npkt = 0;
sd->nchg = sd->short_mark = 0;
sd->work_thread = create_singlethread_workqueue(MODULE_NAME);

return gspca_dev->usb_err;
}

Expand Down Expand Up @@ -2686,6 +2714,20 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
/* reg_w1(gspca_dev, 0xf1, 0x01); */
}

/* called on streamoff with alt==0 and on disconnect */
/* the usb_lock is held at entry - restore on exit */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;

if (sd->work_thread != NULL) {
mutex_unlock(&gspca_dev->usb_lock);
destroy_workqueue(sd->work_thread);
mutex_lock(&gspca_dev->usb_lock);
sd->work_thread = NULL;
}
}

static void do_autogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
Expand Down Expand Up @@ -2778,7 +2820,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
int i, new_qual;

/*
* A frame ends on the marker
Expand Down Expand Up @@ -2818,6 +2860,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
data += i;
}

/* count the packets and their size */
sd->npkt++;
sd->pktsz += len;

/* search backwards if there is a marker in the packet */
for (i = len - 1; --i >= 0; ) {
if (data[i] != 0xff) {
Expand All @@ -2843,27 +2889,60 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
return;

/* marker found */
/* if some error, discard the frame */
/* if some error, discard the frame and decrease the quality */
marker_found:
new_qual = 0;
if (i > 2) {
if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
gspca_dev->last_packet_type = DISCARD_PACKET;
new_qual = -3;
}
} else if (i + 6 < len) {
if (data[i + 6] & 0x08) {
gspca_dev->last_packet_type = DISCARD_PACKET;
new_qual = -5;
}
}

gspca_frame_add(gspca_dev, LAST_PACKET, data, i);

/* compute the filling rate and a new JPEG quality */
if (new_qual == 0) {
int r;

r = (sd->pktsz * 100) /
(sd->npkt *
gspca_dev->urb[0]->iso_frame_desc[0].length);
if (r >= 85)
new_qual = -3;
else if (r < 75)
new_qual = 2;
}
if (new_qual != 0) {
sd->nchg += new_qual;
if (sd->nchg < -6 || sd->nchg >= 12) {
sd->nchg = 0;
new_qual += sd->quality;
if (new_qual < QUALITY_MIN)
new_qual = QUALITY_MIN;
else if (new_qual > QUALITY_MAX)
new_qual = QUALITY_MAX;
if (new_qual != sd->quality) {
sd->quality = new_qual;
queue_work(sd->work_thread, &sd->work);
}
}
} else {
sd->nchg = 0;
}
sd->pktsz = sd->npkt = 0;

/* if the marker is smaller than 62 bytes,
* memorize the number of bytes to skip in the next packet */
if (i + 62 > len) { /* no more usable data */
sd->short_mark = i + 62 - len;
return;
}

if (sd->ag_cnt >= 0)
set_lum(sd, data + i);

Expand All @@ -2878,22 +2957,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
}
}

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)
setjpegqual(gspca_dev);
return 0;
}

static int sd_get_jcomp(struct gspca_dev *gspca_dev,
struct v4l2_jpegcompression *jcomp)
{
Expand Down Expand Up @@ -2955,10 +3018,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,
.dq_callback = do_autogain,
.get_jcomp = sd_get_jcomp,
.set_jcomp = sd_set_jcomp,
.querymenu = sd_querymenu,
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
.int_pkt_scan = sd_int_pkt_scan,
Expand Down

0 comments on commit cc60545

Please sign in to comment.