aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/gspca/sonixj.c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2009-03-03 05:33:41 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 12:43:22 -0300
commit71cb2764fcc51bd9e1b95be5b0f2da6f026634c7 (patch)
treecad0450231d5b4e7db071396ea5a33dabd3e314e /drivers/media/video/gspca/sonixj.c
parentc98afbfc20355dd04a7b817b232e06a4c3e73bac (diff)
V4L/DVB (11039): gspca - most jpeg subdrivers: Change the JPEG header creation.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/sonixj.c')
-rw-r--r--drivers/media/video/gspca/sonixj.c94
1 files changed, 65 insertions, 29 deletions
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index edc26d8ad2a..363c0fa39d9 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -22,7 +22,6 @@
#define MODULE_NAME "sonixj"
#include "gspca.h"
-#define QUANT_VAL 4 /* quantization table */
#include "jpeg.h"
#define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0)
@@ -47,6 +46,10 @@ struct sd {
u8 gamma;
u8 vflip; /* ov7630/ov7648 only */
u8 infrared; /* mt9v111 only */
+ u8 quality; /* image quality */
+ u8 jpegqual; /* webcam quality */
+
+ u8 reg18;
s8 ag_cnt;
#define AG_CNT_START 13
@@ -68,6 +71,8 @@ struct sd {
#define SENSOR_OV7660 7
#define SENSOR_SP80708 8
u8 i2c_base;
+
+ u8 *jpeg_hdr;
};
/* V4L2 controls supported by the driver */
@@ -859,25 +864,6 @@ static const u8 sp80708_sensor_init[][8] = {
{}
};
-static const u8 qtable4[] = {
- 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06,
- 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x0a, 0x11,
- 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f,
- 0x0c, 0x11, 0x19, 0x15, 0x19, 0x19, 0x17, 0x15,
- 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d,
- 0x23, 0x1d, 0x17, 0x17, 0x21, 0x2e, 0x21, 0x23,
- 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30,
- 0x32, 0x2e, 0x29, 0x32, 0x25, 0x29, 0x2c, 0x29,
- 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
- 0x0a, 0x13, 0x29, 0x1b, 0x17, 0x1b, 0x29, 0x29,
- 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
- 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
- 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
- 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
- 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
- 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29
-};
-
/* read <len> bytes to gspca_dev->usb_buf */
static void reg_r(struct gspca_dev *gspca_dev,
u16 value, int len)
@@ -1309,6 +1295,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
else
sd->vflip = 1;
sd->infrared = INFRARED_DEF;
+ sd->quality = 80;
+ sd->jpegqual = 80;
gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
return 0;
@@ -1610,12 +1598,49 @@ static void setinfrared(struct sd *sd)
sd->infrared ? 0x66 : 0x64);
}
+static void setjpegqual(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i, sc;
+
+ if (sd->jpegqual < 50)
+ sc = 5000 / sd->jpegqual;
+ else
+ sc = 200 - sd->jpegqual * 2;
+#if USB_BUF_SZ < 64
+#error "No room enough in usb_buf for quantization table"
+#endif
+ for (i = 0; i < 64; i++)
+ gspca_dev->usb_buf[i] =
+ (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+ usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ 0x08,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+ 0x0100, 0,
+ gspca_dev->usb_buf, 64,
+ 500);
+ for (i = 0; i < 64; i++)
+ gspca_dev->usb_buf[i] =
+ (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+ usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ 0x08,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+ 0x0140, 0,
+ gspca_dev->usb_buf, 64,
+ 500);
+
+ sd->reg18 ^= 0x40;
+ reg_w1(gspca_dev, 0x18, sd->reg18);
+}
+
/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
- u8 reg1, reg17, reg18;
+ u8 reg1, reg17;
const u8 *sn9c1xx;
int mode;
static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
@@ -1624,6 +1649,12 @@ static int sd_start(struct gspca_dev *gspca_dev)
static const u8 CE_ov76xx[] =
{ 0x32, 0xdd, 0x32, 0xdd };
+ /* create the JPEG header */
+ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+ jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ 0x21); /* JPEG 422 */
+ jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
sn9c1xx = sn_tb[(int) sd->sensor];
configure_gpio(gspca_dev, sn9c1xx);
@@ -1782,13 +1813,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
}
/* here change size mode 0 -> VGA; 1 -> CIF */
- reg18 = sn9c1xx[0x18] | (mode << 4);
- reg_w1(gspca_dev, 0x18, reg18 | 0x40);
-
- reg_w(gspca_dev, 0x0100, qtable4, 0x40);
- reg_w(gspca_dev, 0x0140, qtable4 + 0x40, 0x40);
-
- reg_w1(gspca_dev, 0x18, reg18);
+ sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
+ reg_w1(gspca_dev, 0x18, sd->reg18);
+ setjpegqual(gspca_dev);
reg_w1(gspca_dev, 0x17, reg17);
reg_w1(gspca_dev, 0x01, reg1);
@@ -1845,6 +1872,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0xf1, 0x00);
}
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ kfree(sd->jpeg_hdr);
+}
+
static void do_autogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -1928,7 +1962,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
if (gspca_dev->last_packet_type == LAST_PACKET) {
/* put the JPEG 422 header */
- jpeg_put_header(gspca_dev, frame, 0x21);
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+ sd->jpeg_hdr, JPEG_HDR_SZ);
}
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
@@ -2104,6 +2139,7 @@ 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,
};