From c5536de72984b82b7290552ec19a6f71423d0931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 19 Nov 2008 21:58:55 +0100 Subject: Add lost ampersand. This restores the correct boolean expression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 1f72e7eae..4f7c6b8e4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -149,7 +149,7 @@ int s5k4aa_read_sensor(struct sd *sd, const u8 address, if (err < 0) goto out; - for (i = 0; (i < len) & !err; i++) { + for (i = 0; (i < len) && !err; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); PDEBUG(D_CONF, "Reading sensor register " -- cgit v1.2.3 From 3f67ca7405a92018713af04e5aeab89cf383ea24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 20 Nov 2008 07:41:44 +0100 Subject: Minor fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_bridge.h | 1 - linux/drivers/media/video/gspca/m5602/m5602_core.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index c1c7ce524..35db1bb9d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -109,7 +109,6 @@ static const unsigned char sensor_urb_skeleton[] = { 0x13, M5602_XB_I2C_CTRL, 0x81, 0x11 }; -/* m5602 device descriptor, currently it just wraps the m5602_camera struct */ struct sd { struct gspca_dev gspca_dev; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index fd6ce384b..0599b4936 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -150,11 +150,12 @@ static int m5602_start_transfer(struct gspca_dev *gspca_dev) /* Send start command to the camera */ const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01}; + memcpy(buf, buffer, sizeof(buffer)); err = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0x04, 0x40, 0x19, 0x0000, buf, - 4, M5602_URB_MSG_TIMEOUT); + sizeof(buffer), M5602_URB_MSG_TIMEOUT); PDEBUG(D_STREAM, "Transfer started"); return (err < 0) ? err : 0; @@ -284,6 +285,7 @@ static int __init mod_m5602_init(void) PDEBUG(D_PROBE, "registered"); return 0; } + static void __exit mod_m5602_exit(void) { usb_deregister(&sd_driver); -- cgit v1.2.3 From 21bfc3ed0635ea073ada626f3653e525b85d05e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 20 Nov 2008 07:46:55 +0100 Subject: Simplify error handling in the mt9m111 sensor code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index fb700c2d0..c93e7474e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -72,7 +72,7 @@ int mt9m111_init(struct sd *sd) int i, err = 0; /* Init the sensor */ - for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) { + for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) { u8 data[2]; if (init_mt9m111[i][0] == BRIDGE) { @@ -109,7 +109,7 @@ int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) *val = data[0] & MT9M111_RMB_MIRROR_ROWS; PDEBUG(D_V4L2, "Read vertical flip %d", *val); - return (err < 0) ? err : 0; + return err; } int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) @@ -133,7 +133,7 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); out: - return (err < 0) ? err : 0; + return err; } int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -147,7 +147,7 @@ int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) *val = data[0] & MT9M111_RMB_MIRROR_COLS; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return (err < 0) ? err : 0; + return err; } int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) @@ -171,7 +171,7 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); out: - return (err < 0) ? err : 0; + return err; } int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) @@ -190,7 +190,7 @@ int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Read gain %d", *val); - return (err < 0) ? err : 0; + return err; } int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -228,7 +228,7 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); out: - return (err < 0) ? err : 0; + return err; } int mt9m111_read_sensor(struct sd *sd, const u8 address, @@ -261,7 +261,7 @@ int mt9m111_read_sensor(struct sd *sd, const u8 address, "0x%x contains 0x%x ", address, *i2c_data); } out: - return (err < 0) ? err : 0; + return err; } int mt9m111_write_sensor(struct sd *sd, const u8 address, -- cgit v1.2.3 From 5af79e4da3ec79bbb3f90154cc3ac75fbbcf34eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 20 Nov 2008 07:54:43 +0100 Subject: Simplify the error handling in the ov9650 sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 81 ++++++++++++---------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 07ef2b3db..c13943077 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -69,18 +69,29 @@ int ov9650_read_sensor(struct sd *sd, const u8 address, err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); } while ((*i2c_data & I2C_BUSY) && !err); - m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, - ov9650.i2c_slave_id); - m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); - m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); - m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, + ov9650.i2c_slave_id); + if (err < 0) + goto out; - for (i = 0; i < len; i++) { + err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + + for (i = 0; (i < len) && !err; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); PDEBUG(D_CONF, "Reading sensor register " - "0x%x containing 0x%x ", address, *i2c_data); + "0x%x containing 0x%x ", address, *i2c_data); } + +out: return (err < 0) ? err : 0; } @@ -105,7 +116,7 @@ int ov9650_write_sensor(struct sd *sd, const u8 address, /* Special case larger sensor writes */ p = buf + 16; - /* Copy a four byte write sequence for each byte to be written to */ + /* Copy a four byte write sequence for each byte to write over the I2C bus */ for (i = 0; i < len; i++) { memcpy(p, sensor_urb_skeleton + 16, 4); p[3] = i2c_data[i]; @@ -192,28 +203,28 @@ int ov9650_init(struct sd *sd) err = m5602_write_bridge(sd, init_ov9650[i][1], data); } - if (!err && dmi_check_system(ov9650_flip_dmi_table)) { + if (dmi_check_system(ov9650_flip_dmi_table) && !err) { info("vflip quirk active"); data = 0x30; err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1); } - return (err < 0) ? err : 0; + return err; } int ov9650_power_down(struct sd *sd) { - int i; - for (i = 0; i < ARRAY_SIZE(power_down_ov9650); i++) { + int i, err = 0; + for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) { u8 data = power_down_ov9650[i][2]; if (power_down_ov9650[i][0] == SENSOR) - ov9650_write_sensor(sd, + err = ov9650_write_sensor(sd, power_down_ov9650[i][1], &data, 1); else - m5602_write_bridge(sd, power_down_ov9650[i][1], data); + err = m5602_write_bridge(sd, power_down_ov9650[i][1], data); } - return 0; + return err; } int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) @@ -239,7 +250,7 @@ int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Read exposure %d", *val); out: - return (err < 0) ? err : 0; + return err; } int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) @@ -270,7 +281,7 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1); out: - return (err < 0) ? err : 0; + return err; } int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) @@ -285,7 +296,7 @@ int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); *val |= i2c_data; PDEBUG(D_V4L2, "Read gain %d", *val); - return (err < 0) ? err : 0; + return err; } int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -306,7 +317,7 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) /* The 8 LSBs */ i2c_data = val & 0xff; err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); - return (err < 0) ? err : 0; + return err; } int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) @@ -320,7 +331,7 @@ int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Read red gain %d", *val); - return (err < 0) ? err : 0; + return err; } int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) @@ -335,7 +346,7 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1); - return (err < 0) ? err : 0; + return err; } int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) @@ -349,7 +360,7 @@ int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Read blue gain %d", *val); - return (err < 0) ? err : 0; + return err; } int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) @@ -364,7 +375,7 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); - return (err < 0) ? err : 0; + return err; } int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -380,7 +391,7 @@ int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) *val = (i2c_data & OV9650_HFLIP) >> 5; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return (err < 0) ? err : 0; + return err; } int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) @@ -396,14 +407,14 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (dmi_check_system(ov9650_flip_dmi_table)) i2c_data = ((i2c_data & 0xdf) | - (((val ? 0 : 1) & 0x01) << 5)); + (((val ? 0 : 1) & 0x01) << 5)); else i2c_data = ((i2c_data & 0xdf) | - ((val & 0x01) << 5)); + ((val & 0x01) << 5)); err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); out: - return (err < 0) ? err : 0; + return err; } int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -419,7 +430,7 @@ int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) *val = (i2c_data & 0x10) >> 4; PDEBUG(D_V4L2, "Read vertical flip %d", *val); - return (err < 0) ? err : 0; + return err; } int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) @@ -442,7 +453,7 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); out: - return (err < 0) ? err : 0; + return err; } int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) @@ -460,7 +471,7 @@ int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) *val |= i2c_data; PDEBUG(D_V4L2, "Read gain %d", *val); out: - return (err < 0) ? err : 0; + return err; } int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) @@ -488,7 +499,7 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); out: - return (err < 0) ? err : 0; + return err; } int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) @@ -501,7 +512,7 @@ int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) *val = (i2c_data & OV9650_AWB_EN) >> 1; PDEBUG(D_V4L2, "Read auto white balance %d", *val); - return (err < 0) ? err : 0; + return err; } int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) @@ -518,7 +529,7 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); out: - return (err < 0) ? err : 0; + return err; } int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) @@ -531,7 +542,7 @@ int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) *val = (i2c_data & OV9650_AGC_EN) >> 2; PDEBUG(D_V4L2, "Read auto gain control %d", *val); - return (err < 0) ? err : 0; + return err; } int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -548,7 +559,7 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); out: - return (err < 0) ? err : 0; + return err; } void ov9650_dump_registers(struct sd *sd) -- cgit v1.2.3 From b5f8746408edc42ff529198b54e61760d3b9f8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 20 Nov 2008 07:59:02 +0100 Subject: Cleanup the po1030 sensor error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 51 +++++++++++++--------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index d17ac5256..739f2df55 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -73,19 +73,28 @@ int po1030_read_sensor(struct sd *sd, const u8 address, err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); } while ((*i2c_data & I2C_BUSY) && !err); - m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, - sd->sensor->i2c_slave_id); - m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); - m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); - m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, + sd->sensor->i2c_slave_id); + if (err < 0) + goto out; + err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); + if (err < 0) + goto out; + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); + if (err < 0) + goto out; + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + if (err < 0) + goto out; - for (i = 0; i < len; i++) { + for (i = 0; (i < len) && !err; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); PDEBUG(D_CONF, "Reading sensor register " "0x%x containing 0x%x ", address, *i2c_data); } - return (err < 0) ? err : 0; +out: + return err; } int po1030_write_sensor(struct sd *sd, const u8 address, @@ -135,7 +144,7 @@ int po1030_init(struct sd *sd) int i, err = 0; /* Init the sensor */ - for (i = 0; i < ARRAY_SIZE(init_po1030); i++) { + for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) { u8 data[2] = {0x00, 0x00}; switch (init_po1030[i][0]) { @@ -166,7 +175,7 @@ int po1030_init(struct sd *sd) if (dump_sensor) po1030_dump_registers(sd); - return (err < 0) ? err : 0; + return err; } int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) @@ -187,7 +196,7 @@ int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Exposure read as %d", *val); out: - return (err < 0) ? err : 0; + return err; } int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) @@ -214,7 +223,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) &i2c_data, 1); out: - return (err < 0) ? err : 0; + return err; } int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) @@ -228,7 +237,7 @@ int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) *val = i2c_data; PDEBUG(D_V4L2, "Read global gain %d", *val); - return (err < 0) ? err : 0; + return err; } int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -244,7 +253,7 @@ int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Read hflip %d", *val); - return (err < 0) ? err : 0; + return err; } int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) @@ -260,7 +269,7 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) err = po1030_write_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); - return (err < 0) ? err : 0; + return err; } int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -276,7 +285,7 @@ int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Read vflip %d", *val); - return (err < 0) ? err : 0; + return err; } int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) @@ -292,7 +301,7 @@ int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) err = po1030_write_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); - return (err < 0) ? err : 0; + return err; } int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -305,7 +314,7 @@ int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN, &i2c_data, 1); - return (err < 0) ? err : 0; + return err; } int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) @@ -318,7 +327,7 @@ int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) &i2c_data, 1); *val = i2c_data; PDEBUG(D_V4L2, "Read red gain %d", *val); - return (err < 0) ? err : 0; + return err; } int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) @@ -331,7 +340,7 @@ int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set red gain to %d", i2c_data); err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN, &i2c_data, 1); - return (err < 0) ? err : 0; + return err; } int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) @@ -345,7 +354,7 @@ int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) *val = i2c_data; PDEBUG(D_V4L2, "Read blue gain %d", *val); - return (err < 0) ? err : 0; + return err; } int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) @@ -358,7 +367,7 @@ int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN, &i2c_data, 1); - return (err < 0) ? err : 0; + return err; } int po1030_power_down(struct sd *sd) -- cgit v1.2.3 From 5fca367f7519ebcbfb5372997f87187bcf112843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 20 Nov 2008 08:02:44 +0100 Subject: Cleanup the s5k4aa error handling, cull some comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 19 ++++++++++--------- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 9 ++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 4f7c6b8e4..854f3f7f1 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -110,6 +110,7 @@ int s5k4aa_probe(struct sd *sd) return -ENODEV; else info("Detected a s5k4aa sensor"); + sensor_found: sd->gspca_dev.cam.cam_mode = s5k4aa.modes; sd->gspca_dev.cam.nmodes = s5k4aa.nmodes; @@ -156,7 +157,7 @@ int s5k4aa_read_sensor(struct sd *sd, const u8 address, "0x%x containing 0x%x ", address, *i2c_data); } out: - return (err < 0) ? err : 0; + return err; } int s5k4aa_write_sensor(struct sd *sd, const u8 address, @@ -285,7 +286,7 @@ int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) *val |= data; PDEBUG(D_V4L2, "Read exposure %d", *val); out: - return (err < 0) ? err : 0; + return err; } int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) @@ -305,7 +306,7 @@ int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) data = val & 0xff; err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); out: - return (err < 0) ? err : 0; + return err; } int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -323,7 +324,7 @@ int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Read vertical flip %d", *val); out: - return (err < 0) ? err : 0; + return err; } int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) @@ -361,7 +362,7 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } out: - return (err < 0) ? err : 0; + return err; } int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -378,7 +379,7 @@ int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) *val = (data & S5K4AA_RM_H_FLIP) >> 6; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); out: - return (err < 0) ? err : 0; + return err; } int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) @@ -417,7 +418,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); } out: - return (err < 0) ? err : 0; + return err; } int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) @@ -435,7 +436,7 @@ int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) PDEBUG(D_V4L2, "Read gain %d", *val); out: - return (err < 0) ? err : 0; + return err; } int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -453,7 +454,7 @@ int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1); out: - return (err < 0) ? err : 0; + return err; } void s5k4aa_dump_registers(struct sd *sd) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 151c6f530..b6aca3678 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -41,11 +41,10 @@ #define S5K4AA_WINDOW_HEIGHT_LO 0x09 #define S5K4AA_WINDOW_WIDTH_HI 0x0a #define S5K4AA_WINDOW_WIDTH_LO 0x0b -#define S5K4AA_GLOBAL_GAIN__ 0x0f /* Only a guess ATM !!! */ -#define S5K4AA_H_BLANK_HI__ 0x1d /* Only a guess ATM !!! sync lost - if too low, reduces frame rate - if too high */ -#define S5K4AA_H_BLANK_LO__ 0x1e /* Only a guess ATM !!! */ +#define S5K4AA_GLOBAL_GAIN__ 0x0f +/* sync lost, if too low, reduces frame rate if too high */ +#define S5K4AA_H_BLANK_HI__ 0x1d +#define S5K4AA_H_BLANK_LO__ 0x1e #define S5K4AA_EXPOSURE_HI 0x17 #define S5K4AA_EXPOSURE_LO 0x18 #define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */ -- cgit v1.2.3 From a7cb8683d39a907c443815f04d78fd26ec97397d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 20 Nov 2008 18:03:22 +0100 Subject: Align some defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c | 6 +++--- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 8988a728e..0f2addd98 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -69,7 +69,7 @@ sensor_found: } int s5k83a_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) + u8 *i2c_data, const u8 len) { int err, i; @@ -106,11 +106,11 @@ int s5k83a_read_sensor(struct sd *sd, const u8 address, } out: - return (err < 0) ? err : 0; + return err; } int s5k83a_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) + u8 *i2c_data, const u8 len) { int err, i; u8 *p; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index ee3ee9cfc..acc89d08f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -22,15 +22,15 @@ #include "m5602_sensor.h" #define S5K83A_FLIP 0x01 -#define S5K83A_HFLIP_TUNE 0x03 -#define S5K83A_VFLIP_TUNE 0x05 -#define S5K83A_WHITENESS 0x0a +#define S5K83A_HFLIP_TUNE 0x03 +#define S5K83A_VFLIP_TUNE 0x05 +#define S5K83A_WHITENESS 0x0a #define S5K83A_GAIN 0x18 -#define S5K83A_BRIGHTNESS 0x1b -#define S5K83A_PAGE_MAP 0xec +#define S5K83A_BRIGHTNESS 0x1b +#define S5K83A_PAGE_MAP 0xec -#define S5K83A_DEFAULT_BRIGHTNESS 0x71 -#define S5K83A_DEFAULT_WHITENESS 0x7e +#define S5K83A_DEFAULT_BRIGHTNESS 0x71 +#define S5K83A_DEFAULT_WHITENESS 0x7e #define S5K83A_DEFAULT_GAIN 0x00 #define S5K83A_MAXIMUM_GAIN 0x3c #define S5K83A_FLIP_MASK 0x10 -- cgit v1.2.3 From 4ea7c4ecaa98dc74519b6975411037744e48f463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 20 Nov 2008 18:11:58 +0100 Subject: Refactor the error handling in the s5k83a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 62 +++++++++++++--------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 0f2addd98..00f0964e0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -89,15 +89,11 @@ int s5k83a_read_sensor(struct sd *sd, const u8 address, goto out; err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); - if (err < 0) - goto out; do { err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); } while ((*i2c_data & I2C_BUSY) && !err); - if (err < 0) - goto out; for (i = 0; i < len && !len; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); @@ -245,10 +241,14 @@ int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) struct sd *sd = (struct sd *) gspca_dev; err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2); + if (err < 0) + goto out; + data[1] = data[1] << 1; *val = data[1]; - return (err < 0) ? err : 0; +out: + return err; } int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) @@ -261,13 +261,13 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) data[1] = 0x20; err = s5k83a_write_sensor(sd, 0x14, data, 2); if (err < 0) - return err; + goto out; data[0] = 0x01; data[1] = 0x00; err = s5k83a_write_sensor(sd, 0x0d, data, 2); if (err < 0) - return err; + goto out; /* FIXME: This is not sane, we need to figure out the composition of these registers */ @@ -275,7 +275,8 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) data[1] = val >> 1; /* brightness, high 7 bits */ err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2); - return (err < 0) ? err : 0; +out: + return err; } int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val) @@ -285,9 +286,13 @@ int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val) struct sd *sd = (struct sd *) gspca_dev; err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1); + if (err < 0) + goto out; *val = data; - return (err < 0) ? err : 0; + +out: + return err; } int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val) @@ -299,7 +304,7 @@ int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val) data[0] = val; err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1); - return (err < 0) ? err : 0; + return err; } int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) @@ -309,6 +314,8 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) struct sd *sd = (struct sd *) gspca_dev; err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2); + if (err < 0) + goto out; data[1] = data[1] & 0x3f; if (data[1] > S5K83A_MAXIMUM_GAIN) @@ -316,7 +323,8 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) *val = data[1]; - return (err < 0) ? err : 0; +out: + return err; } int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -328,8 +336,7 @@ int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) data[0] = 0; data[1] = val; err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2); - - return (err < 0) ? err : 0; + return err; } int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -341,12 +348,13 @@ int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) data[0] = 0x05; err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) - return err; + goto out; err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); *val = (data[0] | 0x40) ? 1 : 0; - return (err < 0) ? err : 0; +out: + return err; } int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) @@ -358,23 +366,24 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) data[0] = 0x05; err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) - return err; + goto out; err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) - return err; + goto out; /* set or zero six bit, seven is hflip */ data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK : (data[0] & 0x80) | S5K83A_FLIP_MASK; err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) - return err; + goto out; data[0] = (val) ? 0x0b : 0x0a; err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); - return (err < 0) ? err : 0; +out: + return err; } int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) @@ -386,12 +395,13 @@ int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) data[0] = 0x05; err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) - return err; + goto out; err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); *val = (data[0] | 0x80) ? 1 : 0; - return (err < 0) ? err : 0; +out: + return err; } int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) @@ -403,21 +413,21 @@ int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) data[0] = 0x05; err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) - return err; + goto out; err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) - return err; + goto out; /* set or zero seven bit, six is vflip */ data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK : (data[0] & 0x40) | S5K83A_FLIP_MASK; err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) - return err; + goto out; data[0] = (val) ? 0x0a : 0x0b; err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); - - return (err < 0) ? err : 0; +out: + return err; } -- cgit v1.2.3 From d1d4c7f36c5e80f2f6c427b8dd3455f36ae33c6d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 30 Nov 2008 01:36:58 +0100 Subject: v4l2: add v4l2_device and v4l2_subdev structs to the v4l2 framework. From: Hans Verkuil Start implementing a proper v4l2 framework as discussed during the Linux Plumbers Conference 2008. Introduces v4l2_device (for device instances) and v4l2_subdev (representing sub-device instances). Priority: normal Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Andy Walls Reviewed-by: David Brownell --- linux/Documentation/video4linux/v4l2-framework.txt | 362 +++++++++++++++++++++ linux/drivers/media/video/Makefile | 2 +- linux/drivers/media/video/v4l2-device.c | 86 +++++ linux/drivers/media/video/v4l2-subdev.c | 108 ++++++ linux/include/media/v4l2-device.h | 109 +++++++ linux/include/media/v4l2-subdev.h | 188 +++++++++++ 6 files changed, 854 insertions(+), 1 deletion(-) create mode 100644 linux/Documentation/video4linux/v4l2-framework.txt create mode 100644 linux/drivers/media/video/v4l2-device.c create mode 100644 linux/drivers/media/video/v4l2-subdev.c create mode 100644 linux/include/media/v4l2-device.h create mode 100644 linux/include/media/v4l2-subdev.h diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt new file mode 100644 index 000000000..60eaf54e7 --- /dev/null +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -0,0 +1,362 @@ +Overview of the V4L2 driver framework +===================================== + +This text documents the various structures provided by the V4L2 framework and +their relationships. + + +Introduction +------------ + +The V4L2 drivers tend to be very complex due to the complexity of the +hardware: most devices have multiple ICs, export multiple device nodes in +/dev, and create also non-V4L2 devices such as DVB, ALSA, FB, I2C and input +(IR) devices. + +Especially the fact that V4L2 drivers have to setup supporting ICs to +do audio/video muxing/encoding/decoding makes it more complex than most. +Usually these ICs are connected to the main bridge driver through one or +more I2C busses, but other busses can also be used. Such devices are +called 'sub-devices'. + +For a long time the framework was limited to the video_device struct for +creating V4L device nodes and video_buf for handling the video buffers +(note that this document does not discuss the video_buf framework). + +This meant that all drivers had to do the setup of device instances and +connecting to sub-devices themselves. Some of this is quite complicated +to do right and many drivers never did do it correctly. + +There is also a lot of common code that could never be refactored due to +the lack of a framework. + +So this framework sets up the basic building blocks that all drivers +need and this same framework should make it much easier to refactor +common code into utility functions shared by all drivers. + + +Structure of a driver +--------------------- + +All drivers have the following structure: + +1) A struct for each device instance containing the device state. + +2) A way of initializing and commanding sub-devices (if any). + +3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX, /dev/radioX and + /dev/vtxX) and keeping track of device-node specific data. + +4) Filehandle-specific structs containing per-filehandle data. + +This is a rough schematic of how it all relates: + + device instances + | + +-sub-device instances + | + \-V4L2 device nodes + | + \-filehandle instances + + +Structure of the framework +-------------------------- + +The framework closely resembles the driver structure: it has a v4l2_device +struct for the device instance data, a v4l2_subdev struct to refer to +sub-device instances, the video_device struct stores V4L2 device node data +and in the future a v4l2_fh struct will keep track of filehandle instances +(this is not yet implemented). + + +struct v4l2_device +------------------ + +Each device instance is represented by a struct v4l2_device (v4l2-device.h). +Very simple devices can just allocate this struct, but most of the time you +would embed this struct inside a larger struct. + +You must register the device instance: + + v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); + +Registration will initialize the v4l2_device struct and link dev->driver_data +to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from +dev (driver name followed by the bus_id, to be precise). You may change the +name after registration if you want. + +You unregister with: + + v4l2_device_unregister(struct v4l2_device *v4l2_dev); + +Unregistering will also automatically unregister all subdevs from the device. + +Sometimes you need to iterate over all devices registered by a specific +driver. This is usually the case if multiple device drivers use the same +hardware. E.g. the ivtvfb driver is a framebuffer driver that uses the ivtv +hardware. The same is true for alsa drivers for example. + +You can iterate over all registered devices as follows: + +static int callback(struct device *dev, void *p) +{ + struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); + + /* test if this device was inited */ + if (v4l2_dev == NULL) + return 0; + ... + return 0; +} + +int iterate(void *p) +{ + struct device_driver *drv; + int err; + + /* Find driver 'ivtv' on the PCI bus. + pci_bus_type is a global. For USB busses use usb_bus_type. */ + drv = driver_find("ivtv", &pci_bus_type); + /* iterate over all ivtv device instances */ + err = driver_for_each_device(drv, NULL, p, callback); + put_driver(drv); + return err; +} + +Sometimes you need to keep a running counter of the device instance. This is +commonly used to map a device instance to an index of a module option array. + +The recommended approach is as follows: + +static atomic_t drv_instance = ATOMIC_INIT(0); + +static int __devinit drv_probe(struct pci_dev *dev, + const struct pci_device_id *pci_id) +{ + ... + state->instance = atomic_inc_return(&drv_instance) - 1; +} + + +struct v4l2_subdev +------------------ + +Many drivers need to communicate with sub-devices. These devices can do all +sort of tasks, but most commonly they handle audio and/or video muxing, +encoding or decoding. For webcams common sub-devices are sensors and camera +controllers. + +Usually these are I2C devices, but not necessarily. In order to provide the +driver with a consistent interface to these sub-devices the v4l2_subdev struct +(v4l2-subdev.h) was created. + +Each sub-device driver must have a v4l2_subdev struct. This struct can be +stand-alone for simple sub-devices or it might be embedded in a larger struct +if more state information needs to be stored. Usually there is a low-level +device struct (e.g. i2c_client) that contains the device data as setup +by the kernel. It is recommended to store that pointer in the private +data of v4l2_subdev using v4l2_set_subdevdata(). That makes it easy to go +from a v4l2_subdev to the actual low-level bus-specific device data. + +You also need a way to go from the low-level struct to v4l2_subdev. For the +common i2c_client struct the i2c_set_clientdata() call is used to store a +v4l2_subdev pointer, for other busses you may have to use other methods. + +From the bridge driver perspective you load the sub-device module and somehow +obtain the v4l2_subdev pointer. For i2c devices this is easy: you call +i2c_get_clientdata(). For other busses something similar needs to be done. +Helper functions exists for sub-devices on an I2C bus that do most of this +tricky work for you. + +Each v4l2_subdev contains function pointers that sub-device drivers can +implement (or leave NULL if it is not applicable). Since sub-devices can do +so many different things and you do not want to end up with a huge ops struct +of which only a handful of ops are commonly implemented, the function pointers +are sorted according to category and each category has its own ops struct. + +The top-level ops struct contains pointers to the category ops structs, which +may be NULL if the subdev driver does not support anything from that category. + +It looks like this: + +struct v4l2_subdev_core_ops { + int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip); + int (*log_status)(struct v4l2_subdev *sd); + int (*init)(struct v4l2_subdev *sd, u32 val); + ... +}; + +struct v4l2_subdev_tuner_ops { + ... +}; + +struct v4l2_subdev_audio_ops { + ... +}; + +struct v4l2_subdev_video_ops { + ... +}; + +struct v4l2_subdev_ops { + const struct v4l2_subdev_core_ops *core; + const struct v4l2_subdev_tuner_ops *tuner; + const struct v4l2_subdev_audio_ops *audio; + const struct v4l2_subdev_video_ops *video; +}; + +The core ops are common to all subdevs, the other categories are implemented +depending on the sub-device. E.g. a video device is unlikely to support the +audio ops and vice versa. + +This setup limits the number of function pointers while still making it easy +to add new ops and categories. + +A sub-device driver initializes the v4l2_subdev struct using: + + v4l2_subdev_init(subdev, &ops); + +Afterwards you need to initialize subdev->name with a unique name and set the +module owner. This is done for you if you use the i2c helper functions. + +A device (bridge) driver needs to register the v4l2_subdev with the +v4l2_device: + + int err = v4l2_device_register_subdev(device, subdev); + +This can fail if the subdev module disappeared before it could be registered. +After this function was called successfully the subdev->dev field points to +the v4l2_device. + +You can unregister a sub-device using: + + v4l2_device_unregister_subdev(subdev); + +Afterwards the subdev module can be unloaded and subdev->dev == NULL. + +You can call an ops function either directly: + + err = subdev->ops->core->g_chip_ident(subdev, &chip); + +but it is better and easier to use this macro: + + err = v4l2_subdev_call(subdev, core, g_chip_ident, &chip); + +The macro will to the right NULL pointer checks and returns -ENODEV if subdev +is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_chip_ident is +NULL, or the actual result of the subdev->ops->core->g_chip_ident ops. + +It is also possible to call all or a subset of the sub-devices: + + v4l2_device_call_all(dev, 0, core, g_chip_ident, &chip); + +Any subdev that does not support this ops is skipped and error results are +ignored. If you want to check for errors use this: + + err = v4l2_device_call_until_err(dev, 0, core, g_chip_ident, &chip); + +Any error except -ENOIOCTLCMD will exit the loop with that error. If no +errors (except -ENOIOCTLCMD) occured, then 0 is returned. + +The second argument to both calls is a group ID. If 0, then all subdevs are +called. If non-zero, then only those whose group ID match that value will +be called. Before a bridge driver registers a subdev it can set subdev->grp_id +to whatever value it wants (it's 0 by default). This value is owned by the +bridge driver and the sub-device driver will never modify or use it. + +The group ID gives the bridge driver more control how callbacks are called. +For example, there may be multiple audio chips on a board, each capable of +changing the volume. But usually only one will actually be used when the +user want to change the volume. You can set the group ID for that subdev to +e.g. AUDIO_CONTROLLER and specify that as the group ID value when calling +v4l2_device_call_all(). That ensures that it will only go to the subdev +that needs it. + +The advantage of using v4l2_subdev is that it is a generic struct and does +not contain any knowledge about the underlying hardware. So a driver might +contain several subdevs that use an I2C bus, but also a subdev that is +controlled through GPIO pins. This distinction is only relevant when setting +up the device, but once the subdev is registered it is completely transparent. + + +I2C sub-device drivers +---------------------- + +Since these drivers are so common, special helper functions are available to +ease the use of these drivers (v4l2-common.h). + +The recommended method of adding v4l2_subdev support to an I2C driver is to +embed the v4l2_subdev struct into the state struct that is created for each +I2C device instance. Very simple devices have no state struct and in that case +you can just create a v4l2_subdev directly. + +A typical state struct would look like this (where 'chipname' is replaced by +the name of the chip): + +struct chipname_state { + struct v4l2_subdev sd; + ... /* additional state fields */ +}; + +Initialize the v4l2_subdev struct as follows: + + v4l2_i2c_subdev_init(&state->sd, client, subdev_ops); + +This function will fill in all the fields of v4l2_subdev and ensure that the +v4l2_subdev and i2c_client both point to one another. + +You should also add a helper inline function to go from a v4l2_subdev pointer +to a chipname_state struct: + +static inline struct chipname_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct chipname_state, sd); +} + +Use this to go from the v4l2_subdev struct to the i2c_client struct: + + struct i2c_client *client = v4l2_get_subdevdata(sd); + +And this to go from an i2c_client to a v4l2_subdev struct: + + struct v4l2_subdev *sd = i2c_get_clientdata(client); + +Finally you need to make a command function to make driver->command() +call the right subdev_ops functions: + +static int subdev_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +If driver->command is never used then you can leave this out. Eventually the +driver->command usage should be removed from v4l. + +Make sure to call v4l2_device_unregister_subdev(sd) when the remove() callback +is called. This will unregister the sub-device from the bridge driver. It is +safe to call this even if the sub-device was never registered. + + +The bridge driver also has some helper functions it can use: + +struct v4l2_subdev *sd = v4l2_i2c_new_subdev(adapter, "module_foo", "chipid", 0x36); + +This loads the given module (can be NULL if no module needs to be loaded) and +calls i2c_new_device() with the given i2c_adapter and chip/address arguments. +If all goes well, then it registers the subdev with the v4l2_device. It gets +the v4l2_device by calling i2c_get_adapdata(adapter), so you should make sure +that adapdata is set to v4l2_device when you setup the i2c_adapter in your +driver. + +You can also use v4l2_i2c_new_probed_subdev() which is very similar to +v4l2_i2c_new_subdev(), except that it has an array of possible I2C addresses +that it should probe. Internally it calls i2c_new_probed_device(). + +Both functions return NULL if something went wrong. + + +struct video_device +------------------- + +Not yet documented. diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 53d43f9e0..d16356ebe 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -8,7 +8,7 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o stkwebcam-objs := stk-webcam.o stk-sensor.o -videodev-objs := v4l2-dev.o v4l2-ioctl.o +videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-subdev.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-compat-ioctl32.o v4l2-int-device.o diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c new file mode 100644 index 000000000..9eefde031 --- /dev/null +++ b/linux/drivers/media/video/v4l2-device.c @@ -0,0 +1,86 @@ +/* + V4L2 device support. + + Copyright (C) 2008 Hans Verkuil + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) +{ + if (dev == NULL || v4l2_dev == NULL) + return -EINVAL; + /* Warn if we apparently re-register a device */ + WARN_ON(dev_get_drvdata(dev)); + INIT_LIST_HEAD(&v4l2_dev->subdevs); + spin_lock_init(&v4l2_dev->lock); + v4l2_dev->dev = dev; + snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", + dev->driver->name, dev->bus_id); + dev_set_drvdata(dev, v4l2_dev); + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_device_register); + +void v4l2_device_unregister(struct v4l2_device *v4l2_dev) +{ + struct v4l2_subdev *sd, *next; + + if (v4l2_dev == NULL || v4l2_dev->dev == NULL) + return; + dev_set_drvdata(v4l2_dev->dev, NULL); + /* unregister subdevs */ + list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) + v4l2_device_unregister_subdev(sd); + + v4l2_dev->dev = NULL; +} +EXPORT_SYMBOL_GPL(v4l2_device_unregister); + +int v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd) +{ + /* Check for valid input */ + if (dev == NULL || sd == NULL || !sd->name[0]) + return -EINVAL; + /* Warn if we apparently re-register a subdev */ + WARN_ON(sd->dev); + if (!try_module_get(sd->owner)) + return -ENODEV; + sd->dev = dev; + spin_lock(&dev->lock); + list_add_tail(&sd->list, &dev->subdevs); + spin_unlock(&dev->lock); + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); + +void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) +{ + /* return if it isn't registered */ + if (sd == NULL || sd->dev == NULL) + return; + spin_lock(&sd->dev->lock); + list_del(&sd->list); + spin_unlock(&sd->dev->lock); + sd->dev = NULL; + module_put(sd->owner); +} +EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev); diff --git a/linux/drivers/media/video/v4l2-subdev.c b/linux/drivers/media/video/v4l2-subdev.c new file mode 100644 index 000000000..fe1f01c97 --- /dev/null +++ b/linux/drivers/media/video/v4l2-subdev.c @@ -0,0 +1,108 @@ +/* + V4L2 sub-device support. + + Copyright (C) 2008 Hans Verkuil + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) +{ + switch (cmd) { + case VIDIOC_QUERYCTRL: + return v4l2_subdev_call(sd, core, querymenu, arg); + case VIDIOC_G_CTRL: + return v4l2_subdev_call(sd, core, g_ctrl, arg); + case VIDIOC_S_CTRL: + return v4l2_subdev_call(sd, core, s_ctrl, arg); + case VIDIOC_QUERYMENU: + return v4l2_subdev_call(sd, core, queryctrl, arg); + case VIDIOC_LOG_STATUS: + return v4l2_subdev_call(sd, core, log_status); + case VIDIOC_G_CHIP_IDENT: + return v4l2_subdev_call(sd, core, g_chip_ident, arg); + case VIDIOC_INT_S_STANDBY: + return v4l2_subdev_call(sd, core, s_standby, *(u32 *)arg); + case VIDIOC_INT_RESET: + return v4l2_subdev_call(sd, core, reset, *(u32 *)arg); + case VIDIOC_INT_S_GPIO: + return v4l2_subdev_call(sd, core, s_gpio, *(u32 *)arg); + case VIDIOC_INT_INIT: + return v4l2_subdev_call(sd, core, init, *(u32 *)arg); +#ifdef CONFIG_VIDEO_ADV_DEBUG + case VIDIOC_DBG_G_REGISTER: + return v4l2_subdev_call(sd, core, g_register, arg); + case VIDIOC_DBG_S_REGISTER: + return v4l2_subdev_call(sd, core, s_register, arg); +#endif + + case VIDIOC_INT_S_TUNER_MODE: + return v4l2_subdev_call(sd, tuner, s_mode, *(enum v4l2_tuner_type *)arg); + case AUDC_SET_RADIO: + return v4l2_subdev_call(sd, tuner, s_radio); + case VIDIOC_S_TUNER: + return v4l2_subdev_call(sd, tuner, s_tuner, arg); + case VIDIOC_G_TUNER: + return v4l2_subdev_call(sd, tuner, g_tuner, arg); + case VIDIOC_S_STD: + return v4l2_subdev_call(sd, tuner, s_std, *(v4l2_std_id *)arg); + case VIDIOC_S_FREQUENCY: + return v4l2_subdev_call(sd, tuner, s_frequency, arg); + case VIDIOC_G_FREQUENCY: + return v4l2_subdev_call(sd, tuner, g_frequency, arg); + case TUNER_SET_TYPE_ADDR: + return v4l2_subdev_call(sd, tuner, s_type_addr, arg); + case TUNER_SET_CONFIG: + return v4l2_subdev_call(sd, tuner, s_config, arg); + + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + return v4l2_subdev_call(sd, audio, s_clock_freq, *(u32 *)arg); + case VIDIOC_INT_S_AUDIO_ROUTING: + return v4l2_subdev_call(sd, audio, s_routing, arg); + case VIDIOC_INT_I2S_CLOCK_FREQ: + return v4l2_subdev_call(sd, audio, s_i2s_clock_freq, *(u32 *)arg); + + case VIDIOC_INT_S_VIDEO_ROUTING: + return v4l2_subdev_call(sd, video, s_routing, arg); + case VIDIOC_INT_S_CRYSTAL_FREQ: + return v4l2_subdev_call(sd, video, s_crystal_freq, arg); + case VIDIOC_INT_DECODE_VBI_LINE: + return v4l2_subdev_call(sd, video, decode_vbi_line, arg); + case VIDIOC_INT_S_VBI_DATA: + return v4l2_subdev_call(sd, video, s_vbi_data, arg); + case VIDIOC_INT_G_VBI_DATA: + return v4l2_subdev_call(sd, video, g_vbi_data, arg); + case VIDIOC_S_FMT: + return v4l2_subdev_call(sd, video, s_fmt, arg); + case VIDIOC_G_FMT: + return v4l2_subdev_call(sd, video, g_fmt, arg); + case VIDIOC_INT_S_STD_OUTPUT: + return v4l2_subdev_call(sd, video, s_std_output, *(v4l2_std_id *)arg); + case VIDIOC_STREAMON: + return v4l2_subdev_call(sd, video, s_stream, 1); + case VIDIOC_STREAMOFF: + return v4l2_subdev_call(sd, video, s_stream, 0); + + default: + return v4l2_subdev_call(sd, core, ioctl, cmd, arg); + } +} +EXPORT_SYMBOL_GPL(v4l2_subdev_command); diff --git a/linux/include/media/v4l2-device.h b/linux/include/media/v4l2-device.h new file mode 100644 index 000000000..97b283a04 --- /dev/null +++ b/linux/include/media/v4l2-device.h @@ -0,0 +1,109 @@ +/* + V4L2 device support header. + + Copyright (C) 2008 Hans Verkuil + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _V4L2_DEVICE_H +#define _V4L2_DEVICE_H + +#include + +/* Each instance of a V4L2 device should create the v4l2_device struct, + either stand-alone or embedded in a larger struct. + + It allows easy access to sub-devices (see v4l2-subdev.h) and provides + basic V4L2 device-level support. + */ + +#define V4L2_DEVICE_NAME_SIZE (BUS_ID_SIZE + 16) + +struct v4l2_device { + /* dev->driver_data points to this struct */ + struct device *dev; + /* used to keep track of the registered subdevs */ + struct list_head subdevs; + /* lock this struct; can be used by the driver as well if this + struct is embedded into a larger struct. */ + spinlock_t lock; + /* unique device name, by default the driver name + bus ID */ + char name[V4L2_DEVICE_NAME_SIZE]; +}; + +/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev */ +int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); +/* Set v4l2_dev->dev->driver_data to NULL and unregister all sub-devices */ +void v4l2_device_unregister(struct v4l2_device *v4l2_dev); + +/* Register a subdev with a v4l2 device. While registered the subdev module + is marked as in-use. An error is returned if the module is no longer + loaded when you attempt to register it. */ +int __must_check v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd); +/* Unregister a subdev with a v4l2 device. Can also be called if the subdev + wasn't registered. In that case it will do nothing. */ +void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); + +/* Iterate over all subdevs. */ +#define v4l2_device_for_each_subdev(sd, dev) \ + list_for_each_entry(sd, &(dev)->subdevs, list) + +/* Call the specified callback for all subdevs matching the condition. + Ignore any errors. Note that you cannot add or delete a subdev + while walking the subdevs list. */ +#define __v4l2_device_call_subdevs(dev, cond, o, f, args...) \ + do { \ + struct v4l2_subdev *sd; \ + \ + list_for_each_entry(sd, &(dev)->subdevs, list) \ + if ((cond) && sd->ops->o && sd->ops->o->f) \ + sd->ops->o->f(sd , ##args); \ + } while (0) + +/* Call the specified callback for all subdevs matching the condition. + If the callback returns an error other than 0 or -ENOIOCTLCMD, then + return with that error code. Note that you cannot add or delete a + subdev while walking the subdevs list. */ +#define __v4l2_device_call_subdevs_until_err(dev, cond, o, f, args...) \ +({ \ + struct v4l2_subdev *sd; \ + int err = 0; \ + \ + list_for_each_entry(sd, &(dev)->subdevs, list) { \ + if ((cond) && sd->ops->o && sd->ops->o->f) \ + err = sd->ops->o->f(sd , ##args); \ + if (err && err != -ENOIOCTLCMD) \ + break; \ + } \ + (err == -ENOIOCTLCMD) ? 0 : err; \ +}) + +/* Call the specified callback for all subdevs matching grp_id (if 0, then + match them all). Ignore any errors. Note that you cannot add or delete + a subdev while walking the subdevs list. */ +#define v4l2_device_call_all(dev, grp_id, o, f, args...) \ + __v4l2_device_call_subdevs(dev, \ + !(grp_id) || sd->grp_id == (grp_id), o, f , ##args) + +/* Call the specified callback for all subdevs matching grp_id (if 0, then + match them all). If the callback returns an error other than 0 or + -ENOIOCTLCMD, then return with that error code. Note that you cannot + add or delete a subdev while walking the subdevs list. */ +#define v4l2_device_call_until_err(dev, grp_id, o, f, args...) \ + __v4l2_device_call_subdevs_until_err(dev, \ + !(grp_id) || sd->grp_id == (grp_id), o, f , ##args) + +#endif diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h new file mode 100644 index 000000000..bc9e0fbf2 --- /dev/null +++ b/linux/include/media/v4l2-subdev.h @@ -0,0 +1,188 @@ +/* + V4L2 sub-device support header. + + Copyright (C) 2008 Hans Verkuil + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _V4L2_SUBDEV_H +#define _V4L2_SUBDEV_H + +#include + +struct v4l2_device; +struct v4l2_subdev; +struct tuner_setup; + +/* Sub-devices are devices that are connected somehow to the main bridge + device. These devices are usually audio/video muxers/encoders/decoders or + sensors and webcam controllers. + + Usually these devices are controlled through an i2c bus, but other busses + may also be used. + + The v4l2_subdev struct provides a way of accessing these devices in a + generic manner. Most operations that these sub-devices support fall in + a few categories: core ops, audio ops, video ops and tuner ops. + + More categories can be added if needed, although this should remain a + limited set (no more than approx. 8 categories). + + Each category has its own set of ops that subdev drivers can implement. + + A subdev driver can leave the pointer to the category ops NULL if + it does not implement them (e.g. an audio subdev will generally not + implement the video category ops). The exception is the core category: + this must always be present. + + These ops are all used internally so it is no problem to change, remove + or add ops or move ops from one to another category. Currently these + ops are based on the original ioctls, but since ops are not limited to + one argument there is room for improvement here once all i2c subdev + drivers are converted to use these ops. + */ + +/* Core ops: it is highly recommended to implement at least these ops: + + g_chip_ident + log_status + g_register + s_register + + This provides basic debugging support. + + The ioctl ops is meant for generic ioctl-like commands. Depending on + the use-case it might be better to use subdev-specific ops (currently + not yet implemented) since ops provide proper type-checking. + */ +struct v4l2_subdev_core_ops { + int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip); + int (*log_status)(struct v4l2_subdev *sd); + int (*init)(struct v4l2_subdev *sd, u32 val); + int (*s_standby)(struct v4l2_subdev *sd, u32 standby); + int (*reset)(struct v4l2_subdev *sd, u32 val); + int (*s_gpio)(struct v4l2_subdev *sd, u32 val); + int (*queryctrl)(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc); + int (*g_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl); + int (*s_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl); + int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm); + int (*ioctl)(struct v4l2_subdev *sd, int cmd, void *arg); +#ifdef CONFIG_VIDEO_ADV_DEBUG + int (*g_register)(struct v4l2_subdev *sd, struct v4l2_register *reg); + int (*s_register)(struct v4l2_subdev *sd, struct v4l2_register *reg); +#endif +}; + +struct v4l2_subdev_tuner_ops { + int (*s_mode)(struct v4l2_subdev *sd, enum v4l2_tuner_type); + int (*s_radio)(struct v4l2_subdev *sd); + int (*s_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); + int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); + int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt); + int (*s_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt); + int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm); + int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type); + int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config); +}; + +struct v4l2_subdev_audio_ops { + int (*s_clock_freq)(struct v4l2_subdev *sd, u32 freq); + int (*s_i2s_clock_freq)(struct v4l2_subdev *sd, u32 freq); + int (*s_routing)(struct v4l2_subdev *sd, const struct v4l2_routing *route); +}; + +struct v4l2_subdev_video_ops { + int (*s_routing)(struct v4l2_subdev *sd, const struct v4l2_routing *route); + int (*s_crystal_freq)(struct v4l2_subdev *sd, struct v4l2_crystal_freq *freq); + int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line); + int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data); + int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data); + int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std); + int (*s_stream)(struct v4l2_subdev *sd, int enable); + int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); + int (*g_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); +}; + +struct v4l2_subdev_ops { + const struct v4l2_subdev_core_ops *core; + const struct v4l2_subdev_tuner_ops *tuner; + const struct v4l2_subdev_audio_ops *audio; + const struct v4l2_subdev_video_ops *video; +}; + +#define V4L2_SUBDEV_NAME_SIZE 32 + +/* Each instance of a subdev driver should create this struct, either + stand-alone or embedded in a larger struct. + */ +struct v4l2_subdev { + struct list_head list; + struct module *owner; + struct v4l2_device *dev; + const struct v4l2_subdev_ops *ops; + /* name must be unique */ + char name[V4L2_SUBDEV_NAME_SIZE]; + /* can be used to group similar subdevs, value is driver-specific */ + u32 grp_id; + /* pointer to private data */ + void *priv; +}; + +static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p) +{ + sd->priv = p; +} + +static inline void *v4l2_get_subdevdata(const struct v4l2_subdev *sd) +{ + return sd->priv; +} + +/* Convert an ioctl-type command to the proper v4l2_subdev_ops function call. + This is used by subdev modules that can be called by both old-style ioctl + commands and through the v4l2_subdev_ops. + + The ioctl API of the subdev driver can call this function to call the + right ops based on the ioctl cmd and arg. + + Once all subdev drivers have been converted and all drivers no longer + use the ioctl interface, then this function can be removed. + */ +int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg); + +static inline void v4l2_subdev_init(struct v4l2_subdev *sd, + const struct v4l2_subdev_ops *ops) +{ + INIT_LIST_HEAD(&sd->list); + /* ops->core MUST be set */ + BUG_ON(!ops || !ops->core); + sd->ops = ops; + sd->dev = NULL; + sd->name[0] = '\0'; + sd->grp_id = 0; + sd->priv = NULL; +} + +/* Call an ops of a v4l2_subdev, doing the right checks against + NULL pointers. + + Example: err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); + */ +#define v4l2_subdev_call(sd, o, f, args...) \ + (!(sd) ? -ENODEV : (((sd) && (sd)->ops->o && (sd)->ops->o->f) ? \ + (sd)->ops->o->f((sd) , ##args) : -ENOIOCTLCMD)) + +#endif -- cgit v1.2.3 From d3e57a388a0702b9c964e85ee5015d4ab5945ed4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 23 Nov 2008 16:19:45 +0100 Subject: v4l2-common: add i2c helper functions From: Hans Verkuil Add helper functions to load i2c sub-devices, integrating them into the v4l2-framework. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 170 ++++++++++++++++++++++++++++++++ linux/include/media/v4l2-common.h | 41 ++++++++ 2 files changed, 211 insertions(+) diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index e87a04a60..6d5e41ecc 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -58,6 +58,7 @@ #include #define __OLD_VIDIOC_ /* To allow fixing old calls*/ #include +#include #include #include @@ -802,4 +803,173 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver return err != -ENOMEM ? 0 : err; } EXPORT_SYMBOL(v4l2_i2c_attach); + +void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, + const struct v4l2_subdev_ops *ops) +{ + v4l2_subdev_init(sd, ops); + /* the owner is the same as the i2c_client's driver owner */ + sd->owner = client->driver->driver.owner; + /* i2c_client and v4l2_subdev point to one another */ + v4l2_set_subdevdata(sd, client); + i2c_set_clientdata(client, sd); + /* initialize name */ + snprintf(sd->name, sizeof(sd->name), "%s %d-%04x", + client->driver->driver.name, i2c_adapter_id(client->adapter), + client->addr); +} +EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +/* Supporting function to find a client on a specific address on the + given adapter. Used for legacy i2c drivers. */ +static struct i2c_client *v4l2_i2c_legacy_find_client(struct i2c_adapter *adap, u8 addr) +{ + struct i2c_client *result = NULL; + struct i2c_client *client; + struct list_head *item; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) + down(&adap->clist_lock); +#else + mutex_lock(&adap->clist_lock); +#endif + list_for_each(item, &adap->clients) { + client = list_entry(item, struct i2c_client, list); + if (client->addr == addr) { + result = client; + break; + } + } +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) + up(&adap->clist_lock); +#else + mutex_unlock(&adap->clist_lock); +#endif + return result; +} +#endif + + +/* Load an i2c sub-device. It assumes that i2c_get_adapdata(adapter) + returns the v4l2_device and that i2c_get_clientdata(client) + returns the v4l2_subdev. */ +struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, + const char *module_name, const char *client_type, u8 addr) +{ + struct v4l2_device *dev = i2c_get_adapdata(adapter); + struct v4l2_subdev *sd = NULL; + struct i2c_client *client; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + struct i2c_board_info info; +#endif + + BUG_ON(!dev); +#ifdef MODULE + if (module_name) + request_module(module_name); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + /* Setup the i2c board info with the device type and + the device address. */ + memset(&info, 0, sizeof(info)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + strlcpy(info.driver_name, client_type, sizeof(info.driver_name)); +#else + strlcpy(info.type, client_type, sizeof(info.type)); +#endif + info.addr = addr; + + /* Create the i2c client */ + client = i2c_new_device(adapter, &info); +#else + /* Legacy code: loading the module automatically + probes and creates the i2c_client on the adapter. + Try to find the client by walking the adapter's client list. */ + client = v4l2_i2c_legacy_find_client(adapter, addr); +#endif + /* Note: it is possible in the future that + c->driver is NULL if the driver is still being loaded. + We need better support from the kernel so that we + can easily wait for the load to finish. */ + if (client == NULL || client->driver == NULL) + return NULL; + + /* Lock the module so we can safely get the v4l2_subdev pointer */ + if (!try_module_get(client->driver->driver.owner)) + return NULL; + sd = i2c_get_clientdata(client); + + /* Register with the v4l2_device which increases the module's + use count as well. */ + if (v4l2_device_register_subdev(dev, sd)) + sd = NULL; + /* Decrease the module use count to match the first try_module_get. */ + module_put(client->driver->driver.owner); + return sd; + +} +EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); + +/* Probe and load an i2c sub-device. It assumes that i2c_get_adapdata(adapter) + returns the v4l2_device and that i2c_get_clientdata(client) + returns the v4l2_subdev. */ +struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, + const char *module_name, const char *client_type, + const unsigned short *addrs) +{ + struct v4l2_device *dev = i2c_get_adapdata(adapter); + struct v4l2_subdev *sd = NULL; + struct i2c_client *client = NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + struct i2c_board_info info; +#endif + + BUG_ON(!dev); +#ifdef MODULE + if (module_name) + request_module(module_name); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + /* Setup the i2c board info with the device type and + the device address. */ + memset(&info, 0, sizeof(info)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + strlcpy(info.driver_name, client_type, sizeof(info.driver_name)); +#else + strlcpy(info.type, client_type, sizeof(info.type)); +#endif + + /* Probe and create the i2c client */ + client = i2c_new_probed_device(adapter, &info, addrs); +#else + /* Legacy code: loading the module should automatically + probe and create the i2c_client on the adapter. + Try to find the client by walking the adapter's client list + for each of the possible addresses. */ + while (!client && *addrs != I2C_CLIENT_END) + client = v4l2_i2c_legacy_find_client(adapter, *addrs++); +#endif + /* Note: it is possible in the future that + c->driver is NULL if the driver is still being loaded. + We need better support from the kernel so that we + can easily wait for the load to finish. */ + if (client == NULL || client->driver == NULL) + return NULL; + + /* Lock the module so we can safely get the v4l2_subdev pointer */ + if (!try_module_get(client->driver->driver.owner)) + return NULL; + sd = i2c_get_clientdata(client); + + /* Register with the v4l2_device which increases the module's + use count as well. */ + if (v4l2_device_register_subdev(dev, sd)) + sd = NULL; + /* Decrease the module use count to match the first try_module_get. */ + module_put(client->driver->driver.owner); + return sd; +} +EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); + #endif diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h index 2f8719abf..f99c866d8 100644 --- a/linux/include/media/v4l2-common.h +++ b/linux/include/media/v4l2-common.h @@ -57,6 +57,29 @@ /* ------------------------------------------------------------------------- */ +/* These printk constructs can be used with v4l2_device and v4l2_subdev */ +#define v4l2_printk(level, dev, fmt, arg...) \ + printk(level "%s: " fmt, (dev)->name , ## arg) + +#define v4l2_err(dev, fmt, arg...) \ + v4l2_printk(KERN_ERR, dev, fmt , ## arg) + +#define v4l2_warn(dev, fmt, arg...) \ + v4l2_printk(KERN_WARNING, dev, fmt , ## arg) + +#define v4l2_info(dev, fmt, arg...) \ + v4l2_printk(KERN_INFO, dev, fmt , ## arg) + +/* These three macros assume that the debug level is set with a module + parameter called 'debug'. */ +#define v4l2_dbg(level, debug, dev, fmt, arg...) \ + do { \ + if (debug >= (level)) \ + v4l2_printk(KERN_DEBUG, dev, fmt , ## arg); \ + } while (0) + +/* ------------------------------------------------------------------------- */ + /* Priority helper functions */ struct v4l2_prio_state { @@ -104,11 +127,29 @@ struct i2c_driver; struct i2c_adapter; struct i2c_client; struct i2c_device_id; +struct v4l2_device; +struct v4l2_subdev; +struct v4l2_subdev_ops; int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver, const char *name, int (*probe)(struct i2c_client *, const struct i2c_device_id *)); +/* Load an i2c module and return an initialized v4l2_subdev struct. + Only call request_module if module_name != NULL. + The client_type argument is the name of the chip that's on the adapter. */ +struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, + const char *module_name, const char *client_type, u8 addr); +/* Probe and load an i2c module and return an initialized v4l2_subdev struct. + Only call request_module if module_name != NULL. + The client_type argument is the name of the chip that's on the adapter. */ +struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, + const char *module_name, const char *client_type, + const unsigned short *addrs); +/* Initialize an v4l2_subdev with data from an i2c_client struct */ +void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, + const struct v4l2_subdev_ops *ops); + /* ------------------------------------------------------------------------- */ /* Internal ioctls */ -- cgit v1.2.3 From 127fb1f48bed6f38a5a9ad79344a821673bcad7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 23 Nov 2008 17:11:16 +0000 Subject: Add Compro VideoMate E650F (DVB-T part only). From: Igor M. Liplianin Add Compro VideoMate E650F (DVB-T part only). The card based on cx23885 PCI-Express chip, xc3028 tuner and ce6353 demodulator. CC: Steven Toth Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.cx23885 | 1 + linux/drivers/media/video/cx23885/cx23885-cards.c | 12 ++++++++++++ linux/drivers/media/video/cx23885/cx23885-dvb.c | 1 + linux/drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 15 insertions(+) diff --git a/linux/Documentation/video4linux/CARDLIST.cx23885 b/linux/Documentation/video4linux/CARDLIST.cx23885 index 64823ccac..35ea130e9 100644 --- a/linux/Documentation/video4linux/CARDLIST.cx23885 +++ b/linux/Documentation/video4linux/CARDLIST.cx23885 @@ -11,3 +11,4 @@ 10 -> DViCO FusionHDTV7 Dual Express [18ac:d618] 11 -> DViCO FusionHDTV DVB-T Dual Express [18ac:db78] 12 -> Leadtek Winfast PxDVR3200 H [107d:6681] + 13 -> Compro VideoMate E650F [185b:e800] diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index dc3f79638..db1e8bdab 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -159,6 +159,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Leadtek Winfast PxDVR3200 H", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_COMPRO_VIDEOMATE_E650F] = { + .name = "Compro VideoMate E650F", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -238,6 +242,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x107d, .subdevice = 0x6681, .card = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H, + }, { + .subvendor = 0x185b, + .subdevice = 0xe800, + .card = CX23885_BOARD_COMPRO_VIDEOMATE_E650F, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -391,6 +399,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: + case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: /* Tuner Reset Command */ bitmask = 0x04; break; @@ -531,6 +540,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x000f000f); break; case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: + case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: /* GPIO-2 xc3028 tuner reset */ /* The following GPIO's are on the internal AVCore (cx25840) */ @@ -631,6 +641,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1700: case CX23885_BOARD_HAUPPAUGE_HVR1400: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: + case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ @@ -645,6 +656,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1700: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: + case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: request_module("cx25840"); break; } diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index a11fdbfb5..990fd217b 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -503,6 +503,7 @@ static int dvb_register(struct cx23885_tsport *port) break; } case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: + case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(zl10353_attach, diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 26f755354..ad93e0e88 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -67,6 +67,7 @@ #define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10 #define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11 #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12 +#define CX23885_BOARD_COMPRO_VIDEOMATE_E650F 13 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- cgit v1.2.3 From b2c41052eb2e8da66d3ca3d44fcda96ef9be2ee7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 23 Nov 2008 18:47:50 +0100 Subject: gspca: Simplify the brightness/contrast for ov76xx sensors in sonixj. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 73 ++++++-------------------------- 1 file changed, 12 insertions(+), 61 deletions(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 182b84f1c..bfd256716 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1136,25 +1136,6 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, return expo; } -/* this function is used for sensors o76xx only */ -static void setbrightcont(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int val; - __u8 reg84_full[0x15]; - - memcpy(reg84_full, reg84, sizeof reg84_full); - val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10; /* 10..40 */ - reg84_full[0] = (val + 1) / 2; /* red */ - reg84_full[2] = val; /* green */ - reg84_full[4] = (val + 1) / 5; /* blue */ - val = (sd->brightness - BRIGHTNESS_DEF) * 0x10 - / BRIGHTNESS_MAX; - reg84_full[0x12] = val & 0x1f; /* 5:0 signed value */ - reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full); -} - -/* sensor != ov76xx */ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1179,24 +1160,23 @@ static void setbrightness(struct gspca_dev *gspca_dev) case SENSOR_OM6802: expo = sd->brightness >> 6; sd->exposure = setexposure(gspca_dev, expo); - k2 = sd->brightness >> 11; + k2 >>= 1; break; } - reg_w1(gspca_dev, 0x96, k2); + reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ } -/* sensor != ov76xx */ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 k2; __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 }; - k2 = sd->contrast; - contrast[2] = k2; - contrast[0] = (k2 + 1) >> 1; - contrast[4] = (k2 + 1) / 5; + k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10; /* 10..40 */ + contrast[0] = (k2 + 1) / 2; /* red */ + contrast[2] = k2; /* green */ + contrast[4] = (k2 + 1) / 5; /* blue */ reg_w(gspca_dev, 0x84, contrast, 6); } @@ -1413,20 +1393,13 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_MI0360: setinfrared(sd); - /* fall thru */ - case SENSOR_HV7131R: - case SENSOR_MO4000: - case SENSOR_OM6802: - setbrightness(gspca_dev); - setcontrast(gspca_dev); break; case SENSOR_OV7630: setvflip(sd); - /* fall thru */ - default: /* OV76xx */ - setbrightcont(gspca_dev); break; } + setbrightness(gspca_dev); + setcontrast(gspca_dev); setautogain(gspca_dev); return 0; } @@ -1564,19 +1537,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->brightness = val; - if (gspca_dev->streaming) { - switch (sd->sensor) { - case SENSOR_HV7131R: - case SENSOR_MI0360: - case SENSOR_MO4000: - case SENSOR_OM6802: - setbrightness(gspca_dev); - break; - default: /* OV76xx */ - setbrightcont(gspca_dev); - break; - } - } + if (gspca_dev->streaming) + setbrightness(gspca_dev); return 0; } @@ -1593,19 +1555,8 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->contrast = val; - if (gspca_dev->streaming) { - switch (sd->sensor) { - case SENSOR_HV7131R: - case SENSOR_MI0360: - case SENSOR_MO4000: - case SENSOR_OM6802: - setcontrast(gspca_dev); - break; - default: /* OV76xx */ - setbrightcont(gspca_dev); - break; - } - } + if (gspca_dev->streaming) + setcontrast(gspca_dev); return 0; } -- cgit v1.2.3 From 97d6559961971da20d7ea7ac672231e2b2033dc3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 23 Nov 2008 19:53:28 +0100 Subject: gspca: Delay when trying an other altsetting on streaming start. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index d725663fc..79be1e0e4 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -649,8 +649,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) "usb_submit_urb [%d] err %d", n, ret); gspca_dev->streaming = 0; destroy_urbs(gspca_dev); - if (ret == -ENOSPC) + if (ret == -ENOSPC) { + mdelay(20); /* wait for kill + * complete */ break; /* try the previous alt */ + } goto out; } } -- cgit v1.2.3 From f60183b96cdd33d9d00bde6f769048c15bb27c4c Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 23 Nov 2008 20:26:54 +0100 Subject: Add support for the CX24113 DVB-S tuner driver From: Patrick Boettcher This commit adds support for the CX24113 DVB-S tuner driver and thus support for the Technisat Skystar2 revision 2.8. The driver was created with the help of Technisat. Thank you very much. Priority: normal Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/Kconfig | 1 + linux/drivers/media/dvb/frontends/Kconfig | 8 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/cx24113.c | 608 ++++++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/cx24113.h | 8 +- 5 files changed, 621 insertions(+), 5 deletions(-) create mode 100644 linux/drivers/media/dvb/frontends/cx24113.c diff --git a/linux/drivers/media/dvb/b2c2/Kconfig b/linux/drivers/media/dvb/b2c2/Kconfig index 73dc2ee9b..e5c27e355 100644 --- a/linux/drivers/media/dvb/b2c2/Kconfig +++ b/linux/drivers/media/dvb/b2c2/Kconfig @@ -14,6 +14,7 @@ config DVB_B2C2_FLEXCOP select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE + select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 2470d88e9..002695607 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -118,6 +118,14 @@ config DVB_TUNER_ITD1000 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_TUNER_CX24113 + tristate "Conexant CX24113/CX24128 tuner for DVB-S/DSS" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + + config DVB_TDA826X tristate "Philips TDA826X silicon tuner" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 7a19c0c7b..af7bdf0ad 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_DVB_S5H1409) += s5h1409.o obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o obj-$(CONFIG_DVB_AU8522) += au8522.o obj-$(CONFIG_DVB_TDA10048) += tda10048.o +obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c new file mode 100644 index 000000000..e2e5df9de --- /dev/null +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -0,0 +1,608 @@ +/* + * Driver for Conexant CX24113/CX24128 Tuner (Satelite) + * + * Copyright (C) 2007-8 Patrick Boettcher + * + * Developed for BBTI / Technisat + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "cx24113.h" + +static int debug; + +#define info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0) +#define err(args...) do { printk(KERN_ERR "CX24113: " args); } while (0) + +#define dprintk(args...) \ + do { \ + if (debug) { \ + printk(KERN_DEBUG "CX24113: %s: ", __func__); \ + printk(args); \ + } \ + } while (0) + +struct cx24113_state { + struct i2c_adapter *i2c; + const struct cx24113_config *config; + +#define REV_CX24113 0x23 + u8 rev; + u8 ver; + + u8 icp_mode:1; + +#define ICP_LEVEL1 0 +#define ICP_LEVEL2 1 +#define ICP_LEVEL3 2 +#define ICP_LEVEL4 3 + u8 icp_man:2; + u8 icp_auto_low:2; + u8 icp_auto_mlow:2; + u8 icp_auto_mhi:2; + u8 icp_auto_hi:2; + u8 icp_dig; + +#define LNA_MIN_GAIN 0 +#define LNA_MID_GAIN 1 +#define LNA_MAX_GAIN 2 + u8 lna_gain:2; + + u8 acp_on:1; + + u8 vco_mode:2; + u8 vco_shift:1; +#define VCOBANDSEL_6 0x80 +#define VCOBANDSEL_5 0x01 +#define VCOBANDSEL_4 0x02 +#define VCOBANDSEL_3 0x04 +#define VCOBANDSEL_2 0x08 +#define VCOBANDSEL_1 0x10 + u8 vco_band; + +#define VCODIV4 4 +#define VCODIV2 2 + u8 vcodiv; + + u8 bs_delay:4; + u16 bs_freqcnt:13; + u16 bs_rdiv; + u8 prescaler_mode:1; + + u8 rfvga_bias_ctrl; + + s16 tuner_gain_thres; + u8 gain_level; + + u32 frequency; + + u8 refdiv; + + u8 Fwindow_enabled; +}; + +static int cx24113_writereg(struct cx24113_state *state, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = state->config->i2c_addr, + .flags = 0, .buf = buf, .len = 2 }; + int err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) { + printk(KERN_DEBUG "%s: writereg error(err == %i, reg == 0x%02x," + " data == 0x%02x)\n", __func__, err, reg, data); + return err; + } + + return 0; +} + +static int cx24113_readreg(struct cx24113_state *state, u8 reg) +{ + int ret; + u8 b; + struct i2c_msg msg[] = { + { .addr = state->config->i2c_addr, + .flags = 0, .buf = ®, .len = 1 }, + { .addr = state->config->i2c_addr, + .flags = I2C_M_RD, .buf = &b, .len = 1 } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) { + printk(KERN_DEBUG "%s: reg=0x%x (error=%d)\n", + __func__, reg, ret); + return ret; + } + + return b; +} + +static void cx24113_set_parameters(struct cx24113_state *state) +{ + u8 r; + + r = cx24113_readreg(state, 0x10) & 0x82; + r |= state->icp_mode; + r |= state->icp_man << 4; + r |= state->icp_dig << 2; + r |= state->prescaler_mode << 5; + cx24113_writereg(state, 0x10, r); + + r = (state->icp_auto_low << 0) | (state->icp_auto_mlow << 2) + | (state->icp_auto_mhi << 4) | (state->icp_auto_hi << 6); + cx24113_writereg(state, 0x11, r); + + if (state->rev == REV_CX24113) { + r = cx24113_readreg(state, 0x20) & 0xec; + r |= state->lna_gain; + r |= state->rfvga_bias_ctrl << 4; + cx24113_writereg(state, 0x20, r); + } + + r = cx24113_readreg(state, 0x12) & 0x03; + r |= state->acp_on << 2; + r |= state->bs_delay << 4; + cx24113_writereg(state, 0x12, r); + + r = cx24113_readreg(state, 0x18) & 0x40; + r |= state->vco_shift; + if (state->vco_band == VCOBANDSEL_6) + r |= (1 << 7); + else + r |= (state->vco_band << 1); + cx24113_writereg(state, 0x18, r); + + r = cx24113_readreg(state, 0x14) & 0x20; + r |= (state->vco_mode << 6) | ((state->bs_freqcnt >> 8) & 0x1f); + cx24113_writereg(state, 0x14, r); + cx24113_writereg(state, 0x15, (state->bs_freqcnt & 0xff)); + + cx24113_writereg(state, 0x16, (state->bs_rdiv >> 4) & 0xff); + r = (cx24113_readreg(state, 0x17) & 0x0f) | + ((state->bs_rdiv & 0x0f) << 4); + cx24113_writereg(state, 0x17, r); +} + +#define VGA_0 0x00 +#define VGA_1 0x04 +#define VGA_2 0x02 +#define VGA_3 0x06 +#define VGA_4 0x01 +#define VGA_5 0x05 +#define VGA_6 0x03 +#define VGA_7 0x07 + +#define RFVGA_0 0x00 +#define RFVGA_1 0x01 +#define RFVGA_2 0x02 +#define RFVGA_3 0x03 + +static int cx24113_set_gain_settings(struct cx24113_state *state, + s16 power_estimation) +{ + u8 ampout = cx24113_readreg(state, 0x1d) & 0xf0, + vga = cx24113_readreg(state, 0x1f) & 0x3f, + rfvga = cx24113_readreg(state, 0x20) & 0xf3; + u8 gain_level = power_estimation >= state->tuner_gain_thres; + + dprintk("power estimation: %d, thres: %d, gain_level: %d/%d\n", + power_estimation, state->tuner_gain_thres, + state->gain_level, gain_level); + + if (gain_level == state->gain_level) + return 0; /* nothing to be done */ + + ampout |= 0xf; + + if (gain_level) { + rfvga |= RFVGA_0 << 2; + vga |= (VGA_7 << 3) | VGA_7; + } else { + rfvga |= RFVGA_2 << 2; + vga |= (VGA_6 << 3) | VGA_2; + } + state->gain_level = gain_level; + + cx24113_writereg(state, 0x1d, ampout); + cx24113_writereg(state, 0x1f, vga); + cx24113_writereg(state, 0x20, rfvga); + + return 1; /* did something */ +} + +static int cx24113_set_Fref(struct cx24113_state *state, u8 high) +{ + u8 xtal = cx24113_readreg(state, 0x02); + if (state->rev == 0x43 && state->vcodiv == VCODIV4) + high = 1; + + xtal &= ~0x2; + if (high) + xtal |= high << 1; + return cx24113_writereg(state, 0x02, xtal); +} + +static int cx24113_enable(struct cx24113_state *state, u8 enable) +{ + u8 r21 = (cx24113_readreg(state, 0x21) & 0xc0) | enable; + if (state->rev == REV_CX24113) + r21 |= (1 << 1); + return cx24113_writereg(state, 0x21, r21); +} + +static int cx24113_set_bandwidth(struct cx24113_state *state, u32 bandwidth_khz) +{ + u8 r; + + if (bandwidth_khz <= 19000) + r = 0x03 << 6; + else if (bandwidth_khz <= 25000) + r = 0x02 << 6; + else + r = 0x01 << 6; + + dprintk("bandwidth to be set: %d\n", bandwidth_khz); + bandwidth_khz *= 10; + bandwidth_khz -= 10000; + bandwidth_khz /= 1000; + bandwidth_khz += 5; + bandwidth_khz /= 10; + + dprintk("bandwidth: %d %d\n", r >> 6, bandwidth_khz); + + r |= bandwidth_khz & 0x3f; + + return cx24113_writereg(state, 0x1e, r); +} + +static int cx24113_set_clk_inversion(struct cx24113_state *state, u8 on) +{ + u8 r = (cx24113_readreg(state, 0x10) & 0x7f) | ((on & 0x1) << 7); + return cx24113_writereg(state, 0x10, r); +} + +static int cx24113_get_status(struct dvb_frontend *fe, u32 *status) +{ + struct cx24113_state *state = fe->tuner_priv; + u8 r = (cx24113_readreg(state, 0x10) & 0x02) >> 1; + if (r) + *status |= TUNER_STATUS_LOCKED; + dprintk("PLL locked: %d\n", r); + return 0; +} + +static u8 cx24113_set_ref_div(struct cx24113_state *state, u8 refdiv) +{ + if (state->rev == 0x43 && state->vcodiv == VCODIV4) + refdiv = 2; + return state->refdiv = refdiv; +} + +static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) +{ + s32 N; + s64 F; + u8 R, r; + u8 vcodiv; + u8 factor; + s32 freq_hz = state->frequency * 1000; + + if (state->config->xtal_khz < 20000) + factor = 1; + else + factor = 2; + + if (state->rev == REV_CX24113) { + if (state->frequency >= 1100000) + vcodiv = VCODIV2; + else + vcodiv = VCODIV4; + } else { + if (state->frequency >= 1165000) + vcodiv = VCODIV2; + else + vcodiv = VCODIV4; + } + state->vcodiv = vcodiv; + + dprintk("calculating N/F for %dHz with vcodiv %d\n", freq_hz, vcodiv); + R = 0; + do { + R = cx24113_set_ref_div(state, R + 1); + + /* calculate tuner PLL settings: */ + N = (freq_hz / 100 * vcodiv) * R; + N /= (state->config->xtal_khz) * factor * 2; + N += 5; /* For round up. */ + N /= 10; + N -= 32; + } while (N < 6 && R < 3); + + if (N < 6) { + err("strange frequency: N < 6\n"); + return; + } + F = freq_hz; + F *= (u64) (R * vcodiv * 262144); + dprintk("1 N: %d, F: %lld, R: %d\n", N, F, R); + do_div(F, state->config->xtal_khz*1000 * factor * 2); + dprintk("2 N: %d, F: %lld, R: %d\n", N, F, R); + F -= (N + 32) * 262144; + + dprintk("3 N: %d, F: %lld, R: %d\n", N, F, R); + + if (state->Fwindow_enabled) { + if (F > (262144 / 2 - 1638)) + F = 262144 / 2 - 1638; + if (F < (-262144 / 2 + 1638)) + F = -262144 / 2 + 1638; + if ((F < 3277 && F > 0) || (F > -3277 && F < 0)) { + F = 0; + r = cx24113_readreg(state, 0x10); + cx24113_writereg(state, 0x10, r | (1 << 6)); + } + } + dprintk("4 N: %d, F: %lld, R: %d\n", N, F, R); + + *n = (u16) N; + *f = (s32) F; +} + + +static void cx24113_set_nfr(struct cx24113_state *state, u16 n, s32 f, u8 r) +{ + u8 reg; + cx24113_writereg(state, 0x19, (n >> 1) & 0xff); + + reg = ((n & 0x1) << 7) | ((f >> 11) & 0x7f); + cx24113_writereg(state, 0x1a, reg); + + cx24113_writereg(state, 0x1b, (f >> 3) & 0xff); + + reg = cx24113_readreg(state, 0x1c) & 0x1f; + cx24113_writereg(state, 0x1c, reg | ((f & 0x7) << 5)); + + cx24113_set_Fref(state, r - 1); +} + +static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency) +{ + u8 r = 1; /* or 2 */ + u16 n = 6; + s32 f = 0; + + r = cx24113_readreg(state, 0x14); + cx24113_writereg(state, 0x14, r & 0x3f); + + r = cx24113_readreg(state, 0x10); + cx24113_writereg(state, 0x10, r & 0xbf); + + state->frequency = frequency; + + dprintk("tuning to frequency: %d\n", frequency); + + cx24113_calc_pll_nf(state, &n, &f); + cx24113_set_nfr(state, n, f, state->refdiv); + + r = cx24113_readreg(state, 0x18) & 0xbf; + if (state->vcodiv != VCODIV2) + r |= 1 << 6; + cx24113_writereg(state, 0x18, r); + + /* The need for this sleep is not clear. But helps in some cases */ + msleep(5); + + r = cx24113_readreg(state, 0x1c) & 0xef; + cx24113_writereg(state, 0x1c, r | (1 << 4)); + return 0; +} + +static int cx24113_init(struct dvb_frontend *fe) +{ + struct cx24113_state *state = fe->tuner_priv; + int ret; + + state->tuner_gain_thres = -50; + state->gain_level = 255; /* to force a gain-setting initialization */ + state->icp_mode = 0; + + if (state->config->xtal_khz < 11000) { + state->icp_auto_hi = ICP_LEVEL4; + state->icp_auto_mhi = ICP_LEVEL4; + state->icp_auto_mlow = ICP_LEVEL3; + state->icp_auto_low = ICP_LEVEL3; + } else { + state->icp_auto_hi = ICP_LEVEL4; + state->icp_auto_mhi = ICP_LEVEL4; + state->icp_auto_mlow = ICP_LEVEL3; + state->icp_auto_low = ICP_LEVEL2; + } + + state->icp_dig = ICP_LEVEL3; + state->icp_man = ICP_LEVEL1; + state->acp_on = 1; + state->vco_mode = 0; + state->vco_shift = 0; + state->vco_band = VCOBANDSEL_1; + state->bs_delay = 8; + state->bs_freqcnt = 0x0fff; + state->bs_rdiv = 0x0fff; + state->prescaler_mode = 0; + state->lna_gain = LNA_MAX_GAIN; + state->rfvga_bias_ctrl = 1; + state->Fwindow_enabled = 1; + + cx24113_set_Fref(state, 0); + cx24113_enable(state, 0x3d); + cx24113_set_parameters(state); + + cx24113_set_gain_settings(state, -30); + + cx24113_set_bandwidth(state, 18025); + cx24113_set_clk_inversion(state, 1); + + if (state->config->xtal_khz >= 40000) + ret = cx24113_writereg(state, 0x02, + (cx24113_readreg(state, 0x02) & 0xfb) | (1 << 2)); + else + ret = cx24113_writereg(state, 0x02, + (cx24113_readreg(state, 0x02) & 0xfb) | (0 << 2)); + + return ret; +} + +static int cx24113_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct cx24113_state *state = fe->tuner_priv; + /* for a ROLL-OFF factor of 0.35, 0.2: 600, 0.25: 625 */ + u32 roll_off = 675; + u32 bw; + + bw = ((p->u.qpsk.symbol_rate/100) * roll_off) / 1000; + bw += (10000000/100) + 5; + bw /= 10; + bw += 1000; + cx24113_set_bandwidth(state, bw); + + cx24113_set_frequency(state, p->frequency); + msleep(5); + return cx24113_get_status(fe, &bw); +} + +static s8 cx24113_agc_table[2][10] = { + {-54, -41, -35, -30, -25, -21, -16, -10, -6, -2}, + {-39, -35, -30, -25, -19, -15, -11, -5, 1, 9}, +}; + +void cx24113_agc_callback(struct dvb_frontend *fe) +{ + struct cx24113_state *state = fe->tuner_priv; + s16 s, i; + if (!fe->ops.read_signal_strength) + return; + + do { + /* this only works with the current CX24123 implementation */ + fe->ops.read_signal_strength(fe, (u16 *) &s); + s >>= 8; + dprintk("signal strength: %d\n", s); + for (i = 0; i < sizeof(cx24113_agc_table[0]); i++) + if (cx24113_agc_table[state->gain_level][i] > s) + break; + s = -25 - i*5; + } while (cx24113_set_gain_settings(state, s)); +} +EXPORT_SYMBOL(cx24113_agc_callback); + +static int cx24113_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct cx24113_state *state = fe->tuner_priv; + *frequency = state->frequency; + return 0; +} + +static int cx24113_release(struct dvb_frontend *fe) +{ + struct cx24113_state *state = fe->tuner_priv; + dprintk("\n"); + fe->tuner_priv = NULL; + kfree(state); + return 0; +} + +static const struct dvb_tuner_ops cx24113_tuner_ops = { + .info = { + .name = "Conexant CX24113", + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = 125, + }, + + .release = cx24113_release, + + .init = cx24113_init, + .sleep = NULL, + + .set_params = cx24113_set_params, + .get_frequency = cx24113_get_frequency, + .get_bandwidth = NULL, + .get_status = cx24113_get_status, +}; + +struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, + const struct cx24113_config *config, struct i2c_adapter *i2c) +{ + /* allocate memory for the internal state */ + struct cx24113_state *state = + kzalloc(sizeof(struct cx24113_state), GFP_KERNEL); + if (state == NULL) { + err("Unable to kmalloc\n"); + goto error; + } + + /* setup the state */ + state->config = config; + state->i2c = i2c; + + info("trying to detect myself\n"); + + /* making a dummy read, because of some expected troubles + * after power on */ + cx24113_readreg(state, 0x00); + + switch (state->rev = cx24113_readreg(state, 0x00)) { + case 0x43: + info("unknown device\n"); + break; + case REV_CX24113: + info("CX24113\n"); + break; + default: + err("unsupported revision: %x\n", state->rev); + goto error; + } + state->ver = cx24113_readreg(state, 0x01); + info("version: %x\n", state->ver); + + /* create dvb_frontend */ + memcpy(&fe->ops.tuner_ops, &cx24113_tuner_ops, + sizeof(struct dvb_tuner_ops)); + fe->tuner_priv = state; + return fe; + +error: + kfree(state); + + return NULL; +} +EXPORT_SYMBOL(cx24113_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24113/CX24128hardware"); +MODULE_LICENSE("GPL"); + diff --git a/linux/drivers/media/dvb/frontends/cx24113.h b/linux/drivers/media/dvb/frontends/cx24113.h index d549041b2..5de0f7ffd 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.h +++ b/linux/drivers/media/dvb/frontends/cx24113.h @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef CX24113_H @@ -30,10 +30,8 @@ struct cx24113_config { u32 xtal_khz; }; -/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \ - * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */ - -#if 0 +#if defined(CONFIG_DVB_TUNER_CX24113) || \ + (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *, const struct cx24113_config *config, struct i2c_adapter *i2c); -- cgit v1.2.3 From d06ed8475f6edc68d8aee44a9e8c9cf0e87e29ef Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 14 Dec 2008 16:52:12 -0500 Subject: cx18 Replace magic number 63 with CX18_MAX_FW_MDLS_PER_STREAM From: Andy Walls Removed magic number that referred to firmware limit on the number of MDLs the firmware can maintain for any stream at any one time. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.h | 5 +++-- linux/drivers/media/video/cx18/cx18-queue.c | 5 +++-- linux/drivers/media/video/cx18/cx18-streams.c | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 018d98f94..0d2edebc3 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -116,7 +116,7 @@ #define CX18_DEFAULT_ENC_PCM_BUFFERS 1 /* Maximum firmware DMA buffers per stream */ -#define CX18_MAX_MDLS_PER_STREAM 63 +#define CX18_MAX_FW_MDLS_PER_STREAM 63 /* DMA buffer, default size in kB allocated */ #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 @@ -255,7 +255,8 @@ struct cx18_scb; /* forward reference */ #define CX18_MAX_MDL_ACKS 2 -#define CX18_MAX_EPU_WORK_ORDERS 70 /* CPU_DE_RELEASE_MDL bursts 63 commands */ +#define CX18_MAX_EPU_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7) +/* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */ #define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1 #define CX18_F_EWO_MB_STALE_WHILE_PROC 0x2 diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index a6b0666f0..2c58b0c47 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -55,8 +55,9 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, mutex_lock(&s->qlock); - /* q_busy is restricted to 63 buffers to stay within firmware limits */ - if (q == &s->q_busy && atomic_read(&q->buffers) >= 63) + /* q_busy is restricted to a max buffer count imposed by firmware */ + if (q == &s->q_busy && + atomic_read(&q->buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) q = &s->q_free; if (to_front) diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 9ed542624..acaf774d8 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -425,7 +425,7 @@ void cx18_stream_load_fw_queue(struct cx18_stream *s) struct cx18_buffer *buf; if (atomic_read(&s->q_free.buffers) == 0 || - atomic_read(&s->q_busy.buffers) >= 63) + atomic_read(&s->q_busy.buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) return; /* Move from q_free to q_busy notifying the firmware, until the limit */ @@ -434,7 +434,8 @@ void cx18_stream_load_fw_queue(struct cx18_stream *s) if (buf == NULL) break; q = cx18_stream_put_buf_fw(s, buf); - } while (atomic_read(&s->q_busy.buffers) < 63 && q == &s->q_busy); + } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM + && q == &s->q_busy); } int cx18_start_v4l2_encode_stream(struct cx18_stream *s) -- cgit v1.2.3 From 33d2dd93cb9c5d52dfee61dcd037b3dc290ada81 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 14 Dec 2008 17:21:35 -0500 Subject: cx18: VBI comment corrections and comments about VBI issues From: Andy Walls VBI comment corrections to avoid future confusion about standards. Comments on cx18 VBI implementation shortcomings that need resolution. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index cea4735b6..f2a5b2c4d 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -614,18 +614,21 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line * length of 720 pixels @ 4:2:2 sampling. Thus... * - * For NTSC: + * For systems that use a 15.734 kHz horizontal rate, such as + * NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have: * - * (1/15,734 kHz) * 2 * 13.5 MHz = 1716 samples/line = + * (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line = * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples * - * For PAL: + * For systems that use a 15.625 kHz horizontal rate, such as + * PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have: * - * (1/15,625 kHz) * 2 * 13.5 MHz = 1728 samples/line = + * (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line = * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples * */ + /* FIXME: init these based on tuner std & modify when std changes */ /* CX18-AV-Core number of VBI samples output per horizontal line */ cx->vbi.raw_decoder_line_size = 1444; /* 4 byte SAV + 2 * 720 */ cx->vbi.sliced_decoder_line_size = 272; /* 60 Hz: 268+4, 50 Hz: 280+4 */ @@ -929,6 +932,11 @@ static int __devinit cx18_probe(struct pci_dev *dev, } cx->params.video_gop_size = cx->is_60hz ? 15 : 12; + /* + * FIXME: setting the buffer size based on the tuner standard is + * suboptimal, as the CVBS and SVideo inputs could use a different std + * and the buffer could end up being too small in that case. + */ vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; -- cgit v1.2.3 From 75db59d39a9a9df4b32e034d483c126aed873c1a Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 14 Dec 2008 19:05:36 -0500 Subject: cx18: Convert some list manipulations to emphasize entries not lists From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-queue.c | 14 ++++++-------- linux/drivers/media/video/cx18/cx18-streams.c | 4 +--- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index 2c58b0c47..8d9441e88 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -77,8 +77,8 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) mutex_lock(&s->qlock); if (!list_empty(&q->list)) { - buf = list_entry(q->list.next, struct cx18_buffer, list); - list_del_init(q->list.next); + buf = list_first_entry(&q->list, struct cx18_buffer, list); + list_del_init(&buf->list); q->bytesused -= buf->bytesused - buf->readpos; buf->skipped = 0; atomic_dec(&q->buffers); @@ -92,13 +92,11 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, { struct cx18 *cx = s->cx; struct cx18_buffer *buf; + struct cx18_buffer *tmp; struct cx18_buffer *ret = NULL; - struct list_head *p, *t; mutex_lock(&s->qlock); - list_for_each_safe(p, t, &s->q_busy.list) { - buf = list_entry(p, struct cx18_buffer, list); - + list_for_each_entry_safe(buf, tmp, &s->q_busy.list, list) { if (buf->id != id) { buf->skipped++; if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { @@ -152,8 +150,8 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) mutex_lock(&s->qlock); while (!list_empty(&q->list)) { - buf = list_entry(q->list.next, struct cx18_buffer, list); - list_move_tail(q->list.next, &s->q_free.list); + buf = list_first_entry(&q->list, struct cx18_buffer, list); + list_move_tail(&buf->list, &s->q_free.list); buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; atomic_inc(&s->q_free.buffers); } diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index acaf774d8..5acefd059 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -442,7 +442,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) { u32 data[MAX_MB_ARGUMENTS]; struct cx18 *cx = s->cx; - struct list_head *p; struct cx18_buffer *buf; int ts = 0; int captype = 0; @@ -529,8 +528,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) /* Init all the cpu_mdls for this stream */ cx18_flush_queues(s); mutex_lock(&s->qlock); - list_for_each(p, &s->q_free.list) { - buf = list_entry(p, struct cx18_buffer, list); + list_for_each_entry(buf, &s->q_free.list, list) { cx18_writel(cx, buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); -- cgit v1.2.3 From 4a31b6de97b5e45eaff001a1e7a813964660f436 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 23 Nov 2008 17:16:44 -0500 Subject: cx18: Use a known open task handle when setting stream CX2341x parameters From: Andy Walls cx18: Use a known open task handle when setting stream CX2341x parameters Sometimes, we might only have VBI or YUV stream open instead of an MPEG stream. Let's make sure we use a valid task handle to perform the CX2341x control settings. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-controls.c | 5 ++++- linux/drivers/media/video/cx18/cx18-mailbox.c | 5 +++-- linux/drivers/media/video/cx18/cx18-mailbox.h | 7 +++++++ linux/drivers/media/video/cx18/cx18-streams.c | 6 +++++- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index f46c7e5ed..17edf305d 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -259,6 +259,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) return err; } if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + struct cx18_api_func_private priv; struct cx2341x_mpeg_params p = cx->params; int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), c, VIDIOC_S_EXT_CTRLS); @@ -278,7 +279,9 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) fmt.fmt.pix.height = cx->params.height; cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt); } - err = cx2341x_update(cx, cx18_api_func, &cx->params, &p); + priv.cx = cx; + priv.s = &cx->streams[id->type]; + err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p); if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt) err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt); cx->params = p; diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index eb5c31af6..f20fbf091 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -612,8 +612,9 @@ static int cx18_set_filter_param(struct cx18_stream *s) int cx18_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]) { - struct cx18 *cx = priv; - struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_MPG]; + struct cx18_api_func_private *api_priv = priv; + struct cx18 *cx = api_priv->cx; + struct cx18_stream *s = api_priv->s; switch (cmd) { case CX2341X_ENC_SET_OUTPUT_PORT: diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.h b/linux/drivers/media/video/cx18/cx18-mailbox.h index 35104458e..a667f1ae4 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.h +++ b/linux/drivers/media/video/cx18/cx18-mailbox.h @@ -79,6 +79,13 @@ struct cx18_mailbox { u32 error; }; +struct cx18_stream; + +struct cx18_api_func_private { + struct cx18 *cx; + struct cx18_stream *s; +}; + int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]); int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd, int args, ...); diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 5acefd059..f9e44c0cf 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -494,6 +494,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); if (atomic_read(&cx->ana_capturing) == 0 && !ts) { + struct cx18_api_func_private priv; + /* Stuff from Windows, we don't know what it is */ cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); @@ -513,7 +515,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0); /* Setup API for Stream */ - cx2341x_update(cx, cx18_api_func, NULL, &cx->params); + priv.cx = cx; + priv.s = s; + cx2341x_update(&priv, cx18_api_func, NULL, &cx->params); } if (atomic_read(&cx->tot_capturing) == 0) { -- cgit v1.2.3 From 1b1d9fda3678e6dc40cc9670e03f18fd85f6942d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 24 Nov 2008 10:28:58 +0100 Subject: gspca: Simplify the pkt_scan of stk014. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/stk014.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/gspca/stk014.c b/linux/drivers/media/video/gspca/stk014.c index d9d64911f..74f57db53 100644 --- a/linux/drivers/media/video/gspca/stk014.c +++ b/linux/drivers/media/video/gspca/stk014.c @@ -424,10 +424,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* beginning of the frame */ #define STKHDRSZ 12 - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data + STKHDRSZ, len - STKHDRSZ); -#undef STKHDRSZ - return; + data += STKHDRSZ; + len -= STKHDRSZ; } gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -- cgit v1.2.3 From d83c8412dcfbd95cb0794db8f623f0a697097064 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 24 Nov 2008 10:38:21 +0100 Subject: gspca: Use msleep instead of mdelay. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 79be1e0e4..baf4aa524 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -650,7 +650,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->streaming = 0; destroy_urbs(gspca_dev); if (ret == -ENOSPC) { - mdelay(20); /* wait for kill + msleep(20); /* wait for kill * complete */ break; /* try the previous alt */ } -- cgit v1.2.3 From aa768169d1db0c85c977c63223d85d78d353ea03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 24 Nov 2008 18:12:46 +0100 Subject: Checkpatch.pl fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index c13943077..ebf904170 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -116,7 +116,7 @@ int ov9650_write_sensor(struct sd *sd, const u8 address, /* Special case larger sensor writes */ p = buf + 16; - /* Copy a four byte write sequence for each byte to write over the I2C bus */ + /* Copy a four byte sequence for each byte to write over the I2C bus */ for (i = 0; i < len; i++) { memcpy(p, sensor_urb_skeleton + 16, 4); p[3] = i2c_data[i]; @@ -221,7 +221,8 @@ int ov9650_power_down(struct sd *sd) err = ov9650_write_sensor(sd, power_down_ov9650[i][1], &data, 1); else - err = m5602_write_bridge(sd, power_down_ov9650[i][1], data); + err = m5602_write_bridge(sd, power_down_ov9650[i][1], + data); } return err; -- cgit v1.2.3 From acf70f3e5e1945c1204e158365faf52a55c8be7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 24 Nov 2008 18:21:29 +0100 Subject: Convert some functions to be static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 4 +++- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 2 -- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 4 +++- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 4 +--- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 4 +++- linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 2 -- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 3 ++- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 2 -- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c | 2 ++ linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 2 -- 10 files changed, 14 insertions(+), 15 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index c93e7474e..e026e245f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -18,6 +18,8 @@ #include "m5602_mt9m111.h" +static void mt9m111_dump_registers(struct sd *sd); + int mt9m111_probe(struct sd *sd) { u8 data[2] = {0x00, 0x00}; @@ -308,7 +310,7 @@ int mt9m111_write_sensor(struct sd *sd, const u8 address, return (err < 0) ? err : 0; } -void mt9m111_dump_registers(struct sd *sd) +static void mt9m111_dump_registers(struct sd *sd) { u8 address, value[2] = {0x00, 0x00}; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 315209d5a..4b4c1967b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -93,8 +93,6 @@ int mt9m111_read_sensor(struct sd *sd, const u8 address, int mt9m111_write_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); -void mt9m111_dump_registers(struct sd *sd); - int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index ebf904170..95a58a0fa 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -56,6 +56,8 @@ static { } }; +static void ov9650_dump_registers(struct sd *sd); + int ov9650_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len) { @@ -563,7 +565,7 @@ out: return err; } -void ov9650_dump_registers(struct sd *sd) +static void ov9650_dump_registers(struct sd *sd) { int address; info("Dumping the ov9650 register state"); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index e0efdb930..4d90bd085 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -129,9 +129,7 @@ int ov9650_power_down(struct sd *sd); int ov9650_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); int ov9650_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - -void ov9650_dump_registers(struct sd *sd); + u8 *i2c_data, const u8 len); int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 739f2df55..655cc1732 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -18,6 +18,8 @@ #include "m5602_po1030.h" +static void po1030_dump_registers(struct sd *sd); + int po1030_probe(struct sd *sd) { u8 prod_id = 0, ver_id = 0, i; @@ -375,7 +377,7 @@ int po1030_power_down(struct sd *sd) return 0; } -void po1030_dump_registers(struct sd *sd) +static void po1030_dump_registers(struct sd *sd) { int address; u8 value = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index a0b75ff61..02072ccf9 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -128,8 +128,6 @@ int po1030_probe(struct sd *sd); int po1030_init(struct sd *sd); int po1030_power_down(struct sd *sd); -void po1030_dump_registers(struct sd *sd); - int po1030_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); int po1030_write_sensor(struct sd *sd, const u8 address, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 854f3f7f1..fcddbffa2 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -52,6 +52,7 @@ static { } }; +static void s5k4aa_dump_registers(struct sd *sd); int s5k4aa_probe(struct sd *sd) { @@ -457,7 +458,7 @@ out: return err; } -void s5k4aa_dump_registers(struct sd *sd) +static void s5k4aa_dump_registers(struct sd *sd) { int address; u8 page, old_page; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index b6aca3678..1ee649b8d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -67,8 +67,6 @@ int s5k4aa_probe(struct sd *sd); int s5k4aa_init(struct sd *sd); int s5k4aa_power_down(struct sd *sd); -void s5k4aa_dump_registers(struct sd *sd); - int s5k4aa_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); int s5k4aa_write_sensor(struct sd *sd, const u8 address, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 00f0964e0..34b99c000 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -18,6 +18,8 @@ #include "m5602_s5k83a.h" +static void s5k83a_dump_registers(struct sd *sd); + int s5k83a_probe(struct sd *sd) { u8 prod_id = 0, ver_id = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index acc89d08f..5080da196 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -46,8 +46,6 @@ int s5k83a_probe(struct sd *sd); int s5k83a_init(struct sd *sd); int s5k83a_power_down(struct sd *sd); -void s5k83a_dump_registers(struct sd *sd); - int s5k83a_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); int s5k83a_write_sensor(struct sd *sd, const u8 address, -- cgit v1.2.3 From 3738acdddc0414a41b7256e8a40a19f27106dccb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 16:45:59 +0100 Subject: cs53l32a: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cs53l32a.c | 188 +++++++++++++++++++++-------------- 1 file changed, 112 insertions(+), 76 deletions(-) diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c index 68f31270c..0620c4af4 100644 --- a/linux/drivers/media/video/cs53l32a.c +++ b/linux/drivers/media/video/cs53l32a.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -48,84 +48,104 @@ I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ -static int cs53l32a_write(struct i2c_client *client, u8 reg, u8 value) +static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_write_byte_data(client, reg, value); } -static int cs53l32a_read(struct i2c_client *client, u8 reg) +static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } -static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg) +static int cs53l32a_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct v4l2_routing *route = arg; - struct v4l2_control *ctrl = arg; - - switch (cmd) { - case VIDIOC_INT_G_AUDIO_ROUTING: - route->input = (cs53l32a_read(client, 0x01) >> 4) & 3; - route->output = 0; - break; - - case VIDIOC_INT_S_AUDIO_ROUTING: - /* There are 2 physical inputs, but the second input can be - placed in two modes, the first mode bypasses the PGA (gain), - the second goes through the PGA. Hence there are three - possible inputs to choose from. */ - if (route->input > 2) { - v4l_err(client, "Invalid input %d.\n", route->input); - return -EINVAL; - } - cs53l32a_write(client, 0x01, 0x01 + (route->input << 4)); - break; - - case VIDIOC_G_CTRL: - if (ctrl->id == V4L2_CID_AUDIO_MUTE) { - ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0; - break; - } - if (ctrl->id != V4L2_CID_AUDIO_VOLUME) - return -EINVAL; - ctrl->value = (s8)cs53l32a_read(client, 0x04); - break; - - case VIDIOC_S_CTRL: - if (ctrl->id == V4L2_CID_AUDIO_MUTE) { - cs53l32a_write(client, 0x03, ctrl->value ? 0xf0 : 0x30); - break; - } - if (ctrl->id != V4L2_CID_AUDIO_VOLUME) - return -EINVAL; - if (ctrl->value > 12 || ctrl->value < -96) - return -EINVAL; - cs53l32a_write(client, 0x04, (u8) ctrl->value); - cs53l32a_write(client, 0x05, (u8) ctrl->value); - break; - - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, - arg, V4L2_IDENT_CS53l32A, 0); - - case VIDIOC_LOG_STATUS: - { - u8 v = cs53l32a_read(client, 0x01); - u8 m = cs53l32a_read(client, 0x03); - s8 vol = cs53l32a_read(client, 0x04); - - v4l_info(client, "Input: %d%s\n", (v >> 4) & 3, - (m & 0xC0) ? " (muted)" : ""); - v4l_info(client, "Volume: %d dB\n", vol); - break; - } - - default: + /* There are 2 physical inputs, but the second input can be + placed in two modes, the first mode bypasses the PGA (gain), + the second goes through the PGA. Hence there are three + possible inputs to choose from. */ + if (route->input > 2) { + v4l2_err(sd, "Invalid input %d.\n", route->input); return -EINVAL; } + cs53l32a_write(sd, 0x01, 0x01 + (route->input << 4)); + return 0; +} + +static int cs53l32a_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + if (ctrl->id == V4L2_CID_AUDIO_MUTE) { + ctrl->value = (cs53l32a_read(sd, 0x03) & 0xc0) != 0; + return 0; + } + if (ctrl->id != V4L2_CID_AUDIO_VOLUME) + return -EINVAL; + ctrl->value = (s8)cs53l32a_read(sd, 0x04); + return 0; +} + +static int cs53l32a_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + if (ctrl->id == V4L2_CID_AUDIO_MUTE) { + cs53l32a_write(sd, 0x03, ctrl->value ? 0xf0 : 0x30); + return 0; + } + if (ctrl->id != V4L2_CID_AUDIO_VOLUME) + return -EINVAL; + if (ctrl->value > 12 || ctrl->value < -96) + return -EINVAL; + cs53l32a_write(sd, 0x04, (u8) ctrl->value); + cs53l32a_write(sd, 0x05, (u8) ctrl->value); return 0; } +static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, + chip, V4L2_IDENT_CS53l32A, 0); +} + +static int cs53l32a_log_status(struct v4l2_subdev *sd) +{ + u8 v = cs53l32a_read(sd, 0x01); + u8 m = cs53l32a_read(sd, 0x03); + s8 vol = cs53l32a_read(sd, 0x04); + + v4l2_info(sd, "Input: %d%s\n", (v >> 4) & 3, + (m & 0xC0) ? " (muted)" : ""); + v4l2_info(sd, "Volume: %d dB\n", vol); + return 0; +} + +static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { + .log_status = cs53l32a_log_status, + .g_chip_ident = cs53l32a_g_chip_ident, + .g_ctrl = cs53l32a_g_ctrl, + .s_ctrl = cs53l32a_s_ctrl, +}; + +static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = { + .s_routing = cs53l32a_s_routing, +}; + +static const struct v4l2_subdev_ops cs53l32a_ops = { + .core = &cs53l32a_core_ops, + .audio = &cs53l32a_audio_ops, +}; + /* ----------------------------------------------------------------------- */ /* i2c implementation */ @@ -138,6 +158,7 @@ static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg) static int cs53l32a_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct v4l2_subdev *sd; int i; /* Check if the adapter supports the needed features */ @@ -154,32 +175,46 @@ static int cs53l32a_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); + sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops); + for (i = 1; i <= 7; i++) { - u8 v = cs53l32a_read(client, i); + u8 v = cs53l32a_read(sd, i); - v4l_dbg(1, debug, client, "Read Reg %d %02x\n", i, v); + v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v); } /* Set cs53l32a internal register for Adaptec 2010/2410 setup */ - cs53l32a_write(client, 0x01, (u8) 0x21); - cs53l32a_write(client, 0x02, (u8) 0x29); - cs53l32a_write(client, 0x03, (u8) 0x30); - cs53l32a_write(client, 0x04, (u8) 0x00); - cs53l32a_write(client, 0x05, (u8) 0x00); - cs53l32a_write(client, 0x06, (u8) 0x00); - cs53l32a_write(client, 0x07, (u8) 0x00); + cs53l32a_write(sd, 0x01, (u8) 0x21); + cs53l32a_write(sd, 0x02, (u8) 0x29); + cs53l32a_write(sd, 0x03, (u8) 0x30); + cs53l32a_write(sd, 0x04, (u8) 0x00); + cs53l32a_write(sd, 0x05, (u8) 0x00); + cs53l32a_write(sd, 0x06, (u8) 0x00); + cs53l32a_write(sd, 0x07, (u8) 0x00); /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */ for (i = 1; i <= 7; i++) { - u8 v = cs53l32a_read(client, i); + u8 v = cs53l32a_read(sd, i); - v4l_dbg(1, debug, client, "Read Reg %d %02x\n", i, v); + v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v); } return 0; } +static int cs53l32a_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); + return 0; +} + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id cs53l32a_id[] = { { "cs53l32a", 0 }, @@ -192,6 +227,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cs53l32a", .driverid = I2C_DRIVERID_CS53L32A, .command = cs53l32a_command, + .remove = cs53l32a_remove, .probe = cs53l32a_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = cs53l32a_id, -- cgit v1.2.3 From 91617d3e59f1badd43dd28ea7f3157c7781d08dc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 16:50:06 +0100 Subject: cx25840: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx25840/cx25840-audio.c | 14 +- linux/drivers/media/video/cx25840/cx25840-core.c | 447 ++++++++++++--------- linux/drivers/media/video/cx25840/cx25840-core.h | 7 + .../drivers/media/video/cx25840/cx25840-firmware.c | 2 +- linux/drivers/media/video/cx25840/cx25840-vbi.c | 2 +- 5 files changed, 279 insertions(+), 193 deletions(-) diff --git a/linux/drivers/media/video/cx25840/cx25840-audio.c b/linux/drivers/media/video/cx25840/cx25840-audio.c index 8e134312c..3ee7d7a7d 100644 --- a/linux/drivers/media/video/cx25840/cx25840-audio.c +++ b/linux/drivers/media/video/cx25840/cx25840-audio.c @@ -26,7 +26,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); if (freq != 32000 && freq != 44100 && freq != 48000) return -EINVAL; @@ -194,7 +194,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) void cx25840_audio_set_path(struct i2c_client *client) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); /* assert soft reset */ cx25840_and_or(client, 0x810, ~0x1, 0x01); @@ -236,7 +236,7 @@ void cx25840_audio_set_path(struct i2c_client *client) static int get_volume(struct i2c_client *client) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); int vol; if (state->unmute_volume >= 0) @@ -253,7 +253,7 @@ static int get_volume(struct i2c_client *client) static void set_volume(struct i2c_client *client, int volume) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); int vol; if (state->unmute_volume >= 0) { @@ -341,14 +341,14 @@ static void set_balance(struct i2c_client *client, int balance) static int get_mute(struct i2c_client *client) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); return state->unmute_volume >= 0; } static void set_mute(struct i2c_client *client, int mute) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); if (mute && state->unmute_volume == -1) { int vol = get_volume(client); @@ -366,7 +366,7 @@ static void set_mute(struct i2c_client *client, int mute) int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); struct v4l2_control *ctrl = arg; int retval; diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index cb4a9c64e..52a2a5799 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -198,7 +198,7 @@ void cx25840_work_handler(void *arg) static void cx25840_initialize(struct i2c_client *client) { DEFINE_WAIT(wait); - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); struct workqueue_struct *q; /* datasheet startup in numbered steps, refer to page 3-77 */ @@ -270,7 +270,7 @@ static void cx25840_initialize(struct i2c_client *client) static void cx23885_initialize(struct i2c_client *client) { DEFINE_WAIT(wait); - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); struct workqueue_struct *q; /* Internal Reset */ @@ -369,7 +369,7 @@ static void cx23885_initialize(struct i2c_client *client) void cx25840_std_setup(struct i2c_client *client) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); v4l2_std_id std = state->std; int hblank, hactive, burst, vblank, vactive, sc; int vblank656, src_decimation; @@ -516,7 +516,7 @@ void cx25840_std_setup(struct i2c_client *client) static void input_change(struct i2c_client *client) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); v4l2_std_id std = state->std; /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ @@ -570,7 +570,7 @@ static void input_change(struct i2c_client *client) static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, enum cx25840_audio_input aud_input) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); u8 is_composite = (vid_input >= CX25840_COMPOSITE1 && vid_input <= CX25840_COMPOSITE8); u8 reg; @@ -690,7 +690,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp static int set_v4lstd(struct i2c_client *client) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); u8 fmt = 0; /* zero is autodetect */ u8 pal_m = 0; @@ -739,9 +739,10 @@ static int set_v4lstd(struct i2c_client *client) /* ----------------------------------------------------------------------- */ -static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); switch (ctrl->id) { case CX25840_CID_ENABLE_PVR150_WORKAROUND: @@ -805,9 +806,10 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) return 0; } -static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); switch (ctrl->id) { case CX25840_CID_ENABLE_PVR150_WORKAROUND: @@ -842,21 +844,23 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) /* ----------------------------------------------------------------------- */ -static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) +static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + switch (fmt->type) { case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: return cx25840_vbi(client, VIDIOC_G_FMT, fmt); default: return -EINVAL; } - return 0; } -static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) +static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int is_50Hz = !(state->std & V4L2_STD_525_60); @@ -933,7 +937,7 @@ static void log_video_status(struct i2c_client *client) "0xD", "0xE", "0xF" }; - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; u8 gen_stat1 = cx25840_read(client, 0x40d); u8 gen_stat2 = cx25840_read(client, 0x40e); @@ -963,7 +967,7 @@ static void log_video_status(struct i2c_client *client) static void log_audio_status(struct i2c_client *client) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); u8 download_ctl = cx25840_read(client, 0x803); u8 mod_det_stat0 = cx25840_read(client, 0x804); u8 mod_det_stat1 = cx25840_read(client, 0x805); @@ -1116,21 +1120,12 @@ static void log_audio_status(struct i2c_client *client) /* ----------------------------------------------------------------------- */ -static int cx25840_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int cx25840_init(struct v4l2_subdev *sd, u32 val) { - struct cx25840_state *state = i2c_get_clientdata(client); - struct v4l2_tuner *vt = arg; - struct v4l2_routing *route = arg; - - /* ignore these commands */ - switch (cmd) { - case TUNER_SET_TYPE_ADDR: - return 0; - } + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); if (!state->is_initialized) { - v4l_dbg(1, cx25840_debug, client, "cmd %08x triggered fw load\n", cmd); /* initialize on first use */ state->is_initialized = 1; if (state->is_cx25836) @@ -1140,50 +1135,69 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, else cx25840_initialize(client); } + return 0; +} - switch (cmd) { #ifdef CONFIG_VIDEO_ADV_DEBUG - /* ioctls to allow direct access to the - * cx25840 registers for testing */ - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - - if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; +static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - if (cmd == VIDIOC_DBG_G_REGISTER) - reg->val = cx25840_read(client, reg->reg & 0x0fff); - else - cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); - break; - } + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = cx25840_read(client, reg->reg & 0x0fff); + return 0; +} + +static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); + return 0; +} #endif - case VIDIOC_INT_DECODE_VBI_LINE: - return cx25840_vbi(client, cmd, arg); +static int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return cx25840_audio(client, cmd, arg); + return cx25840_vbi(client, VIDIOC_INT_DECODE_VBI_LINE, vbi); +} + +static int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return cx25840_audio(client, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq); +} + +static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_STREAMON: - v4l_dbg(1, cx25840_debug, client, "enable output\n"); + v4l_dbg(1, cx25840_debug, client, "%s output\n", + enable ? "enable" : "disable"); + if (enable) { if (state->is_cx23885) { u8 v = (cx25840_read(client, 0x421) | 0x0b); cx25840_write(client, 0x421, v); } else { cx25840_write(client, 0x115, - state->is_cx25836 ? 0x0c : 0x8c); + state->is_cx25836 ? 0x0c : 0x8c); cx25840_write(client, 0x116, - state->is_cx25836 ? 0x04 : 0x07); + state->is_cx25836 ? 0x04 : 0x07); } - break; - - case VIDIOC_STREAMOFF: - v4l_dbg(1, cx25840_debug, client, "disable output\n"); + } else { if (state->is_cx23885) { u8 v = cx25840_read(client, 0x421) & ~(0x0b); cx25840_write(client, 0x421, v); @@ -1191,133 +1205,136 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, cx25840_write(client, 0x115, 0x00); cx25840_write(client, 0x116, 0x00); } - break; + } + return 0; +} - case VIDIOC_LOG_STATUS: - log_video_status(client); - if (!state->is_cx25836) - log_audio_status(client); - break; +static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + struct cx25840_state *state = to_state(sd); - case VIDIOC_G_CTRL: - return get_v4lctrl(client, (struct v4l2_control *)arg); + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill_std(qc); + default: + break; + } + if (state->is_cx25836) + return -EINVAL; - case VIDIOC_S_CTRL: - return set_v4lctrl(client, (struct v4l2_control *)arg); + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, + 65535 / 100, state->default_volume); + case V4L2_CID_AUDIO_MUTE: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill_std(qc); + default: + return -EINVAL; + } + return -EINVAL; +} - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; +static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); - default: - break; - } - if (state->is_cx25836) - return -EINVAL; + if (state->radio == 0 && state->std == std) + return 0; + state->radio = 0; + state->std = std; + return set_v4lstd(client); +} - switch (qc->id) { - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qc, 0, 65535, - 65535 / 100, state->default_volume); - case V4L2_CID_AUDIO_MUTE: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); - default: - return -EINVAL; - } - return -EINVAL; - } +static int cx25840_s_radio(struct v4l2_subdev *sd) +{ + struct cx25840_state *state = to_state(sd); - case VIDIOC_G_STD: - *(v4l2_std_id *)arg = state->std; - break; + state->radio = 1; + return 0; +} - case VIDIOC_S_STD: - if (state->radio == 0 && state->std == *(v4l2_std_id *)arg) - return 0; - state->radio = 0; - state->std = *(v4l2_std_id *)arg; - return set_v4lstd(client); +static int cx25840_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case AUDC_SET_RADIO: - state->radio = 1; - break; + return set_input(client, route->input, state->aud_input); +} - case VIDIOC_INT_G_VIDEO_ROUTING: - route->input = state->vid_input; - route->output = 0; - break; +static int cx25840_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_INT_S_VIDEO_ROUTING: - return set_input(client, route->input, state->aud_input); + if (state->is_cx25836) + return -EINVAL; + return set_input(client, state->vid_input, route->input); +} - case VIDIOC_INT_G_AUDIO_ROUTING: - if (state->is_cx25836) - return -EINVAL; - route->input = state->aud_input; - route->output = 0; - break; +static int cx25840_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_INT_S_AUDIO_ROUTING: - if (state->is_cx25836) - return -EINVAL; - return set_input(client, state->vid_input, route->input); + if (!state->is_cx25836) + input_change(client); + return 0; +} - case VIDIOC_S_FREQUENCY: - if (!state->is_cx25836) { - input_change(client); - } - break; +static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + u8 vpres = cx25840_read(client, 0x40e) & 0x20; + u8 mode; + int val = 0; - case VIDIOC_G_TUNER: - { - u8 vpres = cx25840_read(client, 0x40e) & 0x20; - u8 mode; - int val = 0; + if (state->radio) + return 0; - if (state->radio) - break; + vt->signal = vpres ? 0xffff : 0x0; + if (state->is_cx25836) + return 0; - vt->signal = vpres ? 0xffff : 0x0; - if (state->is_cx25836) - break; + vt->capability |= + V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | + V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; - vt->capability |= - V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | - V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; + mode = cx25840_read(client, 0x804); - mode = cx25840_read(client, 0x804); + /* get rxsubchans and audmode */ + if ((mode & 0xf) == 1) + val |= V4L2_TUNER_SUB_STEREO; + else + val |= V4L2_TUNER_SUB_MONO; - /* get rxsubchans and audmode */ - if ((mode & 0xf) == 1) - val |= V4L2_TUNER_SUB_STEREO; - else - val |= V4L2_TUNER_SUB_MONO; + if (mode == 2 || mode == 4) + val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - if (mode == 2 || mode == 4) - val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + if (mode & 0x10) + val |= V4L2_TUNER_SUB_SAP; - if (mode & 0x10) - val |= V4L2_TUNER_SUB_SAP; + vt->rxsubchans = val; + vt->audmode = state->audmode; + return 0; +} - vt->rxsubchans = val; - vt->audmode = state->audmode; - break; - } +static int cx25840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_S_TUNER: - if (state->radio || state->is_cx25836) - break; + if (state->radio || state->is_cx25836) + return 0; - switch (vt->audmode) { + switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: /* mono -> mono stereo -> mono @@ -1345,41 +1362,100 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, break; default: return -EINVAL; - } - state->audmode = vt->audmode; - break; + } + state->audmode = vt->audmode; + return 0; +} - case VIDIOC_G_FMT: - return get_v4lfmt(client, (struct v4l2_format *)arg); +static int cx25840_reset(struct v4l2_subdev *sd, u32 val) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_S_FMT: - return set_v4lfmt(client, (struct v4l2_format *)arg); + if (state->is_cx25836) + cx25836_initialize(client); + else if (state->is_cx23885) + cx23885_initialize(client); + else + cx25840_initialize(client); + return 0; +} - case VIDIOC_INT_RESET: - if (state->is_cx25836) - cx25836_initialize(client); - else if (state->is_cx23885) - cx23885_initialize(client); - else - cx25840_initialize(client); - break; +static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, state->id, state->rev); + return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); +} - default: - return -EINVAL; - } +static int cx25840_log_status(struct v4l2_subdev *sd) +{ + struct cx25840_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + log_video_status(client); + if (!state->is_cx25836) + log_audio_status(client); return 0; } +static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops cx25840_core_ops = { + .log_status = cx25840_log_status, + .g_chip_ident = cx25840_g_chip_ident, + .g_ctrl = cx25840_g_ctrl, + .s_ctrl = cx25840_s_ctrl, + .queryctrl = cx25840_queryctrl, + .reset = cx25840_reset, + .init = cx25840_init, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = cx25840_g_register, + .s_register = cx25840_s_register, +#endif +}; + +static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = { + .s_frequency = cx25840_s_frequency, + .s_std = cx25840_s_std, + .s_radio = cx25840_s_radio, + .g_tuner = cx25840_g_tuner, + .s_tuner = cx25840_s_tuner, +}; + +static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { + .s_clock_freq = cx25840_s_clock_freq, + .s_routing = cx25840_s_audio_routing, +}; + +static const struct v4l2_subdev_video_ops cx25840_video_ops = { + .s_routing = cx25840_s_video_routing, + .g_fmt = cx25840_g_fmt, + .s_fmt = cx25840_s_fmt, + .decode_vbi_line = cx25840_decode_vbi_line, + .s_stream = cx25840_s_stream, +}; + +static const struct v4l2_subdev_ops cx25840_ops = { + .core = &cx25840_core_ops, + .tuner = &cx25840_tuner_ops, + .audio = &cx25840_audio_ops, + .video = &cx25840_video_ops, +}; + /* ----------------------------------------------------------------------- */ static int cx25840_probe(struct i2c_client *client, const struct i2c_device_id *did) { struct cx25840_state *state; + struct v4l2_subdev *sd; u32 id; u16 device_id; @@ -1411,10 +1487,11 @@ static int cx25840_probe(struct i2c_client *client, } state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); - if (state == NULL) { + if (state == NULL) return -ENOMEM; - } + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &cx25840_ops); /* Note: revision '(device_id & 0x0f) == 2' was never built. The marking skips from 0x1 == 22 to 0x3 == 23. */ v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", @@ -1422,7 +1499,6 @@ static int cx25840_probe(struct i2c_client *client, (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), client->addr << 1, client->adapter->name); - i2c_set_clientdata(client, state); state->c = client; state->is_cx25836 = ((device_id & 0xff00) == 0x8300); state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); @@ -1449,7 +1525,10 @@ static int cx25840_probe(struct i2c_client *client, static int cx25840_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } diff --git a/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h index cd549b119..0a99c19df 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.h +++ b/linux/drivers/media/video/cx25840/cx25840-core.h @@ -23,6 +23,7 @@ #include "compat.h" #include +#include #include /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is @@ -35,6 +36,7 @@ struct cx25840_state { struct i2c_client *c; + struct v4l2_subdev sd; int pvr150_workaround; int radio; v4l2_std_id std; @@ -54,6 +56,11 @@ struct cx25840_state { struct work_struct fw_work; /* work entry for fw load */ }; +static inline struct cx25840_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct cx25840_state, sd); +} + /* ----------------------------------------------------------------------- */ /* cx25850-core.c */ int cx25840_write(struct i2c_client *client, u16 addr, u8 value); diff --git a/linux/drivers/media/video/cx25840/cx25840-firmware.c b/linux/drivers/media/video/cx25840/cx25840-firmware.c index 04a5dbb65..01fbe174e 100644 --- a/linux/drivers/media/video/cx25840/cx25840-firmware.c +++ b/linux/drivers/media/video/cx25840/cx25840-firmware.c @@ -92,7 +92,7 @@ static int fw_write(struct i2c_client *client, const u8 *data, int size) int cx25840_loadfw(struct i2c_client *client) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); const struct firmware *fw = NULL; u8 buffer[FWSEND]; const u8 *ptr; diff --git a/linux/drivers/media/video/cx25840/cx25840-vbi.c b/linux/drivers/media/video/cx25840/cx25840-vbi.c index e45c39625..7790afd5b 100644 --- a/linux/drivers/media/video/cx25840/cx25840-vbi.c +++ b/linux/drivers/media/video/cx25840/cx25840-vbi.c @@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p) int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) { - struct cx25840_state *state = i2c_get_clientdata(client); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); struct v4l2_format *fmt; struct v4l2_sliced_vbi_format *svbi; -- cgit v1.2.3 From 59736da8febbd58e35798210cb51e2e9e4dbe3a9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 16:51:32 +0100 Subject: m52790: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/m52790.c | 176 +++++++++++++++++++++++-------------- 1 file changed, 111 insertions(+), 65 deletions(-) diff --git a/linux/drivers/media/video/m52790.c b/linux/drivers/media/video/m52790.c index f39da4a36..1976451e0 100644 --- a/linux/drivers/media/video/m52790.c +++ b/linux/drivers/media/video/m52790.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -44,89 +44,130 @@ I2C_CLIENT_INSMOD; #endif struct m52790_state { + struct v4l2_subdev sd; u16 input; u16 output; }; +static inline struct m52790_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct m52790_state, sd); +} + /* ----------------------------------------------------------------------- */ -static int m52790_write(struct i2c_client *client) +static int m52790_write(struct v4l2_subdev *sd) { - struct m52790_state *state = i2c_get_clientdata(client); + struct m52790_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + u8 sw1 = (state->input | state->output) & 0xff; u8 sw2 = (state->input | state->output) >> 8; return i2c_smbus_write_byte_data(client, sw1, sw2); } -static int m52790_command(struct i2c_client *client, unsigned int cmd, - void *arg) +/* Note: audio and video are linked and cannot be switched separately. + So audio and video routing commands are identical for this chip. + In theory the video amplifier and audio modes could be handled + separately for the output, but that seems to be overkill right now. + The same holds for implementing an audio mute control, this is now + part of the audio output routing. The normal case is that another + chip takes care of the actual muting so making it part of the + output routing seems to be the right thing to do for now. */ +static int m52790_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct m52790_state *state = i2c_get_clientdata(client); - struct v4l2_routing *route = arg; - - /* Note: audio and video are linked and cannot be switched separately. - So audio and video routing commands are identical for this chip. - In theory the video amplifier and audio modes could be handled - separately for the output, but that seems to be overkill right now. - The same holds for implementing an audio mute control, this is now - part of the audio output routing. The normal case is that another - chip takes care of the actual muting so making it part of the - output routing seems to be the right thing to do for now. */ - switch (cmd) { - case VIDIOC_INT_G_AUDIO_ROUTING: - case VIDIOC_INT_G_VIDEO_ROUTING: - route->input = state->input; - route->output = state->output; - break; - - case VIDIOC_INT_S_AUDIO_ROUTING: - case VIDIOC_INT_S_VIDEO_ROUTING: - state->input = route->input; - state->output = route->output; - m52790_write(client); - break; + struct m52790_state *state = to_state(sd); + + state->input = route->input; + state->output = route->output; + m52790_write(sd); + return 0; +} #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (reg->reg != 0) - return -EINVAL; - if (cmd == VIDIOC_DBG_G_REGISTER) - reg->val = state->input | state->output; - else { - state->input = reg->val & 0x0303; - state->output = reg->val & ~0x0303; - m52790_write(client); - } - break; - } -#endif +static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct m52790_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, - V4L2_IDENT_M52790, 0); + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (reg->reg != 0) + return -EINVAL; + reg->val = state->input | state->output; + return 0; +} - case VIDIOC_LOG_STATUS: - v4l_info(client, "Switch 1: %02x\n", - (state->input | state->output) & 0xff); - v4l_info(client, "Switch 2: %02x\n", - (state->input | state->output) >> 8); - break; +static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct m52790_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - default: + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) return -EINVAL; - } + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (reg->reg != 0) + return -EINVAL; + state->input = reg->val & 0x0303; + state->output = reg->val & ~0x0303; + m52790_write(sd); return 0; } +#endif + +static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_M52790, 0); +} + +static int m52790_log_status(struct v4l2_subdev *sd) +{ + struct m52790_state *state = to_state(sd); + + v4l2_info(sd, "Switch 1: %02x\n", + (state->input | state->output) & 0xff); + v4l2_info(sd, "Switch 2: %02x\n", + (state->input | state->output) >> 8); + return 0; +} + +static int m52790_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops m52790_core_ops = { + .log_status = m52790_log_status, + .g_chip_ident = m52790_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = m52790_g_register, + .s_register = m52790_s_register, +#endif +}; + +static const struct v4l2_subdev_audio_ops m52790_audio_ops = { + .s_routing = m52790_s_routing, +}; + +static const struct v4l2_subdev_video_ops m52790_video_ops = { + .s_routing = m52790_s_routing, +}; + +static const struct v4l2_subdev_ops m52790_ops = { + .core = &m52790_core_ops, + .audio = &m52790_audio_ops, + .video = &m52790_video_ops, +}; /* ----------------------------------------------------------------------- */ @@ -136,6 +177,7 @@ static int m52790_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct m52790_state *state; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -152,16 +194,20 @@ static int m52790_probe(struct i2c_client *client, if (state == NULL) return -ENOMEM; + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &m52790_ops); state->input = M52790_IN_TUNER; state->output = M52790_OUT_STEREO; - i2c_set_clientdata(client, state); - m52790_write(client); + m52790_write(sd); return 0; } static int m52790_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From 24dc2f33e9336e9e01da8321352fb93173454e88 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 24 Nov 2008 22:16:46 +0100 Subject: msp3400: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/msp3400-driver.c | 406 +++++++++++++++------------ linux/drivers/media/video/msp3400-driver.h | 7 + linux/drivers/media/video/msp3400-kthreads.c | 34 +-- 3 files changed, 249 insertions(+), 198 deletions(-) diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index c6c0a584c..def15e381 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -51,18 +51,18 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) #include #else #include #endif +#include +#include +#include +#include +#include +#include #include "compat.h" #include "msp3400-driver.h" @@ -270,7 +270,7 @@ static char *scart_names[] = { void msp_set_scart(struct i2c_client *client, int in, int out) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); state->in_scart = in; @@ -294,7 +294,7 @@ void msp_set_scart(struct i2c_client *client, int in, int out) void msp_set_audio(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); int bal = 0, bass, treble, loudness; int val = 0; int reallymuted = state->muted | state->scan_in_progress; @@ -341,7 +341,7 @@ void msp_set_audio(struct i2c_client *client) static void msp_wake_thread(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); if (NULL == state->kthread) return; @@ -395,9 +395,9 @@ static int msp_mode_v4l1_to_v4l2(int mode) } #endif -static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int msp_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(sd); switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -438,9 +438,10 @@ static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) return 0; } -static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -486,40 +487,16 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) return 0; } -static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) +#ifdef CONFIG_VIDEO_ALLOW_V4L1 +static int msp_ioctl(struct v4l2_subdev *sd, int cmd, void *arg) { - struct msp_state *state = i2c_get_clientdata(client); - - if (msp_debug >= 2) - v4l_i2c_print_ioctl(client, cmd); + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); switch (cmd) { - case AUDC_SET_RADIO: - if (state->radio) - return 0; - state->radio = 1; - v4l_dbg(1, msp_debug, client, "switching to radio mode\n"); - state->watch_stereo = 0; - switch (state->opmode) { - case OPMODE_MANUAL: - /* set msp3400 to FM radio mode */ - msp3400c_set_mode(client, MSP_MODE_FM_RADIO); - msp3400c_set_carrier(client, MSP_CARRIER(10.7), - MSP_CARRIER(10.7)); - msp_set_audio(client); - break; - case OPMODE_AUTODETECT: - case OPMODE_AUTOSELECT: - /* the thread will do for us */ - msp_wake_thread(client); - break; - } - break; - /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ -#ifdef CONFIG_VIDEO_ALLOW_V4L1 case VIDIOCGAUDIO: { struct video_audio *va = arg; @@ -593,105 +570,137 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp_wake_thread(client); break; } -#endif - case VIDIOC_S_FREQUENCY: - { - /* new channel -- kick audio carrier scan */ - msp_wake_thread(client); - break; + default: + return -ENOIOCTLCMD; } + return 0; +} +#endif - /* --- v4l2 ioctls --- */ - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - int update = state->radio || state->v4l2_std != *id; +/* --- v4l2 ioctls --- */ +static int msp_s_radio(struct v4l2_subdev *sd) +{ + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - state->v4l2_std = *id; - state->radio = 0; - if (update) - msp_wake_thread(client); + if (state->radio) return 0; + state->radio = 1; + v4l_dbg(1, msp_debug, client, "switching to radio mode\n"); + state->watch_stereo = 0; + switch (state->opmode) { + case OPMODE_MANUAL: + /* set msp3400 to FM radio mode */ + msp3400c_set_mode(client, MSP_MODE_FM_RADIO); + msp3400c_set_carrier(client, MSP_CARRIER(10.7), + MSP_CARRIER(10.7)); + msp_set_audio(client); + break; + case OPMODE_AUTODETECT: + case OPMODE_AUTOSELECT: + /* the thread will do for us */ + msp_wake_thread(client); + break; } + return 0; +} - case VIDIOC_INT_G_AUDIO_ROUTING: - { - struct v4l2_routing *rt = arg; +static int msp_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - *rt = state->routing; - break; - } + /* new channel -- kick audio carrier scan */ + msp_wake_thread(client); + return 0; +} - case VIDIOC_INT_S_AUDIO_ROUTING: - { - struct v4l2_routing *rt = arg; - int tuner = (rt->input >> 3) & 1; - int sc_in = rt->input & 0x7; - int sc1_out = rt->output & 0xf; - int sc2_out = (rt->output >> 4) & 0xf; - u16 val, reg; - int i; - int extern_input = 1; - - if (state->routing.input == rt->input && - state->routing.output == rt->output) - break; - state->routing = *rt; - /* check if the tuner input is used */ - for (i = 0; i < 5; i++) { - if (((rt->input >> (4 + i * 4)) & 0xf) == 0) - extern_input = 0; - } - state->mode = extern_input ? MSP_MODE_EXTERN : MSP_MODE_AM_DETECT; - state->rxsubchans = V4L2_TUNER_SUB_STEREO; - msp_set_scart(client, sc_in, 0); - msp_set_scart(client, sc1_out, 1); - msp_set_scart(client, sc2_out, 2); - msp_set_audmode(client); - reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb; - val = msp_read_dem(client, reg); - msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); - /* wake thread when a new input is chosen */ +static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id) +{ + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int update = state->radio || state->v4l2_std != id; + + state->v4l2_std = id; + state->radio = 0; + if (update) msp_wake_thread(client); - break; + return 0; +} + +static int msp_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *rt) +{ + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int tuner = (rt->input >> 3) & 1; + int sc_in = rt->input & 0x7; + int sc1_out = rt->output & 0xf; + int sc2_out = (rt->output >> 4) & 0xf; + u16 val, reg; + int i; + int extern_input = 1; + + if (state->routing.input == rt->input && + state->routing.output == rt->output) + return 0; + state->routing = *rt; + /* check if the tuner input is used */ + for (i = 0; i < 5; i++) { + if (((rt->input >> (4 + i * 4)) & 0xf) == 0) + extern_input = 0; } + state->mode = extern_input ? MSP_MODE_EXTERN : MSP_MODE_AM_DETECT; + state->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp_set_scart(client, sc_in, 0); + msp_set_scart(client, sc1_out, 1); + msp_set_scart(client, sc2_out, 2); + msp_set_audmode(client); + reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb; + val = msp_read_dem(client, reg); + msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); + /* wake thread when a new input is chosen */ + msp_wake_thread(client); + return 0; +} - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *vt = arg; +static int msp_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - if (state->radio) - break; - if (state->opmode == OPMODE_AUTOSELECT) - msp_detect_stereo(client); - vt->audmode = state->audmode; - vt->rxsubchans = state->rxsubchans; - vt->capability |= V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - break; - } + if (state->radio) + return 0; + if (state->opmode == OPMODE_AUTOSELECT) + msp_detect_stereo(client); + vt->audmode = state->audmode; + vt->rxsubchans = state->rxsubchans; + vt->capability |= V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; + return 0; +} - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; +static int msp_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - if (state->radio) /* TODO: add mono/stereo support for radio */ - break; - if (state->audmode == vt->audmode) - break; - state->audmode = vt->audmode; - /* only set audmode */ - msp_set_audmode(client); - break; - } + if (state->radio) /* TODO: add mono/stereo support for radio */ + return 0; + if (state->audmode == vt->audmode) + return 0; + state->audmode = vt->audmode; + /* only set audmode */ + msp_set_audmode(client); + return 0; +} - case VIDIOC_INT_I2S_CLOCK_FREQ: - { - u32 *a = (u32 *)arg; +static int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) +{ + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", *a); + v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", freq); - switch (*a) { + switch (freq) { case 1024000: state->i2s_mode = 0; break; @@ -700,24 +709,24 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; default: return -EINVAL; - } - break; } + return 0; +} - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; +static int msp_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + struct msp_state *state = to_state(sd); - switch (qc->id) { + switch (qc->id) { case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_MUTE: return v4l2_ctrl_query_fill_std(qc); default: break; - } - if (!state->has_sound_processing) - return -EINVAL; - switch (qc->id) { + } + if (!state->has_sound_processing) + return -EINVAL; + switch (qc->id) { case V4L2_CID_AUDIO_LOUDNESS: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: @@ -725,32 +734,38 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return v4l2_ctrl_query_fill_std(qc); default: return -EINVAL; - } } + return 0; +} - case VIDIOC_G_CTRL: - return msp_get_ctrl(client, arg); - - case VIDIOC_S_CTRL: - return msp_set_ctrl(client, arg); +static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_LOG_STATUS: - { - const char *p; + return v4l2_chip_ident_i2c_client(client, chip, state->ident, + (state->rev1 << 16) | state->rev2); +} - if (state->opmode == OPMODE_AUTOSELECT) - msp_detect_stereo(client); - v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", - client->name, state->rev1, state->rev2); - v4l_info(client, "Audio: volume %d%s\n", - state->volume, state->muted ? " (muted)" : ""); - if (state->has_sound_processing) { - v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n", - state->balance, state->bass, - state->treble, - state->loudness ? "on" : "off"); - } - switch (state->mode) { +static int msp_log_status(struct v4l2_subdev *sd) +{ + struct msp_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + const char *p; + + if (state->opmode == OPMODE_AUTOSELECT) + msp_detect_stereo(client); + v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", + client->name, state->rev1, state->rev2); + v4l_info(client, "Audio: volume %d%s\n", + state->volume, state->muted ? " (muted)" : ""); + if (state->has_sound_processing) { + v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n", + state->balance, state->bass, + state->treble, + state->loudness ? "on" : "off"); + } + switch (state->mode) { case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break; case MSP_MODE_FM_RADIO: p = "FM Radio"; break; case MSP_MODE_FM_TERRA: p = "Terrestial FM-mono/stereo"; break; @@ -761,36 +776,25 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case MSP_MODE_BTSC: p = "BTSC"; break; case MSP_MODE_EXTERN: p = "External input"; break; default: p = "unknown"; break; - } - if (state->mode == MSP_MODE_EXTERN) { - v4l_info(client, "Mode: %s\n", p); - } else if (state->opmode == OPMODE_MANUAL) { - v4l_info(client, "Mode: %s (%s%s)\n", p, + } + if (state->mode == MSP_MODE_EXTERN) { + v4l_info(client, "Mode: %s\n", p); + } else if (state->opmode == OPMODE_MANUAL) { + v4l_info(client, "Mode: %s (%s%s)\n", p, (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); - } else { - if (state->opmode == OPMODE_AUTODETECT) - v4l_info(client, "Mode: %s\n", p); - v4l_info(client, "Standard: %s (%s%s)\n", + } else { + if (state->opmode == OPMODE_AUTODETECT) + v4l_info(client, "Mode: %s\n", p); + v4l_info(client, "Standard: %s (%s%s)\n", msp_standard_std_name(state->std), (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); - } - v4l_info(client, "Audmode: 0x%04x\n", state->audmode); - v4l_info(client, "Routing: 0x%08x (input) 0x%08x (output)\n", - state->routing.input, state->routing.output); - v4l_info(client, "ACB: 0x%04x\n", state->acb); - break; - } - - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, state->ident, - (state->rev1 << 16) | state->rev2); - - default: - /* unknown */ - return -EINVAL; } + v4l_info(client, "Audmode: 0x%04x\n", state->audmode); + v4l_info(client, "Routing: 0x%08x (input) 0x%08x (output)\n", + state->routing.input, state->routing.output); + v4l_info(client, "ACB: 0x%04x\n", state->acb); return 0; } @@ -808,11 +812,49 @@ static int msp_resume(struct i2c_client *client) return 0; } +static int msp_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops msp_core_ops = { + .log_status = msp_log_status, + .g_chip_ident = msp_g_chip_ident, + .g_ctrl = msp_g_ctrl, + .s_ctrl = msp_s_ctrl, + .queryctrl = msp_queryctrl, +#ifdef CONFIG_VIDEO_ALLOW_V4L1 + .ioctl = msp_ioctl, +#endif +}; + +static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { + .s_frequency = msp_s_frequency, + .g_tuner = msp_g_tuner, + .s_tuner = msp_s_tuner, + .s_radio = msp_s_radio, + .s_std = msp_s_std, +}; + +static const struct v4l2_subdev_audio_ops msp_audio_ops = { + .s_routing = msp_s_routing, + .s_i2s_clock_freq = msp_s_i2s_clock_freq, +}; + +static const struct v4l2_subdev_ops msp_ops = { + .core = &msp_core_ops, + .tuner = &msp_tuner_ops, + .audio = &msp_audio_ops, +}; + /* ----------------------------------------------------------------------- */ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct msp_state *state; + struct v4l2_subdev *sd; int (*thread_func)(void *data) = NULL; int msp_hard; int msp_family; @@ -836,7 +878,8 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) if (!state) return -ENOMEM; - i2c_set_clientdata(client, state); + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &msp_ops); state->v4l2_std = V4L2_STD_NTSC; state->audmode = V4L2_TUNER_MODE_STEREO; @@ -990,8 +1033,9 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) static int msp_remove(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); + v4l2_device_unregister_subdev(&state->sd); /* shutdown control thread */ if (state->kthread) { state->restart = 1; diff --git a/linux/drivers/media/video/msp3400-driver.h b/linux/drivers/media/video/msp3400-driver.h index ab69a290e..3fe1c1b10 100644 --- a/linux/drivers/media/video/msp3400-driver.h +++ b/linux/drivers/media/video/msp3400-driver.h @@ -5,6 +5,7 @@ #define MSP3400_DRIVER_H #include +#include /* ---------------------------------------------------------------------- */ @@ -49,6 +50,7 @@ extern int msp_dolby; extern int msp_stereo_thresh; struct msp_state { + struct v4l2_subdev sd; int rev1, rev2; int ident; u8 has_nicam; @@ -96,6 +98,11 @@ struct msp_state { unsigned int watch_stereo:1; }; +static inline struct msp_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct msp_state, sd); +} + /* msp3400-driver.c */ int msp_write_dem(struct i2c_client *client, int addr, int val); int msp_write_dsp(struct i2c_client *client, int addr, int val); diff --git a/linux/drivers/media/video/msp3400-kthreads.c b/linux/drivers/media/video/msp3400-kthreads.c index 29c0d5cf6..ccba71d9f 100644 --- a/linux/drivers/media/video/msp3400-kthreads.c +++ b/linux/drivers/media/video/msp3400-kthreads.c @@ -162,7 +162,7 @@ const char *msp_standard_std_name(int std) static void msp_set_source(struct i2c_client *client, u16 src) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); if (msp_dolby) { msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ @@ -189,7 +189,7 @@ void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2) void msp3400c_set_mode(struct i2c_client *client, int mode) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; int tuner = (state->routing.input >> 3) & 1; int i; @@ -230,7 +230,7 @@ static void msp3400c_set_audmode(struct i2c_client *client) static char *strmode[] = { "mono", "stereo", "lang2", "lang1", "lang1+lang2" }; - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); char *modestr = (state->audmode >= 0 && state->audmode < 5) ? strmode[state->audmode] : "unknown"; int src = 0; /* channel source: FM/AM, nicam or SCART */ @@ -359,7 +359,7 @@ static void msp3400c_set_audmode(struct i2c_client *client) static void msp3400c_print_mode(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); if (state->main == state->second) v4l_dbg(1, msp_debug, client, @@ -388,7 +388,7 @@ static void msp3400c_print_mode(struct i2c_client *client) static int msp3400c_detect_stereo(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); int val; int rxsubchans = state->rxsubchans; int newnicam = state->nicam_on; @@ -466,7 +466,7 @@ static int msp3400c_detect_stereo(struct i2c_client *client) /* stereo/multilang monitoring */ static void watch_stereo(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); if (msp_detect_stereo(client)) msp_set_audmode(client); @@ -478,7 +478,7 @@ static void watch_stereo(struct i2c_client *client) int msp3400c_thread(void *data) { struct i2c_client *client = data; - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); struct msp3400c_carrier_detect *cd; int count, max1, max2, val1, val2, val, i; @@ -662,7 +662,7 @@ no_second: int msp3410d_thread(void *data) { struct i2c_client *client = data; - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); int val, i, std, count; v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); @@ -828,7 +828,7 @@ restart: static int msp34xxg_modus(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); if (state->radio) { v4l_dbg(1, msp_debug, client, "selected radio modus\n"); @@ -855,7 +855,7 @@ static int msp34xxg_modus(struct i2c_client *client) static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); int source, matrix; switch (state->audmode) { @@ -898,7 +898,7 @@ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) static void msp34xxg_set_sources(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); u32 in = state->routing.input; msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf); @@ -914,7 +914,7 @@ static void msp34xxg_set_sources(struct i2c_client *client) /* (re-)initialize the msp34xxg */ static void msp34xxg_reset(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); int tuner = (state->routing.input >> 3) & 1; int modus; @@ -957,7 +957,7 @@ static void msp34xxg_reset(struct i2c_client *client) int msp34xxg_thread(void *data) { struct i2c_client *client = data; - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); int val, i; v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); @@ -1052,7 +1052,7 @@ unmute: static int msp34xxg_detect_stereo(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); int status = msp_read_dem(client, 0x0200); int is_bilingual = status & 0x100; int is_stereo = status & 0x40; @@ -1081,7 +1081,7 @@ static int msp34xxg_detect_stereo(struct i2c_client *client) static void msp34xxg_set_audmode(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); if (state->std == 0x20) { if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && @@ -1098,7 +1098,7 @@ static void msp34xxg_set_audmode(struct i2c_client *client) void msp_set_audmode(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); switch (state->opmode) { case OPMODE_MANUAL: @@ -1113,7 +1113,7 @@ void msp_set_audmode(struct i2c_client *client) int msp_detect_stereo(struct i2c_client *client) { - struct msp_state *state = i2c_get_clientdata(client); + struct msp_state *state = to_state(i2c_get_clientdata(client)); switch (state->opmode) { case OPMODE_MANUAL: -- cgit v1.2.3 From 9db11dc4fccfa3ed7eea0e3ab3623990aea228f8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 16:55:19 +0100 Subject: saa7115: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7115.c | 763 +++++++++++++++++++----------------- 1 file changed, 399 insertions(+), 364 deletions(-) diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 02386e403..e9edd4d37 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include #include @@ -71,6 +71,7 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; struct saa711x_state { + struct v4l2_subdev sd; v4l2_std_id std; int input; int output; @@ -90,10 +91,17 @@ struct saa711x_state { u8 apll; }; +static inline struct saa711x_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa711x_state, sd); +} + /* ----------------------------------------------------------------------- */ -static inline int saa711x_write(struct i2c_client *client, u8 reg, u8 value) +static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_write_byte_data(client, reg, value); } @@ -129,9 +137,9 @@ static int saa711x_has_reg(const int id, const u8 reg) return 1; } -static int saa711x_writeregs(struct i2c_client *client, const unsigned char *regs) +static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs) { - struct saa711x_state *state = i2c_get_clientdata(client); + struct saa711x_state *state = to_state(sd); unsigned char reg, data; while (*regs != 0x00) { @@ -140,18 +148,20 @@ static int saa711x_writeregs(struct i2c_client *client, const unsigned char *reg /* According with datasheets, reserved regs should be filled with 0 - seems better not to touch on they */ - if (saa711x_has_reg(state->ident,reg)) { - if (saa711x_write(client, reg, data) < 0) + if (saa711x_has_reg(state->ident, reg)) { + if (saa711x_write(sd, reg, data) < 0) return -1; } else { - v4l_dbg(1, debug, client, "tried to access reserved reg 0x%02x\n", reg); + v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg); } } return 0; } -static inline int saa711x_read(struct i2c_client *client, u8 reg) +static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } @@ -602,7 +612,7 @@ static int saa711x_odd_parity(u8 c) return c & 1; } -static int saa711x_decode_vps(u8 * dst, u8 * p) +static int saa711x_decode_vps(u8 *dst, u8 *p) { static const u8 biphase_tbl[] = { 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, @@ -649,7 +659,7 @@ static int saa711x_decode_vps(u8 * dst, u8 * p) return err & 0xf0; } -static int saa711x_decode_wss(u8 * p) +static int saa711x_decode_wss(u8 *p) { static const int wss_bits[8] = { 0, 0, 0, 1, 0, 1, 1, 1 @@ -676,9 +686,9 @@ static int saa711x_decode_wss(u8 * p) return wss; } -static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq) +static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq) { - struct saa711x_state *state = i2c_get_clientdata(client); + struct saa711x_state *state = to_state(sd); u32 acpf; u32 acni; u32 hz; @@ -686,10 +696,10 @@ static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq) u8 acc = 0; /* reg 0x3a, audio clock control */ /* Checks for chips that don't have audio clock (saa7111, saa7113) */ - if (!saa711x_has_reg(state->ident,R_30_AUD_MAST_CLK_CYCLES_PER_FIELD)) + if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD)) return 0; - v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq); + v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq); /* sanity check */ if (freq < 32000 || freq > 48000) @@ -716,66 +726,66 @@ static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq) if (state->apll) acc |= 0x08; - saa711x_write(client, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03); - saa711x_write(client, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10); - saa711x_write(client, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc); + saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03); + saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10); + saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc); - saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff); - saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1, + saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff); + saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1, (acpf >> 8) & 0xff); - saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2, + saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2, (acpf >> 16) & 0x03); - saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff); - saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff); - saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f); + saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff); + saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff); + saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f); state->audclk_freq = freq; return 0; } -static int saa711x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct saa711x_state *state = i2c_get_clientdata(client); + struct saa711x_state *state = to_state(sd); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: if (ctrl->value < 0 || ctrl->value > 255) { - v4l_err(client, "invalid brightness setting %d\n", ctrl->value); + v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value); return -ERANGE; } state->bright = ctrl->value; - saa711x_write(client, R_0A_LUMA_BRIGHT_CNTL, state->bright); + saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, state->bright); break; case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 127) { - v4l_err(client, "invalid contrast setting %d\n", ctrl->value); + v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value); return -ERANGE; } state->contrast = ctrl->value; - saa711x_write(client, R_0B_LUMA_CONTRAST_CNTL, state->contrast); + saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, state->contrast); break; case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 127) { - v4l_err(client, "invalid saturation setting %d\n", ctrl->value); + v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value); return -ERANGE; } state->sat = ctrl->value; - saa711x_write(client, R_0C_CHROMA_SAT_CNTL, state->sat); + saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, state->sat); break; case V4L2_CID_HUE: if (ctrl->value < -127 || ctrl->value > 127) { - v4l_err(client, "invalid hue setting %d\n", ctrl->value); + v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } state->hue = ctrl->value; - saa711x_write(client, R_0D_CHROMA_HUE_CNTL, state->hue); + saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue); break; default: @@ -785,9 +795,9 @@ static int saa711x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c return 0; } -static int saa711x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct saa711x_state *state = i2c_get_clientdata(client); + struct saa711x_state *state = to_state(sd); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -809,16 +819,16 @@ static int saa711x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *c return 0; } -static int saa711x_set_size(struct i2c_client *client, int width, int height) +static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height) { - struct saa711x_state *state = i2c_get_clientdata(client); + struct saa711x_state *state = to_state(sd); int HPSC, HFSC; int VSCY; int res; int is_50hz = state->std & V4L2_STD_625_50; int Vsrc = is_50hz ? 576 : 480; - v4l_dbg(1, debug, client, "decoder set size to %ix%i\n",width,height); + v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height); /* FIXME need better bounds checking here */ if ((width < 1) || (width > 1440)) @@ -826,7 +836,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) if ((height < 1) || (height > Vsrc)) return -EINVAL; - if (!saa711x_has_reg(state->ident,R_D0_B_HORIZ_PRESCALING)) { + if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) { /* Decoder only supports 720 columns and 480 or 576 lines */ if (width != 720) return -EINVAL; @@ -844,22 +854,22 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) /* Set output width/height */ /* width */ - saa711x_write(client, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, + saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, (u8) (width & 0xff)); - saa711x_write(client, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, + saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, (u8) ((width >> 8) & 0xff)); /* Vertical Scaling uses height/2 */ - res=height/2; + res = height / 2; /* On 60Hz, it is using a higher Vertical Output Size */ if (!is_50hz) res += (VRES_60HZ - 480) >> 1; /* height */ - saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, + saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, (u8) (res & 0xff)); - saa711x_write(client, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB, + saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB, (u8) ((res >> 8) & 0xff)); /* Scaling settings */ @@ -870,54 +880,54 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) HFSC = (int)((1024 * 720) / (HPSC * width)); /* FIXME hardcodes to "Task B" * write H prescaler integer */ - saa711x_write(client, R_D0_B_HORIZ_PRESCALING, + saa711x_write(sd, R_D0_B_HORIZ_PRESCALING, (u8) (HPSC & 0x3f)); - v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); + v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); /* write H fine-scaling (luminance) */ - saa711x_write(client, R_D8_B_HORIZ_LUMA_SCALING_INC, + saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC, (u8) (HFSC & 0xff)); - saa711x_write(client, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, + saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, (u8) ((HFSC >> 8) & 0xff)); /* write H fine-scaling (chrominance) * must be lum/2, so i'll just bitshift :) */ - saa711x_write(client, R_DC_B_HORIZ_CHROMA_SCALING, + saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING, (u8) ((HFSC >> 1) & 0xff)); - saa711x_write(client, R_DD_B_HORIZ_CHROMA_SCALING_MSB, + saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB, (u8) ((HFSC >> 9) & 0xff)); VSCY = (int)((1024 * Vsrc) / height); - v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); + v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); /* Correct Contrast and Luminance */ - saa711x_write(client, R_D5_B_LUMA_CONTRAST_CNTL, + saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL, (u8) (64 * 1024 / VSCY)); - saa711x_write(client, R_D6_B_CHROMA_SATURATION_CNTL, + saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL, (u8) (64 * 1024 / VSCY)); /* write V fine-scaling (luminance) */ - saa711x_write(client, R_E0_B_VERT_LUMA_SCALING_INC, + saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC, (u8) (VSCY & 0xff)); - saa711x_write(client, R_E1_B_VERT_LUMA_SCALING_INC_MSB, + saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB, (u8) ((VSCY >> 8) & 0xff)); /* write V fine-scaling (chrominance) */ - saa711x_write(client, R_E2_B_VERT_CHROMA_SCALING_INC, + saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC, (u8) (VSCY & 0xff)); - saa711x_write(client, R_E3_B_VERT_CHROMA_SCALING_INC_MSB, + saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB, (u8) ((VSCY >> 8) & 0xff)); - saa711x_writeregs(client, saa7115_cfg_reset_scaler); + saa711x_writeregs(sd, saa7115_cfg_reset_scaler); /* Activates task "B" */ - saa711x_write(client, R_80_GLOBAL_CNTL_1, - saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20); + saa711x_write(sd, R_80_GLOBAL_CNTL_1, + saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20); return 0; } -static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) +static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) { - struct saa711x_state *state = i2c_get_clientdata(client); + struct saa711x_state *state = to_state(sd); /* Prevent unnecessary standard changes. During a standard change the I-Port is temporarily disabled. Any devices @@ -933,13 +943,13 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. if (std & V4L2_STD_525_60) { - v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); - saa711x_writeregs(client, saa7115_cfg_60hz_video); - saa711x_set_size(client, 720, 480); + v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); + saa711x_writeregs(sd, saa7115_cfg_60hz_video); + saa711x_set_size(sd, 720, 480); } else { - v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); - saa711x_writeregs(client, saa7115_cfg_50hz_video); - saa711x_set_size(client, 720, 576); + v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); + saa711x_writeregs(sd, saa7115_cfg_50hz_video); + saa711x_set_size(sd, 720, 576); } /* Register 0E - Bits D6-D4 on NO-AUTO mode @@ -953,7 +963,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) */ if (state->ident == V4L2_IDENT_SAA7111 || state->ident == V4L2_IDENT_SAA7113) { - u8 reg = saa711x_read(client, R_0E_CHROMA_CNTL_1) & 0x8f; + u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; if (std == V4L2_STD_PAL_M) { reg |= 0x30; @@ -966,87 +976,31 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) } else if (std & V4L2_STD_SECAM) { reg |= 0x50; } - saa711x_write(client, R_0E_CHROMA_CNTL_1, reg); + saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg); } else { /* restart task B if needed */ - int taskb = saa711x_read(client, R_80_GLOBAL_CNTL_1) & 0x10; + int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10; if (taskb && state->ident == V4L2_IDENT_SAA7114) { - saa711x_writeregs(client, saa7115_cfg_vbi_on); + saa711x_writeregs(sd, saa7115_cfg_vbi_on); } /* switch audio mode too! */ - saa711x_set_audio_clock_freq(client, state->audclk_freq); - } -} - -static v4l2_std_id saa711x_get_v4lstd(struct i2c_client *client) -{ - struct saa711x_state *state = i2c_get_clientdata(client); - - return state->std; -} - -static void saa711x_log_status(struct i2c_client *client) -{ - struct saa711x_state *state = i2c_get_clientdata(client); - int reg1e, reg1f; - int signalOk; - int vcr; - - v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq); - if (state->ident != V4L2_IDENT_SAA7115) { - /* status for the saa7114 */ - reg1f = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC); - signalOk = (reg1f & 0xc1) == 0x81; - v4l_info(client, "Video signal: %s\n", signalOk ? "ok" : "bad"); - v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); - return; - } - - /* status for the saa7115 */ - reg1e = saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC); - reg1f = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC); - - signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; - vcr = !(reg1f & 0x10); - - if (state->input >= 6) { - v4l_info(client, "Input: S-Video %d\n", state->input - 6); - } else { - v4l_info(client, "Input: Composite %d\n", state->input); + saa711x_s_clock_freq(sd, state->audclk_freq); } - v4l_info(client, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); - v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); - - switch (reg1e & 0x03) { - case 1: - v4l_info(client, "Detected format: NTSC\n"); - break; - case 2: - v4l_info(client, "Detected format: PAL\n"); - break; - case 3: - v4l_info(client, "Detected format: SECAM\n"); - break; - default: - v4l_info(client, "Detected format: BW/No color\n"); - break; - } - v4l_info(client, "Width, Height: %d, %d\n", state->width, state->height); } /* setup the sliced VBI lcr registers according to the sliced VBI format */ -static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt) +static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt) { - struct saa711x_state *state = i2c_get_clientdata(client); + struct saa711x_state *state = to_state(sd); int is_50hz = (state->std & V4L2_STD_625_50); u8 lcr[24]; int i, x; #if 1 /* keep */ /* saa7113/7114/7118 VBI support are experimental */ - if (!saa711x_has_reg(state->ident,R_41_LCR_BASE)) + if (!saa711x_has_reg(state->ident, R_41_LCR_BASE)) return; #else @@ -1110,16 +1064,16 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo /* write the lcr registers */ for (i = 2; i <= 23; i++) { - saa711x_write(client, i - 2 + R_41_LCR_BASE, lcr[i]); + saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]); } /* enable/disable raw VBI capturing */ - saa711x_writeregs(client, fmt == NULL ? + saa711x_writeregs(sd, fmt == NULL ? saa7115_cfg_vbi_on : saa7115_cfg_vbi_off); } -static int saa711x_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) +static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { static u16 lcr2vbi[] = { 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ @@ -1135,10 +1089,10 @@ static int saa711x_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt return -EINVAL; memset(sliced, 0, sizeof(*sliced)); /* done if using raw VBI */ - if (saa711x_read(client, R_80_GLOBAL_CNTL_1) & 0x10) + if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10) return 0; for (i = 2; i <= 23; i++) { - u8 v = saa711x_read(client, i - 2 + R_41_LCR_BASE); + u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE); sliced->service_lines[0][i] = lcr2vbi[v >> 4]; sliced->service_lines[1][i] = lcr2vbi[v & 0xf]; @@ -1148,20 +1102,20 @@ static int saa711x_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt return 0; } -static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) +static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { - saa711x_set_lcr(client, &fmt->fmt.sliced); + saa711x_set_lcr(sd, &fmt->fmt.sliced); return 0; } if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - saa711x_set_lcr(client, NULL); + saa711x_set_lcr(sd, NULL); return 0; } if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - return saa711x_set_size(client,fmt->fmt.pix.width,fmt->fmt.pix.height); + return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height); } /* Decode the sliced VBI data stream as created by the saa7115. @@ -1170,13 +1124,12 @@ static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt The current implementation uses SAV/EAV codes and not the ancillary data headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV code. */ -static void saa711x_decode_vbi_line(struct i2c_client *client, - struct v4l2_decode_vbi_line *vbi) +static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi) { + struct saa711x_state *state = to_state(sd); static const char vbi_no_data_pattern[] = { 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0 }; - struct saa711x_state *state = i2c_get_clientdata(client); u8 *p = vbi->p; u32 wss; int id1, id2; /* the ID1 and ID2 bytes from the internal header */ @@ -1203,7 +1156,7 @@ static void saa711x_decode_vbi_line(struct i2c_client *client, /* If the VBI slicer does not detect any signal it will fill up the payload buffer with 0xa0 bytes. */ if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern))) - return; + return 0; /* decode payloads */ switch (id2) { @@ -1212,275 +1165,352 @@ static void saa711x_decode_vbi_line(struct i2c_client *client, break; case 4: if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1])) - return; + return 0; vbi->type = V4L2_SLICED_CAPTION_525; break; case 5: wss = saa711x_decode_wss(p); if (wss == -1) - return; + return 0; p[0] = wss & 0xff; p[1] = wss >> 8; vbi->type = V4L2_SLICED_WSS_625; break; case 7: if (saa711x_decode_vps(p, p) != 0) - return; + return 0; vbi->type = V4L2_SLICED_VPS; break; default: - return; + break; } + return 0; } /* ============ SAA7115 AUDIO settings (end) ============= */ -static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) +static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) { - struct saa711x_state *state = i2c_get_clientdata(client); + struct saa711x_state *state = to_state(sd); + int status; - /* ioctls to allow direct access to the saa7115 registers for testing */ - switch (cmd) { - case VIDIOC_S_FMT: - return saa711x_set_v4lfmt(client, (struct v4l2_format *)arg); + if (state->radio) + return 0; + status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); - case VIDIOC_G_FMT: - return saa711x_get_v4lfmt(client, (struct v4l2_format *)arg); + v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status); + vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; + return 0; +} - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return saa711x_set_audio_clock_freq(client, *(u32 *)arg); +static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill_std(qc); + default: + return -EINVAL; + } +} - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *vt = arg; - int status; +static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct saa711x_state *state = to_state(sd); - if (state->radio) - break; - status = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC); + state->radio = 0; + saa711x_set_v4lstd(sd, std); + return 0; +} - v4l_dbg(1, debug, client, "status: 0x%02x\n", status); - vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; - break; - } +static int saa711x_s_radio(struct v4l2_subdev *sd) +{ + struct saa711x_state *state = to_state(sd); - case VIDIOC_LOG_STATUS: - saa711x_log_status(client); - break; + state->radio = 1; + return 0; +} - case VIDIOC_G_CTRL: - return saa711x_get_v4lctrl(client, (struct v4l2_control *)arg); +static int saa711x_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct saa711x_state *state = to_state(sd); + u32 input = route->input; + u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; + + v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", route->input, route->output); + /* saa7111/3 does not have these inputs */ + if ((state->ident == V4L2_IDENT_SAA7113 || + state->ident == V4L2_IDENT_SAA7111) && + (route->input == SAA7115_COMPOSITE4 || + route->input == SAA7115_COMPOSITE5)) { + return -EINVAL; + } + if (route->input > SAA7115_SVIDEO3) + return -EINVAL; + if (route->output > SAA7115_IPORT_ON) + return -EINVAL; + if (state->input == route->input && state->output == route->output) + return 0; + v4l2_dbg(1, debug, sd, "now setting %s input %s output\n", + (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", + (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); + state->input = route->input; + + /* saa7111 has slightly different input numbering */ + if (state->ident == V4L2_IDENT_SAA7111) { + if (input >= SAA7115_COMPOSITE4) + input -= 2; + /* saa7111 specific */ + saa711x_write(sd, R_10_CHROMA_CNTL_2, + (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) | + ((route->output & 0xc0) ^ 0x40)); + saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, + (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) | + ((route->output & 2) ? 0x0a : 0)); + } - case VIDIOC_S_CTRL: - return saa711x_set_v4lctrl(client, (struct v4l2_control *)arg); + /* select mode */ + saa711x_write(sd, R_02_INPUT_CNTL_1, + (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) | + input); - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; + /* bypass chrominance trap for S-Video modes */ + saa711x_write(sd, R_09_LUMA_CNTL, + (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) | + (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); - default: - return -EINVAL; - } + state->output = route->output; + if (state->ident == V4L2_IDENT_SAA7114 || + state->ident == V4L2_IDENT_SAA7115) { + saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, + (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | + (state->output & 0x01)); } + return 0; +} - case VIDIOC_G_STD: - *(v4l2_std_id *)arg = saa711x_get_v4lstd(client); - break; +static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val) +{ + struct saa711x_state *state = to_state(sd); - case VIDIOC_S_STD: - state->radio = 0; - saa711x_set_v4lstd(client, *(v4l2_std_id *)arg); - break; + if (state->ident != V4L2_IDENT_SAA7111) + return -EINVAL; + saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | + (val ? 0x80 : 0)); + return 0; +} - case AUDC_SET_RADIO: - state->radio = 1; - break; +static int saa711x_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct saa711x_state *state = to_state(sd); - case VIDIOC_INT_G_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; + v4l2_dbg(1, debug, sd, "%s output\n", + enable ? "enable" : "disable"); - route->input = state->input; - route->output = state->output; - break; + if (state->enable != enable) { + state->enable = enable; + saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, + state->enable); } + return 0; +} - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - u32 input = route->input; - u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; - - v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); - /* saa7111/3 does not have these inputs */ - if ((state->ident == V4L2_IDENT_SAA7113 || - state->ident == V4L2_IDENT_SAA7111) && - (route->input == SAA7115_COMPOSITE4 || - route->input == SAA7115_COMPOSITE5)) { - return -EINVAL; - } - if (route->input > SAA7115_SVIDEO3) - return -EINVAL; - if (route->output > SAA7115_IPORT_ON) - return -EINVAL; - if (state->input == route->input && state->output == route->output) - break; - v4l_dbg(1, debug, client, "now setting %s input %s output\n", - (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); - state->input = route->input; - - /* saa7111 has slightly different input numbering */ - if (state->ident == V4L2_IDENT_SAA7111) { - if (input >= SAA7115_COMPOSITE4) - input -= 2; - /* saa7111 specific */ - saa711x_write(client, R_10_CHROMA_CNTL_2, - (saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) | - ((route->output & 0xc0) ^ 0x40)); - saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL, - (saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) | - ((route->output & 2) ? 0x0a : 0)); - } +static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, struct v4l2_crystal_freq *freq) +{ + struct saa711x_state *state = to_state(sd); - /* select mode */ - saa711x_write(client, R_02_INPUT_CNTL_1, - (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) | - input); + if (freq->freq != SAA7115_FREQ_32_11_MHZ && + freq->freq != SAA7115_FREQ_24_576_MHZ) + return -EINVAL; + state->crystal_freq = freq->freq; + state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4; + state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0; + state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0; + saa711x_s_clock_freq(sd, state->audclk_freq); + return 0; +} - /* bypass chrominance trap for S-Video modes */ - saa711x_write(client, R_09_LUMA_CNTL, - (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) | - (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); +static int saa711x_reset(struct v4l2_subdev *sd, u32 val) +{ + v4l2_dbg(1, debug, sd, "decoder RESET\n"); + saa711x_writeregs(sd, saa7115_cfg_reset_scaler); + return 0; +} - state->output = route->output; - if (state->ident == V4L2_IDENT_SAA7114 || - state->ident == V4L2_IDENT_SAA7115) { - saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, - (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | - (state->output & 0x01)); +static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data) +{ + /* Note: the internal field ID is inverted for NTSC, + so data->field 0 maps to the saa7115 even field, + whereas for PAL it maps to the saa7115 odd field. */ + switch (data->id) { + case V4L2_SLICED_WSS_625: + if (saa711x_read(sd, 0x6b) & 0xc0) + return -EIO; + data->data[0] = saa711x_read(sd, 0x6c); + data->data[1] = saa711x_read(sd, 0x6d); + return 0; + case V4L2_SLICED_CAPTION_525: + if (data->field == 0) { + /* CC */ + if (saa711x_read(sd, 0x66) & 0x30) + return -EIO; + data->data[0] = saa711x_read(sd, 0x69); + data->data[1] = saa711x_read(sd, 0x6a); + return 0; } - break; + /* XDS */ + if (saa711x_read(sd, 0x66) & 0xc0) + return -EIO; + data->data[0] = saa711x_read(sd, 0x67); + data->data[1] = saa711x_read(sd, 0x68); + return 0; + default: + return -EINVAL; } +} - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - v4l_dbg(1, debug, client, "%s output\n", - (cmd == VIDIOC_STREAMON) ? "enable" : "disable"); - - if (state->enable != (cmd == VIDIOC_STREAMON)) { - state->enable = (cmd == VIDIOC_STREAMON); - saa711x_write(client, - R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, - state->enable); - } - break; +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_INT_S_CRYSTAL_FREQ: - { - struct v4l2_crystal_freq *freq = arg; + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = saa711x_read(sd, reg->reg & 0xff); + return 0; +} - if (freq->freq != SAA7115_FREQ_32_11_MHZ && - freq->freq != SAA7115_FREQ_24_576_MHZ) - return -EINVAL; - state->crystal_freq = freq->freq; - state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4; - state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0; - state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0; - saa711x_set_audio_clock_freq(client, state->audclk_freq); - break; - } +static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_INT_DECODE_VBI_LINE: - saa711x_decode_vbi_line(client, arg); - break; + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} +#endif - case VIDIOC_INT_RESET: - v4l_dbg(1, debug, client, "decoder RESET\n"); - saa711x_writeregs(client, saa7115_cfg_reset_scaler); - break; +static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct saa711x_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_INT_S_GPIO: - if (state->ident != V4L2_IDENT_SAA7111) - return -EINVAL; - saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) | - (*(u32 *)arg ? 0x80 : 0)); - break; + return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0); +} - case VIDIOC_INT_G_VBI_DATA: - { - struct v4l2_sliced_vbi_data *data = arg; +static int saa711x_log_status(struct v4l2_subdev *sd) +{ + struct saa711x_state *state = to_state(sd); + int reg1e, reg1f; + int signalOk; + int vcr; - /* Note: the internal field ID is inverted for NTSC, - so data->field 0 maps to the saa7115 even field, - whereas for PAL it maps to the saa7115 odd field. */ - switch (data->id) { - case V4L2_SLICED_WSS_625: - if (saa711x_read(client, 0x6b) & 0xc0) - return -EIO; - data->data[0] = saa711x_read(client, 0x6c); - data->data[1] = saa711x_read(client, 0x6d); - return 0; - case V4L2_SLICED_CAPTION_525: - if (data->field == 0) { - /* CC */ - if (saa711x_read(client, 0x66) & 0x30) - return -EIO; - data->data[0] = saa711x_read(client, 0x69); - data->data[1] = saa711x_read(client, 0x6a); - return 0; - } - /* XDS */ - if (saa711x_read(client, 0x66) & 0xc0) - return -EIO; - data->data[0] = saa711x_read(client, 0x67); - data->data[1] = saa711x_read(client, 0x68); - return 0; - default: - return -EINVAL; - } - break; + v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq); + if (state->ident != V4L2_IDENT_SAA7115) { + /* status for the saa7114 */ + reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); + signalOk = (reg1f & 0xc1) == 0x81; + v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad"); + v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); + return 0; } -#ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; + /* status for the saa7115 */ + reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); + reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); - if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (cmd == VIDIOC_DBG_G_REGISTER) - reg->val = saa711x_read(client, reg->reg & 0xff); - else - saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); - break; - } -#endif + signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; + vcr = !(reg1f & 0x10); - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0); + if (state->input >= 6) + v4l2_info(sd, "Input: S-Video %d\n", state->input - 6); + else + v4l2_info(sd, "Input: Composite %d\n", state->input); + v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); + v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); + switch (reg1e & 0x03) { + case 1: + v4l2_info(sd, "Detected format: NTSC\n"); + break; + case 2: + v4l2_info(sd, "Detected format: PAL\n"); + break; + case 3: + v4l2_info(sd, "Detected format: SECAM\n"); + break; default: - return -EINVAL; + v4l2_info(sd, "Detected format: BW/No color\n"); + break; } - + v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height); return 0; } +static int saa711x_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops saa711x_core_ops = { + .log_status = saa711x_log_status, + .g_chip_ident = saa711x_g_chip_ident, + .g_ctrl = saa711x_g_ctrl, + .s_ctrl = saa711x_s_ctrl, + .queryctrl = saa711x_queryctrl, + .reset = saa711x_reset, + .s_gpio = saa711x_s_gpio, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = saa711x_g_register, + .s_register = saa711x_s_register, +#endif +}; + +static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = { + .s_std = saa711x_s_std, + .s_radio = saa711x_s_radio, + .g_tuner = saa711x_g_tuner, +}; + +static const struct v4l2_subdev_audio_ops saa711x_audio_ops = { + .s_clock_freq = saa711x_s_clock_freq, +}; + +static const struct v4l2_subdev_video_ops saa711x_video_ops = { + .s_routing = saa711x_s_routing, + .s_crystal_freq = saa711x_s_crystal_freq, + .g_fmt = saa711x_g_fmt, + .s_fmt = saa711x_s_fmt, + .g_vbi_data = saa711x_g_vbi_data, + .decode_vbi_line = saa711x_decode_vbi_line, + .s_stream = saa711x_s_stream, +}; + +static const struct v4l2_subdev_ops saa711x_ops = { + .core = &saa711x_core_ops, + .tuner = &saa711x_tuner_ops, + .audio = &saa711x_audio_ops, + .video = &saa711x_video_ops, +}; + /* ----------------------------------------------------------------------- */ -static int saa7115_probe(struct i2c_client *client, +static int saa711x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct saa711x_state *state; + struct v4l2_subdev *sd; int i; char name[17]; char chip_id; @@ -1497,8 +1527,8 @@ static int saa7115_probe(struct i2c_client *client, #endif for (i = 0; i < 0x0f; i++) { - saa711x_write(client, 0, i); - name[i] = (saa711x_read(client, 0) & 0x0f) + '0'; + i2c_smbus_write_byte_data(client, 0, i); + name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0'; if (name[i] > '9') name[i] += 'a' - '9' - 1; } @@ -1527,7 +1557,8 @@ static int saa7115_probe(struct i2c_client *client, state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; - i2c_set_clientdata(client, state); + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &saa711x_ops); state->input = -1; state->output = SAA7115_IPORT_ON; state->enable = 1; @@ -1554,41 +1585,45 @@ static int saa7115_probe(struct i2c_client *client, break; default: state->ident = V4L2_IDENT_SAA7111; - v4l_info(client, "WARNING: Chip is not known - Falling back to saa7111\n"); + v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n"); } state->audclk_freq = 48000; - v4l_dbg(1, debug, client, "writing init values\n"); + v4l2_dbg(1, debug, sd, "writing init values\n"); /* init to 60hz/48khz */ state->crystal_freq = SAA7115_FREQ_24_576_MHZ; switch (state->ident) { case V4L2_IDENT_SAA7111: - saa711x_writeregs(client, saa7111_init); + saa711x_writeregs(sd, saa7111_init); break; case V4L2_IDENT_SAA7113: - saa711x_writeregs(client, saa7113_init); + saa711x_writeregs(sd, saa7113_init); break; default: state->crystal_freq = SAA7115_FREQ_32_11_MHZ; - saa711x_writeregs(client, saa7115_init_auto_input); + saa711x_writeregs(sd, saa7115_init_auto_input); } if (state->ident != V4L2_IDENT_SAA7111) - saa711x_writeregs(client, saa7115_init_misc); - saa711x_set_v4lstd(client, V4L2_STD_NTSC); + saa711x_writeregs(sd, saa7115_init_misc); + saa711x_set_v4lstd(sd, V4L2_STD_NTSC); - v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", - saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC), saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC)); + v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n", + saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC), + saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC)); return 0; } /* ----------------------------------------------------------------------- */ -static int saa7115_remove(struct i2c_client *client) +static int saa711x_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } @@ -1608,9 +1643,9 @@ MODULE_DEVICE_TABLE(i2c, saa7115_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7115", .driverid = I2C_DRIVERID_SAA711X, - .command = saa7115_command, - .probe = saa7115_probe, - .remove = saa7115_remove, + .command = saa711x_command, + .probe = saa711x_probe, + .remove = saa711x_remove, .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = saa7115_id, -- cgit v1.2.3 From e9df8e267dfb3180b0e396e7cf94effa8f55d21c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 16:56:38 +0100 Subject: saa7127: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7127.c | 421 ++++++++++++++++++++---------------- 1 file changed, 232 insertions(+), 189 deletions(-) diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c index fd7d15305..5414b027f 100644 --- a/linux/drivers/media/video/saa7127.c +++ b/linux/drivers/media/video/saa7127.c @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include #include @@ -237,6 +237,7 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = { */ struct saa7127_state { + struct v4l2_subdev sd; v4l2_std_id std; u32 ident; enum saa7127_input_type input_type; @@ -256,6 +257,11 @@ struct saa7127_state { u8 reg_61; }; +static inline struct saa7127_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa7127_state, sd); +} + static const char * const output_strs[] = { "S-Video + Composite", @@ -287,32 +293,35 @@ static const char * const wss_strs[] = { /* ----------------------------------------------------------------------- */ -static int saa7127_read(struct i2c_client *client, u8 reg) +static int saa7127_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } /* ----------------------------------------------------------------------- */ -static int saa7127_write(struct i2c_client *client, u8 reg, u8 val) +static int saa7127_write(struct v4l2_subdev *sd, u8 reg, u8 val) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int i; for (i = 0; i < 3; i++) { if (i2c_smbus_write_byte_data(client, reg, val) == 0) return 0; } - v4l_err(client, "I2C Write Problem\n"); + v4l2_err(sd, "I2C Write Problem\n"); return -1; } /* ----------------------------------------------------------------------- */ -static int saa7127_write_inittab(struct i2c_client *client, +static int saa7127_write_inittab(struct v4l2_subdev *sd, const struct i2c_reg_value *regs) { while (regs->reg != 0) { - saa7127_write(client, regs->reg, regs->value); + saa7127_write(sd, regs->reg, regs->value); regs++; } return 0; @@ -320,16 +329,16 @@ static int saa7127_write_inittab(struct i2c_client *client, /* ----------------------------------------------------------------------- */ -static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) +static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) { - struct saa7127_state *state = i2c_get_clientdata(client); + struct saa7127_state *state = to_state(sd); int enable = (data->line != 0); if (enable && (data->field != 0 || data->line != 16)) return -EINVAL; if (state->vps_enable != enable) { - v4l_dbg(1, debug, client, "Turn VPS Signal %s\n", enable ? "on" : "off"); - saa7127_write(client, 0x54, enable << 7); + v4l2_dbg(1, debug, sd, "Turn VPS Signal %s\n", enable ? "on" : "off"); + saa7127_write(sd, 0x54, enable << 7); state->vps_enable = enable; } if (!enable) @@ -340,91 +349,91 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat state->vps_data[2] = data->data[9]; state->vps_data[3] = data->data[10]; state->vps_data[4] = data->data[11]; - v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n", + v4l2_dbg(1, debug, sd, "Set VPS data %02x %02x %02x %02x %02x\n", state->vps_data[0], state->vps_data[1], state->vps_data[2], state->vps_data[3], state->vps_data[4]); - saa7127_write(client, 0x55, state->vps_data[0]); - saa7127_write(client, 0x56, state->vps_data[1]); - saa7127_write(client, 0x57, state->vps_data[2]); - saa7127_write(client, 0x58, state->vps_data[3]); - saa7127_write(client, 0x59, state->vps_data[4]); + saa7127_write(sd, 0x55, state->vps_data[0]); + saa7127_write(sd, 0x56, state->vps_data[1]); + saa7127_write(sd, 0x57, state->vps_data[2]); + saa7127_write(sd, 0x58, state->vps_data[3]); + saa7127_write(sd, 0x59, state->vps_data[4]); return 0; } /* ----------------------------------------------------------------------- */ -static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) +static int saa7127_set_cc(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) { - struct saa7127_state *state = i2c_get_clientdata(client); + struct saa7127_state *state = to_state(sd); u16 cc = data->data[1] << 8 | data->data[0]; int enable = (data->line != 0); if (enable && (data->field != 0 || data->line != 21)) return -EINVAL; if (state->cc_enable != enable) { - v4l_dbg(1, debug, client, + v4l2_dbg(1, debug, sd, "Turn CC %s\n", enable ? "on" : "off"); - saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, + saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION, (state->xds_enable << 7) | (enable << 6) | 0x11); state->cc_enable = enable; } if (!enable) return 0; - v4l_dbg(2, debug, client, "CC data: %04x\n", cc); - saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff); - saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8); + v4l2_dbg(2, debug, sd, "CC data: %04x\n", cc); + saa7127_write(sd, SAA7127_REG_LINE_21_ODD_0, cc & 0xff); + saa7127_write(sd, SAA7127_REG_LINE_21_ODD_1, cc >> 8); state->cc_data = cc; return 0; } /* ----------------------------------------------------------------------- */ -static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) +static int saa7127_set_xds(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) { - struct saa7127_state *state = i2c_get_clientdata(client); + struct saa7127_state *state = to_state(sd); u16 xds = data->data[1] << 8 | data->data[0]; int enable = (data->line != 0); if (enable && (data->field != 1 || data->line != 21)) return -EINVAL; if (state->xds_enable != enable) { - v4l_dbg(1, debug, client, "Turn XDS %s\n", enable ? "on" : "off"); - saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, + v4l2_dbg(1, debug, sd, "Turn XDS %s\n", enable ? "on" : "off"); + saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION, (enable << 7) | (state->cc_enable << 6) | 0x11); state->xds_enable = enable; } if (!enable) return 0; - v4l_dbg(2, debug, client, "XDS data: %04x\n", xds); - saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff); - saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8); + v4l2_dbg(2, debug, sd, "XDS data: %04x\n", xds); + saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff); + saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_1, xds >> 8); state->xds_data = xds; return 0; } /* ----------------------------------------------------------------------- */ -static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) +static int saa7127_set_wss(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) { - struct saa7127_state *state = i2c_get_clientdata(client); + struct saa7127_state *state = to_state(sd); int enable = (data->line != 0); if (enable && (data->field != 0 || data->line != 23)) return -EINVAL; if (state->wss_enable != enable) { - v4l_dbg(1, debug, client, "Turn WSS %s\n", enable ? "on" : "off"); - saa7127_write(client, 0x27, enable << 7); + v4l2_dbg(1, debug, sd, "Turn WSS %s\n", enable ? "on" : "off"); + saa7127_write(sd, 0x27, enable << 7); state->wss_enable = enable; } if (!enable) return 0; - saa7127_write(client, 0x26, data->data[0]); - saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f)); - v4l_dbg(1, debug, client, + saa7127_write(sd, 0x26, data->data[0]); + saa7127_write(sd, 0x27, 0x80 | (data->data[1] & 0x3f)); + v4l2_dbg(1, debug, sd, "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]); state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0]; return 0; @@ -432,18 +441,18 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat /* ----------------------------------------------------------------------- */ -static int saa7127_set_video_enable(struct i2c_client *client, int enable) +static int saa7127_set_video_enable(struct v4l2_subdev *sd, int enable) { - struct saa7127_state *state = i2c_get_clientdata(client); + struct saa7127_state *state = to_state(sd); if (enable) { - v4l_dbg(1, debug, client, "Enable Video Output\n"); - saa7127_write(client, 0x2d, state->reg_2d); - saa7127_write(client, 0x61, state->reg_61); + v4l2_dbg(1, debug, sd, "Enable Video Output\n"); + saa7127_write(sd, 0x2d, state->reg_2d); + saa7127_write(sd, 0x61, state->reg_61); } else { - v4l_dbg(1, debug, client, "Disable Video Output\n"); - saa7127_write(client, 0x2d, (state->reg_2d & 0xf0)); - saa7127_write(client, 0x61, (state->reg_61 | 0xc0)); + v4l2_dbg(1, debug, sd, "Disable Video Output\n"); + saa7127_write(sd, 0x2d, (state->reg_2d & 0xf0)); + saa7127_write(sd, 0x61, (state->reg_61 | 0xc0)); } state->video_enable = enable; return 0; @@ -451,32 +460,32 @@ static int saa7127_set_video_enable(struct i2c_client *client, int enable) /* ----------------------------------------------------------------------- */ -static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std) +static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std) { - struct saa7127_state *state = i2c_get_clientdata(client); + struct saa7127_state *state = to_state(sd); const struct i2c_reg_value *inittab; if (std & V4L2_STD_525_60) { - v4l_dbg(1, debug, client, "Selecting 60 Hz video Standard\n"); + v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n"); inittab = saa7127_init_config_60hz; state->reg_61 = SAA7127_60HZ_DAC_CONTROL; } else { - v4l_dbg(1, debug, client, "Selecting 50 Hz video Standard\n"); + v4l2_dbg(1, debug, sd, "Selecting 50 Hz video Standard\n"); inittab = saa7127_init_config_50hz; state->reg_61 = SAA7127_50HZ_DAC_CONTROL; } /* Write Table */ - saa7127_write_inittab(client, inittab); + saa7127_write_inittab(sd, inittab); state->std = std; return 0; } /* ----------------------------------------------------------------------- */ -static int saa7127_set_output_type(struct i2c_client *client, int output) +static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) { - struct saa7127_state *state = i2c_get_clientdata(client); + struct saa7127_state *state = to_state(sd); switch (output) { case SAA7127_OUTPUT_TYPE_RGB: @@ -512,165 +521,195 @@ static int saa7127_set_output_type(struct i2c_client *client, int output) default: return -EINVAL; } - v4l_dbg(1, debug, client, + v4l2_dbg(1, debug, sd, "Selecting %s output type\n", output_strs[output]); /* Configure Encoder */ - saa7127_write(client, 0x2d, state->reg_2d); - saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); + saa7127_write(sd, 0x2d, state->reg_2d); + saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb); state->output_type = output; return 0; } /* ----------------------------------------------------------------------- */ -static int saa7127_set_input_type(struct i2c_client *client, int input) +static int saa7127_set_input_type(struct v4l2_subdev *sd, int input) { - struct saa7127_state *state = i2c_get_clientdata(client); + struct saa7127_state *state = to_state(sd); switch (input) { case SAA7127_INPUT_TYPE_NORMAL: /* avia */ - v4l_dbg(1, debug, client, "Selecting Normal Encoder Input\n"); + v4l2_dbg(1, debug, sd, "Selecting Normal Encoder Input\n"); state->reg_3a_cb = 0; break; case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */ - v4l_dbg(1, debug, client, "Selecting Color Bar generator\n"); + v4l2_dbg(1, debug, sd, "Selecting Color Bar generator\n"); state->reg_3a_cb = 0x80; break; default: return -EINVAL; } - saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); + saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb); state->input_type = input; return 0; } /* ----------------------------------------------------------------------- */ -static int saa7127_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static int saa7127_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - struct saa7127_state *state = i2c_get_clientdata(client); - struct v4l2_format *fmt = arg; - struct v4l2_routing *route = arg; - - switch (cmd) { - case VIDIOC_INT_S_STD_OUTPUT: - if (state->std == *(v4l2_std_id *)arg) - break; - return saa7127_set_std(client, *(v4l2_std_id *)arg); - - case VIDIOC_INT_G_STD_OUTPUT: - *(v4l2_std_id *)arg = state->std; - break; + struct saa7127_state *state = to_state(sd); - case VIDIOC_INT_G_VIDEO_ROUTING: - route->input = state->input_type; - route->output = state->output_type; - break; + if (state->std == std) + return 0; + return saa7127_set_std(sd, std); +} - case VIDIOC_INT_S_VIDEO_ROUTING: - { - int rc = 0; +static int saa7127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct saa7127_state *state = to_state(sd); + int rc = 0; + + if (state->input_type != route->input) + rc = saa7127_set_input_type(sd, route->input); + if (rc == 0 && state->output_type != route->output) + rc = saa7127_set_output_type(sd, route->output); + return rc; +} - if (state->input_type != route->input) - rc = saa7127_set_input_type(client, route->input); - if (rc == 0 && state->output_type != route->output) - rc = saa7127_set_output_type(client, route->output); - return rc; - } +static int saa7127_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct saa7127_state *state = to_state(sd); - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - if (state->video_enable == (cmd == VIDIOC_STREAMON)) - break; - return saa7127_set_video_enable(client, cmd == VIDIOC_STREAMON); - - case VIDIOC_G_FMT: - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - - memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced)); - if (state->vps_enable) - fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS; - if (state->wss_enable) - fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; - if (state->cc_enable) { - fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525; - fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525; - } - fmt->fmt.sliced.service_set = - (state->vps_enable ? V4L2_SLICED_VPS : 0) | - (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | - (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); - break; + if (state->video_enable == enable) + return 0; + return saa7127_set_video_enable(sd, enable); +} - case VIDIOC_LOG_STATUS: - v4l_info(client, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz"); - v4l_info(client, "Input: %s\n", state->input_type ? "color bars" : "normal"); - v4l_info(client, "Output: %s\n", state->video_enable ? - output_strs[state->output_type] : "disabled"); - v4l_info(client, "WSS: %s\n", state->wss_enable ? - wss_strs[state->wss_mode] : "disabled"); - v4l_info(client, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled"); - v4l_info(client, "CC: %s\n", state->cc_enable ? "enabled" : "disabled"); - break; +static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct saa7127_state *state = to_state(sd); -#ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (cmd == VIDIOC_DBG_G_REGISTER) - reg->val = saa7127_read(client, reg->reg & 0xff); - else - saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); - break; - } -#endif + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; - case VIDIOC_INT_S_VBI_DATA: - { - struct v4l2_sliced_vbi_data *data = arg; - - switch (data->id) { - case V4L2_SLICED_WSS_625: - return saa7127_set_wss(client, data); - case V4L2_SLICED_VPS: - return saa7127_set_vps(client, data); - case V4L2_SLICED_CAPTION_525: - if (data->field == 0) - return saa7127_set_cc(client, data); - return saa7127_set_xds(client, data); - default: - return -EINVAL; - } - break; + memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced)); + if (state->vps_enable) + fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS; + if (state->wss_enable) + fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; + if (state->cc_enable) { + fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525; + fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525; } + fmt->fmt.sliced.service_set = + (state->vps_enable ? V4L2_SLICED_VPS : 0) | + (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | + (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); + return 0; +} - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0); - +static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) +{ + switch (data->id) { + case V4L2_SLICED_WSS_625: + return saa7127_set_wss(sd, data); + case V4L2_SLICED_VPS: + return saa7127_set_vps(sd, data); + case V4L2_SLICED_CAPTION_525: + if (data->field == 0) + return saa7127_set_cc(sd, data); + return saa7127_set_xds(sd, data); default: return -EINVAL; } return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = saa7127_read(sd, reg->reg & 0xff); + return 0; +} + +static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} +#endif + +static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct saa7127_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0); +} + +static int saa7127_log_status(struct v4l2_subdev *sd) +{ + struct saa7127_state *state = to_state(sd); + + v4l2_info(sd, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz"); + v4l2_info(sd, "Input: %s\n", state->input_type ? "color bars" : "normal"); + v4l2_info(sd, "Output: %s\n", state->video_enable ? + output_strs[state->output_type] : "disabled"); + v4l2_info(sd, "WSS: %s\n", state->wss_enable ? + wss_strs[state->wss_mode] : "disabled"); + v4l2_info(sd, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled"); + v4l2_info(sd, "CC: %s\n", state->cc_enable ? "enabled" : "disabled"); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops saa7127_core_ops = { + .log_status = saa7127_log_status, + .g_chip_ident = saa7127_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = saa7127_g_register, + .s_register = saa7127_s_register, +#endif +}; + +static const struct v4l2_subdev_video_ops saa7127_video_ops = { + .s_vbi_data = saa7127_s_vbi_data, + .g_fmt = saa7127_g_fmt, + .s_std_output = saa7127_s_std_output, + .s_routing = saa7127_s_routing, + .s_stream = saa7127_s_stream, +}; + +static const struct v4l2_subdev_ops saa7127_ops = { + .core = &saa7127_core_ops, + .video = &saa7127_video_ops, +}; + /* ----------------------------------------------------------------------- */ static int saa7127_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct saa7127_state *state; + struct v4l2_subdev *sd; struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */ /* Check if the adapter supports the needed features */ @@ -684,40 +723,42 @@ static int saa7127_probe(struct i2c_client *client, v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", client->addr << 1); + state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &saa7127_ops); + /* First test register 0: Bits 5-7 are a version ID (should be 0), and bit 2 should also be 0. This is rather general, so the second test is more specific and looks at the 'ending point of burst in clock cycles' which is 0x1d after a reset and not expected to ever change. */ - if ((saa7127_read(client, 0) & 0xe4) != 0 || - (saa7127_read(client, 0x29) & 0x3f) != 0x1d) { - v4l_dbg(1, debug, client, "saa7127 not found\n"); + if ((saa7127_read(sd, 0) & 0xe4) != 0 || + (saa7127_read(sd, 0x29) & 0x3f) != 0x1d) { + v4l2_dbg(1, debug, sd, "saa7127 not found\n"); + kfree(state); return -ENODEV; } - state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL); - - if (state == NULL) - return -ENOMEM; - - i2c_set_clientdata(client, state); /* Configure Encoder */ - v4l_dbg(1, debug, client, "Configuring encoder\n"); - saa7127_write_inittab(client, saa7127_init_config_common); - saa7127_set_std(client, V4L2_STD_NTSC); - saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH); - saa7127_set_vps(client, &vbi); - saa7127_set_wss(client, &vbi); - saa7127_set_cc(client, &vbi); - saa7127_set_xds(client, &vbi); + v4l2_dbg(1, debug, sd, "Configuring encoder\n"); + saa7127_write_inittab(sd, saa7127_init_config_common); + saa7127_set_std(sd, V4L2_STD_NTSC); + saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH); + saa7127_set_vps(sd, &vbi); + saa7127_set_wss(sd, &vbi); + saa7127_set_cc(sd, &vbi); + saa7127_set_xds(sd, &vbi); if (test_image == 1) /* The Encoder has an internal Colorbar generator */ /* This can be used for debugging */ - saa7127_set_input_type(client, SAA7127_INPUT_TYPE_TEST_IMAGE); + saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE); else - saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL); - saa7127_set_video_enable(client, 1); + saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL); + saa7127_set_video_enable(sd, 1); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) if (id->driver_data) { /* Chip type is already known */ @@ -729,10 +770,10 @@ static int saa7127_probe(struct i2c_client *client, int read_result; /* Detect if it's an saa7129 */ - read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2); - saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa); - if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { - saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, + read_result = saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2); + saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, 0xaa); + if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { + saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, read_result); state->ident = V4L2_IDENT_SAA7129; strlcpy(client->name, "saa7129", I2C_NAME_SIZE); @@ -742,10 +783,10 @@ static int saa7127_probe(struct i2c_client *client, } } - v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, + v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, client->addr << 1, client->adapter->name); if (state->ident == V4L2_IDENT_SAA7129) - saa7127_write_inittab(client, saa7129_init_config_extra); + saa7127_write_inittab(sd, saa7129_init_config_extra); return 0; } @@ -753,9 +794,12 @@ static int saa7127_probe(struct i2c_client *client, static int saa7127_remove(struct i2c_client *client) { + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); /* Turn off TV output */ - saa7127_set_video_enable(client, 0); - kfree(i2c_get_clientdata(client)); + saa7127_set_video_enable(sd, 0); + kfree(to_state(sd)); return 0; } @@ -776,7 +820,6 @@ MODULE_DEVICE_TABLE(i2c, saa7127_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7127", .driverid = I2C_DRIVERID_SAA7127, - .command = saa7127_command, .probe = saa7127_probe, .remove = saa7127_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From a9b4aaf1a121a8ed7f9fd39e8ae69595e252f669 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 16:57:44 +0100 Subject: saa717x: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa717x.c | 610 ++++++++++++++++++------------------ 1 file changed, 313 insertions(+), 297 deletions(-) diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c index b0751c195..2d667e66a 100644 --- a/linux/drivers/media/video/saa717x.c +++ b/linux/drivers/media/video/saa717x.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include "compat.h" @@ -60,6 +60,7 @@ I2C_CLIENT_INSMOD; #endif struct saa717x_state { + struct v4l2_subdev sd; v4l2_std_id std; int input; int enable; @@ -81,6 +82,11 @@ struct saa717x_state { int audio_input; }; +static inline struct saa717x_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa717x_state, sd); +} + /* ----------------------------------------------------------------------- */ /* for audio mode */ @@ -94,8 +100,9 @@ struct saa717x_state { /* ----------------------------------------------------------------------- */ -static int saa717x_write(struct i2c_client *client, u32 reg, u32 value) +static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_adapter *adap = client->adapter; int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488; unsigned char mm1[6]; @@ -115,20 +122,21 @@ static int saa717x_write(struct i2c_client *client, u32 reg, u32 value) } msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */ msg.buf = mm1; - v4l_dbg(2, debug, client, "wrote: reg 0x%03x=%08x\n", reg, value); + v4l2_dbg(2, debug, sd, "wrote: reg 0x%03x=%08x\n", reg, value); return i2c_transfer(adap, &msg, 1) == 1; } -static void saa717x_write_regs(struct i2c_client *client, u32 *data) +static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data) { while (data[0] || data[1]) { - saa717x_write(client, data[0], data[1]); + saa717x_write(sd, data[0], data[1]); data += 2; } } -static u32 saa717x_read(struct i2c_client *client, u32 reg) +static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_adapter *adap = client->adapter; int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528; unsigned char mm1[2]; @@ -152,7 +160,7 @@ static u32 saa717x_read(struct i2c_client *client, u32 reg) else value = mm2[0] & 0xff; - v4l_dbg(2, debug, client, "read: reg 0x%03x=0x%08x\n", reg, value); + v4l2_dbg(2, debug, sd, "read: reg 0x%03x=0x%08x\n", reg, value); return value; } @@ -686,7 +694,7 @@ static u32 reg_set_audio_template[4][2] = /* Get detected audio flags (from saa7134 driver) */ -static void get_inf_dev_status(struct i2c_client *client, +static void get_inf_dev_status(struct v4l2_subdev *sd, int *dual_flag, int *stereo_flag) { u32 reg_data3; @@ -725,13 +733,13 @@ static void get_inf_dev_status(struct i2c_client *client, /* (demdec status: 0x528) */ /* read current status */ - reg_data3 = saa717x_read(client, 0x0528); + reg_data3 = saa717x_read(sd, 0x0528); - v4l_dbg(1, debug, client, "tvaudio thread status: 0x%x [%s%s%s]\n", + v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n", reg_data3, stdres[reg_data3 & 0x1f], (reg_data3 & 0x000020) ? ",stereo" : "", (reg_data3 & 0x000040) ? ",dual" : ""); - v4l_dbg(1, debug, client, "detailed status: " + v4l2_dbg(1, debug, sd, "detailed status: " "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n", (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone " : "", (reg_data3 & 0x000100) ? " A2/EIAJ dual " : "", @@ -752,51 +760,51 @@ static void get_inf_dev_status(struct i2c_client *client, (reg_data3 & 0x100000) ? " init done " : ""); if (reg_data3 & 0x000220) { - v4l_dbg(1, debug, client, "ST!!!\n"); + v4l2_dbg(1, debug, sd, "ST!!!\n"); *stereo_flag = 1; } if (reg_data3 & 0x000140) { - v4l_dbg(1, debug, client, "DUAL!!!\n"); + v4l2_dbg(1, debug, sd, "DUAL!!!\n"); *dual_flag = 1; } } /* regs write to set audio mode */ -static void set_audio_mode(struct i2c_client *client, int audio_mode) +static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode) { - v4l_dbg(1, debug, client, "writing registers to set audio mode by set %d\n", + v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n", audio_mode); - saa717x_write(client, 0x46c, reg_set_audio_template[audio_mode][0]); - saa717x_write(client, 0x470, reg_set_audio_template[audio_mode][1]); + saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]); + saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]); } /* write regs to video output level (bright,contrast,hue,sat) */ -static void set_video_output_level_regs(struct i2c_client *client, +static void set_video_output_level_regs(struct v4l2_subdev *sd, struct saa717x_state *decoder) { /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */ - saa717x_write(client, 0x10a, decoder->bright); + saa717x_write(sd, 0x10a, decoder->bright); /* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) - 0h (luminance off) 40: i2c dump c0h (-1.0 inverse chrominance) 80h (-2.0 inverse chrominance) */ - saa717x_write(client, 0x10b, decoder->contrast); + saa717x_write(sd, 0x10b, decoder->contrast); /* saturation? 7fh(max)-40h(ITU)-0h(color off) c0h (-1.0 inverse chrominance) 80h (-2.0 inverse chrominance) */ - saa717x_write(client, 0x10c, decoder->sat); + saa717x_write(sd, 0x10c, decoder->sat); /* color hue (phase) control 7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */ - saa717x_write(client, 0x10d, decoder->hue); + saa717x_write(sd, 0x10d, decoder->hue); } /* write regs to set audio volume, bass and treble */ -static int set_audio_regs(struct i2c_client *client, +static int set_audio_regs(struct v4l2_subdev *sd, struct saa717x_state *decoder) { u8 mute = 0xac; /* -84 dB */ @@ -804,8 +812,8 @@ static int set_audio_regs(struct i2c_client *client, unsigned int work_l, work_r; /* set SIF analog I/O select */ - saa717x_write(client, 0x0594, decoder->audio_input); - v4l_dbg(1, debug, client, "set audio input %d\n", + saa717x_write(sd, 0x0594, decoder->audio_input); + v4l2_dbg(1, debug, sd, "set audio input %d\n", decoder->audio_input); /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */ @@ -825,17 +833,17 @@ static int set_audio_regs(struct i2c_client *client, ((u8)decoder->audio_main_vol_r << 8); } - saa717x_write(client, 0x480, val); + saa717x_write(sd, 0x480, val); /* bass and treble; go to another function */ /* set bass and treble */ val = decoder->audio_main_bass | (decoder->audio_main_treble << 8); - saa717x_write(client, 0x488, val); + saa717x_write(sd, 0x488, val); return 0; } /********** scaling staff ***********/ -static void set_h_prescale(struct i2c_client *client, +static void set_h_prescale(struct v4l2_subdev *sd, int task, int prescale) { static const struct { @@ -868,107 +876,101 @@ static void set_h_prescale(struct i2c_client *client, return; /* horizonal prescaling */ - saa717x_write(client, 0x60 + task_shift, vals[i].xpsc); + saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc); /* accumulation length */ - saa717x_write(client, 0x61 + task_shift, vals[i].xacl); + saa717x_write(sd, 0x61 + task_shift, vals[i].xacl); /* level control */ - saa717x_write(client, 0x62 + task_shift, + saa717x_write(sd, 0x62 + task_shift, (vals[i].xc2_1 << 3) | vals[i].xdcg); /*FIR prefilter control */ - saa717x_write(client, 0x63 + task_shift, + saa717x_write(sd, 0x63 + task_shift, (vals[i].vpfy << 2) | vals[i].vpfy); } /********** scaling staff ***********/ -static void set_v_scale(struct i2c_client *client, int task, int yscale) +static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale) { int task_shift; task_shift = task * 0x40; /* Vertical scaling ratio (LOW) */ - saa717x_write(client, 0x70 + task_shift, yscale & 0xff); + saa717x_write(sd, 0x70 + task_shift, yscale & 0xff); /* Vertical scaling ratio (HI) */ - saa717x_write(client, 0x71 + task_shift, yscale >> 8); -} - -static int saa717x_set_audio_clock_freq(struct i2c_client *client, u32 freq) -{ - /* not yet implament, so saa717x_cfg_??hz_??_audio is not defined. */ - return 0; + saa717x_write(sd, 0x71 + task_shift, yscale >> 8); } -static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int saa717x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct saa717x_state *state = i2c_get_clientdata(client); + struct saa717x_state *state = to_state(sd); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: if (ctrl->value < 0 || ctrl->value > 255) { - v4l_err(client, "invalid brightness setting %d\n", ctrl->value); + v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value); return -ERANGE; } state->bright = ctrl->value; - v4l_dbg(1, debug, client, "bright:%d\n", state->bright); - saa717x_write(client, 0x10a, state->bright); + v4l2_dbg(1, debug, sd, "bright:%d\n", state->bright); + saa717x_write(sd, 0x10a, state->bright); break; case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 127) { - v4l_err(client, "invalid contrast setting %d\n", ctrl->value); + v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value); return -ERANGE; } state->contrast = ctrl->value; - v4l_dbg(1, debug, client, "contrast:%d\n", state->contrast); - saa717x_write(client, 0x10b, state->contrast); + v4l2_dbg(1, debug, sd, "contrast:%d\n", state->contrast); + saa717x_write(sd, 0x10b, state->contrast); break; case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 127) { - v4l_err(client, "invalid saturation setting %d\n", ctrl->value); + v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value); return -ERANGE; } state->sat = ctrl->value; - v4l_dbg(1, debug, client, "sat:%d\n", state->sat); - saa717x_write(client, 0x10c, state->sat); + v4l2_dbg(1, debug, sd, "sat:%d\n", state->sat); + saa717x_write(sd, 0x10c, state->sat); break; case V4L2_CID_HUE: if (ctrl->value < -127 || ctrl->value > 127) { - v4l_err(client, "invalid hue setting %d\n", ctrl->value); + v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } state->hue = ctrl->value; - v4l_dbg(1, debug, client, "hue:%d\n", state->hue); - saa717x_write(client, 0x10d, state->hue); + v4l2_dbg(1, debug, sd, "hue:%d\n", state->hue); + saa717x_write(sd, 0x10d, state->hue); break; case V4L2_CID_AUDIO_MUTE: state->audio_main_mute = ctrl->value; - set_audio_regs(client, state); + set_audio_regs(sd, state); break; case V4L2_CID_AUDIO_VOLUME: state->audio_main_volume = ctrl->value; - set_audio_regs(client, state); + set_audio_regs(sd, state); break; case V4L2_CID_AUDIO_BALANCE: state->audio_main_balance = ctrl->value; - set_audio_regs(client, state); + set_audio_regs(sd, state); break; case V4L2_CID_AUDIO_TREBLE: state->audio_main_treble = ctrl->value; - set_audio_regs(client, state); + set_audio_regs(sd, state); break; case V4L2_CID_AUDIO_BASS: state->audio_main_bass = ctrl->value; - set_audio_regs(client, state); + set_audio_regs(sd, state); break; default: @@ -978,9 +980,9 @@ static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c return 0; } -static int saa717x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int saa717x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct saa717x_state *state = i2c_get_clientdata(client); + struct saa717x_state *state = to_state(sd); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -1109,13 +1111,15 @@ static struct v4l2_queryctrl saa717x_qctrl[] = { }, }; -static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_state *decoder, int inp) +static int saa717x_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { + struct saa717x_state *decoder = to_state(sd); + int inp = route->input; int is_tuner = inp & 0x80; /* tuner input flag */ inp &= 0x7f; - v4l_dbg(1, debug, client, "decoder set input (%d)\n", inp); + v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", inp); /* inputs from 0-9 are available*/ /* saa717x have mode0-mode9 but mode5 is reserved. */ if (inp < 0 || inp > 9 || inp == 5) @@ -1125,222 +1129,197 @@ static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_sta int input_line = inp; decoder->input = input_line; - v4l_dbg(1, debug, client, "now setting %s input %d\n", + v4l2_dbg(1, debug, sd, "now setting %s input %d\n", input_line >= 6 ? "S-Video" : "Composite", input_line); /* select mode */ - saa717x_write(client, 0x102, - (saa717x_read(client, 0x102) & 0xf0) | + saa717x_write(sd, 0x102, + (saa717x_read(sd, 0x102) & 0xf0) | input_line); /* bypass chrominance trap for modes 6..9 */ - saa717x_write(client, 0x109, - (saa717x_read(client, 0x109) & 0x7f) | + saa717x_write(sd, 0x109, + (saa717x_read(sd, 0x109) & 0x7f) | (input_line < 6 ? 0x0 : 0x80)); /* change audio_mode */ if (is_tuner) { /* tuner */ - set_audio_mode(client, decoder->tuner_audio_mode); + set_audio_mode(sd, decoder->tuner_audio_mode); } else { /* Force to STEREO mode if Composite or * S-Video were chosen */ - set_audio_mode(client, TUNER_AUDIO_STEREO); + set_audio_mode(sd, TUNER_AUDIO_STEREO); } /* change initialize procedure (Composite/S-Video) */ if (is_tuner) - saa717x_write_regs(client, reg_init_tuner_input); + saa717x_write_regs(sd, reg_init_tuner_input); else if (input_line >= 6) - saa717x_write_regs(client, reg_init_svideo_input); + saa717x_write_regs(sd, reg_init_svideo_input); else - saa717x_write_regs(client, reg_init_composite_input); + saa717x_write_regs(sd, reg_init_composite_input); } return 0; } -static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg) +static int saa717x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { - struct saa717x_state *decoder = i2c_get_clientdata(client); - - v4l_dbg(1, debug, client, "IOCTL: %08x\n", cmd); + int i; - switch (cmd) { - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return saa717x_set_audio_clock_freq(client, *(u32 *)arg); + for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++) + if (qc->id && qc->id == saa717x_qctrl[i].id) { + memcpy(qc, &saa717x_qctrl[i], sizeof(*qc)); + return 0; + } + return -EINVAL; +} - case VIDIOC_G_CTRL: - return saa717x_get_v4lctrl(client, (struct v4l2_control *)arg); +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_S_CTRL: - return saa717x_set_v4lctrl(client, (struct v4l2_control *)arg); + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = saa717x_read(sd, reg->reg); + return 0; +} - case VIDIOC_QUERYCTRL: { - struct v4l2_queryctrl *qc = arg; - int i; +static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + u16 addr = reg->reg & 0xffff; + u8 val = reg->val & 0xff; - for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++) - if (qc->id && qc->id == saa717x_qctrl[i].id) { - memcpy(qc, &saa717x_qctrl[i], sizeof(*qc)); - return 0; - } + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; - } - -#ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: { - struct v4l2_register *reg = arg; - - if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - reg->val = saa717x_read(client, reg->reg); - break; - } + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + saa717x_write(sd, addr, val); + return 0; +} +#endif - case VIDIOC_DBG_S_REGISTER: { - struct v4l2_register *reg = arg; - u16 addr = reg->reg & 0xffff; - u8 val = reg->val & 0xff; +static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix; + int prescale, h_scale, v_scale; - if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - saa717x_write(client, addr, val); - break; - } -#endif + pix = &fmt->fmt.pix; + v4l2_dbg(1, debug, sd, "decoder set size\n"); - case VIDIOC_S_FMT: { - struct v4l2_format *fmt = (struct v4l2_format *)arg; - struct v4l2_pix_format *pix; - int prescale, h_scale, v_scale; - - pix = &fmt->fmt.pix; - v4l_dbg(1, debug, client, "decoder set size\n"); - - /* FIXME need better bounds checking here */ - if (pix->width < 1 || pix->width > 1440) - return -EINVAL; - if (pix->height < 1 || pix->height > 960) - return -EINVAL; - - /* scaling setting */ - /* NTSC and interlace only */ - prescale = SAA717X_NTSC_WIDTH / pix->width; - if (prescale == 0) - prescale = 1; - h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width; - /* interlace */ - v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height; - - /* Horizontal prescaling etc */ - set_h_prescale(client, 0, prescale); - set_h_prescale(client, 1, prescale); - - /* Horizontal scaling increment */ - /* TASK A */ - saa717x_write(client, 0x6C, (u8)(h_scale & 0xFF)); - saa717x_write(client, 0x6D, (u8)((h_scale >> 8) & 0xFF)); - /* TASK B */ - saa717x_write(client, 0xAC, (u8)(h_scale & 0xFF)); - saa717x_write(client, 0xAD, (u8)((h_scale >> 8) & 0xFF)); - - /* Vertical prescaling etc */ - set_v_scale(client, 0, v_scale); - set_v_scale(client, 1, v_scale); - - /* set video output size */ - /* video number of pixels at output */ - /* TASK A */ - saa717x_write(client, 0x5C, (u8)(pix->width & 0xFF)); - saa717x_write(client, 0x5D, (u8)((pix->width >> 8) & 0xFF)); - /* TASK B */ - saa717x_write(client, 0x9C, (u8)(pix->width & 0xFF)); - saa717x_write(client, 0x9D, (u8)((pix->width >> 8) & 0xFF)); - - /* video number of lines at output */ - /* TASK A */ - saa717x_write(client, 0x5E, (u8)(pix->height & 0xFF)); - saa717x_write(client, 0x5F, (u8)((pix->height >> 8) & 0xFF)); - /* TASK B */ - saa717x_write(client, 0x9E, (u8)(pix->height & 0xFF)); - saa717x_write(client, 0x9F, (u8)((pix->height >> 8) & 0xFF)); - break; - } + /* FIXME need better bounds checking here */ + if (pix->width < 1 || pix->width > 1440) + return -EINVAL; + if (pix->height < 1 || pix->height > 960) + return -EINVAL; - case AUDC_SET_RADIO: - decoder->radio = 1; - break; + /* scaling setting */ + /* NTSC and interlace only */ + prescale = SAA717X_NTSC_WIDTH / pix->width; + if (prescale == 0) + prescale = 1; + h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width; + /* interlace */ + v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height; + + /* Horizontal prescaling etc */ + set_h_prescale(sd, 0, prescale); + set_h_prescale(sd, 1, prescale); + + /* Horizontal scaling increment */ + /* TASK A */ + saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF)); + saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF)); + /* TASK B */ + saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF)); + saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF)); + + /* Vertical prescaling etc */ + set_v_scale(sd, 0, v_scale); + set_v_scale(sd, 1, v_scale); + + /* set video output size */ + /* video number of pixels at output */ + /* TASK A */ + saa717x_write(sd, 0x5C, (u8)(pix->width & 0xFF)); + saa717x_write(sd, 0x5D, (u8)((pix->width >> 8) & 0xFF)); + /* TASK B */ + saa717x_write(sd, 0x9C, (u8)(pix->width & 0xFF)); + saa717x_write(sd, 0x9D, (u8)((pix->width >> 8) & 0xFF)); + + /* video number of lines at output */ + /* TASK A */ + saa717x_write(sd, 0x5E, (u8)(pix->height & 0xFF)); + saa717x_write(sd, 0x5F, (u8)((pix->height >> 8) & 0xFF)); + /* TASK B */ + saa717x_write(sd, 0x9E, (u8)(pix->height & 0xFF)); + saa717x_write(sd, 0x9F, (u8)((pix->height >> 8) & 0xFF)); + return 0; +} - case VIDIOC_S_STD: { - v4l2_std_id std = *(v4l2_std_id *) arg; +static int saa717x_s_radio(struct v4l2_subdev *sd) +{ + struct saa717x_state *decoder = to_state(sd); - v4l_dbg(1, debug, client, "decoder set norm "); - v4l_dbg(1, debug, client, "(not yet implementd)\n"); + decoder->radio = 1; + return 0; +} - decoder->radio = 0; - decoder->std = std; - break; - } +static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct saa717x_state *decoder = to_state(sd); - case VIDIOC_INT_G_AUDIO_ROUTING: { - struct v4l2_routing *route = arg; + v4l2_dbg(1, debug, sd, "decoder set norm "); + v4l2_dbg(1, debug, sd, "(not yet implementd)\n"); - route->input = decoder->audio_input; - route->output = 0; - break; - } + decoder->radio = 0; + decoder->std = std; + return 0; +} - case VIDIOC_INT_S_AUDIO_ROUTING: { - struct v4l2_routing *route = arg; +static int saa717x_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct saa717x_state *decoder = to_state(sd); - if (route->input < 3) { /* FIXME! --tadachi */ - decoder->audio_input = route->input; - v4l_dbg(1, debug, client, + if (route->input < 3) { /* FIXME! --tadachi */ + decoder->audio_input = route->input; + v4l2_dbg(1, debug, sd, "set decoder audio input to %d\n", decoder->audio_input); - set_audio_regs(client, decoder); - break; - } - return -ERANGE; - } - - case VIDIOC_INT_S_VIDEO_ROUTING: { - struct v4l2_routing *route = arg; - int inp = route->input; - - return saa717x_set_video_input(client, decoder, inp); + set_audio_regs(sd, decoder); + return 0; } + return -ERANGE; +} - case VIDIOC_STREAMON: { - v4l_dbg(1, debug, client, "decoder enable output\n"); - decoder->enable = 1; - saa717x_write(client, 0x193, 0xa6); - break; - } +static int saa717x_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct saa717x_state *decoder = to_state(sd); - case VIDIOC_STREAMOFF: { - v4l_dbg(1, debug, client, "decoder disable output\n"); - decoder->enable = 0; - saa717x_write(client, 0x193, 0x26); /* right? FIXME!--tadachi */ - break; - } + v4l2_dbg(1, debug, sd, "decoder %s output\n", + enable ? "enable" : "disable"); + decoder->enable = enable; + saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26); + return 0; +} - /* change audio mode */ - case VIDIOC_S_TUNER: { - struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; - int audio_mode; - char *mes[4] = { - "MONO", "STEREO", "LANG1", "LANG2/SAP" - }; +/* change audio mode */ +static int saa717x_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct saa717x_state *decoder = to_state(sd); + int audio_mode; + char *mes[4] = { + "MONO", "STEREO", "LANG1", "LANG2/SAP" + }; - audio_mode = V4L2_TUNER_MODE_STEREO; + audio_mode = V4L2_TUNER_MODE_STEREO; - switch (vt->audmode) { + switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: audio_mode = TUNER_AUDIO_MONO; break; @@ -1353,70 +1332,101 @@ static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg) case V4L2_TUNER_MODE_LANG1: audio_mode = TUNER_AUDIO_LANG1; break; - } - - v4l_dbg(1, debug, client, "change audio mode to %s\n", - mes[audio_mode]); - decoder->tuner_audio_mode = audio_mode; - /* The registers are not changed here. */ - /* See DECODER_ENABLE_OUTPUT section. */ - set_audio_mode(client, decoder->tuner_audio_mode); - break; } - case VIDIOC_G_TUNER: { - struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; - int dual_f, stereo_f; + v4l2_dbg(1, debug, sd, "change audio mode to %s\n", + mes[audio_mode]); + decoder->tuner_audio_mode = audio_mode; + /* The registers are not changed here. */ + /* See DECODER_ENABLE_OUTPUT section. */ + set_audio_mode(sd, decoder->tuner_audio_mode); + return 0; +} - if (decoder->radio) - break; - get_inf_dev_status(client, &dual_f, &stereo_f); +static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct saa717x_state *decoder = to_state(sd); + int dual_f, stereo_f; - v4l_dbg(1, debug, client, "DETECT==st:%d dual:%d\n", - stereo_f, dual_f); + if (decoder->radio) + return 0; + get_inf_dev_status(sd, &dual_f, &stereo_f); - /* mono */ - if ((dual_f == 0) && (stereo_f == 0)) { - vt->rxsubchans = V4L2_TUNER_SUB_MONO; - v4l_dbg(1, debug, client, "DETECT==MONO\n"); - } + v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n", + stereo_f, dual_f); - /* stereo */ - if (stereo_f == 1) { - if (vt->audmode == V4L2_TUNER_MODE_STEREO || - vt->audmode == V4L2_TUNER_MODE_LANG1) { - vt->rxsubchans = V4L2_TUNER_SUB_STEREO; - v4l_dbg(1, debug, client, "DETECT==ST(ST)\n"); - } else { - vt->rxsubchans = V4L2_TUNER_SUB_MONO; - v4l_dbg(1, debug, client, "DETECT==ST(MONO)\n"); - } - } + /* mono */ + if ((dual_f == 0) && (stereo_f == 0)) { + vt->rxsubchans = V4L2_TUNER_SUB_MONO; + v4l2_dbg(1, debug, sd, "DETECT==MONO\n"); + } - /* dual */ - if (dual_f == 1) { - if (vt->audmode == V4L2_TUNER_MODE_LANG2) { - vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO; - v4l_dbg(1, debug, client, "DETECT==DUAL1\n"); - } else { - vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO; - v4l_dbg(1, debug, client, "DETECT==DUAL2\n"); - } + /* stereo */ + if (stereo_f == 1) { + if (vt->audmode == V4L2_TUNER_MODE_STEREO || + vt->audmode == V4L2_TUNER_MODE_LANG1) { + vt->rxsubchans = V4L2_TUNER_SUB_STEREO; + v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n"); + } else { + vt->rxsubchans = V4L2_TUNER_SUB_MONO; + v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n"); } - break; } - case VIDIOC_LOG_STATUS: - /* not yet implemented */ - break; - - default: - return -EINVAL; + /* dual */ + if (dual_f == 1) { + if (vt->audmode == V4L2_TUNER_MODE_LANG2) { + vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO; + v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n"); + } else { + vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO; + v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n"); + } } - return 0; } +static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops saa717x_core_ops = { +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = saa717x_g_register, + .s_register = saa717x_s_register, +#endif + .queryctrl = saa717x_queryctrl, + .g_ctrl = saa717x_g_ctrl, + .s_ctrl = saa717x_s_ctrl, +}; + +static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = { + .g_tuner = saa717x_g_tuner, + .s_tuner = saa717x_s_tuner, + .s_std = saa717x_s_std, + .s_radio = saa717x_s_radio, +}; + +static const struct v4l2_subdev_video_ops saa717x_video_ops = { + .s_routing = saa717x_s_video_routing, + .s_fmt = saa717x_s_fmt, + .s_stream = saa717x_s_stream, +}; + +static const struct v4l2_subdev_audio_ops saa717x_audio_ops = { + .s_routing = saa717x_s_audio_routing, +}; + +static const struct v4l2_subdev_ops saa717x_ops = { + .core = &saa717x_core_ops, + .tuner = &saa717x_tuner_ops, + .audio = &saa717x_audio_ops, + .video = &saa717x_video_ops, +}; + /* ----------------------------------------------------------------------- */ @@ -1427,6 +1437,7 @@ static int saa717x_probe(struct i2c_client *client, const struct i2c_device_id *did) { struct saa717x_state *decoder; + struct v4l2_subdev *sd; u8 id = 0; char *p = ""; @@ -1434,16 +1445,24 @@ static int saa717x_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; + decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL); + if (decoder == NULL) + return -ENOMEM; + + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &saa717x_ops); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) snprintf(client->name, sizeof(client->name) - 1, "saa717x"); #endif - if (saa717x_write(client, 0x5a4, 0xfe) && - saa717x_write(client, 0x5a5, 0x0f) && - saa717x_write(client, 0x5a6, 0x00) && - saa717x_write(client, 0x5a7, 0x01)) - id = saa717x_read(client, 0x5a0); + if (saa717x_write(sd, 0x5a4, 0xfe) && + saa717x_write(sd, 0x5a5, 0x0f) && + saa717x_write(sd, 0x5a6, 0x00) && + saa717x_write(sd, 0x5a7, 0x01)) + id = saa717x_read(sd, 0x5a0); if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) { - v4l_dbg(1, debug, client, "saa717x not found (id=%02x)\n", id); + v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id); + kfree(decoder); return -ENODEV; } if (id == 0xc2) @@ -1454,14 +1473,8 @@ static int saa717x_probe(struct i2c_client *client, p = "saa7174HL"; else p = "saa7171"; - v4l_info(client, "%s found @ 0x%x (%s)\n", p, + v4l2_info(sd, "%s found @ 0x%x (%s)\n", p, client->addr << 1, client->adapter->name); - - decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL); - i2c_set_clientdata(client, decoder); - - if (decoder == NULL) - return -ENOMEM; decoder->std = V4L2_STD_NTSC; decoder->input = -1; decoder->enable = 1; @@ -1490,15 +1503,15 @@ static int saa717x_probe(struct i2c_client *client, decoder->audio_main_volume = (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40)); - v4l_dbg(1, debug, client, "writing init values\n"); + v4l2_dbg(1, debug, sd, "writing init values\n"); /* FIXME!! */ - saa717x_write_regs(client, reg_init_initialize); - set_video_output_level_regs(client, decoder); + saa717x_write_regs(sd, reg_init_initialize); + set_video_output_level_regs(sd, decoder); /* set bass,treble to 0db 20041101 K.Ohta */ decoder->audio_main_bass = 0; decoder->audio_main_treble = 0; - set_audio_regs(client, decoder); + set_audio_regs(sd, decoder); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(2*HZ); @@ -1507,7 +1520,10 @@ static int saa717x_probe(struct i2c_client *client, static int saa717x_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From 912b4df6a7f733ecd3a6b3d58d0661a3e9ec2474 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 24 Nov 2008 22:21:40 +0100 Subject: tuner: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tuner-core.c | 391 +++++++++++++++++++-------------- 1 file changed, 229 insertions(+), 162 deletions(-) diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 5dd4bd660..e649f2eb7 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include "mt20xx.h" @@ -79,6 +79,7 @@ struct tuner { /* device */ struct dvb_frontend fe; struct i2c_client *i2c; + struct v4l2_subdev sd; struct list_head list; unsigned int using_v4l2:1; @@ -96,6 +97,11 @@ struct tuner { const char *name; }; +static inline struct tuner *to_tuner(struct v4l2_subdev *sd) +{ + return container_of(sd, struct tuner, sd); +} + /* standard i2c insmod options */ static unsigned short normal_i2c[] = { #if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE)) @@ -214,7 +220,7 @@ static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg) static void tuner_status(struct dvb_frontend *fe); -static struct analog_demod_ops tuner_core_ops = { +static struct analog_demod_ops tuner_analog_ops = { .set_params = fe_set_params, .standby = fe_standby, .has_signal = fe_has_signal, @@ -225,7 +231,7 @@ static struct analog_demod_ops tuner_core_ops = { /* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */ static void set_tv_freq(struct i2c_client *c, unsigned int freq) { - struct tuner *t = i2c_get_clientdata(c); + struct tuner *t = to_tuner(i2c_get_clientdata(c)); struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; struct analog_parameters params = { @@ -260,7 +266,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) static void set_radio_freq(struct i2c_client *c, unsigned int freq) { - struct tuner *t = i2c_get_clientdata(c); + struct tuner *t = to_tuner(i2c_get_clientdata(c)); struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; struct analog_parameters params = { @@ -295,7 +301,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) static void set_freq(struct i2c_client *c, unsigned long freq) { - struct tuner *t = i2c_get_clientdata(c); + struct tuner *t = to_tuner(i2c_get_clientdata(c)); switch (t->mode) { case V4L2_TUNER_RADIO: @@ -348,7 +354,7 @@ static void set_type(struct i2c_client *c, unsigned int type, unsigned int new_mode_mask, unsigned int new_config, int (*tuner_callback) (void *dev, int component, int cmd, int arg)) { - struct tuner *t = i2c_get_clientdata(c); + struct tuner *t = to_tuner(i2c_get_clientdata(c)); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; unsigned char buffer[4]; @@ -471,7 +477,7 @@ static void set_type(struct i2c_client *c, unsigned int type, t->name = fe_tuner_ops->info.name; t->fe.analog_demod_priv = t; - memcpy(analog_ops, &tuner_core_ops, + memcpy(analog_ops, &tuner_analog_ops, sizeof(struct analog_demod_ops)); } else { @@ -516,7 +522,7 @@ attach_failed: static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup) { - struct tuner *t = i2c_get_clientdata(c); + struct tuner *t = to_tuner(i2c_get_clientdata(c)); if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) && (t->mode_mask & tun_setup->mode_mask))) || @@ -758,43 +764,56 @@ static inline int check_v4l2(struct tuner *t) return 0; } -static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) +static int tuner_s_type_addr(struct v4l2_subdev *sd, struct tuner_setup *type) { - struct tuner *t = i2c_get_clientdata(client); - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct tuner *t = to_tuner(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=0x%02x\n", + type->type, + type->addr, + type->mode_mask, + type->config); + + set_addr(client, type); + return 0; +} + +static int tuner_s_radio(struct v4l2_subdev *sd) +{ + struct tuner *t = to_tuner(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") + == -EINVAL) + return 0; + if (t->radio_freq) + set_freq(client, t->radio_freq); + return 0; +} + +static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) +{ + struct tuner *t = to_tuner(sd); struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; - if (tuner_debug > 1) { - v4l_i2c_print_ioctl(client,cmd); - printk("\n"); - } + if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL) + return 0; + t->mode = T_STANDBY; + if (analog_ops->standby) + analog_ops->standby(&t->fe); + return 0; +} - switch (cmd) { - /* --- configuration --- */ - case TUNER_SET_TYPE_ADDR: - tuner_dbg ("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=0x%02x\n", - ((struct tuner_setup *)arg)->type, - ((struct tuner_setup *)arg)->addr, - ((struct tuner_setup *)arg)->mode_mask, - ((struct tuner_setup *)arg)->config); - - set_addr(client, (struct tuner_setup *)arg); - break; - case AUDC_SET_RADIO: - if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") - == -EINVAL) - return 0; - if (t->radio_freq) - set_freq(client, t->radio_freq); - break; - case TUNER_SET_STANDBY: - if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL) - return 0; - t->mode = T_STANDBY; - if (analog_ops->standby) - analog_ops->standby(&t->fe); - break; #ifdef CONFIG_VIDEO_ALLOW_V4L1 +static int tuner_ioctl(struct v4l2_subdev *sd, int cmd, void *arg) +{ + struct tuner *t = to_tuner(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; + struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + + switch (cmd) { case VIDIOCSAUDIO: if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL) return 0; @@ -907,149 +926,172 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) } return 0; } + } + return -ENOIOCTLCMD; +} #endif - case TUNER_SET_CONFIG: - { - struct v4l2_priv_tun_config *cfg = arg; - if (t->type != cfg->tuner) - break; +static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg) +{ + struct tuner *t = to_tuner(sd); + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; - if (analog_ops->set_config) { - analog_ops->set_config(&t->fe, cfg->priv); - break; - } + if (t->type != cfg->tuner) + return 0; - tuner_dbg("Tuner frontend module has no way to set config\n"); - break; + if (analog_ops->set_config) { + analog_ops->set_config(&t->fe, cfg->priv); + return 0; } - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD") - == -EINVAL) - return 0; + tuner_dbg("Tuner frontend module has no way to set config\n"); + return 0; +} - switch_v4l2(); +/* --- v4l ioctls --- */ +/* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ +static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct tuner *t = to_tuner(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - t->std = *id; - tuner_fixup_std(t); - if (t->tv_freq) - set_freq(client, t->tv_freq); - break; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; + if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD") + == -EINVAL) + return 0; - if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") - == -EINVAL) - return 0; - switch_v4l2(); - set_freq(client,f->frequency); + switch_v4l2(); - break; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; + t->std = std; + tuner_fixup_std(t); + if (t->tv_freq) + set_freq(client, t->tv_freq); + return 0; +} - if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL) - return 0; - switch_v4l2(); - f->type = t->mode; - if (fe_tuner_ops->get_frequency) { - u32 abs_freq; - - fe_tuner_ops->get_frequency(&t->fe, &abs_freq); - f->frequency = (V4L2_TUNER_RADIO == t->mode) ? - (abs_freq * 2 + 125/2) / 125 : - (abs_freq + 62500/2) / 62500; - break; - } - f->frequency = (V4L2_TUNER_RADIO == t->mode) ? - t->radio_freq : t->tv_freq; - break; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *tuner = arg; +static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) +{ + struct tuner *t = to_tuner(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL) - return 0; - switch_v4l2(); - - tuner->type = t->mode; - if (analog_ops->get_afc) - tuner->afc = analog_ops->get_afc(&t->fe); - if (t->mode == V4L2_TUNER_ANALOG_TV) - tuner->capability |= V4L2_TUNER_CAP_NORM; - if (t->mode != V4L2_TUNER_RADIO) { - tuner->rangelow = tv_range[0] * 16; - tuner->rangehigh = tv_range[1] * 16; - break; - } + if (set_mode(client, t, f->type, "VIDIOC_S_FREQUENCY") + == -EINVAL) + return 0; + switch_v4l2(); + set_freq(client, f->frequency); - /* radio mode */ - tuner->rxsubchans = - V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - if (fe_tuner_ops->get_status) { - u32 tuner_status; - - fe_tuner_ops->get_status(&t->fe, &tuner_status); - tuner->rxsubchans = - (tuner_status & TUNER_STATUS_STEREO) ? - V4L2_TUNER_SUB_STEREO : - V4L2_TUNER_SUB_MONO; - } else { - if (analog_ops->is_stereo) { - tuner->rxsubchans = - analog_ops->is_stereo(&t->fe) ? - V4L2_TUNER_SUB_STEREO : - V4L2_TUNER_SUB_MONO; - } - } - if (analog_ops->has_signal) - tuner->signal = analog_ops->has_signal(&t->fe); - tuner->capability |= - V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - tuner->audmode = t->audmode; - tuner->rangelow = radio_range[0] * 16000; - tuner->rangehigh = radio_range[1] * 16000; - break; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *tuner = arg; + return 0; +} - if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL) - return 0; +static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) +{ + struct tuner *t = to_tuner(sd); + struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - switch_v4l2(); + if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL) + return 0; + switch_v4l2(); + f->type = t->mode; + if (fe_tuner_ops->get_frequency) { + u32 abs_freq; + + fe_tuner_ops->get_frequency(&t->fe, &abs_freq); + f->frequency = (V4L2_TUNER_RADIO == t->mode) ? + (abs_freq * 2 + 125/2) / 125 : + (abs_freq + 62500/2) / 62500; + return 0; + } + f->frequency = (V4L2_TUNER_RADIO == t->mode) ? + t->radio_freq : t->tv_freq; + return 0; +} - /* do nothing unless we're a radio tuner */ - if (t->mode != V4L2_TUNER_RADIO) - break; - t->audmode = tuner->audmode; - set_radio_freq(client, t->radio_freq); - break; +static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct tuner *t = to_tuner(sd); + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; + struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + + if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL) + return 0; + switch_v4l2(); + + vt->type = t->mode; + if (analog_ops->get_afc) + vt->afc = analog_ops->get_afc(&t->fe); + if (t->mode == V4L2_TUNER_ANALOG_TV) + vt->capability |= V4L2_TUNER_CAP_NORM; + if (t->mode != V4L2_TUNER_RADIO) { + vt->rangelow = tv_range[0] * 16; + vt->rangehigh = tv_range[1] * 16; + return 0; + } + + /* radio mode */ + vt->rxsubchans = + V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + if (fe_tuner_ops->get_status) { + u32 tuner_status; + + fe_tuner_ops->get_status(&t->fe, &tuner_status); + vt->rxsubchans = + (tuner_status & TUNER_STATUS_STEREO) ? + V4L2_TUNER_SUB_STEREO : + V4L2_TUNER_SUB_MONO; + } else { + if (analog_ops->is_stereo) { + vt->rxsubchans = + analog_ops->is_stereo(&t->fe) ? + V4L2_TUNER_SUB_STEREO : + V4L2_TUNER_SUB_MONO; } - case VIDIOC_LOG_STATUS: - if (analog_ops->tuner_status) - analog_ops->tuner_status(&t->fe); - break; } + if (analog_ops->has_signal) + vt->signal = analog_ops->has_signal(&t->fe); + vt->capability |= + V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + vt->audmode = t->audmode; + vt->rangelow = radio_range[0] * 16000; + vt->rangehigh = radio_range[1] * 16000; + return 0; +} + +static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct tuner *t = to_tuner(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL) + return 0; + + switch_v4l2(); + + /* do nothing unless we're a radio tuner */ + if (t->mode != V4L2_TUNER_RADIO) + return 0; + t->audmode = vt->audmode; + set_radio_freq(client, t->radio_freq); + return 0; +} + +static int tuner_log_status(struct v4l2_subdev *sd) +{ + struct tuner *t = to_tuner(sd); + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; + if (analog_ops->tuner_status) + analog_ops->tuner_status(&t->fe); return 0; } +static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + static int tuner_suspend(struct i2c_client *c, pm_message_t state) { - struct tuner *t = i2c_get_clientdata(c); + struct tuner *t = to_tuner(i2c_get_clientdata(c)); tuner_dbg("suspend\n"); /* FIXME: power down ??? */ @@ -1058,7 +1100,7 @@ static int tuner_suspend(struct i2c_client *c, pm_message_t state) static int tuner_resume(struct i2c_client *c) { - struct tuner *t = i2c_get_clientdata(c); + struct tuner *t = to_tuner(i2c_get_clientdata(c)); tuner_dbg("resume\n"); if (V4L2_TUNER_RADIO == t->mode) { @@ -1071,6 +1113,30 @@ static int tuner_resume(struct i2c_client *c) return 0; } +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops tuner_core_ops = { + .log_status = tuner_log_status, + .s_standby = tuner_s_standby, + .ioctl = tuner_ioctl, +}; + +static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { + .s_std = tuner_s_std, + .s_radio = tuner_s_radio, + .g_tuner = tuner_g_tuner, + .s_tuner = tuner_s_tuner, + .s_frequency = tuner_s_frequency, + .g_frequency = tuner_g_frequency, + .s_type_addr = tuner_s_type_addr, + .s_config = tuner_s_config, +}; + +static const struct v4l2_subdev_ops tuner_ops = { + .core = &tuner_core_ops, + .tuner = &tuner_tuner_ops, +}; + /* ---------------------------------------------------------------------- */ static LIST_HEAD(tuner_list); @@ -1119,9 +1185,9 @@ static int tuner_probe(struct i2c_client *client, t = kzalloc(sizeof(struct tuner), GFP_KERNEL); if (NULL == t) return -ENOMEM; + v4l2_i2c_subdev_init(&t->sd, client, &tuner_ops); t->i2c = client; t->name = "(tuner unset)"; - i2c_set_clientdata(client, t); t->type = UNSET; t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; @@ -1271,8 +1337,9 @@ static int tuner_legacy_probe(struct i2c_adapter *adap) static int tuner_remove(struct i2c_client *client) { - struct tuner *t = i2c_get_clientdata(client); + struct tuner *t = to_tuner(i2c_get_clientdata(client)); + v4l2_device_unregister_subdev(&t->sd); tuner_detach(&t->fe); t->fe.analog_demod_priv = NULL; -- cgit v1.2.3 From 2455970680b1cd007de40507e020551086150422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 25 Nov 2008 07:15:15 +0100 Subject: Add vflip quirk for the ASUS A6Ja MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 95a58a0fa..9d22308fc 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -46,6 +46,13 @@ static DMI_MATCH(DMI_PRODUCT_NAME, "A6JC") } }, + { + .ident = "ASUS A6Ja", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6J") + } + }, { .ident = "ASUS A6Kt", .matches = { -- cgit v1.2.3 From d2f64b019b20b0786835491dbe35cd0db996aa45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 25 Nov 2008 07:50:05 +0100 Subject: Remove the write and read sensor members from the main struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 3 --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 4 +--- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 2 -- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 2 -- linux/drivers/media/video/gspca/m5602/m5602_sensor.h | 8 -------- 5 files changed, 1 insertion(+), 18 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 4b4c1967b..0fe4d6327 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -109,9 +109,6 @@ static struct m5602_sensor mt9m111 = { .init = mt9m111_init, .power_down = mt9m111_power_down, - .read_sensor = mt9m111_read_sensor, - .write_sensor = mt9m111_write_sensor, - .nctrls = 3, .ctrls = { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 4d90bd085..32fc440c5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -156,8 +156,6 @@ static struct m5602_sensor ov9650 = { .probe = ov9650_probe, .init = ov9650_init, .power_down = ov9650_power_down, - .read_sensor = ov9650_read_sensor, - .write_sensor = ov9650_write_sensor, .nctrls = 8, .ctrls = { @@ -341,7 +339,7 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_ACOM38, 0x81}, /* Turn off color matrix coefficient double option */ {SENSOR, OV9650_COM16, 0x00}, - /* Enable color matrix for RGB/YUV, Delay Y channel, + /* Enable color matrix for RGB/YUV, Delay Y channel, set output Y/UV delay to 1 */ {SENSOR, OV9650_COM13, 0x19}, /* Enable digital BLC, Set output mode to U Y V Y */ diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 1ee649b8d..701d30292 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -86,8 +86,6 @@ static struct m5602_sensor s5k4aa = { .probe = s5k4aa_probe, .init = s5k4aa_init, .power_down = s5k4aa_power_down, - .read_sensor = s5k4aa_read_sensor, - .write_sensor = s5k4aa_write_sensor, .i2c_slave_id = 0x5a, .nctrls = 4, .ctrls = { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 5080da196..793c96787 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -68,8 +68,6 @@ static struct m5602_sensor s5k83a = { .probe = s5k83a_probe, .init = s5k83a_init, .power_down = s5k83a_power_down, - .read_sensor = s5k83a_read_sensor, - .write_sensor = s5k83a_write_sensor, .i2c_slave_id = 0x5a, .nctrls = 5, .ctrls = { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 60c9a48e0..c09000236 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -58,14 +58,6 @@ struct m5602_sensor { /* Performs a power down sequence */ int (*power_down)(struct sd *sd); - /* Reads a sensor register */ - int (*read_sensor)(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - - /* Writes to a sensor register */ - int (*write_sensor)(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - int nctrls; struct ctrl ctrls[M5602_MAX_CTRLS]; -- cgit v1.2.3 From f29ecdd796231f10eb0808a5a4d213ea2c8a264f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 25 Nov 2008 08:47:09 +0100 Subject: gspca: Center the brightness in sonixj. From: Jean-Francois Moine The brightness jumped from max to min at the middle of the control values. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index bfd256716..9d9f90669 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -89,7 +89,7 @@ static struct ctrl sd_ctrls[] = { #define BRIGHTNESS_MAX 0xffff .maximum = BRIGHTNESS_MAX, .step = 1, -#define BRIGHTNESS_DEF 0x7fff +#define BRIGHTNESS_DEF 0x8000 .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, @@ -1142,7 +1142,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) unsigned int expo; __u8 k2; - k2 = sd->brightness >> 10; + k2 = ((int) sd->brightness - 0x8000) >> 10; switch (sd->sensor) { case SENSOR_HV7131R: expo = sd->brightness << 4; @@ -1160,7 +1160,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) case SENSOR_OM6802: expo = sd->brightness >> 6; sd->exposure = setexposure(gspca_dev, expo); - k2 >>= 1; + k2 = sd->brightness >> 11; break; } -- cgit v1.2.3 From da0e5a7cc6dc76cf99879f3ee26a2256c67e4cde Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 27 Nov 2008 22:04:21 -0500 Subject: cx18: Eliminate q_io from stream buffer handling From: Andy Walls Eliminate q_io from stream buffer handling in anticipation of upcoming changes in buffer handling. q_io was a holdover from ivtv and it's function in cx18 was trivial and not necessary. We just push things back onto the front of q_full now, instead of maintaining a 1 buffer q_io queue. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.h | 1 - linux/drivers/media/video/cx18/cx18-fileops.c | 9 ++------- linux/drivers/media/video/cx18/cx18-queue.c | 10 ++++++---- linux/drivers/media/video/cx18/cx18-queue.h | 19 +++++++++++++++++-- linux/drivers/media/video/cx18/cx18-streams.c | 1 - 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 94c196a91..f88d82348 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -290,7 +290,6 @@ struct cx18_stream { /* Buffer Queues */ struct cx18_queue q_free; /* free buffers */ struct cx18_queue q_full; /* full buffers */ - struct cx18_queue q_io; /* waiting for I/O */ /* DVB / Digital Transport */ struct cx18_dvb dvb; diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index 45b5f402e..b298faa59 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -233,11 +233,6 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, return buf; } - /* do we have leftover data? */ - buf = cx18_dequeue(s, &s->q_io); - if (buf) - return buf; - /* do we have new data? */ buf = cx18_dequeue(s, &s->q_full); if (buf) { @@ -413,7 +408,7 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, cx->enc_mem, 1, buf->id, s->buf_size); } else - cx18_enqueue(s, buf, &s->q_io); + cx18_push(s, buf, &s->q_full); } else if (buf->readpos == buf->bytesused) { int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; @@ -557,7 +552,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) CX18_DEBUG_HI_FILE("Encoder poll\n"); poll_wait(filp, &s->waitq, wait); - if (atomic_read(&s->q_full.buffers) || atomic_read(&s->q_io.buffers)) + if (atomic_read(&s->q_full.buffers)) return POLLIN | POLLRDNORM; if (eof) return POLLHUP; diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index 7b09c9a3e..fdfc83ee3 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -42,8 +42,8 @@ void cx18_queue_init(struct cx18_queue *q) q->bytesused = 0; } -void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, - struct cx18_queue *q) +void _cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, + struct cx18_queue *q, int to_front) { /* clear the buffer if it is going to be enqueued to the free queue */ if (q == &s->q_free) { @@ -53,7 +53,10 @@ void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, buf->skipped = 0; } mutex_lock(&s->qlock); - list_add_tail(&buf->list, &q->list); + if (to_front) + list_add(&buf->list, &q->list); /* LIFO */ + else + list_add_tail(&buf->list, &q->list); /* FIFO */ atomic_inc(&q->buffers); q->bytesused += buf->bytesused - buf->readpos; mutex_unlock(&s->qlock); @@ -159,7 +162,6 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) void cx18_flush_queues(struct cx18_stream *s) { - cx18_queue_flush(s, &s->q_io); cx18_queue_flush(s, &s->q_full); } diff --git a/linux/drivers/media/video/cx18/cx18-queue.h b/linux/drivers/media/video/cx18/cx18-queue.h index ff50a2b7e..d184e55ce 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.h +++ b/linux/drivers/media/video/cx18/cx18-queue.h @@ -43,9 +43,24 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s, void cx18_buf_swap(struct cx18_buffer *buf); /* cx18_queue utility functions */ -void cx18_queue_init(struct cx18_queue *q); +void _cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, + struct cx18_queue *q, int to_front); + +static inline void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, - struct cx18_queue *q); + struct cx18_queue *q) +{ + _cx18_enqueue(s, buf, q, 0); /* FIFO */ +} + +static inline +void cx18_push(struct cx18_stream *s, struct cx18_buffer *buf, + struct cx18_queue *q) +{ + _cx18_enqueue(s, buf, q, 1); /* LIFO */ +} + +void cx18_queue_init(struct cx18_queue *q); struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, u32 bytesused); diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index f7a7f38d8..67d20b062 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -138,7 +138,6 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->id = -1; cx18_queue_init(&s->q_free); cx18_queue_init(&s->q_full); - cx18_queue_init(&s->q_io); } static int cx18_prep_dev(struct cx18 *cx, int type) -- cgit v1.2.3 From b358f380079ca3db20d7409c3d39c2f5e80f871c Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 8 Dec 2008 21:02:45 -0500 Subject: cx18: Allow more than 63 capture buffers in rotation per stream From: Andy Walls cx18: Allow more than 63 capture buffers in rotation per stream. Implement q_busy to hold buffers the firmware has for use. q_free holds truly unused buffers in a pool. New buffers are given to the firmware as soon as the firmware returns one, if there are any to give to the firmware. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.h | 3 +- linux/drivers/media/video/cx18/cx18-fileops.c | 14 ++--- linux/drivers/media/video/cx18/cx18-ioctl.c | 3 +- linux/drivers/media/video/cx18/cx18-mailbox.c | 11 +--- linux/drivers/media/video/cx18/cx18-queue.c | 56 +++++++++---------- linux/drivers/media/video/cx18/cx18-queue.h | 16 +++--- linux/drivers/media/video/cx18/cx18-streams.c | 77 ++++++++++++++++++++++----- linux/drivers/media/video/cx18/cx18-streams.h | 3 ++ 8 files changed, 113 insertions(+), 70 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index f88d82348..4d56d0719 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -289,7 +289,8 @@ struct cx18_stream { /* Buffer Queues */ struct cx18_queue q_free; /* free buffers */ - struct cx18_queue q_full; /* full buffers */ + struct cx18_queue q_busy; /* busy buffers - in use by firmware */ + struct cx18_queue q_full; /* full buffers - data for user apps */ /* DVB / Digital Transport */ struct cx18_dvb dvb; diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index b298faa59..f59525565 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -225,7 +225,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { /* byteswap and process VBI data */ /* cx18_process_vbi_data(cx, buf, s_vbi->dma_pts, s_vbi->type); */ - cx18_enqueue(s_vbi, buf, &s_vbi->q_free); + cx18_stream_put_buf_fw(s_vbi, buf); } } buf = &cx->vbi.sliced_mpeg_buf; @@ -399,15 +399,9 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, tot_count - tot_written); if (buf != &cx->vbi.sliced_mpeg_buf) { - if (buf->readpos == buf->bytesused) { - cx18_buf_sync_for_device(s, buf); - cx18_enqueue(s, buf, &s->q_free); - cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, - s->handle, - (void __iomem *)&cx->scb->cpu_mdl[buf->id] - - cx->enc_mem, - 1, buf->id, s->buf_size); - } else + if (buf->readpos == buf->bytesused) + cx18_stream_put_buf_fw(s, buf); + else cx18_push(s, buf, &s->q_full); } else if (buf->readpos == buf->bytesused) { int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 5d9c1146e..85a2e5a3b 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -851,8 +851,7 @@ static int cx18_log_status(struct file *file, void *fh) continue; CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, - (s->buffers - atomic_read(&s->q_free.buffers)) - * 100 / s->buffers, + atomic_read(&s->q_full.buffers) * 100 / s->buffers, (s->buffers * s->buf_size) / 1024, s->buffers); } CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index f62aee719..2f7060cc1 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -189,16 +189,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused); - cx18_buf_sync_for_device(s, buf); - cx18_enqueue(s, buf, &s->q_free); - - if (s->handle != CX18_INVALID_TASK_HANDLE && - test_bit(CX18_F_S_STREAMING, &s->s_flags)) - cx18_vapi(cx, - CX18_CPU_DE_SET_MDL, 5, s->handle, - (void __iomem *) - &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, - 1, buf->id, s->buf_size); + cx18_stream_put_buf_fw(s, buf); } else set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); } diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index fdfc83ee3..40379d807 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -42,24 +42,32 @@ void cx18_queue_init(struct cx18_queue *q) q->bytesused = 0; } -void _cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, - struct cx18_queue *q, int to_front) +struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, + struct cx18_queue *q, int to_front) { - /* clear the buffer if it is going to be enqueued to the free queue */ - if (q == &s->q_free) { + /* clear the buffer if it is not to be enqueued to the full queue */ + if (q != &s->q_full) { buf->bytesused = 0; buf->readpos = 0; buf->b_flags = 0; buf->skipped = 0; } + mutex_lock(&s->qlock); + + /* q_busy is restricted to 63 buffers to stay within firmware limits */ + if (q == &s->q_busy && atomic_read(&q->buffers) >= 63) + q = &s->q_free; + if (to_front) list_add(&buf->list, &q->list); /* LIFO */ else list_add_tail(&buf->list, &q->list); /* FIFO */ - atomic_inc(&q->buffers); q->bytesused += buf->bytesused - buf->readpos; + atomic_inc(&q->buffers); + mutex_unlock(&s->qlock); + return q; } struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) @@ -70,9 +78,9 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) if (!list_empty(&q->list)) { buf = list_entry(q->list.next, struct cx18_buffer, list); list_del_init(q->list.next); - atomic_dec(&q->buffers); q->bytesused -= buf->bytesused - buf->readpos; buf->skipped = 0; + atomic_dec(&q->buffers); } mutex_unlock(&s->qlock); return buf; @@ -85,28 +93,30 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, struct cx18_buffer *buf; struct cx18_buffer *ret = NULL; struct list_head *p, *t; - LIST_HEAD(r); mutex_lock(&s->qlock); - list_for_each_safe(p, t, &s->q_free.list) { + list_for_each_safe(p, t, &s->q_busy.list) { buf = list_entry(p, struct cx18_buffer, list); if (buf->id != id) { buf->skipped++; - if (buf->skipped >= atomic_read(&s->q_free.buffers)-1) { + if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { /* buffer must have fallen out of rotation */ - atomic_dec(&s->q_free.buffers); - list_move_tail(&buf->list, &r); CX18_WARN("Skipped %s, buffer %d, %d " "times - it must have dropped out of " "rotation\n", s->name, buf->id, buf->skipped); + /* move it to q_free */ + list_move_tail(&buf->list, &s->q_free.list); + buf->bytesused = buf->readpos = buf->b_flags = + buf->skipped = 0; + atomic_dec(&s->q_busy.buffers); + atomic_inc(&s->q_free.buffers); } continue; } buf->bytesused = bytesused; - atomic_dec(&s->q_free.buffers); if (s->type == CX18_ENC_STREAM_TYPE_TS) { /* * TS doesn't use q_full, but for sweeping up lost @@ -116,28 +126,19 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, */ list_del_init(&buf->list); } else { - atomic_inc(&s->q_full.buffers); - s->q_full.bytesused += buf->bytesused; list_move_tail(&buf->list, &s->q_full.list); + s->q_full.bytesused += buf->bytesused; + atomic_inc(&s->q_full.buffers); } + atomic_dec(&s->q_busy.buffers); ret = buf; break; } - mutex_unlock(&s->qlock); - /* Put lost buffers back into firmware transfer rotation */ - while (!list_empty(&r)) { - buf = list_entry(r.next, struct cx18_buffer, list); - list_del_init(r.next); - cx18_enqueue(s, buf, &s->q_free); - cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, - (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, - 1, buf->id, s->buf_size); - CX18_INFO("Returning %s, buffer %d back to transfer rotation\n", - s->name, buf->id); - /* and there was much rejoicing... */ - } + /* Put more buffers into the transfer rotation from q_free, if we can */ + cx18_stream_load_fw_queue_nolock(s); + mutex_unlock(&s->qlock); return ret; } @@ -162,6 +163,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) void cx18_flush_queues(struct cx18_stream *s) { + cx18_queue_flush(s, &s->q_busy); cx18_queue_flush(s, &s->q_full); } diff --git a/linux/drivers/media/video/cx18/cx18-queue.h b/linux/drivers/media/video/cx18/cx18-queue.h index d184e55ce..456cec3bc 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.h +++ b/linux/drivers/media/video/cx18/cx18-queue.h @@ -43,21 +43,21 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s, void cx18_buf_swap(struct cx18_buffer *buf); /* cx18_queue utility functions */ -void _cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, - struct cx18_queue *q, int to_front); +struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, + struct cx18_queue *q, int to_front); static inline -void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, - struct cx18_queue *q) +struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, + struct cx18_queue *q) { - _cx18_enqueue(s, buf, q, 0); /* FIFO */ + return _cx18_enqueue(s, buf, q, 0); /* FIFO */ } static inline -void cx18_push(struct cx18_stream *s, struct cx18_buffer *buf, - struct cx18_queue *q) +struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_buffer *buf, + struct cx18_queue *q) { - _cx18_enqueue(s, buf, q, 1); /* LIFO */ + return _cx18_enqueue(s, buf, q, 1); /* LIFO */ } void cx18_queue_init(struct cx18_queue *q); diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 67d20b062..864ce1cf5 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -127,16 +127,11 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->buf_size = cx->stream_buf_size[type]; if (s->buf_size) s->buffers = max_size / s->buf_size; - if (s->buffers > 63) { - /* Each stream has a maximum of 63 buffers, - ensure we do not exceed that. */ - s->buffers = 63; - s->buf_size = (max_size / s->buffers) & ~0xfff; - } mutex_init(&s->qlock); init_waitqueue_head(&s->waitq); s->id = -1; cx18_queue_init(&s->q_free); + cx18_queue_init(&s->q_busy); cx18_queue_init(&s->q_full); } @@ -401,11 +396,61 @@ static void cx18_vbi_setup(struct cx18_stream *s) cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); } +struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, + struct cx18_buffer *buf) +{ + struct cx18 *cx = s->cx; + struct cx18_queue *q; + + /* Don't give it to the firmware, if we're not running a capture */ + if (s->handle == CX18_INVALID_TASK_HANDLE || + !test_bit(CX18_F_S_STREAMING, &s->s_flags)) + return cx18_enqueue(s, buf, &s->q_free); + + q = cx18_enqueue(s, buf, &s->q_busy); + if (q != &s->q_busy) + return q; /* The firmware has the max buffers it can handle */ + + cx18_buf_sync_for_device(s, buf); + cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, + (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, + 1, buf->id, s->buf_size); + return q; +} + +/* Must hold s->qlock when calling */ +void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s) +{ + struct cx18_buffer *buf; + struct cx18 *cx = s->cx; + + /* Move from q_free to q_busy notifying the firmware: 63 buf limit */ + while (s->handle != CX18_INVALID_TASK_HANDLE && + test_bit(CX18_F_S_STREAMING, &s->s_flags) && + atomic_read(&s->q_busy.buffers) < 63 && + !list_empty(&s->q_free.list)) { + + /* Move from q_free to q_busy */ + buf = list_entry(s->q_free.list.next, struct cx18_buffer, list); + list_move_tail(&buf->list, &s->q_busy.list); + buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; + atomic_dec(&s->q_free.buffers); + atomic_inc(&s->q_busy.buffers); + + /* Notify firmware */ + cx18_buf_sync_for_device(s, buf); + cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, + (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, + 1, buf->id, s->buf_size); + } +} + int cx18_start_v4l2_encode_stream(struct cx18_stream *s) { u32 data[MAX_MB_ARGUMENTS]; struct cx18 *cx = s->cx; struct list_head *p; + struct cx18_buffer *buf; int ts = 0; int captype = 0; @@ -488,16 +533,18 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); + /* Init all the cpu_mdls for this stream */ + cx18_flush_queues(s); + mutex_lock(&s->qlock); list_for_each(p, &s->q_free.list) { - struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); - + buf = list_entry(p, struct cx18_buffer, list); cx18_writel(cx, buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); - cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, - (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, - 1, buf->id, s->buf_size); } + cx18_stream_load_fw_queue_nolock(s); + mutex_unlock(&s->qlock); + /* begin_capture */ if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { CX18_DEBUG_WARN("Error starting capture!\n"); @@ -506,9 +553,15 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); else cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle); + clear_bit(CX18_F_S_STREAMING, &s->s_flags); + /* FIXME - CX18_F_S_STREAMOFF as well? */ cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); - /* FIXME - clean-up DSP0_INT mask, i_flags, s_flags, etc. */ + s->handle = CX18_INVALID_TASK_HANDLE; + if (atomic_read(&cx->tot_capturing) == 0) { + set_bit(CX18_F_I_EOS, &cx->i_flags); + cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK); + } return -EINVAL; } diff --git a/linux/drivers/media/video/cx18/cx18-streams.h b/linux/drivers/media/video/cx18/cx18-streams.h index 7218b1504..635d34b75 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.h +++ b/linux/drivers/media/video/cx18/cx18-streams.h @@ -29,6 +29,9 @@ int cx18_streams_register(struct cx18 *cx); void cx18_streams_cleanup(struct cx18 *cx, int unregister); /* Capture related */ +void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s); +struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, + struct cx18_buffer *buf); int cx18_start_v4l2_encode_stream(struct cx18_stream *s); int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end); -- cgit v1.2.3 From c5e1c44c0f6bebacab6b4fc91acbe1c60e479523 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 7 Dec 2008 21:30:17 -0500 Subject: cx18: Add module parameters for finer control over buffer allocations From: Andy Walls cx18: Add module parameters for finer control over buffer allocations. User now has the option of setting smaller buffers to get lower latency transfers from the encoder. User can also now set the number of buffers used for a stream explicitly. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 154 +++++++++++++++++++++++--- linux/drivers/media/video/cx18/cx18-driver.h | 12 ++ linux/drivers/media/video/cx18/cx18-dvb.c | 4 + linux/drivers/media/video/cx18/cx18-streams.c | 21 ++-- 4 files changed, 167 insertions(+), 24 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 57fcce84b..a358bcce2 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -83,12 +83,28 @@ static char secam[] = "--"; static char ntsc[] = "-"; /* Buffers */ -static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS; static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS; +static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS; +static int enc_idx_buffers = CX18_DEFAULT_ENC_IDX_BUFFERS; static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS; static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS; static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS; +static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE; +static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE; +static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE; +static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE; +/* VBI bufsize based on standards supported by card tuner for now */ +static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE; + +static int enc_ts_bufs = -1; +static int enc_mpg_bufs = -1; +static int enc_idx_bufs = -1; +static int enc_yuv_bufs = -1; +static int enc_vbi_bufs = -1; +static int enc_pcm_bufs = -1; + + static int cx18_pci_latency = 1; static int mmio_ndelay; @@ -108,12 +124,27 @@ module_param(retry_mmio, int, 0644); module_param(cx18_pci_latency, int, 0644); module_param(cx18_first_minor, int, 0644); -module_param(enc_mpg_buffers, int, 0644); module_param(enc_ts_buffers, int, 0644); +module_param(enc_mpg_buffers, int, 0644); +module_param(enc_idx_buffers, int, 0644); module_param(enc_yuv_buffers, int, 0644); module_param(enc_vbi_buffers, int, 0644); module_param(enc_pcm_buffers, int, 0644); +module_param(enc_ts_bufsize, int, 0644); +module_param(enc_mpg_bufsize, int, 0644); +module_param(enc_idx_bufsize, int, 0644); +module_param(enc_yuv_bufsize, int, 0644); +/* VBI bufsize based on standards supported by card tuner for now */ +module_param(enc_pcm_bufsize, int, 0644); + +module_param(enc_ts_bufs, int, 0644); +module_param(enc_mpg_bufs, int, 0644); +module_param(enc_idx_bufs, int, 0644); +module_param(enc_yuv_bufs, int, 0644); +module_param(enc_vbi_bufs, int, 0644); +module_param(enc_pcm_bufs, int, 0644); + MODULE_PARM_DESC(tuner, "Tuner type selection,\n" "\t\t\tsee tuner.h for values"); MODULE_PARM_DESC(radio, @@ -154,21 +185,57 @@ MODULE_PARM_DESC(retry_mmio, MODULE_PARM_DESC(mmio_ndelay, "(Deprecated) MMIO accesses are now never purposely delayed\n" "\t\t\tEffectively: 0 ns"); -MODULE_PARM_DESC(enc_mpg_buffers, - "Encoder MPG Buffers (in MB)\n" - "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); MODULE_PARM_DESC(enc_ts_buffers, - "Encoder TS Buffers (in MB)\n" + "Encoder TS buffer memory (MB). (enc_ts_bufs can override)\n" "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS)); +MODULE_PARM_DESC(enc_ts_bufsize, + "Size of an encoder TS buffer (kB)\n" + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFSIZE)); +MODULE_PARM_DESC(enc_ts_bufs, + "Number of encoder TS buffers\n" + "\t\t\tDefault is computed from other enc_ts_* parameters"); +MODULE_PARM_DESC(enc_mpg_buffers, + "Encoder MPG buffer memory (MB). (enc_mpg_bufs can override)\n" + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); +MODULE_PARM_DESC(enc_mpg_bufsize, + "Size of an encoder MPG buffer (kB)\n" + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFSIZE)); +MODULE_PARM_DESC(enc_mpg_bufs, + "Number of encoder MPG buffers\n" + "\t\t\tDefault is computed from other enc_mpg_* parameters"); +MODULE_PARM_DESC(enc_idx_buffers, + "Encoder IDX buffer memory (MB). (enc_idx_bufs can override)\n" + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFFERS)); +MODULE_PARM_DESC(enc_idx_bufsize, + "Size of an encoder IDX buffer (kB)\n" + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFSIZE)); +MODULE_PARM_DESC(enc_idx_bufs, + "Number of encoder IDX buffers\n" + "\t\t\tDefault is computed from other enc_idx_* parameters"); MODULE_PARM_DESC(enc_yuv_buffers, - "Encoder YUV Buffers (in MB)\n" + "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n" "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); +MODULE_PARM_DESC(enc_yuv_bufsize, + "Size of an encoder YUV buffer (kB)\n" + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFSIZE)); +MODULE_PARM_DESC(enc_yuv_bufs, + "Number of encoder YUV buffers\n" + "\t\t\tDefault is computed from other enc_yuv_* parameters"); MODULE_PARM_DESC(enc_vbi_buffers, - "Encoder VBI Buffers (in MB)\n" + "Encoder VBI buffer memory (MB). (enc_vbi_bufs can override)\n" "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS)); +MODULE_PARM_DESC(enc_vbi_bufs, + "Number of encoder VBI buffers\n" + "\t\t\tDefault is computed from enc_vbi_buffers & tuner std"); MODULE_PARM_DESC(enc_pcm_buffers, - "Encoder PCM buffers (in MB)\n" + "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n" "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); +MODULE_PARM_DESC(enc_pcm_bufsize, + "Size of an encoder PCM buffer (kB)\n" + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFSIZE)); +MODULE_PARM_DESC(enc_pcm_bufs, + "Number of encoder PCM buffers\n" + "\t\t\tDefault is computed from other enc_pcm_* parameters"); MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card"); @@ -361,11 +428,65 @@ static void cx18_process_options(struct cx18 *cx) { int i, j; - cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers; cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers; + cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers; + cx->options.megabytes[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_buffers; cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers; cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers; cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers; + cx->options.megabytes[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control only */ + + cx->stream_buffers[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufs; + cx->stream_buffers[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufs; + cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufs; + cx->stream_buffers[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufs; + cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_bufs; + cx->stream_buffers[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufs; + cx->stream_buffers[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control, no data */ + + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufsize; + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize; + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize; + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize; + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = 0; /* computed later */ + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize; + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */ + + /* Except for VBI ensure stream_buffers & stream_buf_size are valid */ + for (i = 0; i < CX18_MAX_STREAMS; i++) { + /* User said to use 0 buffers */ + if (cx->stream_buffers[i] == 0) { + cx->options.megabytes[i] = 0; + cx->stream_buf_size[i] = 0; + continue; + } + /* User said to use 0 MB total */ + if (cx->options.megabytes[i] <= 0) { + cx->options.megabytes[i] = 0; + cx->stream_buffers[i] = 0; + cx->stream_buf_size[i] = 0; + continue; + } + /* VBI is computed later or user said buffer has size 0 */ + if (cx->stream_buf_size[i] <= 0) { + if (i != CX18_ENC_STREAM_TYPE_VBI) { + cx->options.megabytes[i] = 0; + cx->stream_buffers[i] = 0; + cx->stream_buf_size[i] = 0; + } + continue; + } + if (cx->stream_buffers[i] < 0) { + cx->stream_buffers[i] = cx->options.megabytes[i] * 1024 + / cx->stream_buf_size[i]; + } else { + /* N.B. This might round down to 0 */ + cx->options.megabytes[i] = + cx->stream_buffers[i] * cx->stream_buf_size[i] / 1024; + } + cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */ + } + cx->options.cardtype = cardtype[cx->num]; cx->options.tuner = tuner[cx->num]; cx->options.radio = radio[cx->num]; @@ -773,13 +894,18 @@ static int __devinit cx18_probe(struct pci_dev *dev, } cx->params.video_gop_size = cx->is_60hz ? 15 : 12; - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = 0x08000; - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = 0x08000; - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = 0x01200; - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = 0x20000; vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; + if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0) + cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = + cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] * 1024 * 1024 + / vbi_buf_size; + else + cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = + cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] * vbi_buf_size + / (1024 * 1024); + if (cx->options.radio > 0) cx->v4l2_cap |= V4L2_CAP_RADIO; diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 4d56d0719..29c296f39 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -115,6 +115,17 @@ #define CX18_DEFAULT_ENC_VBI_BUFFERS 1 #define CX18_DEFAULT_ENC_PCM_BUFFERS 1 +/* Maximum firmware DMA buffers per stream */ +#define CX18_MAX_MDLS_PER_STREAM 63 + +/* DMA buffer, default size in kB allocated */ +#define CX18_DEFAULT_ENC_TS_BUFSIZE 32 +#define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 +#define CX18_DEFAULT_ENC_IDX_BUFSIZE 32 +#define CX18_DEFAULT_ENC_YUV_BUFSIZE 128 +/* Default VBI bufsize based on standards supported by card tuner for now */ +#define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 + /* i2c stuff */ #define I2C_CLIENTS_MAX 16 @@ -408,6 +419,7 @@ struct cx18 { struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ struct cx18_options options; /* User options */ + int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */ int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ unsigned long i_flags; /* global cx18 flags */ diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c index 034e09a37..bd5e6f3fd 100644 --- a/linux/drivers/media/video/cx18/cx18-dvb.c +++ b/linux/drivers/media/video/cx18/cx18-dvb.c @@ -217,6 +217,10 @@ int cx18_dvb_register(struct cx18_stream *stream) dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx); CX18_INFO("DVB Frontend registered\n"); + CX18_INFO("Registered DVB adapter%d for %s (%d x %d kB)\n", + stream->dvb.dvb_adapter.num, stream->name, + stream->buffers, stream->buf_size/1024); + mutex_init(&dvb->feedlock); dvb->enabled = 1; return ret; diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 864ce1cf5..c80f361c8 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -111,7 +111,6 @@ static void cx18_stream_init(struct cx18 *cx, int type) { struct cx18_stream *s = &cx->streams[type]; struct video_device *dev = s->v4l2dev; - u32 max_size = cx->options.megabytes[type] * 1024 * 1024; /* we need to keep v4l2dev, so restore it afterwards */ memset(s, 0, sizeof(*s)); @@ -124,9 +123,9 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->handle = CX18_INVALID_TASK_HANDLE; s->dma = cx18_stream_info[type].dma; + s->buffers = cx->stream_buffers[type]; s->buf_size = cx->stream_buf_size[type]; - if (s->buf_size) - s->buffers = max_size / s->buf_size; + mutex_init(&s->qlock); init_waitqueue_head(&s->waitq); s->id = -1; @@ -162,7 +161,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) /* User explicitly selected 0 buffers for these streams, so don't create them. */ if (cx18_stream_info[type].dma != PCI_DMA_NONE && - cx->options.megabytes[type] == 0) { + cx->stream_buffers[type] == 0) { CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name); return 0; } @@ -262,8 +261,9 @@ static int cx18_reg_dev(struct cx18 *cx, int type) switch (vfl_type) { case VFL_TYPE_GRABBER: - CX18_INFO("Registered device video%d for %s (%d MB)\n", - num, s->name, cx->options.megabytes[type]); + CX18_INFO("Registered device video%d for %s (%d x %d kB)\n", + num, s->name, cx->stream_buffers[type], + cx->stream_buf_size[type]/1024); break; case VFL_TYPE_RADIO: @@ -272,10 +272,11 @@ static int cx18_reg_dev(struct cx18 *cx, int type) break; case VFL_TYPE_VBI: - if (cx->options.megabytes[type]) - CX18_INFO("Registered device vbi%d for %s (%d MB)\n", - num, - s->name, cx->options.megabytes[type]); + if (cx->stream_buffers[type]) + CX18_INFO("Registered device vbi%d for %s " + "(%d x %d bytes)\n", + num, s->name, cx->stream_buffers[type], + cx->stream_buf_size[type]); else CX18_INFO("Registered device vbi%d for %s\n", num, s->name); -- cgit v1.2.3 From e5df23b4a1dac3d29cb3f3713ecebbac3fd550d1 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 8 Dec 2008 21:14:46 -0500 Subject: cx18: Increment version number due to siginificant buffering changes From: Andy Walls cx18: Increment version number due to siginificant buffering changes. Now version 1.0.4 Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/cx18/cx18-version.h b/linux/drivers/media/video/cx18/cx18-version.h index eb043d599..84c0ff13b 100644 --- a/linux/drivers/media/video/cx18/cx18-version.h +++ b/linux/drivers/media/video/cx18/cx18-version.h @@ -25,7 +25,7 @@ #define CX18_DRIVER_NAME "cx18" #define CX18_DRIVER_VERSION_MAJOR 1 #define CX18_DRIVER_VERSION_MINOR 0 -#define CX18_DRIVER_VERSION_PATCHLEVEL 3 +#define CX18_DRIVER_VERSION_PATCHLEVEL 4 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \ -- cgit v1.2.3 From a00ab36aaa26baf7d88c5763300d06dc47327148 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 12 Dec 2008 13:50:27 -0500 Subject: cx18: Avoid making firmware API calls with the queue lock held From: Andy Walls cx18: Avoid making firmware API calls with the queue lock held. The source of MPEG strem corruption when not holding the queue lock was found to be that the MPEG buffer could be retrieved by the user app before it was sync'ed for the host cpu. Incoming buffers are now sync'ed before being put on q_full and releasing the queue lock. We can thus avoid the sometimes lengthy call to the firmware for CPU_DE_SET_MDL while holding the queue lock, so we can get better performance. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-mailbox.c | 15 ++++++----- linux/drivers/media/video/cx18/cx18-queue.c | 13 +++++----- linux/drivers/media/video/cx18/cx18-streams.c | 37 ++++++++++----------------- linux/drivers/media/video/cx18/cx18-streams.h | 2 +- 4 files changed, 30 insertions(+), 37 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index 2f7060cc1..eb5c31af6 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -163,7 +163,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) * it's filled in). * * cx18_queue_get buf() will detect the lost buffers - * and put them back in rotation eventually. + * and send them back to q_free for fw rotation eventually. */ if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) && !(id >= s->mdl_offset && @@ -174,24 +174,27 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) break; } buf = cx18_queue_get_buf(s, id, mdl_ack->data_used); + CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); if (buf == NULL) { CX18_WARN("Could not find buf %d for stream %s\n", id, s->name); + /* Put as many buffers as possible back into fw use */ + cx18_stream_load_fw_queue(s); continue; } - cx18_buf_sync_for_cpu(s, buf); if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n", buf->bytesused); - dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused); - + } + /* Put as many buffers as possible back into fw use */ + cx18_stream_load_fw_queue(s); + /* Put back TS buffer, since it was removed from all queues */ + if (s->type == CX18_ENC_STREAM_TYPE_TS) cx18_stream_put_buf_fw(s, buf); - } else - set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); } wake_up(&cx->dma_waitq); if (s->id != -1) diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index 40379d807..a6b0666f0 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -117,16 +117,18 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, } buf->bytesused = bytesused; + /* Sync the buffer before we release the qlock */ + cx18_buf_sync_for_cpu(s, buf); if (s->type == CX18_ENC_STREAM_TYPE_TS) { /* - * TS doesn't use q_full, but for sweeping up lost - * buffers, we want the TS to requeue the buffer just - * before sending the MDL back to the firmware, so we - * pull it off the list here. + * TS doesn't use q_full. As we pull the buffer off of + * the queue here, the caller will have to put it back. */ list_del_init(&buf->list); } else { + /* Move buffer from q_busy to q_full */ list_move_tail(&buf->list, &s->q_full.list); + set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); s->q_full.bytesused += buf->bytesused; atomic_inc(&s->q_full.buffers); } @@ -135,9 +137,6 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, ret = buf; break; } - - /* Put more buffers into the transfer rotation from q_free, if we can */ - cx18_stream_load_fw_queue_nolock(s); mutex_unlock(&s->qlock); return ret; } diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index c80f361c8..7dc5b82f1 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -419,31 +419,22 @@ struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, return q; } -/* Must hold s->qlock when calling */ -void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s) +void cx18_stream_load_fw_queue(struct cx18_stream *s) { + struct cx18_queue *q; struct cx18_buffer *buf; - struct cx18 *cx = s->cx; - /* Move from q_free to q_busy notifying the firmware: 63 buf limit */ - while (s->handle != CX18_INVALID_TASK_HANDLE && - test_bit(CX18_F_S_STREAMING, &s->s_flags) && - atomic_read(&s->q_busy.buffers) < 63 && - !list_empty(&s->q_free.list)) { - - /* Move from q_free to q_busy */ - buf = list_entry(s->q_free.list.next, struct cx18_buffer, list); - list_move_tail(&buf->list, &s->q_busy.list); - buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; - atomic_dec(&s->q_free.buffers); - atomic_inc(&s->q_busy.buffers); - - /* Notify firmware */ - cx18_buf_sync_for_device(s, buf); - cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, - (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, - 1, buf->id, s->buf_size); - } + if (atomic_read(&s->q_free.buffers) == 0 || + atomic_read(&s->q_busy.buffers) >= 63) + return; + + /* Move from q_free to q_busy notifying the firmware, until the limit */ + do { + buf = cx18_dequeue(s, &s->q_free); + if (buf == NULL) + break; + q = cx18_stream_put_buf_fw(s, buf); + } while (atomic_read(&s->q_busy.buffers) < 63 && q == &s->q_busy); } int cx18_start_v4l2_encode_stream(struct cx18_stream *s) @@ -543,8 +534,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) &cx->scb->cpu_mdl[buf->id].paddr); cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); } - cx18_stream_load_fw_queue_nolock(s); mutex_unlock(&s->qlock); + cx18_stream_load_fw_queue(s); /* begin_capture */ if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { diff --git a/linux/drivers/media/video/cx18/cx18-streams.h b/linux/drivers/media/video/cx18/cx18-streams.h index 635d34b75..420e0a172 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.h +++ b/linux/drivers/media/video/cx18/cx18-streams.h @@ -29,7 +29,7 @@ int cx18_streams_register(struct cx18 *cx); void cx18_streams_cleanup(struct cx18 *cx, int unregister); /* Capture related */ -void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s); +void cx18_stream_load_fw_queue(struct cx18_stream *s); struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, struct cx18_buffer *buf); int cx18_start_v4l2_encode_stream(struct cx18_stream *s); -- cgit v1.2.3 From 4b1de397a8c3dfe7e1f5e1b3165b70fb0193f099 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 12 Dec 2008 14:24:04 -0500 Subject: cx18: Port fix for raw/sliced VBI mixup from ivtv and cx25840 From: Andy Walls This is a port of the fixes Hans Verkuil made for ivtv/cx25840: The service_set field was used to determine whether raw or sliced VBI was desired. This is incorrect since it is perfectly valid to select sliced VBI with a service_set of 0. Instead the driver should check on VIDIOC_S_FMT whether the type field matches the raw or sliced VBI type. Updated the cx18 driver accordingly, including an additional check in cx18_start_v4l2_encode_stream() that didn't exist in ivtv. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-vbi.c | 5 +++-- linux/drivers/media/video/cx18/cx18-driver.c | 2 +- linux/drivers/media/video/cx18/cx18-driver.h | 6 ++++++ linux/drivers/media/video/cx18/cx18-fileops.c | 10 ++++------ linux/drivers/media/video/cx18/cx18-ioctl.c | 11 +++++------ linux/drivers/media/video/cx18/cx18-streams.c | 6 +++--- linux/drivers/media/video/cx18/cx18-vbi.c | 2 +- 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index 02fdf57bb..1527ea4f6 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -141,10 +141,11 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) u8 lcr[24]; fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && + fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) return -EINVAL; svbi = &fmt->fmt.sliced; - if (svbi->service_set == 0) { + if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { /* raw VBI */ memset(svbi, 0, sizeof(*svbi)); diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index a358bcce2..6f1654945 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -599,7 +599,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) init_waitqueue_head(&cx->dma_waitq); /* VBI */ - cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; + cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; cx->vbi.raw_size = 1456; cx->vbi.raw_decoder_line_size = 1456; diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 29c296f39..018d98f94 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -504,4 +504,10 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); /* First-open initialization: load firmware, etc. */ int cx18_init_on_first_open(struct cx18 *cx); +/* Test if the current VBI mode is raw (1) or sliced (0) */ +static inline int cx18_raw_vbi(const struct cx18 *cx) +{ + return cx->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE; +} + #endif /* CX18_DRIVER_H */ diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index f59525565..ade4c66ba 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -67,12 +67,11 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type) } s->id = id->open_id; - /* CX18_DEC_STREAM_TYPE_MPG needs to claim CX18_DEC_STREAM_TYPE_VBI, - CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI + /* CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI (provided VBI insertion is on and sliced VBI is selected), for all other streams we're done */ if (type == CX18_ENC_STREAM_TYPE_MPG && - cx->vbi.insert_mpeg && cx->vbi.sliced_in->service_set) { + cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) { vbi_type = CX18_ENC_STREAM_TYPE_VBI; } else { return 0; @@ -296,7 +295,7 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, if (len > ucount) len = ucount; if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && - cx->vbi.sliced_in->service_set && buf != &cx->vbi.sliced_mpeg_buf) { + !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) { const char *start = buf->buf + buf->readpos; const char *p = start + 1; const u8 *q; @@ -371,8 +370,7 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should arrive one-by-one, so make sure we never output more than one VBI frame at a time */ - if (s->type == CX18_ENC_STREAM_TYPE_VBI && - cx->vbi.sliced_in->service_set) + if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx)) single_frame = 1; for (;;) { diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 85a2e5a3b..c83fcc0c5 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -284,13 +284,12 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, if (ret) return ret; - if (id->type == CX18_ENC_STREAM_TYPE_VBI && - cx->vbi.sliced_in->service_set && - atomic_read(&cx->ana_capturing) > 0) + if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) return -EBUSY; cx->vbi.sliced_in->service_set = 0; - cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); + cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; + cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); return cx18_g_fmt_vbi_cap(file, fh, fmt); } @@ -315,9 +314,9 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, if (check_service_set(vbifmt, cx->is_50hz) == 0) return -EINVAL; - if (atomic_read(&cx->ana_capturing) > 0 && - cx->vbi.sliced_in->service_set == 0) + if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) return -EBUSY; + cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); return 0; diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 7dc5b82f1..081131fab 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -340,7 +340,7 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) static void cx18_vbi_setup(struct cx18_stream *s) { struct cx18 *cx = s->cx; - int raw = cx->vbi.sliced_in->service_set == 0; + int raw = cx18_raw_vbi(cx); u32 data[CX2341X_MBOX_MAX_DATA]; int lines; @@ -471,8 +471,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) captype = CAPTURE_CHANNEL_TYPE_PCM; break; case CX18_ENC_STREAM_TYPE_VBI: - captype = cx->vbi.sliced_in->service_set ? - CAPTURE_CHANNEL_TYPE_SLICED_VBI : CAPTURE_CHANNEL_TYPE_VBI; + captype = cx18_raw_vbi(cx) ? + CAPTURE_CHANNEL_TYPE_VBI : CAPTURE_CHANNEL_TYPE_SLICED_VBI; cx->vbi.frame = 0; cx->vbi.inserted_frame = 0; memset(cx->vbi.sliced_mpeg_size, diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index 22e76ee3f..03f0e8130 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -160,7 +160,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, return; /* Raw VBI data */ - if (cx->vbi.sliced_in->service_set == 0) { + if (cx18_raw_vbi(cx)) { u8 type; cx18_buf_swap(buf); -- cgit v1.2.3 From 61a2de789c256e6a8c6c184ed07b18f06b19e1dd Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 12 Dec 2008 18:00:29 -0500 Subject: cx18: Enable raw VBI capture From: Andy Walls A combined authorship patch from Hans Verkuil and Andy Walls. Raw VBI can now be captured but requires a video capture to be in progress as well. Priority: normal Signed-off-by: Andy Walls Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx18/cx18-cards.c | 8 ++--- linux/drivers/media/video/cx18/cx18-cards.h | 5 +-- linux/drivers/media/video/cx18/cx18-driver.c | 49 +++++++++++++++++++++++---- linux/drivers/media/video/cx18/cx18-fileops.c | 4 ++- linux/drivers/media/video/cx18/cx18-streams.c | 8 ++--- linux/drivers/media/video/cx18/cx18-vbi.c | 3 ++ 6 files changed, 59 insertions(+), 18 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index 23bd871b7..10cddba3e 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -51,7 +51,7 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { static const struct cx18_card cx18_card_hvr1600_esmt = { .type = CX18_CARD_HVR_1600_ESMT, .name = "Hauppauge HVR-1600", - .comment = "VBI is not yet supported\n", + .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, @@ -97,7 +97,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { static const struct cx18_card cx18_card_hvr1600_samsung = { .type = CX18_CARD_HVR_1600_SAMSUNG, .name = "Hauppauge HVR-1600 (Preproduction)", - .comment = "VBI is not yet supported\n", + .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, @@ -152,7 +152,7 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = { static const struct cx18_card cx18_card_h900 = { .type = CX18_CARD_COMPRO_H900, .name = "Compro VideoMate H900", - .comment = "VBI is not yet supported\n", + .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_all = CX18_HW_TUNER, @@ -249,7 +249,7 @@ static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = { static const struct cx18_card cx18_card_cnxt_raptor_pal = { .type = CX18_CARD_CNXT_RAPTOR_PAL, .name = "Conexant Raptor PAL/SECAM", - .comment = "VBI is not yet supported\n", + .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_GPIO, diff --git a/linux/drivers/media/video/cx18/cx18-cards.h b/linux/drivers/media/video/cx18/cx18-cards.h index a54aae9ed..6fa7bcb42 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.h +++ b/linux/drivers/media/video/cx18/cx18-cards.h @@ -48,8 +48,9 @@ /* V4L2 capability aliases */ #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ - V4L2_CAP_AUDIO | V4L2_CAP_READWRITE) -/* | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */ + V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \ + V4L2_CAP_VBI_CAPTURE) +/* | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */ struct cx18_card_video_input { u8 video_type; /* video input type */ diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 6f1654945..cea4735b6 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -601,13 +601,47 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) /* VBI */ cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; - cx->vbi.raw_size = 1456; - cx->vbi.raw_decoder_line_size = 1456; - cx->vbi.raw_decoder_sav_odd_field = 0x20; - cx->vbi.raw_decoder_sav_even_field = 0x60; - cx->vbi.sliced_decoder_line_size = 272; - cx->vbi.sliced_decoder_sav_odd_field = 0xB0; - cx->vbi.sliced_decoder_sav_even_field = 0xF0; + + /* + * The VBI line sizes depend on the pixel clock and the horiz rate + * + * (1/Fh)*(2*Fp) = Samples/line + * = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples + * + * Sliced VBI is sent as ancillary data during horizontal blanking + * Raw VBI is sent as active video samples during vertcal blanking + * + * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line + * length of 720 pixels @ 4:2:2 sampling. Thus... + * + * For NTSC: + * + * (1/15,734 kHz) * 2 * 13.5 MHz = 1716 samples/line = + * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples + * + * For PAL: + * + * (1/15,625 kHz) * 2 * 13.5 MHz = 1728 samples/line = + * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples + * + */ + + /* CX18-AV-Core number of VBI samples output per horizontal line */ + cx->vbi.raw_decoder_line_size = 1444; /* 4 byte SAV + 2 * 720 */ + cx->vbi.sliced_decoder_line_size = 272; /* 60 Hz: 268+4, 50 Hz: 280+4 */ + + /* CX18-AV-Core VBI samples/line possibly rounded up */ + cx->vbi.raw_size = 1444; /* Real max size is 1444 */ + cx->vbi.sliced_size = 284; /* Real max size is 284 */ + + /* + * CX18-AV-Core SAV/EAV RP codes in VIP 1.x mode + * Task Field VerticalBlank HorizontalBlank 0 0 0 0 + */ + cx->vbi.raw_decoder_sav_odd_field = 0x20; /* V */ + cx->vbi.raw_decoder_sav_even_field = 0x60; /* FV */ + cx->vbi.sliced_decoder_sav_odd_field = 0xB0; /* T VH - actually EAV */ + cx->vbi.sliced_decoder_sav_even_field = 0xF0; /* TFVH - actually EAV */ return 0; } @@ -640,6 +674,7 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) cx->av_state.aud_input = CX18_AV_AUDIO8; cx->av_state.audclk_freq = 48000; cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; + /* FIXME - 8 is NTSC value, investigate */ cx->av_state.vbi_line_offset = 8; } diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index ade4c66ba..ef4589ef6 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -223,7 +223,9 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { /* byteswap and process VBI data */ -/* cx18_process_vbi_data(cx, buf, s_vbi->dma_pts, s_vbi->type); */ + cx18_process_vbi_data(cx, buf, + s_vbi->dma_pts, + s_vbi->type); cx18_stream_put_buf_fw(s_vbi, buf); } } diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 081131fab..9ed542624 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -358,8 +358,7 @@ static void cx18_vbi_setup(struct cx18_stream *s) cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); /* determine number of lines and total number of VBI bytes. - A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1 - The '- 1' byte is probably an unused U or V byte. Or something... + A raw line takes 1444 bytes: 4 byte SAV code + 2 * 720 A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal header, 42 data bytes + checksum (to be confirmed) */ if (raw) { @@ -377,14 +376,15 @@ static void cx18_vbi_setup(struct cx18_stream *s) /* Lines per field */ data[1] = (lines / 2) | ((lines / 2) << 16); /* bytes per line */ - data[2] = (raw ? cx->vbi.raw_size : cx->vbi.sliced_size); + data[2] = (raw ? cx->vbi.raw_decoder_line_size + : cx->vbi.sliced_decoder_line_size); /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */ data[3] = 1; /* Setup VBI for the cx25840 digitizer */ if (raw) { data[4] = 0x20602060; - data[5] = 0x30703070; + data[5] = 0x307090d0; } else { data[4] = 0xB0F0B0F0; data[5] = 0xA0E0A0E0; diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index 03f0e8130..fb595bd54 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -165,6 +165,9 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, cx18_buf_swap(buf); + /* Skip 12 bytes of header that gets stuffed in */ + size -= 12; + memcpy(p, &buf->buf[12], size); type = p[3]; size = buf->bytesused = compress_raw_buf(cx, p, size); -- cgit v1.2.3 From 4d8582967a124a215baac71664035b0d6d4a346f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 25 Nov 2008 22:26:38 +0100 Subject: uvcvideo: Prevent compat.h from being included in userspace code. From: Laurent Pinchart When used in userspace code, the uvcvideo.h header shouldn't pull compat.h. Make sure this won't happen by moving the #include to a __KERNEL__ protected section. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvcvideo.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index f95040380..09b169b69 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -4,8 +4,6 @@ #include #include -#include "compat.h" - /* * Dynamic controls */ @@ -69,6 +67,7 @@ struct uvc_xu_control { #ifdef __KERNEL__ #include +#include "compat.h" /* -------------------------------------------------------------------------- * UVC constants -- cgit v1.2.3 From 53397dd1cc3dab09ffcc5805bfa3c22c09b567fc Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 25 Nov 2008 19:43:05 -0500 Subject: cx18: Change to per CX23418 device work queues for deferrable work handling From: Andy Walls cx18: Change to per CX23418 device work queues for deferrable work handling. Needed to support 2.6.22 and earlier kernels that can't selectively cancel work orders. Also will provide slightly better performance on SMP systems. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 33 ++++++++++----------------- linux/drivers/media/video/cx18/cx18-driver.h | 2 +- linux/drivers/media/video/cx18/cx18-mailbox.c | 2 +- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 1fa9a670b..198fdf9a6 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -56,9 +56,6 @@ struct cx18 *cx18_cards[CX18_MAX_CARDS]; /* Protects cx18_cards_active */ DEFINE_SPINLOCK(cx18_cards_lock); -/* Queue for deferrable IRQ handling work for all cx18 cards in system */ -struct workqueue_struct *cx18_work_queue; - /* add your revision and whatnot here */ static struct pci_device_id cx18_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, @@ -446,6 +443,12 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) spin_lock_init(&cx->lock); + cx->work_queue = create_singlethread_workqueue(cx->name); + if (cx->work_queue == NULL) { + CX18_ERR("Unable to create work hander thread\n"); + return -ENOMEM; + } + for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) { cx->epu_work_order[i].cx = cx; cx->epu_work_order[i].str = cx->epu_debug_str; @@ -660,12 +663,9 @@ static int __devinit cx18_probe(struct pci_dev *dev, /* PCI Device Setup */ retval = cx18_setup_pci(cx, dev, pci_id); - if (retval != 0) { - if (retval == -EIO) - goto free_workqueue; - else if (retval == -ENXIO) - goto free_mem; - } + if (retval != 0) + goto free_workqueue; + /* save cx in the pci struct for later use */ pci_set_drvdata(dev, cx); @@ -835,6 +835,7 @@ free_map: free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); free_workqueue: + destroy_workqueue(cx->work_queue); err: if (retval == 0) retval = -ENODEV; @@ -943,6 +944,8 @@ static void cx18_remove(struct pci_dev *pci_dev) cx18_cancel_epu_work_orders(cx); + destroy_workqueue(cx->work_queue); + cx18_streams_cleanup(cx, 1); exit_cx18_i2c(cx); @@ -984,17 +987,8 @@ static int module_start(void) printk(KERN_INFO "cx18: Debug value must be >= 0 and <= 511!\n"); } - cx18_work_queue = create_singlethread_workqueue("cx18"); - if (cx18_work_queue == NULL) { - printk(KERN_ERR - "cx18: Unable to create work hander thread\n"); - return -ENOMEM; - } - if (pci_register_driver(&cx18_pci_driver)) { printk(KERN_ERR "cx18: Error detecting PCI card\n"); - destroy_workqueue(cx18_work_queue); - cx18_work_queue = NULL; return -ENODEV; } printk(KERN_INFO "cx18: End initialization\n"); @@ -1007,9 +1001,6 @@ static void module_cleanup(void) pci_unregister_driver(&cx18_pci_driver); - destroy_workqueue(cx18_work_queue); - cx18_work_queue = NULL; - for (i = 0; i < cx18_cards_active; i++) { if (cx18_cards[i] == NULL) continue; diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index ca1f43781..94c196a91 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -447,6 +447,7 @@ struct cx18 { u32 sw2_irq_mask; u32 hw2_irq_mask; + struct workqueue_struct *work_queue; struct cx18_epu_work_order epu_work_order[CX18_MAX_EPU_WORK_ORDERS]; char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */ @@ -478,7 +479,6 @@ extern struct cx18 *cx18_cards[]; extern int cx18_cards_active; extern int cx18_first_minor; extern spinlock_t cx18_cards_lock; -extern struct workqueue_struct *cx18_work_queue; /*==============Prototypes==================*/ diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index 8415b9683..f62aee719 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -460,7 +460,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu) */ submit = epu_cmd_irq(cx, order); if (submit > 0) { - queue_work(cx18_work_queue, &order->work); + queue_work(cx->work_queue, &order->work); } } -- cgit v1.2.3 From 96b9b00e9e8f7771c45723ec0c869db9f2260585 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 25 Nov 2008 20:02:45 -0500 Subject: cx18: Change work_queue teardown to work for kernels earlier than 2.6.22 From: Andy Walls For kernels earlier than 2.6.22, we can't cancel work, so we have to flush the work queue to completion before destroying it. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 11 +++++++++++ v4l/versions.txt | 2 -- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 198fdf9a6..57fcce84b 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -918,6 +918,7 @@ int cx18_init_on_first_open(struct cx18 *cx) return 0; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) static void cx18_cancel_epu_work_orders(struct cx18 *cx) { int i; @@ -925,6 +926,7 @@ static void cx18_cancel_epu_work_orders(struct cx18 *cx) cancel_work_sync(&cx->epu_work_order[i].work); } +#endif static void cx18_remove(struct pci_dev *pci_dev) { struct cx18 *cx = pci_get_drvdata(pci_dev); @@ -938,11 +940,20 @@ static void cx18_remove(struct pci_dev *pci_dev) /* Interrupts */ cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); cx18_halt_firmware(cx); cx18_cancel_epu_work_orders(cx); +#else + + flush_workqueue(cx->work_queue); + + cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); + + cx18_halt_firmware(cx); +#endif destroy_workqueue(cx->work_queue); diff --git a/v4l/versions.txt b/v4l/versions.txt index c09b5d69a..3ef9af5d8 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -20,8 +20,6 @@ USB_STKWEBCAM DVB_DRX397XD # Assumes struct input_dev has a dev field DVB_DM1105 -# Need cancel_work_sync -VIDEO_CX18 [2.6.20] #This driver requires HID_REQ_GET_REPORT -- cgit v1.2.3 From ce2cf97b4e1f9afaa1793ab9f2b23336974569b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 26 Nov 2008 08:01:40 +0100 Subject: First step into unifying the read and write sensor functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 44 ++++++++++++++++++++++ .../media/video/gspca/m5602/m5602_mt9m111.h | 1 + .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 1 + .../drivers/media/video/gspca/m5602/m5602_po1030.h | 1 + .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 1 + .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 1 + .../drivers/media/video/gspca/m5602/m5602_sensor.h | 3 ++ 7 files changed, 52 insertions(+) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 0599b4936..d68037af6 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -80,6 +80,50 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) return (err < 0) ? err : 0; } +int m5602_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + u8 *p; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + /* No sensor with a data width larger than 16 bits has yet been seen */ + if (len > sd->sensor->i2c_regW || !len) + return -EINVAL; + + memcpy(buf, sensor_urb_skeleton, + sizeof(sensor_urb_skeleton)); + + buf[11] = sd->sensor->i2c_slave_id; + buf[15] = address; + + /* Special case larger sensor writes */ + p = buf + 16; + + /* Copy a four byte write sequence for each byte to be written to */ + for (i = 0; i < len; i++) { + memcpy(p, sensor_urb_skeleton + 16, 4); + p[3] = i2c_data[i]; + p += 4; + PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", + address, i2c_data[i]); + } + + /* Copy the tailer */ + memcpy(p, sensor_urb_skeleton + 20, 4); + + /* Set the total length */ + p[3] = 0x10 + len; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x19, + 0x0000, buf, + 20 + len * 4, M5602_URB_MSG_TIMEOUT); + + return (err < 0) ? err : 0; +} + /* Dump all the registers of the m5602 bridge, unfortunately this breaks the camera until it's power cycled */ static void m5602_dump_bridge(struct sd *sd) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 0fe4d6327..2c7b2a49c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -104,6 +104,7 @@ static struct m5602_sensor mt9m111 = { .name = "MT9M111", .i2c_slave_id = 0xba, + .i2c_regW = 2, .probe = mt9m111_probe, .init = mt9m111_init, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 32fc440c5..293be3f7f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -153,6 +153,7 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); static struct m5602_sensor ov9650 = { .name = "OV9650", .i2c_slave_id = 0x60, + .i2c_regW = 1, .probe = ov9650_probe, .init = ov9650_init, .power_down = ov9650_power_down, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 02072ccf9..3a49d15bd 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -150,6 +150,7 @@ static struct m5602_sensor po1030 = { .name = "PO1030", .i2c_slave_id = 0xdc, + .i2c_regW = 1, .probe = po1030_probe, .init = po1030_init, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 701d30292..3d04ff9b2 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -87,6 +87,7 @@ static struct m5602_sensor s5k4aa = { .init = s5k4aa_init, .power_down = s5k4aa_power_down, .i2c_slave_id = 0x5a, + .i2c_regW = 2, .nctrls = 4, .ctrls = { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 793c96787..6a884d73e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -69,6 +69,7 @@ static struct m5602_sensor s5k83a = { .init = s5k83a_init, .power_down = s5k83a_power_down, .i2c_slave_id = 0x5a, + .i2c_regW = 2, .nctrls = 5, .ctrls = { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index c09000236..23c0ef948 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -49,6 +49,9 @@ struct m5602_sensor { /* What i2c address the sensor is connected to */ u8 i2c_slave_id; + /* Width of each i2c register (in bytes) */ + u8 i2c_regW; + /* Probes if the sensor is connected */ int (*probe)(struct sd *sd); -- cgit v1.2.3 From 14526dcda1524c3bdfabd8c55cc67d87de8e5d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 26 Nov 2008 08:08:10 +0100 Subject: Convert all sensors to use the unified write sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_bridge.h | 3 + .../media/video/gspca/m5602/m5602_mt9m111.c | 22 ++++---- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 38 ++++++------- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 24 ++++---- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 64 +++++++++++----------- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 42 +++++++------- 6 files changed, 98 insertions(+), 95 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index 35db1bb9d..51376e2a9 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -133,4 +133,7 @@ int m5602_read_bridge( int m5602_write_bridge( struct sd *sd, u8 address, u8 i2c_data); +int m5602_write_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + #endif diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index e026e245f..0dedd3102 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -46,7 +46,7 @@ int mt9m111_probe(struct sd *sd) } else { data[0] = preinit_mt9m111[i][2]; data[1] = preinit_mt9m111[i][3]; - mt9m111_write_sensor(sd, + m5602_write_sensor(sd, preinit_mt9m111[i][1], data, 2); } } @@ -84,7 +84,7 @@ int mt9m111_init(struct sd *sd) } else { data[0] = init_mt9m111[i][2]; data[1] = init_mt9m111[i][3]; - err = mt9m111_write_sensor(sd, + err = m5602_write_sensor(sd, init_mt9m111[i][1], data, 2); } } @@ -123,7 +123,7 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set vertical flip to %d", val); /* Set the correct page map */ - err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); + err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) goto out; @@ -132,7 +132,7 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) goto out; data[0] = (data[0] & 0xfe) | val; - err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, + err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); out: return err; @@ -161,7 +161,7 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set horizontal flip to %d", val); /* Set the correct page map */ - err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); + err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) goto out; @@ -170,7 +170,7 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) goto out; data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02); - err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, + err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); out: return err; @@ -202,7 +202,7 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; /* Set the correct page map */ - err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); + err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) goto out; @@ -227,7 +227,7 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp, data[1], data[0]); - err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, + err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); out: return err; @@ -318,7 +318,7 @@ static void mt9m111_dump_registers(struct sd *sd) info("Dumping the mt9m111 sensor core registers"); value[1] = MT9M111_SENSOR_CORE; - mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); + m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); for (address = 0; address < 0xff; address++) { mt9m111_read_sensor(sd, address, value, 2); info("register 0x%x contains 0x%x%x", @@ -327,7 +327,7 @@ static void mt9m111_dump_registers(struct sd *sd) info("Dumping the mt9m111 color pipeline registers"); value[1] = MT9M111_COLORPIPE; - mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); + m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); for (address = 0; address < 0xff; address++) { mt9m111_read_sensor(sd, address, value, 2); info("register 0x%x contains 0x%x%x", @@ -336,7 +336,7 @@ static void mt9m111_dump_registers(struct sd *sd) info("Dumping the mt9m111 camera control registers"); value[1] = MT9M111_CAMERA_CONTROL; - mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); + m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); for (address = 0; address < 0xff; address++) { mt9m111_read_sensor(sd, address, value, 2); info("register 0x%x contains 0x%x%x", diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 9d22308fc..bbb5d0858 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -168,7 +168,7 @@ int ov9650_probe(struct sd *sd) for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) { u8 data = preinit_ov9650[i][2]; if (preinit_ov9650[i][0] == SENSOR) - ov9650_write_sensor(sd, + m5602_write_sensor(sd, preinit_ov9650[i][1], &data, 1); else m5602_write_bridge(sd, preinit_ov9650[i][1], data); @@ -206,7 +206,7 @@ int ov9650_init(struct sd *sd) for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) { data = init_ov9650[i][2]; if (init_ov9650[i][0] == SENSOR) - err = ov9650_write_sensor(sd, init_ov9650[i][1], + err = m5602_write_sensor(sd, init_ov9650[i][1], &data, 1); else err = m5602_write_bridge(sd, init_ov9650[i][1], data); @@ -215,7 +215,7 @@ int ov9650_init(struct sd *sd) if (dmi_check_system(ov9650_flip_dmi_table) && !err) { info("vflip quirk active"); data = 0x30; - err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1); + err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1); } return err; @@ -227,7 +227,7 @@ int ov9650_power_down(struct sd *sd) for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) { u8 data = power_down_ov9650[i][2]; if (power_down_ov9650[i][0] == SENSOR) - err = ov9650_write_sensor(sd, + err = m5602_write_sensor(sd, power_down_ov9650[i][1], &data, 1); else err = m5602_write_bridge(sd, power_down_ov9650[i][1], @@ -274,21 +274,21 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) /* The 6 MSBs */ i2c_data = (val >> 10) & 0x3f; - err = ov9650_write_sensor(sd, OV9650_AECHM, + err = m5602_write_sensor(sd, OV9650_AECHM, &i2c_data, 1); if (err < 0) goto out; /* The 8 middle bits */ i2c_data = (val >> 2) & 0xff; - err = ov9650_write_sensor(sd, OV9650_AECH, + err = m5602_write_sensor(sd, OV9650_AECH, &i2c_data, 1); if (err < 0) goto out; /* The 2 LSBs */ i2c_data = val & 0x03; - err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1); out: return err; @@ -322,11 +322,11 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) /* Mask away all uninteresting bits */ i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); - err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); /* The 8 LSBs */ i2c_data = val & 0xff; - err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); return err; } @@ -354,7 +354,7 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) val & 0xff); i2c_data = val & 0xff; - err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1); return err; } @@ -383,7 +383,7 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) val & 0xff); i2c_data = val & 0xff; - err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); return err; } @@ -422,7 +422,7 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) i2c_data = ((i2c_data & 0xdf) | ((val & 0x01) << 5)); - err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); out: return err; } @@ -461,7 +461,7 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) i2c_data = ((i2c_data & 0xef) | ((val & 0x01) << 4)); - err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); out: return err; } @@ -500,13 +500,13 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) /* Mask away all uninteresting bits */ i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); - err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) goto out; /* The 8 LSBs */ i2c_data = val & 0xff; - err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); out: return err; @@ -537,7 +537,7 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) goto out; i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); - err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); out: return err; } @@ -567,7 +567,7 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) goto out; i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); - err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); + err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); out: return err; } @@ -591,7 +591,7 @@ static void ov9650_dump_registers(struct sd *sd) u8 test_value[2] = {0xff, 0xff}; ov9650_read_sensor(sd, address, &old_value, 1); - ov9650_write_sensor(sd, address, test_value, 1); + m5602_write_sensor(sd, address, test_value, 1); ov9650_read_sensor(sd, address, &ctrl_value, 1); if (ctrl_value == test_value[0]) @@ -600,6 +600,6 @@ static void ov9650_dump_registers(struct sd *sd) info("register 0x%x is read only", address); /* Restore original value */ - ov9650_write_sensor(sd, address, &old_value, 1); + m5602_write_sensor(sd, address, &old_value, 1); } } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 655cc1732..2c65f0c37 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -40,7 +40,7 @@ int po1030_probe(struct sd *sd) for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { u8 data = preinit_po1030[i][2]; if (preinit_po1030[i][0] == SENSOR) - po1030_write_sensor(sd, + m5602_write_sensor(sd, preinit_po1030[i][1], &data, 1); else m5602_write_bridge(sd, preinit_po1030[i][1], data); @@ -158,14 +158,14 @@ int po1030_init(struct sd *sd) case SENSOR: data[0] = init_po1030[i][2]; - err = po1030_write_sensor(sd, + err = m5602_write_sensor(sd, init_po1030[i][1], data, 1); break; case SENSOR_LONG: data[0] = init_po1030[i][2]; data[1] = init_po1030[i][3]; - err = po1030_write_sensor(sd, + err = m5602_write_sensor(sd, init_po1030[i][1], data, 2); break; default: @@ -213,7 +213,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x", i2c_data); - err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H, + err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_H, &i2c_data, 1); if (err < 0) goto out; @@ -221,7 +221,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) i2c_data = (val & 0xff); PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x", i2c_data); - err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M, + err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_M, &i2c_data, 1); out: @@ -268,7 +268,7 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) i2c_data = (val & 0x01) << 7; - err = po1030_write_sensor(sd, PO1030_REG_CONTROL2, + err = m5602_write_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); return err; @@ -300,7 +300,7 @@ int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) i2c_data = (val & 0x01) << 6; - err = po1030_write_sensor(sd, PO1030_REG_CONTROL2, + err = m5602_write_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); return err; @@ -314,7 +314,7 @@ int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); - err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN, + err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN, &i2c_data, 1); return err; } @@ -340,7 +340,7 @@ int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; PDEBUG(D_V4L2, "Set red gain to %d", i2c_data); - err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN, + err = m5602_write_sensor(sd, PO1030_REG_RED_GAIN, &i2c_data, 1); return err; } @@ -366,7 +366,7 @@ int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) int err; i2c_data = val & 0xff; PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data); - err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN, + err = m5602_write_sensor(sd, PO1030_REG_BLUE_GAIN, &i2c_data, 1); return err; @@ -397,7 +397,7 @@ static void po1030_dump_registers(struct sd *sd) u8 test_value[2] = {0xff, 0xff}; po1030_read_sensor(sd, address, &old_value, 1); - po1030_write_sensor(sd, address, test_value, 1); + m5602_write_sensor(sd, address, test_value, 1); po1030_read_sensor(sd, address, &ctrl_value, 1); if (ctrl_value == test_value[0]) @@ -406,6 +406,6 @@ static void po1030_dump_registers(struct sd *sd) info("register 0x%x is read only", address); /* Restore original value */ - po1030_write_sensor(sd, address, &old_value, 1); + m5602_write_sensor(sd, address, &old_value, 1); } } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index fcddbffa2..67a4424cf 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -85,7 +85,7 @@ int s5k4aa_probe(struct sd *sd) case SENSOR: data[0] = preinit_s5k4aa[i][2]; - err = s5k4aa_write_sensor(sd, + err = m5602_write_sensor(sd, preinit_s5k4aa[i][1], data, 1); break; @@ -93,7 +93,7 @@ int s5k4aa_probe(struct sd *sd) case SENSOR_LONG: data[0] = preinit_s5k4aa[i][2]; data[1] = preinit_s5k4aa[i][3]; - err = s5k4aa_write_sensor(sd, + err = m5602_write_sensor(sd, preinit_s5k4aa[i][1], data, 2); break; @@ -221,14 +221,14 @@ int s5k4aa_init(struct sd *sd) case SENSOR: data[0] = init_s5k4aa[i][2]; - err = s5k4aa_write_sensor(sd, + err = m5602_write_sensor(sd, init_s5k4aa[i][1], data, 1); break; case SENSOR_LONG: data[0] = init_s5k4aa[i][2]; data[1] = init_s5k4aa[i][3]; - err = s5k4aa_write_sensor(sd, + err = m5602_write_sensor(sd, init_s5k4aa[i][1], data, 2); break; default: @@ -243,21 +243,21 @@ int s5k4aa_init(struct sd *sd) if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) { u8 data = 0x02; info("vertical flip quirk active"); - s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); data |= S5K4AA_RM_V_FLIP; data &= ~S5K4AA_RM_H_FLIP; - s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); /* Decrement COLSTART to preserve color order (BGGR) */ s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); data--; - s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); /* Increment ROWSTART to preserve color order (BGGR) */ s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); data++; - s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } return (err < 0) ? err : 0; @@ -274,7 +274,7 @@ int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) u8 data = S5K4AA_PAGE_MAP_2; int err; - err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; @@ -297,15 +297,15 @@ int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) int err; PDEBUG(D_V4L2, "Set exposure to %d", val); - err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; data = (val >> 8) & 0xff; - err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); if (err < 0) goto out; data = val & 0xff; - err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); out: return err; } @@ -316,7 +316,7 @@ int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) u8 data = S5K4AA_PAGE_MAP_2; int err; - err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; @@ -335,15 +335,15 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) int err; PDEBUG(D_V4L2, "Set vertical flip to %d", val); - err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; - err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) goto out; data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7)); - err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) goto out; @@ -353,14 +353,14 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) goto out; data++; - err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } else { err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); if (err < 0) goto out; data--; - err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } out: return err; @@ -372,7 +372,7 @@ int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) u8 data = S5K4AA_PAGE_MAP_2; int err; - err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; @@ -391,15 +391,15 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set horizontal flip to %d", val); - err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; - err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) goto out; data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); - err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) goto out; @@ -408,7 +408,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) goto out; data++; - err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); if (err < 0) goto out; } else { @@ -416,7 +416,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) goto out; data--; - err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); } out: return err; @@ -428,7 +428,7 @@ int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) u8 data = S5K4AA_PAGE_MAP_2; int err; - err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; @@ -447,12 +447,12 @@ int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) int err; PDEBUG(D_V4L2, "Set gain to %d", val); - err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; data = val & 0xff; - err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_GAIN_2, &data, 1); out: return err; @@ -464,7 +464,7 @@ static void s5k4aa_dump_registers(struct sd *sd) u8 page, old_page; s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); for (page = 0; page < 16; page++) { - s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); + m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); info("Dumping the s5k4aa register state for page 0x%x", page); for (address = 0; address <= 0xff; address++) { u8 value = 0; @@ -476,14 +476,14 @@ static void s5k4aa_dump_registers(struct sd *sd) info("s5k4aa register state dump complete"); for (page = 0; page < 16; page++) { - s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); + m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); info("Probing for which registers that are " "read/write for page 0x%x", page); for (address = 0; address <= 0xff; address++) { u8 old_value, ctrl_value, test_value = 0xff; s5k4aa_read_sensor(sd, address, &old_value, 1); - s5k4aa_write_sensor(sd, address, &test_value, 1); + m5602_write_sensor(sd, address, &test_value, 1); s5k4aa_read_sensor(sd, address, &ctrl_value, 1); if (ctrl_value == test_value) @@ -492,9 +492,9 @@ static void s5k4aa_dump_registers(struct sd *sd) info("register 0x%x is read only", address); /* Restore original value */ - s5k4aa_write_sensor(sd, address, &old_value, 1); + m5602_write_sensor(sd, address, &old_value, 1); } } info("Read/write register probing complete"); - s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); + m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 34b99c000..84a648d70 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -41,7 +41,7 @@ int s5k83a_probe(struct sd *sd) for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]}; if (preinit_s5k83a[i][0] == SENSOR) - err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1], + err = m5602_write_sensor(sd, preinit_s5k83a[i][1], data, 2); else err = m5602_write_bridge(sd, preinit_s5k83a[i][1], @@ -167,14 +167,14 @@ int s5k83a_init(struct sd *sd) case SENSOR: data[0] = init_s5k83a[i][2]; - err = s5k83a_write_sensor(sd, + err = m5602_write_sensor(sd, init_s5k83a[i][1], data, 1); break; case SENSOR_LONG: data[0] = init_s5k83a[i][2]; data[1] = init_s5k83a[i][3]; - err = s5k83a_write_sensor(sd, + err = m5602_write_sensor(sd, init_s5k83a[i][1], data, 2); break; default: @@ -201,7 +201,7 @@ void s5k83a_dump_registers(struct sd *sd) s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); for (page = 0; page < 16; page++) { - s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); + m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); info("Dumping the s5k83a register state for page 0x%x", page); for (address = 0; address <= 0xff; address++) { u8 val = 0; @@ -213,14 +213,14 @@ void s5k83a_dump_registers(struct sd *sd) info("s5k83a register state dump complete"); for (page = 0; page < 16; page++) { - s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); + m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); info("Probing for which registers that are read/write " "for page 0x%x", page); for (address = 0; address <= 0xff; address++) { u8 old_val, ctrl_val, test_val = 0xff; s5k83a_read_sensor(sd, address, &old_val, 1); - s5k83a_write_sensor(sd, address, &test_val, 1); + m5602_write_sensor(sd, address, &test_val, 1); s5k83a_read_sensor(sd, address, &ctrl_val, 1); if (ctrl_val == test_val) @@ -229,11 +229,11 @@ void s5k83a_dump_registers(struct sd *sd) info("register 0x%x is read only", address); /* Restore original val */ - s5k83a_write_sensor(sd, address, &old_val, 1); + m5602_write_sensor(sd, address, &old_val, 1); } } info("Read/write register probing complete"); - s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); + m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); } int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) @@ -261,13 +261,13 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) data[0] = 0x00; data[1] = 0x20; - err = s5k83a_write_sensor(sd, 0x14, data, 2); + err = m5602_write_sensor(sd, 0x14, data, 2); if (err < 0) goto out; data[0] = 0x01; data[1] = 0x00; - err = s5k83a_write_sensor(sd, 0x0d, data, 2); + err = m5602_write_sensor(sd, 0x0d, data, 2); if (err < 0) goto out; @@ -275,7 +275,7 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) of these registers */ data[0] = val >> 3; /* brightness, high 5 bits */ data[1] = val >> 1; /* brightness, high 7 bits */ - err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2); + err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2); out: return err; @@ -304,7 +304,7 @@ int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; data[0] = val; - err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1); + err = m5602_write_sensor(sd, S5K83A_WHITENESS, data, 1); return err; } @@ -337,7 +337,7 @@ int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) data[0] = 0; data[1] = val; - err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2); + err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2); return err; } @@ -348,7 +348,7 @@ int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) struct sd *sd = (struct sd *) gspca_dev; data[0] = 0x05; - err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) goto out; @@ -366,7 +366,7 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; data[0] = 0x05; - err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) goto out; @@ -377,12 +377,12 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) /* set or zero six bit, seven is hflip */ data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK : (data[0] & 0x80) | S5K83A_FLIP_MASK; - err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); + err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) goto out; data[0] = (val) ? 0x0b : 0x0a; - err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); + err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); out: return err; @@ -395,7 +395,7 @@ int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) struct sd *sd = (struct sd *) gspca_dev; data[0] = 0x05; - err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) goto out; @@ -413,7 +413,7 @@ int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; data[0] = 0x05; - err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) goto out; @@ -424,12 +424,12 @@ int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) /* set or zero seven bit, six is vflip */ data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK : (data[0] & 0x40) | S5K83A_FLIP_MASK; - err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); + err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) goto out; data[0] = (val) ? 0x0a : 0x0b; - err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); + err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); out: return err; } -- cgit v1.2.3 From 8f369853f1f50927d68e46e838850b26710af902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 26 Nov 2008 08:12:59 +0100 Subject: Remove all sensor specific write functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../media/video/gspca/m5602/m5602_mt9m111.c | 44 ---------------------- .../media/video/gspca/m5602/m5602_mt9m111.h | 3 -- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 44 ---------------------- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 - .../drivers/media/video/gspca/m5602/m5602_po1030.c | 42 --------------------- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 2 - .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 44 ---------------------- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 2 - .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 44 ---------------------- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 3 -- 10 files changed, 230 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 0dedd3102..ae3b62ab4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -266,50 +266,6 @@ out: return err; } -int mt9m111_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - u8 *p; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - /* No sensor with a data width larger - than 16 bits has yet been seen, nor with 0 :p*/ - if (len > 2 || !len) - return -EINVAL; - - memcpy(buf, sensor_urb_skeleton, - sizeof(sensor_urb_skeleton)); - - buf[11] = sd->sensor->i2c_slave_id; - buf[15] = address; - - p = buf + 16; - - /* Copy a four byte write sequence for each byte to be written to */ - for (i = 0; i < len; i++) { - memcpy(p, sensor_urb_skeleton + 16, 4); - p[3] = i2c_data[i]; - p += 4; - PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", - address, i2c_data[i]); - } - - /* Copy the tailer */ - memcpy(p, sensor_urb_skeleton + 20, 4); - - /* Set the total length */ - p[3] = 0x10 + len; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x19, - 0x0000, buf, - 20 + len * 4, M5602_URB_MSG_TIMEOUT); - - return (err < 0) ? err : 0; -} - static void mt9m111_dump_registers(struct sd *sd) { u8 address, value[2] = {0x00, 0x00}; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 2c7b2a49c..763b17ee6 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -90,9 +90,6 @@ int mt9m111_power_down(struct sd *sd); int mt9m111_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); -int mt9m111_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index bbb5d0858..8e4a7ad48 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -104,50 +104,6 @@ out: return (err < 0) ? err : 0; } -int ov9650_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - u8 *p; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - /* The ov9650 only supports one byte writes */ - if (len > 1 || !len) - return -EINVAL; - - memcpy(buf, sensor_urb_skeleton, - sizeof(sensor_urb_skeleton)); - - buf[11] = sd->sensor->i2c_slave_id; - buf[15] = address; - - /* Special case larger sensor writes */ - p = buf + 16; - - /* Copy a four byte sequence for each byte to write over the I2C bus */ - for (i = 0; i < len; i++) { - memcpy(p, sensor_urb_skeleton + 16, 4); - p[3] = i2c_data[i]; - p += 4; - PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", - address, i2c_data[i]); - } - - /* Copy the tailer */ - memcpy(p, sensor_urb_skeleton + 20, 4); - - /* Set the total length */ - p[3] = 0x10 + len; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x19, - 0x0000, buf, - 20 + len * 4, M5602_URB_MSG_TIMEOUT); - - return (err < 0) ? err : 0; -} - int ov9650_probe(struct sd *sd) { u8 prod_id = 0, ver_id = 0, i; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 293be3f7f..1f33a7b8d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -128,8 +128,6 @@ int ov9650_power_down(struct sd *sd); int ov9650_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); -int ov9650_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 2c65f0c37..f52a3cd33 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -99,48 +99,6 @@ out: return err; } -int po1030_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - u8 *p; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - /* The po1030 only supports one byte writes */ - if (len > 1 || !len) - return -EINVAL; - - memcpy(buf, sensor_urb_skeleton, sizeof(sensor_urb_skeleton)); - - buf[11] = sd->sensor->i2c_slave_id; - buf[15] = address; - - p = buf + 16; - - /* Copy a four byte write sequence for each byte to be written to */ - for (i = 0; i < len; i++) { - memcpy(p, sensor_urb_skeleton + 16, 4); - p[3] = i2c_data[i]; - p += 4; - PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", - address, i2c_data[i]); - } - - /* Copy the footer */ - memcpy(p, sensor_urb_skeleton + 20, 4); - - /* Set the total length */ - p[3] = 0x10 + len; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x19, - 0x0000, buf, - 20 + len * 4, M5602_URB_MSG_TIMEOUT); - - return (err < 0) ? err : 0; -} - int po1030_init(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 3a49d15bd..c4dad6449 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -130,8 +130,6 @@ int po1030_power_down(struct sd *sd); int po1030_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); -int po1030_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 67a4424cf..d420ee6ba 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -161,50 +161,6 @@ out: return err; } -int s5k4aa_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - u8 *p; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - /* No sensor with a data width larger than 16 bits has yet been seen */ - if (len > 2 || !len) - return -EINVAL; - - memcpy(buf, sensor_urb_skeleton, - sizeof(sensor_urb_skeleton)); - - buf[11] = sd->sensor->i2c_slave_id; - buf[15] = address; - - /* Special case larger sensor writes */ - p = buf + 16; - - /* Copy a four byte write sequence for each byte to be written to */ - for (i = 0; i < len; i++) { - memcpy(p, sensor_urb_skeleton + 16, 4); - p[3] = i2c_data[i]; - p += 4; - PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", - address, i2c_data[i]); - } - - /* Copy the tailer */ - memcpy(p, sensor_urb_skeleton + 20, 4); - - /* Set the total length */ - p[3] = 0x10 + len; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x19, - 0x0000, buf, - 20 + len * 4, M5602_URB_MSG_TIMEOUT); - - return (err < 0) ? err : 0; -} - int s5k4aa_init(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 3d04ff9b2..a38103a88 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -69,8 +69,6 @@ int s5k4aa_power_down(struct sd *sd); int s5k4aa_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); -int s5k4aa_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 84a648d70..372303074 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -107,50 +107,6 @@ out: return err; } -int s5k83a_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - u8 *p; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - /* No sensor with a data width larger than 16 bits has yet been seen */ - if (len > 2 || !len) - return -EINVAL; - - memcpy(buf, sensor_urb_skeleton, - sizeof(sensor_urb_skeleton)); - - buf[11] = sd->sensor->i2c_slave_id; - buf[15] = address; - - /* Special case larger sensor writes */ - p = buf + 16; - - /* Copy a four byte write sequence for each byte to be written to */ - for (i = 0; i < len; i++) { - memcpy(p, sensor_urb_skeleton + 16, 4); - p[3] = i2c_data[i]; - p += 4; - PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", - address, i2c_data[i]); - } - - /* Copy the tailer */ - memcpy(p, sensor_urb_skeleton + 20, 4); - - /* Set the total length */ - p[3] = 0x10 + len; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x19, - 0x0000, buf, - 20 + len * 4, M5602_URB_MSG_TIMEOUT); - - return (err < 0) ? err : 0; -} - int s5k83a_init(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 6a884d73e..735701127 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -48,8 +48,6 @@ int s5k83a_power_down(struct sd *sd); int s5k83a_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); -int s5k83a_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); @@ -62,7 +60,6 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); - static struct m5602_sensor s5k83a = { .name = "S5K83A", .probe = s5k83a_probe, -- cgit v1.2.3 From d6fee5ac91e4b7196341e6da1708ce5b4481cd79 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 26 Nov 2008 08:46:15 +0100 Subject: gspca: Change the colors and add the red and blue controls in sonixj. From: Jean-Francois Moine The colors control (saturation) acted as color balance. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 117 ++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 18 deletions(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 9d9f90669..8037a4ec9 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -41,6 +41,8 @@ struct sd { unsigned char contrast; unsigned char colors; unsigned char autogain; + __u8 blue; + __u8 red; __u8 vflip; /* ov7630 only */ __u8 infrared; /* mi0360 only */ @@ -72,6 +74,10 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); @@ -116,7 +122,7 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Color", .minimum = 0, - .maximum = 64, + .maximum = 40, .step = 1, #define COLOR_DEF 32 .default_value = COLOR_DEF, @@ -124,7 +130,35 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, -#define AUTOGAIN_IDX 3 + { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = 24, + .maximum = 40, + .step = 1, +#define BLUE_BALANCE_DEF 32 + .default_value = BLUE_BALANCE_DEF, + }, + .set = sd_setblue_balance, + .get = sd_getblue_balance, + }, + { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = 24, + .maximum = 40, + .step = 1, +#define RED_BALANCE_DEF 32 + .default_value = RED_BALANCE_DEF, + }, + .set = sd_setred_balance, + .get = sd_getred_balance, + }, +#define AUTOGAIN_IDX 5 { { .id = V4L2_CID_AUTOGAIN, @@ -140,7 +174,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getautogain, }, /* ov7630 only */ -#define VFLIP_IDX 4 +#define VFLIP_IDX 6 { { .id = V4L2_CID_VFLIP, @@ -156,7 +190,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getvflip, }, /* mi0360 only */ -#define INFRARED_IDX 5 +#define INFRARED_IDX 7 { { .id = V4L2_CID_INFRARED, @@ -989,6 +1023,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->blue = BLUE_BALANCE_DEF; + sd->red = RED_BALANCE_DEF; sd->autogain = AUTOGAIN_DEF; sd->ag_cnt = -1; sd->vflip = VFLIP_DEF; @@ -1183,18 +1219,27 @@ static void setcontrast(struct gspca_dev *gspca_dev) static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 blue, red; - - if (sd->colors >= 32) { - red = 32 + (sd->colors - 32) / 2; - blue = 64 - sd->colors; - } else { - red = sd->colors; - blue = 32 + (32 - sd->colors) / 2; + int i, v; + __u8 rega0[12]; /* U & V gains */ + static __s16 uv[6] = { /* same as reg84 in signed decimal */ + -24, -38, 64, /* UR UG UB */ + 62, -51, -9 /* VR VG VB */ + }; + for (i = 0; i < 6; i++) { + v = uv[i] * sd->colors / COLOR_DEF; + rega0[i * 2] = v; + rega0[i * 2 + 1] = (v >> 8) & 0x0f; } - reg_w1(gspca_dev, 0x05, red); + reg_w(gspca_dev, 0x84, rega0, sizeof rega0); +} + +static void setredblue(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + reg_w1(gspca_dev, 0x05, sd->red); /* reg_w1(gspca_dev, 0x07, 32); */ - reg_w1(gspca_dev, 0x06, blue); + reg_w1(gspca_dev, 0x06, sd->blue); } static void setautogain(struct gspca_dev *gspca_dev) @@ -1280,9 +1325,9 @@ static int sd_start(struct gspca_dev *gspca_dev) } reg_w1(gspca_dev, 0x17, reg17); /* set reg1 was here */ - reg_w1(gspca_dev, 0x05, sn9c1xx[5]); - reg_w1(gspca_dev, 0x07, sn9c1xx[7]); - reg_w1(gspca_dev, 0x06, sn9c1xx[6]); + reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */ + reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ + reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def); for (i = 0; i < 8; i++) @@ -1483,7 +1528,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) expotimes = 0; sd->exposure = setexposure(gspca_dev, (unsigned int) expotimes); - setcolors(gspca_dev); + setredblue(gspca_dev); break; } } @@ -1586,6 +1631,42 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->blue = val; + if (gspca_dev->streaming) + setredblue(gspca_dev); + return 0; +} + +static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->blue; + return 0; +} + +static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->red = val; + if (gspca_dev->streaming) + setredblue(gspca_dev); + return 0; +} + +static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->red; + return 0; +} + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From 4afcf3e7639390bd67f0720078b16234019af1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 26 Nov 2008 17:15:35 +0100 Subject: Add initial read sensor implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_bridge.h | 3 ++ linux/drivers/media/video/gspca/m5602/m5602_core.c | 36 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index 51376e2a9..a3f3b7a0c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -136,4 +136,7 @@ int m5602_write_bridge( int m5602_write_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); +int m5602_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + #endif diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index d68037af6..1d1fb541f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -80,6 +80,42 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) return (err < 0) ? err : 0; } +int m5602_read_sensor(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len) +{ + int err, i; + + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); + } while ((*i2c_data & I2C_BUSY) && !err); + + err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, + sd->sensor->i2c_slave_id); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); + if (err < 0) + goto out; + + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + if (err < 0) + goto out; + + for (i = 0; (i < len) && !err; i++) { + err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); + + PDEBUG(D_CONF, "Reading sensor register " + "0x%x containing 0x%x ", address, *i2c_data); + } +out: + return err; +} + int m5602_write_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len) { -- cgit v1.2.3 From 35f33378721e6f823dde92b83dd9f37348905cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 26 Nov 2008 17:32:46 +0100 Subject: Add flush control to each sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 11 ++++++++--- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 1 + linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 ++ linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 1 + linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 5 ++++- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 3 +++ linux/drivers/media/video/gspca/m5602/m5602_sensor.h | 2 ++ 7 files changed, 21 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 1d1fb541f..d86b905cb 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -85,6 +85,9 @@ int m5602_read_sensor(struct sd *sd, const u8 address, { int err, i; + if (!len || (len > sd->sensor->i2c_regW)) + return -EINVAL; + do { err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); } while ((*i2c_data & I2C_BUSY) && !err); @@ -102,9 +105,11 @@ int m5602_read_sensor(struct sd *sd, const u8 address, if (err < 0) goto out; - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); - if (err < 0) - goto out; + if (sd->sensor->i2c_need_flush) { + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + if (err < 0) + goto out; + } for (i = 0; (i < len) && !err; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 763b17ee6..db64c122b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -102,6 +102,7 @@ static struct m5602_sensor mt9m111 = { .i2c_slave_id = 0xba, .i2c_regW = 2, + .i2c_need_flush = 0, .probe = mt9m111_probe, .init = mt9m111_init, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 1f33a7b8d..732447932 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -152,6 +152,8 @@ static struct m5602_sensor ov9650 = { .name = "OV9650", .i2c_slave_id = 0x60, .i2c_regW = 1, + .i2c_need_flush = 1, + .probe = ov9650_probe, .init = ov9650_init, .power_down = ov9650_power_down, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index c4dad6449..a44a4ac6b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -149,6 +149,7 @@ static struct m5602_sensor po1030 = { .i2c_slave_id = 0xdc, .i2c_regW = 1, + .i2c_need_flush = 1, .probe = po1030_probe, .init = po1030_init, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index a38103a88..8088e8ea4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -83,9 +83,12 @@ static struct m5602_sensor s5k4aa = { .name = "S5K4AA", .probe = s5k4aa_probe, .init = s5k4aa_init, - .power_down = s5k4aa_power_down, + .i2c_slave_id = 0x5a, .i2c_regW = 2, + .i2c_need_flush = 1, + + .power_down = s5k4aa_power_down, .nctrls = 4, .ctrls = { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 735701127..e721229eb 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -65,8 +65,11 @@ static struct m5602_sensor s5k83a = { .probe = s5k83a_probe, .init = s5k83a_init, .power_down = s5k83a_power_down, + .i2c_slave_id = 0x5a, .i2c_regW = 2, + .i2c_need_flush = 0, + .nctrls = 5, .ctrls = { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 23c0ef948..0f6e1d83f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -52,6 +52,8 @@ struct m5602_sensor { /* Width of each i2c register (in bytes) */ u8 i2c_regW; + u8 i2c_need_flush; + /* Probes if the sensor is connected */ int (*probe)(struct sd *sd); -- cgit v1.2.3 From 5e8806761e3146cdf8f1c400b2ff0090bfb6d2f0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 26 Nov 2008 20:17:13 +0100 Subject: gspca: Add sensor mi0360 in vc032x. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 477 ++++++++++++++++++------------- 1 file changed, 271 insertions(+), 206 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index f6fae60ae..db5deb957 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -41,11 +41,12 @@ struct sd { #define BRIDGE_VC0323 1 char sensor; #define SENSOR_HV7131R 0 -#define SENSOR_MI1320 1 -#define SENSOR_MI1310_SOC 2 -#define SENSOR_OV7660 3 -#define SENSOR_OV7670 4 -#define SENSOR_PO3130NC 5 +#define SENSOR_MI0360 1 +#define SENSOR_MI1320 2 +#define SENSOR_MI1310_SOC 3 +#define SENSOR_OV7660 4 +#define SENSOR_OV7670 5 +#define SENSOR_PO3130NC 6 }; /* V4L2 controls supported by the driver */ @@ -111,15 +112,239 @@ static struct v4l2_pix_format vc0323_mode[] = { .priv = 0}, }; -#if 0 -static const __u8 mi1310soc_gamma[17] = { - 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff +static const __u8 mi0360_matrix[9] = { + 0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50 }; -static const __u8 mi1310soc_matrix[9] = { - 0x56, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x58 + +static const __u8 mi0360_initVGA_JPG[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0xb3, 0x00, 0x24, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xb8, 0x00, 0x13, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x2c, 0x50, 0xcc}, + {0xb8, 0x2d, 0xf8, 0xcc}, + {0xb8, 0x2e, 0xf8, 0xcc}, + {0xb8, 0x2f, 0xf8, 0xcc}, + {0xb8, 0x30, 0x50, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf8, 0xcc}, + {0xb8, 0x33, 0xf8, 0xcc}, + {0xb8, 0x34, 0x50, 0xcc}, + {0xb8, 0x35, 0x00, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, + {0xb8, 0x01, 0x79, 0xcc}, + {0xb8, 0x08, 0xe0, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xb8, 0x01, 0x79, 0xcc}, + {0xb8, 0x14, 0x18, 0xcc}, + {0xb8, 0xb2, 0x0a, 0xcc}, + {0xb8, 0xb4, 0x0a, 0xcc}, + {0xb8, 0xb5, 0x0a, 0xcc}, + {0xb8, 0xfe, 0x00, 0xcc}, + {0xb8, 0xff, 0x28, 0xcc}, + {0xb9, 0x00, 0x28, 0xcc}, + {0xb9, 0x01, 0x28, 0xcc}, + {0xb9, 0x02, 0x28, 0xcc}, + {0xb9, 0x03, 0x00, 0xcc}, + {0xb9, 0x04, 0x00, 0xcc}, + {0xb9, 0x05, 0x3c, 0xcc}, + {0xb9, 0x06, 0x3c, 0xcc}, + {0xb9, 0x07, 0x3c, 0xcc}, + {0xb9, 0x08, 0x3c, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0x31, 0x00, 0x00, 0xbb}, + {0x09, 0x01, 0xc7, 0xbb}, + {0x34, 0x01, 0x00, 0xbb}, + {0x2b, 0x00, 0x28, 0xbb}, + {0x2c, 0x00, 0x30, 0xbb}, + {0x2d, 0x00, 0x30, 0xbb}, + {0x2e, 0x00, 0x28, 0xbb}, + {0x62, 0x04, 0x11, 0xbb}, + {0x03, 0x01, 0xe0, 0xbb}, + {0x2c, 0x00, 0x2c, 0xbb}, + {0x20, 0xd0, 0x00, 0xbb}, + {0x01, 0x00, 0x08, 0xbb}, + {0x06, 0x00, 0x10, 0xbb}, + {0x05, 0x00, 0x20, 0xbb}, + {0x20, 0x00, 0x00, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x02, 0xcc}, + {0xb6, 0x02, 0x80, 0xcc}, + {0xb6, 0x05, 0x01, 0xcc}, + {0xb6, 0x04, 0xe0, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x18, 0x02, 0xcc}, + {0xb6, 0x17, 0x58, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0x35, 0x00, 0x60, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} }; -#endif +static const __u8 mi0360_initQVGA_JPG[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0xb3, 0x00, 0x24, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xbc, 0x00, 0xd1, 0xcc}, + {0xb8, 0x00, 0x13, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x2c, 0x50, 0xcc}, + {0xb8, 0x2d, 0xf8, 0xcc}, + {0xb8, 0x2e, 0xf8, 0xcc}, + {0xb8, 0x2f, 0xf8, 0xcc}, + {0xb8, 0x30, 0x50, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf8, 0xcc}, + {0xb8, 0x33, 0xf8, 0xcc}, + {0xb8, 0x34, 0x50, 0xcc}, + {0xb8, 0x35, 0x00, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, + {0xb8, 0x01, 0x79, 0xcc}, + {0xb8, 0x08, 0xe0, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xb8, 0x01, 0x79, 0xcc}, + {0xb8, 0x14, 0x18, 0xcc}, + {0xb8, 0xb2, 0x0a, 0xcc}, + {0xb8, 0xb4, 0x0a, 0xcc}, + {0xb8, 0xb5, 0x0a, 0xcc}, + {0xb8, 0xfe, 0x00, 0xcc}, + {0xb8, 0xff, 0x28, 0xcc}, + {0xb9, 0x00, 0x28, 0xcc}, + {0xb9, 0x01, 0x28, 0xcc}, + {0xb9, 0x02, 0x28, 0xcc}, + {0xb9, 0x03, 0x00, 0xcc}, + {0xb9, 0x04, 0x00, 0xcc}, + {0xb9, 0x05, 0x3c, 0xcc}, + {0xb9, 0x06, 0x3c, 0xcc}, + {0xb9, 0x07, 0x3c, 0xcc}, + {0xb9, 0x08, 0x3c, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0x31, 0x00, 0x00, 0xbb}, + {0x09, 0x01, 0xc7, 0xbb}, + {0x34, 0x01, 0x00, 0xbb}, + {0x2b, 0x00, 0x28, 0xbb}, + {0x2c, 0x00, 0x30, 0xbb}, + {0x2d, 0x00, 0x30, 0xbb}, + {0x2e, 0x00, 0x28, 0xbb}, + {0x62, 0x04, 0x11, 0xbb}, + {0x03, 0x01, 0xe0, 0xbb}, + {0x2c, 0x00, 0x2c, 0xbb}, + {0x20, 0xd0, 0x00, 0xbb}, + {0x01, 0x00, 0x08, 0xbb}, + {0x06, 0x00, 0x10, 0xbb}, + {0x05, 0x00, 0x20, 0xbb}, + {0x20, 0x00, 0x00, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, + {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, + {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, + {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0xbc, 0x02, 0x18, 0xcc}, + {0xbc, 0x03, 0x50, 0xcc}, + {0xbc, 0x04, 0x18, 0xcc}, + {0xbc, 0x05, 0x00, 0xcc}, + {0xbc, 0x06, 0x00, 0xcc}, + {0xbc, 0x08, 0x30, 0xcc}, + {0xbc, 0x09, 0x40, 0xcc}, + {0xbc, 0x0a, 0x10, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xbc, 0x0b, 0x00, 0xcc}, + {0xbc, 0x0c, 0x00, 0xcc}, + {0x35, 0x00, 0xef, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; + static const __u8 mi1310_socinitVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, @@ -1212,178 +1437,6 @@ static const __u8 ov7670_initQVGA_JPG[][4] = { {0x00, 0x77, 0x05, 0xaa }, {}, }; -#if 0 -static const __u8 ov7670_initQVGA_JPG[][4] = { - {0xb3, 0x00, 0x00, 0xcc}, - {0xb0, 0x16, 0x0d, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x16, 0x00, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x19, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb3, 0x49, 0x11, 0xcc}, - {0xb3, 0x49, 0x00, 0xcc}, {0xb0, 0x16, 0x00, 0xcc}, - - {0xb3, 0x01, 0x05, 0xcc}, {0x00, 0x00, 0x50, 0xdd}, - {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb3, 0x00, 0x66, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, {0xb3, 0x35, 0xa1, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x02, 0x02, 0xcc}, - {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc}, - {0xbc, 0x00, 0xd1, 0xcc}, /* set QVGA */ - {0xbc, 0x01, 0x01, 0xcc},/* */ - {0x00, 0x12, 0x80, 0xaa},/* OV sensor reset */ - {0x00, 0x00, 0x50, 0xdd},/* wait sometimes */ - {0, 0x12, 0x00, 0xaa}, - {0, 0x11, 0x40, 0xaa}, {0, 0x6b, 0x0a, 0xaa}, - {0, 0x3a, 0x04, 0xaa}, {0, 0x40, 0xc0, 0xaa}, - {0, 0x8c, 0x00, 0xaa}, {0, 0x7a, 0x29, 0xaa}, - {0, 0x7b, 0x0e, 0xaa}, {0, 0x7c, 0x1a, 0xaa}, - {0, 0x7d, 0x31, 0xaa}, {0, 0x7e, 0x53, 0xaa}, - {0, 0x7f, 0x60, 0xaa}, {0, 0x80, 0x6b, 0xaa}, - {0, 0x81, 0x73, 0xaa}, {0, 0x82, 0x7b, 0xaa}, - {0, 0x83, 0x82, 0xaa}, {0, 0x84, 0x89, 0xaa}, - {0, 0x85, 0x96, 0xaa}, {0, 0x86, 0xa1, 0xaa}, - {0, 0x87, 0xb7, 0xaa}, {0, 0x88, 0xcc, 0xaa}, - {0, 0x89, 0xe1, 0xaa}, {0, 0x13, 0xe0, 0xaa}, - {0, 0x00, 0x00, 0xaa}, {0, 0x10, 0x00, 0xaa}, - {0, 0x0d, 0x40, 0xaa}, {0, 0x14, 0x28, 0xaa}, - {0, 0xa5, 0x05, 0xaa}, {0, 0xab, 0x07, 0xaa}, - {0, 0x24, 0x95, 0xaa}, {0, 0x25, 0x33, 0xaa}, - {0, 0x26, 0xe3, 0xaa}, {0, 0x9f, 0x88, 0xaa}, - {0, 0xa0, 0x78, 0xaa}, {0, 0x55, 0x90, 0xaa}, - {0, 0xa1, 0x03, 0xaa}, {0, 0xa6, 0xe0, 0xaa}, - {0, 0xa7, 0xd8, 0xaa}, {0, 0xa8, 0xf0, 0xaa}, - {0, 0xa9, 0x90, 0xaa}, {0, 0xaa, 0x14, 0xaa}, - {0, 0x13, 0xe5, 0xaa}, {0, 0x0e, 0x61, 0xaa}, - {0, 0x0f, 0x4b, 0xaa}, {0, 0x16, 0x02, 0xaa}, - {0, 0x1e, 0x07, 0xaa}, {0, 0x21, 0x02, 0xaa}, - {0, 0x22, 0x91, 0xaa}, {0, 0x29, 0x07, 0xaa}, - {0, 0x33, 0x0b, 0xaa}, {0, 0x35, 0x0b, 0xaa}, - {0, 0x37, 0x1d, 0xaa}, {0, 0x38, 0x71, 0xaa}, - {0, 0x39, 0x2a, 0xaa}, {0, 0x3c, 0x78, 0xaa}, - {0, 0x4d, 0x40, 0xaa}, {0, 0x4e, 0x20, 0xaa}, - {0, 0x74, 0x19, 0xaa}, {0, 0x8d, 0x4f, 0xaa}, - {0, 0x8e, 0x00, 0xaa}, {0, 0x8f, 0x00, 0xaa}, - {0, 0x90, 0x00, 0xaa}, {0, 0x91, 0x00, 0xaa}, - {0, 0x96, 0x00, 0xaa}, {0, 0x9a, 0x80, 0xaa}, - {0, 0xb0, 0x84, 0xaa}, {0, 0xb1, 0x0c, 0xaa}, - {0, 0xb2, 0x0e, 0xaa}, {0, 0xb3, 0x82, 0xaa}, - {0, 0xb8, 0x0a, 0xaa}, {0, 0x43, 0x14, 0xaa}, - {0, 0x44, 0xf0, 0xaa}, {0, 0x45, 0x45, 0xaa}, - {0, 0x46, 0x63, 0xaa}, {0, 0x47, 0x2d, 0xaa}, - {0, 0x48, 0x46, 0xaa}, {0, 0x59, 0x88, 0xaa}, - {0, 0x5a, 0xa0, 0xaa}, {0, 0x5b, 0xc6, 0xaa}, - {0, 0x5c, 0x7d, 0xaa}, {0, 0x5d, 0x5f, 0xaa}, - {0, 0x5e, 0x19, 0xaa}, {0, 0x6c, 0x0a, 0xaa}, - {0, 0x6d, 0x55, 0xaa}, {0, 0x6e, 0x11, 0xaa}, - {0, 0x6f, 0x9e, 0xaa}, {0, 0x69, 0x00, 0xaa}, - {0, 0x6a, 0x40, 0xaa}, {0, 0x01, 0x40, 0xaa}, - {0, 0x02, 0x40, 0xaa}, {0, 0x13, 0xe7, 0xaa}, - {0, 0x5f, 0xf0, 0xaa}, {0, 0x60, 0xf0, 0xaa}, - {0, 0x61, 0xf0, 0xaa}, {0, 0x27, 0xa0, 0xaa}, - {0, 0x28, 0x80, 0xaa}, {0, 0x2c, 0x90, 0xaa}, - {0, 0x4f, 0x66, 0xaa}, {0, 0x50, 0x66, 0xaa}, - {0, 0x51, 0x00, 0xaa}, {0, 0x52, 0x22, 0xaa}, - {0, 0x53, 0x5e, 0xaa}, {0, 0x54, 0x80, 0xaa}, - {0, 0x58, 0x9e, 0xaa}, {0, 0x41, 0x08, 0xaa}, - {0, 0x3f, 0x00, 0xaa}, {0, 0x75, 0x85, 0xaa}, - {0, 0x76, 0xe1, 0xaa}, {0, 0x4c, 0x00, 0xaa}, - {0, 0x77, 0x0a, 0xaa}, {0, 0x3d, 0x88, 0xaa}, - {0, 0x4b, 0x09, 0xaa}, {0, 0xc9, 0x60, 0xaa}, - {0, 0x41, 0x38, 0xaa}, {0, 0x62, 0x30, 0xaa}, - {0, 0x63, 0x30, 0xaa}, {0, 0x64, 0x08, 0xaa}, - {0, 0x94, 0x07, 0xaa}, {0, 0x95, 0x0b, 0xaa}, - {0, 0x65, 0x00, 0xaa}, {0, 0x66, 0x05, 0xaa}, - {0, 0x56, 0x50, 0xaa}, {0, 0x34, 0x11, 0xaa}, - {0, 0xa4, 0x88, 0xaa}, {0, 0x96, 0x00, 0xaa}, - {0, 0x97, 0x30, 0xaa}, {0, 0x98, 0x20, 0xaa}, - {0, 0x99, 0x30, 0xaa}, {0, 0x9a, 0x84, 0xaa}, - {0, 0x9b, 0x29, 0xaa}, {0, 0x9c, 0x03, 0xaa}, - {0, 0x78, 0x04, 0xaa}, {0, 0x79, 0x01, 0xaa}, - {0, 0xc8, 0xf0, 0xaa}, {0, 0x79, 0x0f, 0xaa}, - {0, 0xc8, 0x00, 0xaa}, {0, 0x79, 0x10, 0xaa}, - {0, 0xc8, 0x7e, 0xaa}, {0, 0x79, 0x0a, 0xaa}, - {0, 0xc8, 0x80, 0xaa}, {0, 0x79, 0x0b, 0xaa}, - {0, 0xc8, 0x01, 0xaa}, {0, 0x79, 0x0c, 0xaa}, - {0, 0xc8, 0x0f, 0xaa}, {0, 0x79, 0x0d, 0xaa}, - {0, 0xc8, 0x20, 0xaa}, {0, 0x79, 0x09, 0xaa}, - {0, 0xc8, 0x80, 0xaa}, {0, 0x79, 0x02, 0xaa}, - {0, 0xc8, 0xc0, 0xaa}, {0, 0x79, 0x03, 0xaa}, - {0, 0xc8, 0x40, 0xaa}, {0, 0x79, 0x05, 0xaa}, - {0, 0xc8, 0x30, 0xaa}, {0, 0x79, 0x26, 0xaa}, - {0, 0x11, 0x40, 0xaa}, {0, 0x3a, 0x04, 0xaa}, - {0, 0x12, 0x00, 0xaa}, {0, 0x40, 0xc0, 0xaa}, - {0, 0x8c, 0x00, 0xaa}, {0, 0x17, 0x14, 0xaa}, - {0, 0x18, 0x02, 0xaa}, {0, 0x32, 0x92, 0xaa}, - {0, 0x19, 0x02, 0xaa}, {0, 0x1a, 0x7a, 0xaa}, - {0, 0x03, 0x0a, 0xaa}, {0, 0x0c, 0x00, 0xaa}, - {0, 0x3e, 0x00, 0xaa}, {0, 0x70, 0x3a, 0xaa}, - {0, 0x71, 0x35, 0xaa}, {0, 0x72, 0x11, 0xaa}, - {0, 0x73, 0xf0, 0xaa}, {0, 0xa2, 0x02, 0xaa}, - {0, 0xb1, 0x00, 0xaa}, {0, 0xb1, 0x0c, 0xaa}, - {0, 0x1e, 0x37, 0xaa}, {0, 0xaa, 0x14, 0xaa}, - {0, 0x24, 0x80, 0xaa}, {0, 0x25, 0x74, 0xaa}, - {0, 0x26, 0xd3, 0xaa}, {0, 0x0d, 0x00, 0xaa}, - {0, 0x14, 0x18, 0xaa}, {0, 0x9d, 0x99, 0xaa}, - {0, 0x9e, 0x7f, 0xaa}, {0, 0x64, 0x08, 0xaa}, - {0, 0x94, 0x07, 0xaa}, {0, 0x95, 0x06, 0xaa}, - {0, 0x66, 0x05, 0xaa}, {0, 0x41, 0x08, 0xaa}, - {0, 0x3f, 0x00, 0xaa}, {0, 0x75, 0x07, 0xaa}, - {0, 0x76, 0xe1, 0xaa}, {0, 0x4c, 0x00, 0xaa}, - {0, 0x77, 0x00, 0xaa}, {0, 0x3d, 0xc2, 0xaa}, - {0, 0x4b, 0x09, 0xaa}, {0, 0xc9, 0x60, 0xaa}, - {0, 0x41, 0x38, 0xaa}, - {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x01, 0xcc}, - {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x21, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc},/* set jpeg */ - {0xbf, 0xc1, 0x04, 0xcc},/* */ - {0xbf, 0xcc, 0x00, 0xcc},/* */ - {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc}, - {0, 0x77, 0x05, 0xaa}, {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x20, 0xcc}, - {0, 0x24, 0x6c, 0xaa}, - {0, 0x25, 0x5c, 0xaa}, {0, 0x56, 0x50, 0xaa}, - {0, 0x4f, 0xa8, 0xaa}, {0, 0x50, 0xa5, 0xaa}, - {0, 0x51, 0x02, 0xaa}, {0, 0x52, 0x22, 0xaa}, - {0, 0x53, 0x86, 0xaa}, {0, 0x54, 0xaa, 0xaa}, - {0, 0x7a, 0x19, 0xaa}, {0, 0x7b, 0x0c, 0xaa}, - {0, 0x7c, 0x18, 0xaa}, {0, 0x7d, 0x2f, 0xaa}, - {0, 0x7e, 0x54, 0xaa}, {0, 0x7f, 0x64, 0xaa}, - {0, 0x80, 0x71, 0xaa}, {0, 0x81, 0x7d, 0xaa}, - {0, 0x82, 0x88, 0xaa}, {0, 0x83, 0x91, 0xaa}, - {0, 0x84, 0x98, 0xaa}, {0, 0x85, 0xa7, 0xaa}, - {0, 0x86, 0xb4, 0xaa}, {0, 0x87, 0xcb, 0xaa}, - {0, 0x88, 0xde, 0xaa}, {0, 0x89, 0xed, 0xaa}, - {0, 0x75, 0x86, 0xaa}, {0, 0x92, 0x00, 0xaa}, - {0, 0x3b, 0, 0xbb}, - {0, 0x3b, 0x00, 0xaa}, - {0, 0x13, 0, 0xbb}, {0, 0x13, 0xe7, 0xaa}, - {0, 0x2d, 0x00, 0xaa}, {0, 0x2e, 0x00, 0xaa}, - {0, 0x04, 0x00, 0xaa}, {0, 0x10, 0x00, 0xaa}, - {0, 0x3b, 0, 0xbb}, {0, 0x3b, 0x80, 0xaa}, - {0, 0x13, 0, 0xbb}, - {0, 0x13, 0xe7, 0xaa}, - {0, 0x1e, 0x27, 0xaa}, - {0, 0x1e, 0x27, 0xaa}, - {0, 0x3b, 0xc8, 0xaa}, - {} -}; -#endif - struct sensor_info { int sensorId; __u8 I2cAdd; @@ -1402,6 +1455,8 @@ static const struct sensor_info sensor_info_data[] = { {SENSOR_MI1320, 0x80 | 0xc8, 0x00, 0x148c, 0x64, 0x65, 0x01}, {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, +/* (tested in vc032x_probe_sensor) */ +/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x4382, 0x24, 0x25, 0x01}, */ }; /* read 'len' bytes in gspca_dev->usb_buf */ @@ -1463,7 +1518,7 @@ static void read_sensor_register(struct gspca_dev *gspca_dev, mdata = gspca_dev->usb_buf[0]; reg_r(gspca_dev, 0xa1, 0xb33c, 1); ldata = gspca_dev->usb_buf[0]; - PDEBUG(D_PROBE, "Read Sensor h (0x%02X) m (0x%02X) l (0x%02X)", + PDEBUG(D_PROBE, "Read Sensor %02x %02x%02x", hdata, mdata, ldata); reg_r(gspca_dev, 0xa1, 0xb334, 1); if (gspca_dev->usb_buf[0] == 0x02) @@ -1480,7 +1535,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) const struct sensor_info *ptsensor_info; reg_r(gspca_dev, 0xa1, 0xbfcf, 1); - PDEBUG(D_PROBE, "check sensor header %d", gspca_dev->usb_buf[0]); + PDEBUG(D_PROBE, "check sensor header %02x", gspca_dev->usb_buf[0]); for (i = 0; i < ARRAY_SIZE(sensor_info_data); i++) { ptsensor_info = &sensor_info_data[i]; reg_w(dev, 0xa0, 0x02, 0xb334); @@ -1489,16 +1544,15 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) reg_w(dev, 0xa0, 0x01, 0xb308); reg_w(dev, 0xa0, 0x0c, 0xb309); reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335); -/* PDEBUG(D_PROBE, - "check sensor VC032X -> %d Add -> ox%02X!", - i, ptsensor_info->I2cAdd); */ reg_w(dev, 0xa0, ptsensor_info->op, 0xb301); read_sensor_register(gspca_dev, ptsensor_info->IdAdd, &value); - if (value == ptsensor_info->VpId) { -/* PDEBUG(D_PROBE, "find sensor VC032X -> ox%04X!", - ptsensor_info->VpId); */ + if (value == ptsensor_info->VpId) + return ptsensor_info->sensorId; + + /* special case for MI0360 */ + if (ptsensor_info->sensorId == SENSOR_MI1310_SOC + && value == 0x4382) return ptsensor_info->sensorId; - } } return -1; } @@ -1600,13 +1654,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->epaddr = 0x02; sd->bridge = id->driver_info; - if (sd->bridge == BRIDGE_VC0321) { - cam->cam_mode = vc0321_mode; - cam->nmodes = ARRAY_SIZE(vc0321_mode); - } else { - cam->cam_mode = vc0323_mode; - cam->nmodes = ARRAY_SIZE(vc0323_mode); - } vc0321_reset(gspca_dev); sensor = vc032x_probe_sensor(gspca_dev); @@ -1616,29 +1663,36 @@ static int sd_config(struct gspca_dev *gspca_dev, return -EINVAL; case SENSOR_HV7131R: PDEBUG(D_PROBE, "Find Sensor HV7131R"); - sd->sensor = SENSOR_HV7131R; + break; + case SENSOR_MI0360: + PDEBUG(D_PROBE, "Find Sensor MI0360"); + sd->bridge = BRIDGE_VC0323; break; case SENSOR_MI1310_SOC: PDEBUG(D_PROBE, "Find Sensor MI1310_SOC"); - sd->sensor = SENSOR_MI1310_SOC; break; case SENSOR_MI1320: PDEBUG(D_PROBE, "Find Sensor MI1320"); - sd->sensor = SENSOR_MI1320; break; case SENSOR_OV7660: PDEBUG(D_PROBE, "Find Sensor OV7660"); - sd->sensor = SENSOR_OV7660; break; case SENSOR_OV7670: PDEBUG(D_PROBE, "Find Sensor OV7670"); - sd->sensor = SENSOR_OV7670; break; case SENSOR_PO3130NC: PDEBUG(D_PROBE, "Find Sensor PO3130NC"); - sd->sensor = SENSOR_PO3130NC; break; } + sd->sensor = sensor; + + if (sd->bridge == BRIDGE_VC0321) { + cam->cam_mode = vc0321_mode; + cam->nmodes = ARRAY_SIZE(vc0321_mode); + } else { + cam->cam_mode = vc0323_mode; + cam->nmodes = ARRAY_SIZE(vc0323_mode); + } sd->qindex = 7; sd->autogain = AUTOGAIN_DEF; @@ -1748,6 +1802,17 @@ static int sd_start(struct gspca_dev *gspca_dev) usb_exchange(gspca_dev, ov7670_initVGA_JPG); } break; + case SENSOR_MI0360: + GammaT = mi1320_gamma; + MatrixT = mi0360_matrix; + if (mode) { + /* 320x240 */ + usb_exchange(gspca_dev, mi0360_initQVGA_JPG); + } else { + /* 640x480 */ + usb_exchange(gspca_dev, mi0360_initVGA_JPG); + } + break; case SENSOR_MI1310_SOC: if (mode) { /* 320x240 */ -- cgit v1.2.3 From 78c81fef14409a4ac0fdcd42958b1eb1e85abdcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 07:58:29 +0100 Subject: Backed out changeset 394ff1552cd4 --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 11 +++-------- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 1 - linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 -- linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 1 - linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 5 +---- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 3 --- linux/drivers/media/video/gspca/m5602/m5602_sensor.h | 2 -- 7 files changed, 4 insertions(+), 21 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index d86b905cb..1d1fb541f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -85,9 +85,6 @@ int m5602_read_sensor(struct sd *sd, const u8 address, { int err, i; - if (!len || (len > sd->sensor->i2c_regW)) - return -EINVAL; - do { err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); } while ((*i2c_data & I2C_BUSY) && !err); @@ -105,11 +102,9 @@ int m5602_read_sensor(struct sd *sd, const u8 address, if (err < 0) goto out; - if (sd->sensor->i2c_need_flush) { - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); - if (err < 0) - goto out; - } + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + if (err < 0) + goto out; for (i = 0; (i < len) && !err; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index db64c122b..763b17ee6 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -102,7 +102,6 @@ static struct m5602_sensor mt9m111 = { .i2c_slave_id = 0xba, .i2c_regW = 2, - .i2c_need_flush = 0, .probe = mt9m111_probe, .init = mt9m111_init, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 732447932..1f33a7b8d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -152,8 +152,6 @@ static struct m5602_sensor ov9650 = { .name = "OV9650", .i2c_slave_id = 0x60, .i2c_regW = 1, - .i2c_need_flush = 1, - .probe = ov9650_probe, .init = ov9650_init, .power_down = ov9650_power_down, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index a44a4ac6b..c4dad6449 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -149,7 +149,6 @@ static struct m5602_sensor po1030 = { .i2c_slave_id = 0xdc, .i2c_regW = 1, - .i2c_need_flush = 1, .probe = po1030_probe, .init = po1030_init, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 8088e8ea4..a38103a88 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -83,12 +83,9 @@ static struct m5602_sensor s5k4aa = { .name = "S5K4AA", .probe = s5k4aa_probe, .init = s5k4aa_init, - + .power_down = s5k4aa_power_down, .i2c_slave_id = 0x5a, .i2c_regW = 2, - .i2c_need_flush = 1, - - .power_down = s5k4aa_power_down, .nctrls = 4, .ctrls = { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index e721229eb..735701127 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -65,11 +65,8 @@ static struct m5602_sensor s5k83a = { .probe = s5k83a_probe, .init = s5k83a_init, .power_down = s5k83a_power_down, - .i2c_slave_id = 0x5a, .i2c_regW = 2, - .i2c_need_flush = 0, - .nctrls = 5, .ctrls = { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 0f6e1d83f..23c0ef948 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -52,8 +52,6 @@ struct m5602_sensor { /* Width of each i2c register (in bytes) */ u8 i2c_regW; - u8 i2c_need_flush; - /* Probes if the sensor is connected */ int (*probe)(struct sd *sd); -- cgit v1.2.3 From be64de249728659c3b938b711fab3847454b10eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:41:55 +0100 Subject: Toggle read sensor sequence depending on type of sensor. Check that no more than max width of a sensor is read --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 23 ++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 1d1fb541f..fd4a1b419 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -85,9 +85,14 @@ int m5602_read_sensor(struct sd *sd, const u8 address, { int err, i; + if (!len || len > sd->sensor->i2c_regW) + return -EINVAL; + do { err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); } while ((*i2c_data & I2C_BUSY) && !err); + if (err < 0) + goto out; err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, sd->sensor->i2c_slave_id); @@ -98,13 +103,19 @@ int m5602_read_sensor(struct sd *sd, const u8 address, if (err < 0) goto out; - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); - if (err < 0) - goto out; + if (sd->sensor->i2c_regW == 1) { + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, len); + if (err < 0) + goto out; - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); - if (err < 0) - goto out; + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); + if (err < 0) + goto out; + } else { + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); + if (err < 0) + goto out; + } for (i = 0; (i < len) && !err; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); -- cgit v1.2.3 From fcb95e4cbc1e18796e71501ba453cb7b94ca300d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:42:45 +0100 Subject: Let the ov9650 use the common read sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 48 +++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 8e4a7ad48..22718c763 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -130,10 +130,10 @@ int ov9650_probe(struct sd *sd) m5602_write_bridge(sd, preinit_ov9650[i][1], data); } - if (ov9650_read_sensor(sd, OV9650_PID, &prod_id, 1)) + if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1)) return -ENODEV; - if (ov9650_read_sensor(sd, OV9650_VER, &ver_id, 1)) + if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1)) return -ENODEV; if ((prod_id == 0x96) && (ver_id == 0x52)) { @@ -199,17 +199,17 @@ int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; int err; - err = ov9650_read_sensor(sd, OV9650_COM1, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_COM1, &i2c_data, 1); if (err < 0) goto out; *val = i2c_data & 0x03; - err = ov9650_read_sensor(sd, OV9650_AECH, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1); if (err < 0) goto out; *val |= (i2c_data << 2); - err = ov9650_read_sensor(sd, OV9650_AECHM, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_AECHM, &i2c_data, 1); if (err < 0) goto out; *val |= (i2c_data & 0x3f) << 10; @@ -256,10 +256,10 @@ int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); *val = (i2c_data & 0x03) << 8; - err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); *val |= i2c_data; PDEBUG(D_V4L2, "Read gain %d", *val); return err; @@ -274,7 +274,7 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) /* The 2 MSB */ /* Read the OV9650_VREF register first to avoid corrupting the VREF high and low bits */ - ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); /* Mask away all uninteresting bits */ i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); @@ -292,7 +292,7 @@ int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_RED, &i2c_data, 1); *val = i2c_data; PDEBUG(D_V4L2, "Read red gain %d", *val); @@ -321,7 +321,7 @@ int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_BLUE, &i2c_data, 1); *val = i2c_data; PDEBUG(D_V4L2, "Read blue gain %d", *val); @@ -350,7 +350,7 @@ int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (dmi_check_system(ov9650_flip_dmi_table)) *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1; else @@ -367,7 +367,7 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; PDEBUG(D_V4L2, "Set horizontal flip to %d", val); - err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) goto out; @@ -389,7 +389,7 @@ int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (dmi_check_system(ov9650_flip_dmi_table)) *val = ((i2c_data & 0x10) >> 4) ? 0 : 1; else @@ -406,7 +406,7 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; PDEBUG(D_V4L2, "Set vertical flip to %d", val); - err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) goto out; @@ -428,12 +428,12 @@ int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) goto out; *val = (i2c_data & 0x03) << 8; - err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); *val |= i2c_data; PDEBUG(D_V4L2, "Read gain %d", *val); out: @@ -450,7 +450,7 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) /* Read the OV9650_VREF register first to avoid corrupting the VREF high and low bits */ - err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) goto out; @@ -474,7 +474,7 @@ int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); *val = (i2c_data & OV9650_AWB_EN) >> 1; PDEBUG(D_V4L2, "Read auto white balance %d", *val); @@ -488,7 +488,7 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; PDEBUG(D_V4L2, "Set auto white balance to %d", val); - err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); if (err < 0) goto out; @@ -504,7 +504,7 @@ int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); *val = (i2c_data & OV9650_AGC_EN) >> 2; PDEBUG(D_V4L2, "Read auto gain control %d", *val); @@ -518,7 +518,7 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; PDEBUG(D_V4L2, "Set auto gain control to %d", val); - err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); if (err < 0) goto out; @@ -534,7 +534,7 @@ static void ov9650_dump_registers(struct sd *sd) info("Dumping the ov9650 register state"); for (address = 0; address < 0xa9; address++) { u8 value; - ov9650_read_sensor(sd, address, &value, 1); + m5602_read_sensor(sd, address, &value, 1); info("register 0x%x contains 0x%x", address, value); } @@ -546,9 +546,9 @@ static void ov9650_dump_registers(struct sd *sd) u8 old_value, ctrl_value; u8 test_value[2] = {0xff, 0xff}; - ov9650_read_sensor(sd, address, &old_value, 1); + m5602_read_sensor(sd, address, &old_value, 1); m5602_write_sensor(sd, address, test_value, 1); - ov9650_read_sensor(sd, address, &ctrl_value, 1); + m5602_read_sensor(sd, address, &ctrl_value, 1); if (ctrl_value == test_value[0]) info("register 0x%x is writeable", address); -- cgit v1.2.3 From ed7d5fae25dac6127a863ac401037230e03e621a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:44:19 +0100 Subject: Remove the ov9650 implementation of the read sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 39 ---------------------- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 3 -- 2 files changed, 42 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 22718c763..6531f46e8 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -65,45 +65,6 @@ static static void ov9650_dump_registers(struct sd *sd); -int ov9650_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - - /* The ov9650 registers have a max depth of one byte */ - if (len > 1 || !len) - return -EINVAL; - - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); - } while ((*i2c_data & I2C_BUSY) && !err); - - err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, - ov9650.i2c_slave_id); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); - - for (i = 0; (i < len) && !err; i++) { - err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - - PDEBUG(D_CONF, "Reading sensor register " - "0x%x containing 0x%x ", address, *i2c_data); - } - -out: - return (err < 0) ? err : 0; -} - int ov9650_probe(struct sd *sd) { u8 prod_id = 0, ver_id = 0, i; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 1f33a7b8d..3435a05ab 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -126,9 +126,6 @@ int ov9650_probe(struct sd *sd); int ov9650_init(struct sd *sd); int ov9650_power_down(struct sd *sd); -int ov9650_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -- cgit v1.2.3 From 3672a2698d0c9c85a3b0425464b6810b07cb9f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:46:39 +0100 Subject: Let the po1030 use the common read_sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index f52a3cd33..ae257a9a5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -46,10 +46,10 @@ int po1030_probe(struct sd *sd) m5602_write_bridge(sd, preinit_po1030[i][1], data); } - if (po1030_read_sensor(sd, 0x3, &prod_id, 1)) + if (m5602_read_sensor(sd, 0x3, &prod_id, 1)) return -ENODEV; - if (po1030_read_sensor(sd, 0x4, &ver_id, 1)) + if (m5602_read_sensor(sd, 0x4, &ver_id, 1)) return -ENODEV; if ((prod_id == 0x02) && (ver_id == 0xef)) { @@ -67,7 +67,7 @@ sensor_found: } int po1030_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) + u8 *i2c_data, const u8 len) { int err, i; @@ -144,13 +144,13 @@ int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; int err; - err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_H, + err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_H, &i2c_data, 1); if (err < 0) goto out; *val = (i2c_data << 8); - err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_M, + err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_M, &i2c_data, 1); *val |= i2c_data; @@ -192,7 +192,7 @@ int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; int err; - err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN, + err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN, &i2c_data, 1); *val = i2c_data; PDEBUG(D_V4L2, "Read global gain %d", *val); @@ -206,7 +206,7 @@ int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; int err; - err = po1030_read_sensor(sd, PO1030_REG_CONTROL2, + err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); *val = (i2c_data >> 7) & 0x01 ; @@ -238,7 +238,7 @@ int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; int err; - err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN, + err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN, &i2c_data, 1); *val = (i2c_data >> 6) & 0x01; @@ -283,7 +283,7 @@ int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; int err; - err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN, + err = m5602_read_sensor(sd, PO1030_REG_RED_GAIN, &i2c_data, 1); *val = i2c_data; PDEBUG(D_V4L2, "Read red gain %d", *val); @@ -309,7 +309,7 @@ int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; int err; - err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN, + err = m5602_read_sensor(sd, PO1030_REG_BLUE_GAIN, &i2c_data, 1); *val = i2c_data; PDEBUG(D_V4L2, "Read blue gain %d", *val); @@ -342,7 +342,7 @@ static void po1030_dump_registers(struct sd *sd) info("Dumping the po1030 sensor core registers"); for (address = 0; address < 0x7f; address++) { - po1030_read_sensor(sd, address, &value, 1); + m5602_read_sensor(sd, address, &value, 1); info("register 0x%x contains 0x%x", address, value); } @@ -354,9 +354,9 @@ static void po1030_dump_registers(struct sd *sd) u8 old_value, ctrl_value; u8 test_value[2] = {0xff, 0xff}; - po1030_read_sensor(sd, address, &old_value, 1); + m5602_read_sensor(sd, address, &old_value, 1); m5602_write_sensor(sd, address, test_value, 1); - po1030_read_sensor(sd, address, &ctrl_value, 1); + m5602_read_sensor(sd, address, &ctrl_value, 1); if (ctrl_value == test_value[0]) info("register 0x%x is writeable", address); -- cgit v1.2.3 From 278cc4046c62855b1ef808a2c69e15c6e619bd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:47:21 +0100 Subject: Remove the po1030 read_sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 33 ---------------------- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 3 -- 2 files changed, 36 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index ae257a9a5..6ec4d2c63 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -66,39 +66,6 @@ sensor_found: return 0; } -int po1030_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); - } while ((*i2c_data & I2C_BUSY) && !err); - - err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, - sd->sensor->i2c_slave_id); - if (err < 0) - goto out; - err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); - if (err < 0) - goto out; - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); - if (err < 0) - goto out; - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); - if (err < 0) - goto out; - - for (i = 0; (i < len) && !err; i++) { - err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - - PDEBUG(D_CONF, "Reading sensor register " - "0x%x containing 0x%x ", address, *i2c_data); - } -out: - return err; -} - int po1030_init(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index c4dad6449..3ca5a0218 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -128,9 +128,6 @@ int po1030_probe(struct sd *sd); int po1030_init(struct sd *sd); int po1030_power_down(struct sd *sd); -int po1030_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -- cgit v1.2.3 From 731f837521aa564ec800b1549cefd34d489ea56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:48:33 +0100 Subject: Convert the mt9m111 to use the common read_sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index ae3b62ab4..0a4158f57 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -51,7 +51,7 @@ int mt9m111_probe(struct sd *sd) } } - if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2)) + if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2)) return -ENODEV; if ((data[0] == 0x14) && (data[1] == 0x3a)) { @@ -106,7 +106,7 @@ int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; - err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, + err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); *val = data[0] & MT9M111_RMB_MIRROR_ROWS; PDEBUG(D_V4L2, "Read vertical flip %d", *val); @@ -127,7 +127,7 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) goto out; - err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); if (err < 0) goto out; @@ -144,7 +144,7 @@ int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; - err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, + err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); *val = data[0] & MT9M111_RMB_MIRROR_COLS; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); @@ -165,7 +165,7 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) goto out; - err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); if (err < 0) goto out; @@ -182,7 +182,7 @@ int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; - err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); + err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); tmp = ((data[1] << 8) | data[0]); *val = ((tmp & (1 << 10)) * 2) | @@ -276,7 +276,7 @@ static void mt9m111_dump_registers(struct sd *sd) value[1] = MT9M111_SENSOR_CORE; m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); for (address = 0; address < 0xff; address++) { - mt9m111_read_sensor(sd, address, value, 2); + m5602_read_sensor(sd, address, value, 2); info("register 0x%x contains 0x%x%x", address, value[0], value[1]); } @@ -285,7 +285,7 @@ static void mt9m111_dump_registers(struct sd *sd) value[1] = MT9M111_COLORPIPE; m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); for (address = 0; address < 0xff; address++) { - mt9m111_read_sensor(sd, address, value, 2); + m5602_read_sensor(sd, address, value, 2); info("register 0x%x contains 0x%x%x", address, value[0], value[1]); } @@ -294,7 +294,7 @@ static void mt9m111_dump_registers(struct sd *sd) value[1] = MT9M111_CAMERA_CONTROL; m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); for (address = 0; address < 0xff; address++) { - mt9m111_read_sensor(sd, address, value, 2); + m5602_read_sensor(sd, address, value, 2); info("register 0x%x contains 0x%x%x", address, value[0], value[1]); } -- cgit v1.2.3 From d5770604b7be7fb4a69f630bf417e41bceea1ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:50:17 +0100 Subject: Remove the mt9m111 implementation of the read_sensor function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../media/video/gspca/m5602/m5602_mt9m111.c | 33 ---------------------- .../media/video/gspca/m5602/m5602_mt9m111.h | 3 -- 2 files changed, 36 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 0a4158f57..c0e71c331 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -233,39 +233,6 @@ out: return err; } -int mt9m111_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) { - int err, i; - - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); - } while ((*i2c_data & I2C_BUSY) && !err); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, - sd->sensor->i2c_slave_id); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a); - if (err < 0) - goto out; - - for (i = 0; i < len && !err; i++) { - err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - - PDEBUG(D_CONF, "Reading sensor register " - "0x%x contains 0x%x ", address, *i2c_data); - } -out: - return err; -} - static void mt9m111_dump_registers(struct sd *sd) { u8 address, value[2] = {0x00, 0x00}; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 763b17ee6..c5f75aa59 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -87,9 +87,6 @@ int mt9m111_probe(struct sd *sd); int mt9m111_init(struct sd *sd); int mt9m111_power_down(struct sd *sd); -int mt9m111_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -- cgit v1.2.3 From 66e7a7fdefc402243c05f0448c242d6b7b87cc84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:51:11 +0100 Subject: Convert the s5k4aa sensor to use the common read_sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index d420ee6ba..327315e25 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -104,7 +104,7 @@ int s5k4aa_probe(struct sd *sd) } /* Test some registers, but we don't know their exact meaning yet */ - if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) + if (m5602_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) return -ENODEV; if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) @@ -200,18 +200,18 @@ int s5k4aa_init(struct sd *sd) u8 data = 0x02; info("vertical flip quirk active"); m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); + m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); data |= S5K4AA_RM_V_FLIP; data &= ~S5K4AA_RM_H_FLIP; m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); /* Decrement COLSTART to preserve color order (BGGR) */ - s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); data--; m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); /* Increment ROWSTART to preserve color order (BGGR) */ - s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); data++; m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } @@ -234,12 +234,12 @@ int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) if (err < 0) goto out; - err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); if (err < 0) goto out; *val = data << 8; - err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); *val |= data; PDEBUG(D_V4L2, "Read exposure %d", *val); out: @@ -276,7 +276,7 @@ int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) if (err < 0) goto out; - err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); *val = (data & S5K4AA_RM_V_FLIP) >> 7; PDEBUG(D_V4L2, "Read vertical flip %d", *val); @@ -304,14 +304,14 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) goto out; if (val) { - err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); if (err < 0) goto out; data++; err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } else { - err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); if (err < 0) goto out; @@ -332,7 +332,7 @@ int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) if (err < 0) goto out; - err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); *val = (data & S5K4AA_RM_H_FLIP) >> 6; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); out: @@ -360,7 +360,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) goto out; if (val) { - err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); if (err < 0) goto out; data++; @@ -368,7 +368,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) goto out; } else { - err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); if (err < 0) goto out; data--; @@ -388,7 +388,7 @@ int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) if (err < 0) goto out; - err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1); + err = m5602_read_sensor(sd, S5K4AA_GAIN_2, &data, 1); *val = data; PDEBUG(D_V4L2, "Read gain %d", *val); @@ -418,13 +418,13 @@ static void s5k4aa_dump_registers(struct sd *sd) { int address; u8 page, old_page; - s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); + m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); for (page = 0; page < 16; page++) { m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); info("Dumping the s5k4aa register state for page 0x%x", page); for (address = 0; address <= 0xff; address++) { u8 value = 0; - s5k4aa_read_sensor(sd, address, &value, 1); + m5602_read_sensor(sd, address, &value, 1); info("register 0x%x contains 0x%x", address, value); } @@ -438,9 +438,9 @@ static void s5k4aa_dump_registers(struct sd *sd) for (address = 0; address <= 0xff; address++) { u8 old_value, ctrl_value, test_value = 0xff; - s5k4aa_read_sensor(sd, address, &old_value, 1); + m5602_read_sensor(sd, address, &old_value, 1); m5602_write_sensor(sd, address, &test_value, 1); - s5k4aa_read_sensor(sd, address, &ctrl_value, 1); + m5602_read_sensor(sd, address, &ctrl_value, 1); if (ctrl_value == test_value) info("register 0x%x is writeable", address); -- cgit v1.2.3 From ad39d2a87788f70483d08d0b03e60c1a4f7717aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:52:53 +0100 Subject: Remove the s5k4aa implementation of the read_sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 40 ---------------------- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 3 -- 2 files changed, 43 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 327315e25..2bd7d4d99 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -121,46 +121,6 @@ sensor_found: return 0; } -int s5k4aa_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); - } while ((*i2c_data & I2C_BUSY) && !err); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, - sd->sensor->i2c_slave_id); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); - if (err < 0) - goto out; - - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); - } while ((*i2c_data & I2C_BUSY) && !err); - if (err < 0) - goto out; - - for (i = 0; (i < len) && !err; i++) { - err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - - PDEBUG(D_CONF, "Reading sensor register " - "0x%x containing 0x%x ", address, *i2c_data); - } -out: - return err; -} - int s5k4aa_init(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index a38103a88..1f88b0d04 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -67,9 +67,6 @@ int s5k4aa_probe(struct sd *sd); int s5k4aa_init(struct sd *sd); int s5k4aa_power_down(struct sd *sd); -int s5k4aa_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -- cgit v1.2.3 From 13ab4de92d1f918e6d93824e0964c9726183c1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:54:13 +0100 Subject: Convert the s5k83a sensor to use the common read_sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 372303074..811766b32 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -51,10 +51,10 @@ int s5k83a_probe(struct sd *sd) /* We don't know what register (if any) that contain the product id * Just pick the first addresses that seem to produce the same results * on multiple machines */ - if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1)) + if (m5602_read_sensor(sd, 0x00, &prod_id, 1)) return -ENODEV; - if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1)) + if (m5602_read_sensor(sd, 0x01, &ver_id, 1)) return -ENODEV; if ((prod_id == 0xff) || (ver_id == 0xff)) @@ -154,14 +154,14 @@ void s5k83a_dump_registers(struct sd *sd) { int address; u8 page, old_page; - s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); + m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); for (page = 0; page < 16; page++) { m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); info("Dumping the s5k83a register state for page 0x%x", page); for (address = 0; address <= 0xff; address++) { u8 val = 0; - s5k83a_read_sensor(sd, address, &val, 1); + m5602_read_sensor(sd, address, &val, 1); info("register 0x%x contains 0x%x", address, val); } @@ -175,9 +175,9 @@ void s5k83a_dump_registers(struct sd *sd) for (address = 0; address <= 0xff; address++) { u8 old_val, ctrl_val, test_val = 0xff; - s5k83a_read_sensor(sd, address, &old_val, 1); + m5602_read_sensor(sd, address, &old_val, 1); m5602_write_sensor(sd, address, &test_val, 1); - s5k83a_read_sensor(sd, address, &ctrl_val, 1); + m5602_read_sensor(sd, address, &ctrl_val, 1); if (ctrl_val == test_val) info("register 0x%x is writeable", address); @@ -198,7 +198,7 @@ int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) u8 data[2]; struct sd *sd = (struct sd *) gspca_dev; - err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2); + err = m5602_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2); if (err < 0) goto out; @@ -243,7 +243,7 @@ int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val) u8 data; struct sd *sd = (struct sd *) gspca_dev; - err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1); + err = m5602_read_sensor(sd, S5K83A_WHITENESS, &data, 1); if (err < 0) goto out; @@ -271,7 +271,7 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) u8 data[2]; struct sd *sd = (struct sd *) gspca_dev; - err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2); + err = m5602_read_sensor(sd, S5K83A_GAIN, data, 2); if (err < 0) goto out; @@ -308,7 +308,7 @@ int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) if (err < 0) goto out; - err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); + err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); *val = (data[0] | 0x40) ? 1 : 0; out: @@ -326,7 +326,7 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) goto out; - err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); + err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) goto out; @@ -355,7 +355,7 @@ int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) if (err < 0) goto out; - err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); + err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); *val = (data[0] | 0x80) ? 1 : 0; out: @@ -373,7 +373,7 @@ int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) goto out; - err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); + err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) goto out; -- cgit v1.2.3 From fd81ab668355ea851600bbdd6d3f3414c8cd0c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:55:07 +0100 Subject: Remove the s5k83a specific read_sensor function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 37 ---------------------- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 3 -- 2 files changed, 40 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 811766b32..af3f2dc2c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -70,43 +70,6 @@ sensor_found: return 0; } -int s5k83a_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); - } while ((*i2c_data & I2C_BUSY) && !err); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, - sd->sensor->i2c_slave_id); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); - if (err < 0) - goto out; - - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); - - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); - } while ((*i2c_data & I2C_BUSY) && !err); - - for (i = 0; i < len && !len; i++) { - err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - - PDEBUG(D_CONF, "Reading sensor register " - "0x%x containing 0x%x ", address, *i2c_data); - } - -out: - return err; -} - int s5k83a_init(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 735701127..05ccb5b57 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -46,9 +46,6 @@ int s5k83a_probe(struct sd *sd); int s5k83a_init(struct sd *sd); int s5k83a_power_down(struct sd *sd); -int s5k83a_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val); -- cgit v1.2.3 From cf10cacd2fad010966042d84b062929da66d1bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 17:58:20 +0100 Subject: The po1030 never sends long i2c messages, no need to test for that in the init phase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 6ec4d2c63..f9932a16f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -87,12 +87,6 @@ int po1030_init(struct sd *sd) init_po1030[i][1], data, 1); break; - case SENSOR_LONG: - data[0] = init_po1030[i][2]; - data[1] = init_po1030[i][3]; - err = m5602_write_sensor(sd, - init_po1030[i][1], data, 2); - break; default: info("Invalid stream command, exiting init"); return -EINVAL; -- cgit v1.2.3 From b42f864d198ae7d339ae2ad20df320588c9d4550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 27 Nov 2008 18:07:24 +0100 Subject: Use read/modify/write when toggling vflip on the po1030 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index f9932a16f..2e7fb9167 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -184,12 +184,16 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) int err; PDEBUG(D_V4L2, "Set hflip %d", val); + err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); + if (err < 0) + goto out; - i2c_data = (val & 0x01) << 7; + i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7); err = m5602_write_sensor(sd, PO1030_REG_CONTROL2, - &i2c_data, 1); + &i2c_data, 1); +out: return err; } @@ -216,12 +220,16 @@ int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) int err; PDEBUG(D_V4L2, "Set vflip %d", val); + err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); + if (err < 0) + goto out; - i2c_data = (val & 0x01) << 6; + i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6); err = m5602_write_sensor(sd, PO1030_REG_CONTROL2, - &i2c_data, 1); + &i2c_data, 1); +out: return err; } -- cgit v1.2.3 From 24e5836b4aa995ffe84be439a2a69517f01201ed Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 28 Nov 2008 12:51:50 +0100 Subject: gspca: Do the webcam microphone work when present. From: Jean-Francois Moine This patch adds the set/get/enum audio controls. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 34 ++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index baf4aa524..4fda0fca6 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -671,7 +671,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0); if (ret < 0) - PDEBUG(D_ERR|D_STREAM, "set interface 0 err %d", ret); + PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret); return ret; } @@ -1081,6 +1081,35 @@ static int vidioc_g_ctrl(struct file *file, void *priv, return -EINVAL; } +/*fixme: have an audio flag in gspca_dev?*/ +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + if (audio->index != 0) + return -EINVAL; + return 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + memset(audio, 0, sizeof *audio); + strcpy(audio->name, "Microphone"); + return 0; +} + +static int vidioc_enumaudio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + if (audio->index != 0) + return -EINVAL; + + strcpy(audio->name, "Microphone"); + audio->capability = 0; + audio->mode = 0; + return 0; +} + static int vidioc_querymenu(struct file *file, void *priv, struct v4l2_querymenu *qmenu) { @@ -1797,6 +1826,9 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_enumaudio = vidioc_enumaudio, .vidioc_querymenu = vidioc_querymenu, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, -- cgit v1.2.3 From aa5b5a04837a6bb93286e723b500f6923e366c4d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 28 Nov 2008 19:31:43 +0100 Subject: gspca: Align the 640x480 and 320x240 init of tas5130 in zc3xx. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/zc3xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index adbca6a9d..ae4e30b52 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -5760,7 +5760,7 @@ static const struct usb_action tas5130cxx_Initial[] = { {} }; static const struct usb_action tas5130cxx_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, +/*?? {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, @@ -6084,7 +6084,7 @@ static const struct usb_action tas5130c_vf0250_InitialScale[] = { {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */ {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */ {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */ - {0xaa, 0x01, 0x0000}, +/*?? {0xaa, 0x01, 0x0000}, */ {0xaa, 0x01, 0x0000}, {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */ {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */ @@ -6100,8 +6100,8 @@ static const struct usb_action tas5130c_vf0250_InitialScale[] = { {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */ {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */ {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */ - {0xa0, 0x00, 0x0039}, - {0xa1, 0x01, 0x0037}, +/*?? {0xa0, 0x00, 0x0039}, + {0xa1, 0x01, 0x0037}, */ {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */ {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */ {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */ -- cgit v1.2.3 From 64c1d1df18357731250591e657cbacd874f743ce Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 16:59:33 +0100 Subject: upd64031a: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/upd64031a.c | 193 ++++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 80 deletions(-) diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c index dfca5ed6e..df5f4b0c8 100644 --- a/linux/drivers/media/video/upd64031a.c +++ b/linux/drivers/media/video/upd64031a.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -68,6 +68,7 @@ enum { }; struct upd64031a_state { + struct v4l2_subdev sd; u8 regs[TOT_REGS]; u8 gr_mode; u8 direct_3dycs_connect; @@ -75,6 +76,11 @@ struct upd64031a_state { u8 ext_vert_sync; }; +static inline struct upd64031a_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct upd64031a_state, sd); +} + static u8 upd64031a_init[] = { 0x00, 0xb8, 0x48, 0xd2, 0xe6, 0x03, 0x10, 0x0b, 0xaf, 0x7f, @@ -84,8 +90,9 @@ static u8 upd64031a_init[] = { /* ------------------------------------------------------------------------ */ -static u8 upd64031a_read(struct i2c_client *client, u8 reg) +static u8 upd64031a_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); u8 buf[2]; if (reg >= sizeof(buf)) @@ -96,106 +103,127 @@ static u8 upd64031a_read(struct i2c_client *client, u8 reg) /* ------------------------------------------------------------------------ */ -static void upd64031a_write(struct i2c_client *client, u8 reg, u8 val) +static void upd64031a_write(struct v4l2_subdev *sd, u8 reg, u8 val) { + struct i2c_client *client = v4l2_get_subdevdata(sd); u8 buf[2]; buf[0] = reg; buf[1] = val; - v4l_dbg(1, debug, client, "write reg: %02X val: %02X\n", reg, val); + v4l2_dbg(1, debug, sd, "write reg: %02X val: %02X\n", reg, val); if (i2c_master_send(client, buf, 2) != 2) - v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val); + v4l2_err(sd, "I/O error write 0x%02x/0x%02x\n", reg, val); } /* ------------------------------------------------------------------------ */ /* The input changed due to new input or channel changed */ -static void upd64031a_change(struct i2c_client *client) +static int upd64031a_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) { - struct upd64031a_state *state = i2c_get_clientdata(client); + struct upd64031a_state *state = to_state(sd); u8 reg = state->regs[R00]; - v4l_dbg(1, debug, client, "changed input or channel\n"); - upd64031a_write(client, R00, reg | 0x10); - upd64031a_write(client, R00, reg & ~0x10); + v4l2_dbg(1, debug, sd, "changed input or channel\n"); + upd64031a_write(sd, R00, reg | 0x10); + upd64031a_write(sd, R00, reg & ~0x10); + return 0; } /* ------------------------------------------------------------------------ */ +static int upd64031a_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct upd64031a_state *state = to_state(sd); + u8 r00, r05, r08; + + state->gr_mode = (route->input & 3) << 6; + state->direct_3dycs_connect = (route->input & 0xc) << 4; + state->ext_comp_sync = + (route->input & UPD64031A_COMPOSITE_EXTERNAL) << 1; + state->ext_vert_sync = + (route->input & UPD64031A_VERTICAL_EXTERNAL) << 2; + r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode; + r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) | + state->ext_comp_sync | state->ext_vert_sync; + r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) | + state->direct_3dycs_connect; + upd64031a_write(sd, R00, r00); + upd64031a_write(sd, R05, r05); + upd64031a_write(sd, R08, r08); + return upd64031a_s_frequency(sd, NULL); +} + +static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_UPD64031A, 0); +} + +static int upd64031a_log_status(struct v4l2_subdev *sd) +{ + v4l2_info(sd, "Status: SA00=0x%02x SA01=0x%02x\n", + upd64031a_read(sd, 0), upd64031a_read(sd, 1)); + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = upd64031a_read(sd, reg->reg & 0xff); + return 0; +} + +static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + upd64031a_write(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} +#endif + static int upd64031a_command(struct i2c_client *client, unsigned cmd, void *arg) { - struct upd64031a_state *state = i2c_get_clientdata(client); - struct v4l2_routing *route = arg; - - switch (cmd) { - case VIDIOC_S_FREQUENCY: - upd64031a_change(client); - break; - - case VIDIOC_INT_G_VIDEO_ROUTING: - route->input = (state->gr_mode >> 6) | - (state->direct_3dycs_connect >> 4) | - (state->ext_comp_sync >> 1) | - (state->ext_vert_sync >> 2); - route->output = 0; - break; - - case VIDIOC_INT_S_VIDEO_ROUTING: - { - u8 r00, r05, r08; - - state->gr_mode = (route->input & 3) << 6; - state->direct_3dycs_connect = (route->input & 0xc) << 4; - state->ext_comp_sync = - (route->input & UPD64031A_COMPOSITE_EXTERNAL) << 1; - state->ext_vert_sync = - (route->input & UPD64031A_VERTICAL_EXTERNAL) << 2; - r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode; - r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) | - state->ext_comp_sync | state->ext_vert_sync; - r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) | - state->direct_3dycs_connect; - upd64031a_write(client, R00, r00); - upd64031a_write(client, R05, r05); - upd64031a_write(client, R08, r08); - upd64031a_change(client); - break; - } - - case VIDIOC_LOG_STATUS: - v4l_info(client, "Status: SA00=0x%02x SA01=0x%02x\n", - upd64031a_read(client, 0), upd64031a_read(client, 1)); - break; + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ +static const struct v4l2_subdev_core_ops upd64031a_core_ops = { + .log_status = upd64031a_log_status, + .g_chip_ident = upd64031a_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (cmd == VIDIOC_DBG_G_REGISTER) { - reg->val = upd64031a_read(client, reg->reg & 0xff); - break; - } - upd64031a_write(client, reg->reg & 0xff, reg->val & 0xff); - break; - } + .g_register = upd64031a_g_register, + .s_register = upd64031a_s_register, #endif +}; - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, - V4L2_IDENT_UPD64031A, 0); +static const struct v4l2_subdev_tuner_ops upd64031a_tuner_ops = { + .s_frequency = upd64031a_s_frequency, +}; - default: - break; - } - return 0; -} +static const struct v4l2_subdev_video_ops upd64031a_video_ops = { + .s_routing = upd64031a_s_routing, +}; + +static const struct v4l2_subdev_ops upd64031a_ops = { + .core = &upd64031a_core_ops, + .tuner = &upd64031a_tuner_ops, + .video = &upd64031a_video_ops, +}; /* ------------------------------------------------------------------------ */ @@ -205,6 +233,7 @@ static int upd64031a_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct upd64031a_state *state; + struct v4l2_subdev *sd; int i; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -216,19 +245,23 @@ static int upd64031a_probe(struct i2c_client *client, state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; - i2c_set_clientdata(client, state); + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &upd64031a_ops); memcpy(state->regs, upd64031a_init, sizeof(state->regs)); state->gr_mode = UPD64031A_GR_ON << 6; state->direct_3dycs_connect = UPD64031A_3DYCS_COMPOSITE << 4; state->ext_comp_sync = state->ext_vert_sync = 0; for (i = 0; i < TOT_REGS; i++) - upd64031a_write(client, i, state->regs[i]); + upd64031a_write(sd, i, state->regs[i]); return 0; } static int upd64031a_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From ebd704a6cbea5701de4bf28b48459fe0eb62021f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 17:00:30 +0100 Subject: upd64083: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/upd64083.c | 166 ++++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 69 deletions(-) diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c index 5f0c6919d..fe71b038b 100644 --- a/linux/drivers/media/video/upd64083.c +++ b/linux/drivers/media/video/upd64083.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -57,11 +57,17 @@ enum { }; struct upd64083_state { + struct v4l2_subdev sd; u8 mode; u8 ext_y_adc; u8 regs[TOT_REGS]; }; +static inline struct upd64083_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct upd64083_state, sd); +} + /* Initial values when used in combination with the NEC upd64031a ghost reduction chip. */ static u8 upd64083_init[] = { @@ -74,34 +80,24 @@ static u8 upd64083_init[] = { /* ------------------------------------------------------------------------ */ -static void upd64083_log_status(struct i2c_client *client) -{ - u8 buf[7]; - - i2c_master_recv(client, buf, 7); - v4l_info(client, "Status: SA00=%02x SA01=%02x SA02=%02x SA03=%02x " - "SA04=%02x SA05=%02x SA06=%02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); -} - -/* ------------------------------------------------------------------------ */ - -static void upd64083_write(struct i2c_client *client, u8 reg, u8 val) +static void upd64083_write(struct v4l2_subdev *sd, u8 reg, u8 val) { + struct i2c_client *client = v4l2_get_subdevdata(sd); u8 buf[2]; buf[0] = reg; buf[1] = val; - v4l_dbg(1, debug, client, "write reg: %02x val: %02x\n", reg, val); + v4l2_dbg(1, debug, sd, "write reg: %02x val: %02x\n", reg, val); if (i2c_master_send(client, buf, 2) != 2) - v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val); + v4l2_err(sd, "I/O error write 0x%02x/0x%02x\n", reg, val); } /* ------------------------------------------------------------------------ */ #ifdef CONFIG_VIDEO_ADV_DEBUG -static u8 upd64083_read(struct i2c_client *client, u8 reg) +static u8 upd64083_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); u8 buf[7]; if (reg >= sizeof(buf)) @@ -113,67 +109,94 @@ static u8 upd64083_read(struct i2c_client *client, u8 reg) /* ------------------------------------------------------------------------ */ -static int upd64083_command(struct i2c_client *client, unsigned cmd, void *arg) +static int upd64083_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct upd64083_state *state = i2c_get_clientdata(client); - struct v4l2_routing *route = arg; - - switch (cmd) { - case VIDIOC_INT_G_VIDEO_ROUTING: - route->input = (state->mode >> 6) | (state->ext_y_adc >> 3); - route->output = 0; - break; - - case VIDIOC_INT_S_VIDEO_ROUTING: - { - u8 r00, r02; - - if (route->input > 7 || (route->input & 6) == 6) - return -EINVAL; - state->mode = (route->input & 3) << 6; - state->ext_y_adc = (route->input & UPD64083_EXT_Y_ADC) << 3; - r00 = (state->regs[R00] & ~(3 << 6)) | state->mode; - r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc; - upd64083_write(client, R00, r00); - upd64083_write(client, R02, r02); - break; - } - - case VIDIOC_LOG_STATUS: - upd64083_log_status(client); - break; + struct upd64083_state *state = to_state(sd); + u8 r00, r02; + + if (route->input > 7 || (route->input & 6) == 6) + return -EINVAL; + state->mode = (route->input & 3) << 6; + state->ext_y_adc = (route->input & UPD64083_EXT_Y_ADC) << 3; + r00 = (state->regs[R00] & ~(3 << 6)) | state->mode; + r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc; + upd64083_write(sd, R00, r00); + upd64083_write(sd, R02, r02); + return 0; +} #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; +static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = upd64083_read(sd, reg->reg & 0xff); + return 0; +} - if (!v4l2_chip_match_i2c_client(client, +static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (cmd == VIDIOC_DBG_G_REGISTER) { - reg->val = upd64083_read(client, reg->reg & 0xff); - break; - } - upd64083_write(client, reg->reg & 0xff, reg->val & 0xff); - break; - } + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + upd64083_write(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} #endif - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, - V4L2_IDENT_UPD64083, 0); +static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_UPD64083, 0); +} - default: - break; - } +static int upd64083_log_status(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + u8 buf[7]; + i2c_master_recv(client, buf, 7); + v4l2_info(sd, "Status: SA00=%02x SA01=%02x SA02=%02x SA03=%02x " + "SA04=%02x SA05=%02x SA06=%02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); return 0; } +static int upd64083_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops upd64083_core_ops = { + .log_status = upd64083_log_status, + .g_chip_ident = upd64083_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = upd64083_g_register, + .s_register = upd64083_s_register, +#endif +}; + +static const struct v4l2_subdev_video_ops upd64083_video_ops = { + .s_routing = upd64083_s_routing, +}; + +static const struct v4l2_subdev_ops upd64083_ops = { + .core = &upd64083_core_ops, + .video = &upd64083_video_ops, +}; + /* ------------------------------------------------------------------------ */ /* i2c implementation */ @@ -182,6 +205,7 @@ static int upd64083_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct upd64083_state *state; + struct v4l2_subdev *sd; int i; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -193,19 +217,23 @@ static int upd64083_probe(struct i2c_client *client, state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; - i2c_set_clientdata(client, state); + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &upd64083_ops); /* Initially assume that a ghost reduction chip is present */ state->mode = 0; /* YCS mode */ state->ext_y_adc = (1 << 5); memcpy(state->regs, upd64083_init, TOT_REGS); for (i = 0; i < TOT_REGS; i++) - upd64083_write(client, i, state->regs[i]); + upd64083_write(sd, i, state->regs[i]); return 0; } static int upd64083_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From 88c733e9ba8fc0b0911bd97cd808ec5b080fa9e4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 17:01:28 +0100 Subject: vp27smpx: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vp27smpx.c | 126 ++++++++++++++++++++++++----------- 1 file changed, 86 insertions(+), 40 deletions(-) diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c index 80de9e796..cd9df6a1c 100644 --- a/linux/drivers/media/video/vp27smpx.c +++ b/linux/drivers/media/video/vp27smpx.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -46,13 +46,20 @@ I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ struct vp27smpx_state { + struct v4l2_subdev sd; int radio; u32 audmode; }; -static void vp27smpx_set_audmode(struct i2c_client *client, u32 audmode) +static inline struct vp27smpx_state *to_state(struct v4l2_subdev *sd) { - struct vp27smpx_state *state = i2c_get_clientdata(client); + return container_of(sd, struct vp27smpx_state, sd); +} + +static void vp27smpx_set_audmode(struct v4l2_subdev *sd, u32 audmode) +{ + struct vp27smpx_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); u8 data[3] = { 0x00, 0x00, 0x04 }; switch (audmode) { @@ -69,55 +76,89 @@ static void vp27smpx_set_audmode(struct i2c_client *client, u32 audmode) } if (i2c_master_send(client, data, sizeof(data)) != sizeof(data)) - v4l_err(client, "%s: I/O error setting audmode\n", - client->name); + v4l2_err(sd, "I/O error setting audmode\n"); else state->audmode = audmode; } -static int vp27smpx_command(struct i2c_client *client, unsigned cmd, void *arg) +static int vp27smpx_s_radio(struct v4l2_subdev *sd) { - struct vp27smpx_state *state = i2c_get_clientdata(client); - struct v4l2_tuner *vt = arg; + struct vp27smpx_state *state = to_state(sd); - switch (cmd) { - case AUDC_SET_RADIO: - state->radio = 1; - break; + state->radio = 1; + return 0; +} - case VIDIOC_S_STD: - state->radio = 0; - break; +static int vp27smpx_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) +{ + struct vp27smpx_state *state = to_state(sd); - case VIDIOC_S_TUNER: - if (!state->radio) - vp27smpx_set_audmode(client, vt->audmode); - break; + state->radio = 0; + return 0; +} - case VIDIOC_G_TUNER: - if (state->radio) - break; - vt->audmode = state->audmode; - vt->capability = V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - vt->rxsubchans = V4L2_TUNER_SUB_MONO; - break; +static int vp27smpx_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct vp27smpx_state *state = to_state(sd); - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, - V4L2_IDENT_VP27SMPX, 0); + if (!state->radio) + vp27smpx_set_audmode(sd, vt->audmode); + return 0; +} - case VIDIOC_LOG_STATUS: - v4l_info(client, "Audio Mode: %u%s\n", state->audmode, - state->radio ? " (Radio)" : ""); - break; +static int vp27smpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct vp27smpx_state *state = to_state(sd); + + if (state->radio) + return 0; + vt->audmode = state->audmode; + vt->capability = V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; + vt->rxsubchans = V4L2_TUNER_SUB_MONO; + return 0; +} - default: - return -EINVAL; - } +static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VP27SMPX, 0); +} + +static int vp27smpx_log_status(struct v4l2_subdev *sd) +{ + struct vp27smpx_state *state = to_state(sd); + + v4l2_info(sd, "Audio Mode: %u%s\n", state->audmode, + state->radio ? " (Radio)" : ""); return 0; } +static int vp27smpx_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops vp27smpx_core_ops = { + .log_status = vp27smpx_log_status, + .g_chip_ident = vp27smpx_g_chip_ident, +}; + +static const struct v4l2_subdev_tuner_ops vp27smpx_tuner_ops = { + .s_radio = vp27smpx_s_radio, + .s_std = vp27smpx_s_std, + .s_tuner = vp27smpx_s_tuner, + .g_tuner = vp27smpx_g_tuner, +}; + +static const struct v4l2_subdev_ops vp27smpx_ops = { + .core = &vp27smpx_core_ops, + .tuner = &vp27smpx_tuner_ops, +}; + /* ----------------------------------------------------------------------- */ /* i2c implementation */ @@ -131,6 +172,7 @@ static int vp27smpx_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct vp27smpx_state *state; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -145,17 +187,21 @@ static int vp27smpx_probe(struct i2c_client *client, state = kzalloc(sizeof(struct vp27smpx_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &vp27smpx_ops); state->audmode = V4L2_TUNER_MODE_STEREO; - i2c_set_clientdata(client, state); /* initialize vp27smpx */ - vp27smpx_set_audmode(client, state->audmode); + vp27smpx_set_audmode(sd, state->audmode); return 0; } static int vp27smpx_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From b7a1da99296bb70d499b52c1f35f9e8909ef7935 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 17:02:26 +0100 Subject: wm8739: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/wm8739.c | 188 +++++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 82 deletions(-) diff --git a/linux/drivers/media/video/wm8739.c b/linux/drivers/media/video/wm8739.c index f9d13b89a..ea311672c 100644 --- a/linux/drivers/media/video/wm8739.c +++ b/linux/drivers/media/video/wm8739.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -58,6 +58,7 @@ enum { }; struct wm8739_state { + struct v4l2_subdev sd; u32 clock_freq; u8 muted; u16 volume; @@ -66,43 +67,49 @@ struct wm8739_state { u8 vol_r; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */ }; +static inline struct wm8739_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct wm8739_state, sd); +} + /* ------------------------------------------------------------------------ */ -static int wm8739_write(struct i2c_client *client, int reg, u16 val) +static int wm8739_write(struct v4l2_subdev *sd, int reg, u16 val) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int i; if (reg < 0 || reg >= TOT_REGS) { - v4l_err(client, "Invalid register R%d\n", reg); + v4l2_err(sd, "Invalid register R%d\n", reg); return -1; } - v4l_dbg(1, debug, client, "write: %02x %02x\n", reg, val); + v4l2_dbg(1, debug, sd, "write: %02x %02x\n", reg, val); for (i = 0; i < 3; i++) if (i2c_smbus_write_byte_data(client, (reg << 1) | (val >> 8), val & 0xff) == 0) return 0; - v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); + v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg); return -1; } /* write regs to set audio volume etc */ -static void wm8739_set_audio(struct i2c_client *client) +static void wm8739_set_audio(struct v4l2_subdev *sd) { - struct wm8739_state *state = i2c_get_clientdata(client); + struct wm8739_state *state = to_state(sd); u16 mute = state->muted ? 0x80 : 0; /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB * Default setting: 0x17 = 0 dB */ - wm8739_write(client, R0, (state->vol_l & 0x1f) | mute); - wm8739_write(client, R1, (state->vol_r & 0x1f) | mute); + wm8739_write(sd, R0, (state->vol_l & 0x1f) | mute); + wm8739_write(sd, R1, (state->vol_r & 0x1f) | mute); } -static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int wm8739_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct wm8739_state *state = i2c_get_clientdata(client); + struct wm8739_state *state = to_state(sd); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -123,9 +130,9 @@ static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) return 0; } -static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int wm8739_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct wm8739_state *state = i2c_get_clientdata(client); + struct wm8739_state *state = to_state(sd); unsigned int work_l, work_r; switch (ctrl->id) { @@ -153,7 +160,7 @@ static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) state->vol_r = (long)work_r * 31 / 65535; /* set audio volume etc. */ - wm8739_set_audio(client); + wm8739_set_audio(sd); return 0; } @@ -192,77 +199,89 @@ static struct v4l2_queryctrl wm8739_qctrl[] = { /* ------------------------------------------------------------------------ */ -static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg) +static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq) { - struct wm8739_state *state = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - { - u32 audiofreq = *(u32 *)arg; - - state->clock_freq = audiofreq; - /* de-activate */ - wm8739_write(client, R9, 0x000); - switch (audiofreq) { - case 44100: - /* 256fps, fs=44.1k */ - wm8739_write(client, R8, 0x020); - break; - case 48000: - /* 256fps, fs=48k */ - wm8739_write(client, R8, 0x000); - break; - case 32000: - /* 256fps, fs=32k */ - wm8739_write(client, R8, 0x018); - break; - default: - break; - } - /* activate */ - wm8739_write(client, R9, 0x001); + struct wm8739_state *state = to_state(sd); + + state->clock_freq = audiofreq; + /* de-activate */ + wm8739_write(sd, R9, 0x000); + switch (audiofreq) { + case 44100: + /* 256fps, fs=44.1k */ + wm8739_write(sd, R8, 0x020); + break; + case 48000: + /* 256fps, fs=48k */ + wm8739_write(sd, R8, 0x000); + break; + case 32000: + /* 256fps, fs=32k */ + wm8739_write(sd, R8, 0x018); + break; + default: break; } + /* activate */ + wm8739_write(sd, R9, 0x001); + return 0; +} - case VIDIOC_G_CTRL: - return wm8739_get_ctrl(client, arg); - - case VIDIOC_S_CTRL: - return wm8739_set_ctrl(client, arg); +static int wm8739_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + int i; - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - int i; - - for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++) - if (qc->id && qc->id == wm8739_qctrl[i].id) { - memcpy(qc, &wm8739_qctrl[i], sizeof(*qc)); - return 0; - } - return -EINVAL; - } + for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++) + if (qc->id && qc->id == wm8739_qctrl[i].id) { + memcpy(qc, &wm8739_qctrl[i], sizeof(*qc)); + return 0; + } + return -EINVAL; +} - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, - arg, V4L2_IDENT_WM8739, 0); +static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_LOG_STATUS: - v4l_info(client, "Frequency: %u Hz\n", state->clock_freq); - v4l_info(client, "Volume L: %02x%s\n", state->vol_l & 0x1f, - state->muted ? " (muted)" : ""); - v4l_info(client, "Volume R: %02x%s\n", state->vol_r & 0x1f, - state->muted ? " (muted)" : ""); - break; + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_WM8739, 0); +} - default: - return -EINVAL; - } +static int wm8739_log_status(struct v4l2_subdev *sd) +{ + struct wm8739_state *state = to_state(sd); + v4l2_info(sd, "Frequency: %u Hz\n", state->clock_freq); + v4l2_info(sd, "Volume L: %02x%s\n", state->vol_l & 0x1f, + state->muted ? " (muted)" : ""); + v4l2_info(sd, "Volume R: %02x%s\n", state->vol_r & 0x1f, + state->muted ? " (muted)" : ""); return 0; } +static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops wm8739_core_ops = { + .log_status = wm8739_log_status, + .g_chip_ident = wm8739_g_chip_ident, + .queryctrl = wm8739_queryctrl, + .g_ctrl = wm8739_g_ctrl, + .s_ctrl = wm8739_s_ctrl, +}; + +static const struct v4l2_subdev_audio_ops wm8739_audio_ops = { + .s_clock_freq = wm8739_s_clock_freq, +}; + +static const struct v4l2_subdev_ops wm8739_ops = { + .core = &wm8739_core_ops, + .audio = &wm8739_audio_ops, +}; + /* ------------------------------------------------------------------------ */ /* i2c implementation */ @@ -271,6 +290,7 @@ static int wm8739_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct wm8739_state *state; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -282,6 +302,8 @@ static int wm8739_probe(struct i2c_client *client, state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &wm8739_ops); state->vol_l = 0x17; /* 0dB */ state->vol_r = 0x17; /* 0dB */ state->muted = 0; @@ -289,31 +311,33 @@ static int wm8739_probe(struct i2c_client *client, /* normalize (12dB(31) to -34.5dB(0) [0dB(23)] -> 65535 to 0) */ state->volume = ((long)state->vol_l + 1) * 65535 / 31; state->clock_freq = 48000; - i2c_set_clientdata(client, state); /* Initialize wm8739 */ /* reset */ - wm8739_write(client, R15, 0x00); + wm8739_write(sd, R15, 0x00); /* filter setting, high path, offet clear */ - wm8739_write(client, R5, 0x000); + wm8739_write(sd, R5, 0x000); /* ADC, OSC, Power Off mode Disable */ - wm8739_write(client, R6, 0x000); + wm8739_write(sd, R6, 0x000); /* Digital Audio interface format: Enable Master mode, 24 bit, MSB first/left justified */ - wm8739_write(client, R7, 0x049); + wm8739_write(sd, R7, 0x049); /* sampling control: normal, 256fs, 48KHz sampling rate */ - wm8739_write(client, R8, 0x000); + wm8739_write(sd, R8, 0x000); /* activate */ - wm8739_write(client, R9, 0x001); + wm8739_write(sd, R9, 0x001); /* set volume/mute */ - wm8739_set_audio(client); + wm8739_set_audio(sd); return 0; } static int wm8739_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From f31539f27272076e6d9a47292196d7ca1008b467 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 17:03:22 +0100 Subject: wm8775: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/wm8775.c | 221 ++++++++++++++++++++++--------------- 1 file changed, 133 insertions(+), 88 deletions(-) diff --git a/linux/drivers/media/video/wm8775.c b/linux/drivers/media/video/wm8775.c index ff7fa162b..526926635 100644 --- a/linux/drivers/media/video/wm8775.c +++ b/linux/drivers/media/video/wm8775.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -55,16 +55,23 @@ enum { }; struct wm8775_state { + struct v4l2_subdev sd; u8 input; /* Last selected input (0-0xf) */ u8 muted; }; -static int wm8775_write(struct i2c_client *client, int reg, u16 val) +static inline struct wm8775_state *to_state(struct v4l2_subdev *sd) { + return container_of(sd, struct wm8775_state, sd); +} + +static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); int i; if (reg < 0 || reg >= TOT_REGS) { - v4l_err(client, "Invalid register R%d\n", reg); + v4l2_err(sd, "Invalid register R%d\n", reg); return -1; } @@ -72,84 +79,117 @@ static int wm8775_write(struct i2c_client *client, int reg, u16 val) if (i2c_smbus_write_byte_data(client, (reg << 1) | (val >> 8), val & 0xff) == 0) return 0; - v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); + v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg); return -1; } -static int wm8775_command(struct i2c_client *client, unsigned cmd, void *arg) +static int wm8775_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct wm8775_state *state = i2c_get_clientdata(client); - struct v4l2_routing *route = arg; - struct v4l2_control *ctrl = arg; - - switch (cmd) { - case VIDIOC_INT_G_AUDIO_ROUTING: - route->input = state->input; - route->output = 0; - break; - - case VIDIOC_INT_S_AUDIO_ROUTING: - /* There are 4 inputs and one output. Zero or more inputs - are multiplexed together to the output. Hence there are - 16 combinations. - If only one input is active (the normal case) then the - input values 1, 2, 4 or 8 should be used. */ - if (route->input > 15) { - v4l_err(client, "Invalid input %d.\n", route->input); - return -EINVAL; - } - state->input = route->input; - if (state->muted) - break; - wm8775_write(client, R21, 0x0c0); - wm8775_write(client, R14, 0x1d4); - wm8775_write(client, R15, 0x1d4); - wm8775_write(client, R21, 0x100 + state->input); - break; - - case VIDIOC_G_CTRL: - if (ctrl->id != V4L2_CID_AUDIO_MUTE) - return -EINVAL; - ctrl->value = state->muted; - break; - - case VIDIOC_S_CTRL: - if (ctrl->id != V4L2_CID_AUDIO_MUTE) - return -EINVAL; - state->muted = ctrl->value; - wm8775_write(client, R21, 0x0c0); - wm8775_write(client, R14, 0x1d4); - wm8775_write(client, R15, 0x1d4); - if (!state->muted) - wm8775_write(client, R21, 0x100 + state->input); - break; - - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, - arg, V4L2_IDENT_WM8775, 0); - - case VIDIOC_LOG_STATUS: - v4l_info(client, "Input: %d%s\n", state->input, - state->muted ? " (muted)" : ""); - break; - - case VIDIOC_S_FREQUENCY: - /* If I remove this, then it can happen that I have no - sound the first time I tune from static to a valid channel. - It's difficult to reproduce and is almost certainly related - to the zero cross detect circuit. */ - wm8775_write(client, R21, 0x0c0); - wm8775_write(client, R14, 0x1d4); - wm8775_write(client, R15, 0x1d4); - wm8775_write(client, R21, 0x100 + state->input); - break; - - default: + struct wm8775_state *state = to_state(sd); + + /* There are 4 inputs and one output. Zero or more inputs + are multiplexed together to the output. Hence there are + 16 combinations. + If only one input is active (the normal case) then the + input values 1, 2, 4 or 8 should be used. */ + if (route->input > 15) { + v4l2_err(sd, "Invalid input %d.\n", route->input); return -EINVAL; } + state->input = route->input; + if (state->muted) + return 0; + wm8775_write(sd, R21, 0x0c0); + wm8775_write(sd, R14, 0x1d4); + wm8775_write(sd, R15, 0x1d4); + wm8775_write(sd, R21, 0x100 + state->input); + return 0; +} + +static int wm8775_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct wm8775_state *state = to_state(sd); + + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + ctrl->value = state->muted; + return 0; +} + +static int wm8775_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct wm8775_state *state = to_state(sd); + + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + state->muted = ctrl->value; + wm8775_write(sd, R21, 0x0c0); + wm8775_write(sd, R14, 0x1d4); + wm8775_write(sd, R15, 0x1d4); + if (!state->muted) + wm8775_write(sd, R21, 0x100 + state->input); + return 0; +} + +static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_WM8775, 0); +} + +static int wm8775_log_status(struct v4l2_subdev *sd) +{ + struct wm8775_state *state = to_state(sd); + + v4l2_info(sd, "Input: %d%s\n", state->input, + state->muted ? " (muted)" : ""); return 0; } +static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) +{ + struct wm8775_state *state = to_state(sd); + + /* If I remove this, then it can happen that I have no + sound the first time I tune from static to a valid channel. + It's difficult to reproduce and is almost certainly related + to the zero cross detect circuit. */ + wm8775_write(sd, R21, 0x0c0); + wm8775_write(sd, R14, 0x1d4); + wm8775_write(sd, R15, 0x1d4); + wm8775_write(sd, R21, 0x100 + state->input); + return 0; +} + +static int wm8775_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops wm8775_core_ops = { + .log_status = wm8775_log_status, + .g_chip_ident = wm8775_g_chip_ident, + .g_ctrl = wm8775_g_ctrl, + .s_ctrl = wm8775_s_ctrl, +}; + +static const struct v4l2_subdev_tuner_ops wm8775_tuner_ops = { + .s_frequency = wm8775_s_frequency, +}; + +static const struct v4l2_subdev_audio_ops wm8775_audio_ops = { + .s_routing = wm8775_s_routing, +}; + +static const struct v4l2_subdev_ops wm8775_ops = { + .core = &wm8775_core_ops, + .tuner = &wm8775_tuner_ops, + .audio = &wm8775_audio_ops, +}; + /* ----------------------------------------------------------------------- */ /* i2c implementation */ @@ -163,56 +203,61 @@ static int wm8775_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct wm8775_state *state; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - v4l_info(client, "chip found @ 0x%x (%s)\n", + v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); state = kmalloc(sizeof(struct wm8775_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &wm8775_ops); state->input = 2; state->muted = 0; - i2c_set_clientdata(client, state); /* Initialize wm8775 */ /* RESET */ - wm8775_write(client, R23, 0x000); + wm8775_write(sd, R23, 0x000); /* Disable zero cross detect timeout */ - wm8775_write(client, R7, 0x000); + wm8775_write(sd, R7, 0x000); /* Left justified, 24-bit mode */ - wm8775_write(client, R11, 0x021); + wm8775_write(sd, R11, 0x021); /* Master mode, clock ratio 256fs */ - wm8775_write(client, R12, 0x102); + wm8775_write(sd, R12, 0x102); /* Powered up */ - wm8775_write(client, R13, 0x000); + wm8775_write(sd, R13, 0x000); /* ADC gain +2.5dB, enable zero cross */ - wm8775_write(client, R14, 0x1d4); + wm8775_write(sd, R14, 0x1d4); /* ADC gain +2.5dB, enable zero cross */ - wm8775_write(client, R15, 0x1d4); + wm8775_write(sd, R15, 0x1d4); /* ALC Stereo, ALC target level -1dB FS max gain +8dB */ - wm8775_write(client, R16, 0x1bf); + wm8775_write(sd, R16, 0x1bf); /* Enable gain control, use zero cross detection, ALC hold time 42.6 ms */ - wm8775_write(client, R17, 0x185); + wm8775_write(sd, R17, 0x185); /* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */ - wm8775_write(client, R18, 0x0a2); + wm8775_write(sd, R18, 0x0a2); /* Enable noise gate, threshold -72dBfs */ - wm8775_write(client, R19, 0x005); + wm8775_write(sd, R19, 0x005); /* Transient window 4ms, lower PGA gain limit -1dB */ - wm8775_write(client, R20, 0x07a); + wm8775_write(sd, R20, 0x07a); /* LRBOTH = 1, use input 2. */ - wm8775_write(client, R21, 0x102); + wm8775_write(sd, R21, 0x102); return 0; } static int wm8775_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From 427b70d46df23ba54523af265fd2bc28d061e435 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Nov 2008 23:38:23 +0100 Subject: ivtv/ivtvfb: convert to v4l2_device/v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ivtv/ivtv-controls.c | 16 +- linux/drivers/media/video/ivtv/ivtv-driver.c | 214 +++++----------- linux/drivers/media/video/ivtv/ivtv-driver.h | 52 ++-- linux/drivers/media/video/ivtv/ivtv-fileops.c | 44 +--- linux/drivers/media/video/ivtv/ivtv-gpio.c | 324 +++++++++++++++--------- linux/drivers/media/video/ivtv/ivtv-gpio.h | 3 +- linux/drivers/media/video/ivtv/ivtv-i2c.c | 338 +++++-------------------- linux/drivers/media/video/ivtv/ivtv-i2c.h | 13 +- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 73 +++--- linux/drivers/media/video/ivtv/ivtv-routing.c | 12 +- linux/drivers/media/video/ivtv/ivtv-streams.c | 13 +- linux/drivers/media/video/ivtv/ivtv-vbi.c | 17 +- linux/drivers/media/video/ivtv/ivtvfb.c | 91 ++++--- 13 files changed, 503 insertions(+), 707 deletions(-) diff --git a/linux/drivers/media/video/ivtv/ivtv-controls.c b/linux/drivers/media/video/ivtv/ivtv-controls.c index 48e103be7..62aa06f5d 100644 --- a/linux/drivers/media/video/ivtv/ivtv-controls.c +++ b/linux/drivers/media/video/ivtv/ivtv-controls.c @@ -63,7 +63,7 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) case V4L2_CID_HUE: case V4L2_CID_SATURATION: case V4L2_CID_CONTRAST: - if (itv->video_dec_func(itv, VIDIOC_QUERYCTRL, qctrl)) + if (v4l2_subdev_call(itv->sd_video, core, queryctrl, qctrl)) qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; return 0; @@ -73,7 +73,7 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_LOUDNESS: - if (ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_QUERYCTRL, qctrl)) + if (v4l2_subdev_call(itv->sd_audio, core, queryctrl, qctrl)) qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; return 0; @@ -122,7 +122,7 @@ static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) case V4L2_CID_HUE: case V4L2_CID_SATURATION: case V4L2_CID_CONTRAST: - return itv->video_dec_func(itv, VIDIOC_S_CTRL, vctrl); + return v4l2_subdev_call(itv->sd_video, core, s_ctrl, vctrl); case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_MUTE: @@ -130,7 +130,7 @@ static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_LOUDNESS: - return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl); + return v4l2_subdev_call(itv->sd_audio, core, s_ctrl, vctrl); default: IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); @@ -147,7 +147,7 @@ static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) case V4L2_CID_HUE: case V4L2_CID_SATURATION: case V4L2_CID_CONTRAST: - return itv->video_dec_func(itv, VIDIOC_G_CTRL, vctrl); + return v4l2_subdev_call(itv->sd_video, core, g_ctrl, vctrl); case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_MUTE: @@ -155,7 +155,7 @@ static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_LOUDNESS: - return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl); + return v4l2_subdev_call(itv->sd_audio, core, g_ctrl, vctrl); default: IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); return -EINVAL; @@ -268,7 +268,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1); fmt.fmt.pix.height = itv->params.height; - itv->video_dec_func(itv, VIDIOC_S_FMT, &fmt); + v4l2_subdev_call(itv->sd_video, video, s_fmt, &fmt); } err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p); if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt) @@ -279,7 +279,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) /* The audio clock of the digitizer must match the codec sample rate otherwise you get some very strange effects. */ if (idx < sizeof(freqs)) - ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[idx]); + ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]); return err; } return -EINVAL; diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index db866d912..b29625ca2 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -60,9 +60,6 @@ #include #include "tuner-xc2028.h" -/* var to keep track of the number of array elements in use */ -int ivtv_cards_active; - /* If you have already X v4l cards, then set this to X. This way the device numbers stay matched. Example: you have a WinTV card without radio and a PVR-350 with. Normally this would give a @@ -70,12 +67,6 @@ int ivtv_cards_active; setting this to 1 you ensure that radio0 is now also radio1. */ int ivtv_first_minor; -/* Master variable for all ivtv info */ -struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; - -/* Protects ivtv_cards_active */ -DEFINE_SPINLOCK(ivtv_cards_lock); - /* add your revision and whatnot here */ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15, @@ -87,6 +78,9 @@ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl); +/* ivtv instance counter */ +static atomic_t ivtv_instance = ATOMIC_INIT(0); + /* Parameter declarations */ static int cardtype[IVTV_MAX_CARDS]; static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, @@ -599,9 +593,9 @@ static void ivtv_process_options(struct ivtv *itv) itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers * 1024; itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers * 1024; itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers; - itv->options.cardtype = cardtype[itv->num]; - itv->options.tuner = tuner[itv->num]; - itv->options.radio = radio[itv->num]; + itv->options.cardtype = cardtype[itv->instance]; + itv->options.tuner = tuner[itv->instance]; + itv->options.radio = radio[itv->instance]; itv->options.newi2c = newi2c; if (tunertype < -1 || tunertype > 1) { IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); @@ -688,7 +682,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) spin_lock_init(&itv->lock); spin_lock_init(&itv->dma_reg_lock); - itv->irq_work_queues = create_singlethread_workqueue(itv->name); + itv->irq_work_queues = create_singlethread_workqueue(itv->device.name); if (itv->irq_work_queues == NULL) { IVTV_ERR("Could not create ivtv workqueue\n"); return -1; @@ -774,12 +768,6 @@ static void __devinit ivtv_init_struct2(struct ivtv *itv) i = 0; itv->active_input = i; itv->audio_input = itv->card->video_inputs[i].audio_index; - if (itv->card->hw_all & IVTV_HW_CX25840) - itv->video_dec_func = ivtv_cx25840; - else if (itv->card->hw_all & IVTV_HW_SAA717X) - itv->video_dec_func = ivtv_saa717x; - else - itv->video_dec_func = ivtv_saa7115; } static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, @@ -792,21 +780,21 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, IVTV_DEBUG_INFO("Enabling pci device\n"); if (pci_enable_device(dev)) { - IVTV_ERR("Can't enable device %d!\n", itv->num); + IVTV_ERR("Can't enable device!\n"); return -EIO; } if (pci_set_dma_mask(dev, 0xffffffff)) { - IVTV_ERR("No suitable DMA available on card %d.\n", itv->num); + IVTV_ERR("No suitable DMA available.\n"); return -EIO; } if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) { - IVTV_ERR("Cannot request encoder memory region on card %d.\n", itv->num); + IVTV_ERR("Cannot request encoder memory region.\n"); return -EIO; } if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE, "ivtv registers")) { - IVTV_ERR("Cannot request register memory region on card %d.\n", itv->num); + IVTV_ERR("Cannot request register memory region.\n"); release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); return -EIO; } @@ -814,7 +802,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, if (itv->has_cx23415 && !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE, "ivtv decoder")) { - IVTV_ERR("Cannot request decoder memory region on card %d.\n", itv->num); + IVTV_ERR("Cannot request decoder memory region.\n"); release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); return -EIO; @@ -857,69 +845,11 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, return 0; } -#ifdef MODULE -static u32 ivtv_request_module(struct ivtv *itv, u32 hw, - const char *name, u32 id) -{ - if ((hw & id) == 0) - return hw; - if (request_module(name) != 0) { - IVTV_ERR("Failed to load module %s\n", name); - return hw & ~id; - } - IVTV_DEBUG_INFO("Loaded module %s\n", name); - return hw; -} -#endif - static void ivtv_load_and_init_modules(struct ivtv *itv) { u32 hw = itv->card->hw_all; unsigned i; -#ifdef MODULE - /* load modules */ -#ifdef CONFIG_MEDIA_TUNER_MODULE - hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER); -#endif -#ifdef CONFIG_VIDEO_CX25840_MODULE - hw = ivtv_request_module(itv, hw, "cx25840", IVTV_HW_CX25840); -#endif -#ifdef CONFIG_VIDEO_SAA711X_MODULE - hw = ivtv_request_module(itv, hw, "saa7115", IVTV_HW_SAA711X); -#endif -#ifdef CONFIG_VIDEO_SAA7127_MODULE - hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127); -#endif -#ifdef CONFIG_VIDEO_SAA717X_MODULE - hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X); -#endif -#ifdef CONFIG_VIDEO_UPD64031A_MODULE - hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A); -#endif -#ifdef CONFIG_VIDEO_UPD64083_MODULE - hw = ivtv_request_module(itv, hw, "upd64083", IVTV_HW_UPD6408X); -#endif -#ifdef CONFIG_VIDEO_MSP3400_MODULE - hw = ivtv_request_module(itv, hw, "msp3400", IVTV_HW_MSP34XX); -#endif -#ifdef CONFIG_VIDEO_VP27SMPX_MODULE - hw = ivtv_request_module(itv, hw, "vp27smpx", IVTV_HW_VP27SMPX); -#endif -#ifdef CONFIG_VIDEO_WM8775_MODULE - hw = ivtv_request_module(itv, hw, "wm8775", IVTV_HW_WM8775); -#endif -#ifdef CONFIG_VIDEO_WM8739_MODULE - hw = ivtv_request_module(itv, hw, "wm8739", IVTV_HW_WM8739); -#endif -#ifdef CONFIG_VIDEO_CS53L32A_MODULE - hw = ivtv_request_module(itv, hw, "cs53l32a", IVTV_HW_CS53L32A); -#endif -#ifdef CONFIG_VIDEO_M52790_MODULE - hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790); -#endif -#endif - /* check which i2c devices are actually found */ for (i = 0; i < 32; i++) { u32 device = 1 << i; @@ -931,11 +861,21 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) itv->hw_flags |= device; continue; } - ivtv_i2c_register(itv, i); - if (ivtv_i2c_hw_addr(itv, device) > 0) + if (ivtv_i2c_register(itv, i) == 0) itv->hw_flags |= device; } + if (itv->card->hw_all & IVTV_HW_CX25840) + itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840); + else if (itv->card->hw_all & IVTV_HW_SAA717X) + itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA717X); + else if (itv->card->hw_all & IVTV_HW_SAA7114) + itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7114); + else + itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7115); + itv->sd_audio = ivtv_find_hw(itv, itv->card->hw_audio_ctrl); + itv->sd_muxer = ivtv_find_hw(itv, itv->card->hw_muxer); + hw = itv->hw_flags; if (itv->card->type == IVTV_CARD_CX23416GYC) { @@ -953,7 +893,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) /* The crystal frequency of GVMVPRX is 24.576MHz */ crystal_freq.freq = SAA7115_FREQ_24_576_MHZ; crystal_freq.flags = SAA7115_FREQ_FL_UCGC; - itv->video_dec_func(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); + v4l2_subdev_call(itv->sd_video, video, s_crystal_freq, &crystal_freq); } if (hw & IVTV_HW_CX25840) { @@ -971,7 +911,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) /* determine the exact saa711x model */ itv->hw_flags &= ~IVTV_HW_SAA711X; - ivtv_saa7115(itv, VIDIOC_G_CHIP_IDENT, &v); + ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v); if (v.ident == V4L2_IDENT_SAA7114) { itv->hw_flags |= IVTV_HW_SAA7114; /* VBI is not yet supported by the saa7114 driver. */ @@ -1005,28 +945,20 @@ static int __devinit ivtv_probe(struct pci_dev *dev, int vbi_buf_size; struct ivtv *itv; - spin_lock(&ivtv_cards_lock); - - /* Make sure we've got a place for this card */ - if (ivtv_cards_active == IVTV_MAX_CARDS) { - printk(KERN_ERR "ivtv: Maximum number of cards detected (%d)\n", - ivtv_cards_active); - spin_unlock(&ivtv_cards_lock); - return -ENOMEM; - } - itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC); - if (itv == NULL) { - spin_unlock(&ivtv_cards_lock); + if (itv == NULL) return -ENOMEM; - } - ivtv_cards[ivtv_cards_active] = itv; itv->dev = dev; - itv->num = ivtv_cards_active++; - snprintf(itv->name, sizeof(itv->name), "ivtv%d", itv->num); - IVTV_INFO("Initializing card #%d\n", itv->num); + itv->instance = atomic_inc_return(&ivtv_instance) - 1; - spin_unlock(&ivtv_cards_lock); + retval = v4l2_device_register(&dev->dev, &itv->device); + if (retval) + return retval; + /* "ivtv + PCI ID" is a bit of a mouthful, so use + "ivtv + instance" instead. */ + snprintf(itv->device.name, sizeof(itv->device.name), + "ivtv%d", itv->instance); + IVTV_INFO("Initializing card %d\n", itv->instance); ivtv_process_options(itv); if (itv->options.cardtype == -1) { @@ -1047,8 +979,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, else if (retval == -ENXIO) goto free_mem; } - /* save itv in the pci struct for later use */ - pci_set_drvdata(dev, itv); /* map io memory */ IVTV_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", @@ -1090,7 +1020,9 @@ static int __devinit ivtv_probe(struct pci_dev *dev, goto free_io; } - ivtv_gpio_init(itv); + retval = ivtv_gpio_init(itv); + if (retval) + goto free_io; /* active i2c */ IVTV_DEBUG_INFO("activating i2c...\n"); @@ -1099,8 +1031,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, goto free_io; } - IVTV_DEBUG_INFO("Active card count: %d.\n", ivtv_cards_active); - if (itv->card->hw_all & IVTV_HW_TVEEPROM) { /* Based on the model number the cardtype may be changed. The PCI IDs are not always reliable. */ @@ -1195,7 +1125,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ setup.tuner_callback = (setup.type == TUNER_XC2028) ? ivtv_reset_tuner_gpio : NULL; - ivtv_call_i2c_clients(itv, TUNER_SET_TYPE_ADDR, &setup); + ivtv_call_all(itv, tuner, s_type_addr, &setup); if (setup.type == TUNER_XC2028) { static struct xc2028_ctrl ctrl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -1205,7 +1135,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, .tuner = itv->options.tuner, .priv = &ctrl, }; - ivtv_call_i2c_clients(itv, TUNER_SET_CONFIG, &cfg); + ivtv_call_all(itv, tuner, s_config, &cfg); } } @@ -1214,11 +1144,11 @@ static int __devinit ivtv_probe(struct pci_dev *dev, itv->tuner_std = itv->std; if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std); + ivtv_call_all(itv, video, s_std_output, itv->std); /* Turn off the output signal. The mpeg decoder is not yet active so without this you would get a green image until the mpeg decoder becomes active. */ - ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); } /* clear interrupt mask, effectively disabling interrupts */ @@ -1226,7 +1156,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, /* Register IRQ */ retval = request_irq(itv->dev->irq, ivtv_irq_handler, - IRQF_SHARED | IRQF_DISABLED, itv->name, (void *)itv); + IRQF_SHARED | IRQF_DISABLED, itv->device.name, (void *)itv); if (retval) { IVTV_ERR("Failed to register irq %d\n", retval); goto free_i2c; @@ -1242,7 +1172,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, IVTV_ERR("Error %d registering devices\n", retval); goto free_streams; } - IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name); + IVTV_INFO("Initialized card: %s\n", itv->card_name); return 0; free_streams: @@ -1265,10 +1195,8 @@ err: retval = -ENODEV; IVTV_ERR("Error %d on initialization\n", retval); - spin_lock(&ivtv_cards_lock); - kfree(ivtv_cards[ivtv_cards_active]); - ivtv_cards[ivtv_cards_active] = NULL; - spin_unlock(&ivtv_cards_lock); + v4l2_device_unregister(&itv->device); + kfree(itv); return retval; } @@ -1308,10 +1236,11 @@ int ivtv_init_on_first_open(struct ivtv *itv) if (itv->card->hw_all & IVTV_HW_CX25840) { struct v4l2_control ctrl; + v4l2_subdev_call(itv->sd_video, core, init, 0); /* CX25840_CID_ENABLE_PVR150_WORKAROUND */ ctrl.id = V4L2_CID_PRIVATE_BASE; ctrl.value = itv->pvr150_workaround; - itv->video_dec_func(itv, VIDIOC_S_CTRL, &ctrl); + v4l2_subdev_call(itv->sd_video, core, s_ctrl, &ctrl); } vf.tuner = 0; @@ -1341,7 +1270,7 @@ int ivtv_init_on_first_open(struct ivtv *itv) /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes the mpeg decoder so now the saa7127 receives a proper signal. */ - ivtv_saa7127(itv, VIDIOC_STREAMON, NULL); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); ivtv_init_mpeg_decoder(itv); } ivtv_s_std(NULL, &fh, &itv->tuner_std); @@ -1366,9 +1295,11 @@ int ivtv_init_on_first_open(struct ivtv *itv) static void ivtv_remove(struct pci_dev *pci_dev) { - struct ivtv *itv = pci_get_drvdata(pci_dev); + struct v4l2_device *dev = dev_get_drvdata(&pci_dev->dev); + struct ivtv *itv = to_ivtv(dev); + int i; - IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num); + IVTV_DEBUG_INFO("Removing card\n"); if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) { /* Stop all captures */ @@ -1381,7 +1312,7 @@ static void ivtv_remove(struct pci_dev *pci_dev) /* Turn off the TV-out */ if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) - ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); if (atomic_read(&itv->decoding) > 0) { int type; @@ -1406,6 +1337,8 @@ static void ivtv_remove(struct pci_dev *pci_dev) ivtv_streams_cleanup(itv, 1); ivtv_udma_free(itv); + v4l2_device_unregister(&itv->device); + exit_ivtv_i2c(itv); free_irq(itv->dev->irq, (void *)itv); @@ -1417,8 +1350,11 @@ static void ivtv_remove(struct pci_dev *pci_dev) release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); pci_disable_device(itv->dev); + for (i = 0; i < IVTV_VBI_FRAMES; i++) + kfree(itv->vbi.sliced_mpeg_data[i]); - IVTV_INFO("Removed %s, card #%d\n", itv->card_name, itv->num); + printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name); + kfree(itv); } /* define a pci_driver for card detection */ @@ -1431,54 +1367,36 @@ static struct pci_driver ivtv_pci_driver = { static int module_start(void) { - printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION); - - memset(ivtv_cards, 0, sizeof(ivtv_cards)); + printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION); /* Validate parameters */ if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) { - printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n", + printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n", IVTV_MAX_CARDS - 1); return -1; } if (ivtv_debug < 0 || ivtv_debug > 2047) { ivtv_debug = 0; - printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n"); + printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n"); } if (pci_register_driver(&ivtv_pci_driver)) { - printk(KERN_ERR "ivtv: Error detecting PCI card\n"); + printk(KERN_ERR "ivtv: Error detecting PCI card\n"); return -ENODEV; } - printk(KERN_INFO "ivtv: End initialization\n"); + printk(KERN_INFO "ivtv: End initialization\n"); return 0; } static void module_cleanup(void) { - int i, j; - pci_unregister_driver(&ivtv_pci_driver); - - spin_lock(&ivtv_cards_lock); - for (i = 0; i < ivtv_cards_active; i++) { - if (ivtv_cards[i] == NULL) - continue; - for (j = 0; j < IVTV_VBI_FRAMES; j++) { - kfree(ivtv_cards[i]->vbi.sliced_mpeg_data[j]); - } - kfree(ivtv_cards[i]); - } - spin_unlock(&ivtv_cards_lock); } /* Note: These symbols are exported because they are used by the ivtvfb framebuffer module and an infrared module for the IR-blaster. */ EXPORT_SYMBOL(ivtv_set_irq_mask); -EXPORT_SYMBOL(ivtv_cards_active); -EXPORT_SYMBOL(ivtv_cards); -EXPORT_SYMBOL(ivtv_cards_lock); EXPORT_SYMBOL(ivtv_api); EXPORT_SYMBOL(ivtv_vapi); EXPORT_SYMBOL(ivtv_vapi_result); diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.h b/linux/drivers/media/video/ivtv/ivtv-driver.h index 9128df0f3..51f6e54ba 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.h +++ b/linux/drivers/media/video/ivtv/ivtv-driver.h @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -114,9 +115,6 @@ #define IVTV_REG_VPU (0x9058) #define IVTV_REG_APU (0xA064) -/* i2c stuff */ -#define I2C_CLIENTS_MAX 16 - /* debugging */ extern int ivtv_debug; @@ -133,12 +131,10 @@ extern int ivtv_debug; /* Flag to turn on high volume debugging */ #define IVTV_DBGFLG_HIGHVOL (1 << 10) -/* NOTE: extra space before comma in 'itv->num , ## args' is required for - gcc-2.95, otherwise it won't compile. */ #define IVTV_DEBUG(x, type, fmt, args...) \ do { \ if ((x) & ivtv_debug) \ - printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ + v4l2_info(&itv->device, " " type ": " fmt , ##args); \ } while (0) #define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warn", fmt , ## args) #define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args) @@ -153,8 +149,8 @@ extern int ivtv_debug; #define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \ do { \ - if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ - printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ + if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ + v4l2_info(&itv->device, " " type ": " fmt , ##args); \ } while (0) #define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warn", fmt , ## args) #define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info", fmt , ## args) @@ -168,9 +164,9 @@ extern int ivtv_debug; #define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) /* Standard kernel messages */ -#define IVTV_ERR(fmt, args...) printk(KERN_ERR "ivtv%d: " fmt, itv->num , ## args) -#define IVTV_WARN(fmt, args...) printk(KERN_WARNING "ivtv%d: " fmt, itv->num , ## args) -#define IVTV_INFO(fmt, args...) printk(KERN_INFO "ivtv%d: " fmt, itv->num , ## args) +#define IVTV_ERR(fmt, args...) v4l2_err(&itv->device, fmt , ## args) +#define IVTV_WARN(fmt, args...) v4l2_warn(&itv->device, fmt , ## args) +#define IVTV_INFO(fmt, args...) v4l2_info(&itv->device, fmt , ## args) /* output modes (cx23415 only) */ #define OUT_NONE 0 @@ -597,8 +593,6 @@ struct ivtv_card; /* Struct to hold info about ivtv cards */ struct ivtv { /* General fixed card data */ - int num; /* board number, -1 during init! */ - char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */ struct pci_dev *dev; /* PCI device */ const struct ivtv_card *card; /* card information */ const char *card_name; /* full name of the card */ @@ -610,14 +604,18 @@ struct ivtv { u32 v4l2_cap; /* V4L2 capabilities of card */ u32 hw_flags; /* hardware description of the board */ v4l2_std_id tuner_std; /* the norm of the card's tuner (fixed) */ - /* controlling video decoder function */ - int (*video_dec_func)(struct ivtv *, unsigned int, void *); + struct v4l2_subdev *sd_video; /* controlling video decoder subdev */ + struct v4l2_subdev *sd_audio; /* controlling audio subdev */ + struct v4l2_subdev *sd_muxer; /* controlling audio muxer subdev */ u32 base_addr; /* PCI resource base address */ volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */ volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */ volatile void __iomem *reg_mem; /* pointer to mapped registers */ struct ivtv_options options; /* user options */ + struct v4l2_device device; + struct v4l2_subdev sd_gpio; /* GPIO sub-device */ + u16 instance; /* High-level state info */ unsigned long i_flags; /* global ivtv flags */ @@ -677,7 +675,6 @@ struct ivtv { struct i2c_adapter i2c_adap; struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; - struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];/* pointers to all I2C clients */ int i2c_state; /* i2c bit state */ struct mutex i2c_bus_lock; /* lock i2c bus */ @@ -723,11 +720,13 @@ struct ivtv { struct osd_info *osd_info; /* ivtvfb private OSD info */ }; +static inline struct ivtv *to_ivtv(struct v4l2_device *dev) +{ + return container_of(dev, struct ivtv, device); +} + /* Globals */ -extern struct ivtv *ivtv_cards[]; -extern int ivtv_cards_active; extern int ivtv_first_minor; -extern spinlock_t ivtv_cards_lock; /*==============Prototypes==================*/ @@ -787,4 +786,19 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv) #define write_dec_sync(val, addr) \ do { write_dec(val, addr); read_dec(addr); } while (0) +/* Call the specified callback for all subdevs matching hw (if 0, then + match them all). Ignore any errors. */ +#define ivtv_call_hw(itv, hw, o, f, args...) \ + __v4l2_device_call_subdevs(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args) + +#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args) + +/* Call the specified callback for all subdevs matching hw (if 0, then + match them all). If the callback returns an error other than 0 or + -ENOIOCTLCMD, then return with that error code. */ +#define ivtv_call_hw_err(itv, hw, o, f, args...) \ + __v4l2_device_call_subdevs_until_err(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args) + +#define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args) + #endif diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c index 1c404e454..5eb587592 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.c +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c @@ -155,7 +155,7 @@ static void ivtv_dualwatch(struct ivtv *itv) new_stereo_mode = itv->params.audio_properties & stereo_mask; memset(&vt, 0, sizeof(vt)); - ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, &vt); + ivtv_call_all(itv, tuner, g_tuner, &vt); if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2)) new_stereo_mode = dual; @@ -857,7 +857,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) /* Mark that the radio is no longer in use */ clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); /* Switch tuner to TV */ - ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); + ivtv_call_all(itv, tuner, s_std, itv->std); /* Select correct audio input (i.e. TV tuner or Line in) */ ivtv_audio_set_io(itv); if (itv->hw_flags & IVTV_HW_SAA711X) @@ -865,7 +865,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) struct v4l2_crystal_freq crystal_freq; crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; crystal_freq.flags = 0; - ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); + ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, &crystal_freq); } if (atomic_read(&itv->capturing) > 0) { /* Undo video mute */ @@ -952,15 +952,14 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) /* We have the radio */ ivtv_mute(itv); /* Switch tuner to radio */ - ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL); + ivtv_call_all(itv, tuner, s_radio); /* Select the correct audio input (i.e. radio tuner) */ ivtv_audio_set_io(itv); - if (itv->hw_flags & IVTV_HW_SAA711X) - { + if (itv->hw_flags & IVTV_HW_SAA711X) { struct v4l2_crystal_freq crystal_freq; crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; crystal_freq.flags = SAA7115_FREQ_FL_APLL; - ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); + ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, &crystal_freq); } /* Done! Unmute and continue. */ ivtv_unmute(itv); @@ -981,37 +980,18 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) int ivtv_v4l2_open(struct inode *inode, struct file *filp) { - int res, x, y = 0; + int res; struct ivtv *itv = NULL; struct ivtv_stream *s = NULL; - int minor = iminor(inode); - - /* Find which card this open was on */ - spin_lock(&ivtv_cards_lock); - for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { - if (ivtv_cards[x] == NULL) - continue; - /* find out which stream this open was on */ - for (y = 0; y < IVTV_MAX_STREAMS; y++) { - s = &ivtv_cards[x]->streams[y]; - if (s->v4l2dev && s->v4l2dev->minor == minor) { - itv = ivtv_cards[x]; - break; - } - } - } - spin_unlock(&ivtv_cards_lock); + struct video_device *vdev = video_devdata(filp); - if (itv == NULL) { - /* Couldn't find a device registered - on that minor, shouldn't happen! */ - printk(KERN_WARNING "No ivtv device found on minor %d\n", minor); - return -ENXIO; - } + s = video_get_drvdata(vdev); + itv = s->itv; mutex_lock(&itv->serialize_lock); if (ivtv_init_on_first_open(itv)) { - IVTV_ERR("Failed to initialize on minor %d\n", minor); + IVTV_ERR("Failed to initialize on minor %d\n", + s->v4l2dev->minor); mutex_unlock(&itv->serialize_lock); return -ENXIO; } diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c index 74a44844c..dc2850e87 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.c +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c @@ -144,22 +144,9 @@ int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value) return 0; } -void ivtv_gpio_init(struct ivtv *itv) +static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd) { - u16 pin = 0; - - if (itv->card->xceive_pin) - pin = 1 << itv->card->xceive_pin; - - if ((itv->card->gpio_init.direction | pin) == 0) - return; - - IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n", - read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT)); - - /* init output data then direction */ - write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT); - write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR); + return container_of(sd, struct ivtv, sd_gpio); } static struct v4l2_queryctrl gpio_ctrl_mute = { @@ -173,134 +160,231 @@ static struct v4l2_queryctrl gpio_ctrl_mute = { .flags = 0, }; -int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) +static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq) { - struct v4l2_tuner *tuner = arg; - struct v4l2_control *ctrl = arg; - struct v4l2_routing *route = arg; + struct ivtv *itv = sd_to_ivtv(sd); u16 mask, data; - switch (command) { - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - mask = itv->card->gpio_audio_freq.mask; - switch (*(u32 *)arg) { - case 32000: - data = itv->card->gpio_audio_freq.f32000; - break; - case 44100: - data = itv->card->gpio_audio_freq.f44100; - break; - case 48000: - default: - data = itv->card->gpio_audio_freq.f48000; - break; - } + mask = itv->card->gpio_audio_freq.mask; + switch (freq) { + case 32000: + data = itv->card->gpio_audio_freq.f32000; + break; + case 44100: + data = itv->card->gpio_audio_freq.f44100; + break; + case 48000: + default: + data = itv->card->gpio_audio_freq.f48000; break; + } + if (mask) + write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); + return 0; +} - case VIDIOC_G_TUNER: - mask = itv->card->gpio_audio_detect.mask; - if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) - tuner->rxsubchans = V4L2_TUNER_MODE_STEREO | - V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; - else - tuner->rxsubchans = V4L2_TUNER_SUB_MONO; - return 0; +static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct ivtv *itv = sd_to_ivtv(sd); + u16 mask; + + mask = itv->card->gpio_audio_detect.mask; + if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) + vt->rxsubchans = V4L2_TUNER_MODE_STEREO | + V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + else + vt->rxsubchans = V4L2_TUNER_SUB_MONO; + return 0; +} - case VIDIOC_S_TUNER: - mask = itv->card->gpio_audio_mode.mask; - switch (tuner->audmode) { - case V4L2_TUNER_MODE_LANG1: - data = itv->card->gpio_audio_mode.lang1; - break; - case V4L2_TUNER_MODE_LANG2: - data = itv->card->gpio_audio_mode.lang2; - break; - case V4L2_TUNER_MODE_MONO: - data = itv->card->gpio_audio_mode.mono; - break; - case V4L2_TUNER_MODE_STEREO: - case V4L2_TUNER_MODE_LANG1_LANG2: - default: - data = itv->card->gpio_audio_mode.stereo; - break; - } - break; +static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct ivtv *itv = sd_to_ivtv(sd); + u16 mask, data; - case AUDC_SET_RADIO: - mask = itv->card->gpio_audio_input.mask; - data = itv->card->gpio_audio_input.radio; + mask = itv->card->gpio_audio_mode.mask; + switch (vt->audmode) { + case V4L2_TUNER_MODE_LANG1: + data = itv->card->gpio_audio_mode.lang1; + break; + case V4L2_TUNER_MODE_LANG2: + data = itv->card->gpio_audio_mode.lang2; + break; + case V4L2_TUNER_MODE_MONO: + data = itv->card->gpio_audio_mode.mono; break; + case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: + default: + data = itv->card->gpio_audio_mode.stereo; + break; + } + if (mask) + write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); + return 0; +} + +static int subdev_s_radio(struct v4l2_subdev *sd) +{ + struct ivtv *itv = sd_to_ivtv(sd); + u16 mask, data; + + mask = itv->card->gpio_audio_input.mask; + data = itv->card->gpio_audio_input.radio; + if (mask) + write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); + return 0; +} - case VIDIOC_S_STD: - mask = itv->card->gpio_audio_input.mask; +static int subdev_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct ivtv *itv = sd_to_ivtv(sd); + u16 mask, data; + + mask = itv->card->gpio_audio_input.mask; + data = itv->card->gpio_audio_input.tuner; + if (mask) + write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); + return 0; +} + +static int subdev_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct ivtv *itv = sd_to_ivtv(sd); + u16 mask, data; + + if (route->input > 2) + return -EINVAL; + mask = itv->card->gpio_audio_input.mask; + switch (route->input) { + case 0: data = itv->card->gpio_audio_input.tuner; break; - - case VIDIOC_INT_S_AUDIO_ROUTING: - if (route->input > 2) - return -EINVAL; - mask = itv->card->gpio_audio_input.mask; - switch (route->input) { - case 0: - data = itv->card->gpio_audio_input.tuner; - break; - case 1: - data = itv->card->gpio_audio_input.linein; - break; - case 2: - default: - data = itv->card->gpio_audio_input.radio; - break; - } + case 1: + data = itv->card->gpio_audio_input.linein; + break; + case 2: + default: + data = itv->card->gpio_audio_input.radio; break; + } + if (mask) + write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); + return 0; +} - case VIDIOC_G_CTRL: - if (ctrl->id != V4L2_CID_AUDIO_MUTE) - return -EINVAL; - mask = itv->card->gpio_audio_mute.mask; - data = itv->card->gpio_audio_mute.mute; - ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data; - return 0; +static int subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct ivtv *itv = sd_to_ivtv(sd); + u16 mask, data; - case VIDIOC_S_CTRL: - if (ctrl->id != V4L2_CID_AUDIO_MUTE) - return -EINVAL; - mask = itv->card->gpio_audio_mute.mask; - data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0; - break; + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + mask = itv->card->gpio_audio_mute.mask; + data = itv->card->gpio_audio_mute.mute; + ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data; + return 0; +} - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; +static int subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct ivtv *itv = sd_to_ivtv(sd); + u16 mask, data; - if (qc->id != V4L2_CID_AUDIO_MUTE) - return -EINVAL; - *qc = gpio_ctrl_mute; - return 0; - } + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + mask = itv->card->gpio_audio_mute.mask; + data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0; + if (mask) + write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); + return 0; +} + +static int subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + if (qc->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + *qc = gpio_ctrl_mute; + return 0; +} + +static int subdev_log_status(struct v4l2_subdev *sd) +{ + struct ivtv *itv = sd_to_ivtv(sd); - case VIDIOC_LOG_STATUS: - IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", + IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), read_reg(IVTV_REG_GPIO_IN)); - return 0; + return 0; +} - case VIDIOC_INT_S_VIDEO_ROUTING: - if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */ - return -EINVAL; - mask = itv->card->gpio_video_input.mask; - if (route->input == 0) - data = itv->card->gpio_video_input.tuner; - else if (route->input == 1) - data = itv->card->gpio_video_input.composite; - else - data = itv->card->gpio_video_input.svideo; - break; +static int subdev_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct ivtv *itv = sd_to_ivtv(sd); + u16 mask, data; - default: + if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */ return -EINVAL; - } + mask = itv->card->gpio_video_input.mask; + if (route->input == 0) + data = itv->card->gpio_video_input.tuner; + else if (route->input == 1) + data = itv->card->gpio_video_input.composite; + else + data = itv->card->gpio_video_input.svideo; if (mask) write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); return 0; } + +static const struct v4l2_subdev_core_ops subdev_core_ops = { + .log_status = subdev_log_status, + .g_ctrl = subdev_g_ctrl, + .s_ctrl = subdev_s_ctrl, + .queryctrl = subdev_queryctrl, +}; + +static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = { + .s_std = subdev_s_std, + .s_radio = subdev_s_radio, + .g_tuner = subdev_g_tuner, + .s_tuner = subdev_s_tuner, +}; + +static const struct v4l2_subdev_audio_ops subdev_audio_ops = { + .s_clock_freq = subdev_s_clock_freq, + .s_routing = subdev_s_audio_routing, +}; + +static const struct v4l2_subdev_video_ops subdev_video_ops = { + .s_routing = subdev_s_video_routing, +}; + +static const struct v4l2_subdev_ops subdev_ops = { + .core = &subdev_core_ops, + .tuner = &subdev_tuner_ops, + .audio = &subdev_audio_ops, + .video = &subdev_video_ops, +}; + +int ivtv_gpio_init(struct ivtv *itv) +{ + u16 pin = 0; + + if (itv->card->xceive_pin) + pin = 1 << itv->card->xceive_pin; + + if ((itv->card->gpio_init.direction | pin) == 0) + return 0; + + IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n", + read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT)); + + /* init output data then direction */ + write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT); + write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR); + v4l2_subdev_init(&itv->sd_gpio, &subdev_ops); + snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->device.name); + itv->sd_gpio.grp_id = IVTV_HW_GPIO; + return v4l2_device_register_subdev(&itv->device, &itv->sd_gpio); +} diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.h b/linux/drivers/media/video/ivtv/ivtv-gpio.h index 48b629161..0b5d19c8e 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.h +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.h @@ -22,9 +22,8 @@ #define IVTV_GPIO_H /* GPIO stuff */ -void ivtv_gpio_init(struct ivtv *itv); +int ivtv_gpio_init(struct ivtv *itv); void ivtv_reset_ir_gpio(struct ivtv *itv); int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value); -int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); #endif diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index fa18eae17..41452e111 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -89,26 +89,6 @@ #define IVTV_VP27SMPX_I2C_ADDR 0x5b #define IVTV_M52790_I2C_ADDR 0x48 -/* This array should match the IVTV_HW_ defines */ -static const u8 hw_driverids[] = { - I2C_DRIVERID_CX25840, - I2C_DRIVERID_SAA711X, - I2C_DRIVERID_SAA7127, - I2C_DRIVERID_MSP3400, - I2C_DRIVERID_TUNER, - I2C_DRIVERID_WM8775, - I2C_DRIVERID_CS53L32A, - I2C_DRIVERID_TVEEPROM, - I2C_DRIVERID_SAA711X, - I2C_DRIVERID_UPD64031A, - I2C_DRIVERID_UPD64083, - I2C_DRIVERID_SAA717X, - I2C_DRIVERID_WM8739, - I2C_DRIVERID_VP27SMPX, - I2C_DRIVERID_M52790, - 0 /* IVTV_HW_GPIO dummy driver ID */ -}; - /* This array should match the IVTV_HW_ defines */ static const u8 hw_addrs[] = { IVTV_CX25840_I2C_ADDR, @@ -129,6 +109,26 @@ static const u8 hw_addrs[] = { 0 /* IVTV_HW_GPIO dummy driver ID */ }; +/* This array should match the IVTV_HW_ defines */ +static const char *hw_modules[] = { + "cx25840", + "saa7115", + "saa7127", + "msp3400", + "tuner", + "wm8775", + "cs53l32a", + NULL, + "saa7115", + "upd64031a", + "upd64083", + "saa717x", + "wm8739", + "vp27smpx", + "m52790", + NULL +}; + /* This array should match the IVTV_HW_ defines */ static const char * const hw_devicenames[] = { "cx25840", @@ -155,104 +155,58 @@ static const char * const hw_devicenames[] = { int ivtv_i2c_register(struct ivtv *itv, unsigned idx) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) - struct i2c_board_info info; - struct i2c_client *c; - u8 id; - int i; + struct v4l2_subdev *sd; + struct i2c_adapter *adap = &itv->i2c_adap; + const char *mod = hw_modules[idx]; + const char *type = hw_devicenames[idx]; + u32 hw = 1 << idx; - IVTV_DEBUG_I2C("i2c client register\n"); - if (idx >= ARRAY_SIZE(hw_driverids) || hw_driverids[idx] == 0) + if (idx >= ARRAY_SIZE(hw_addrs)) return -1; - id = hw_driverids[idx]; - memset(&info, 0, sizeof(info)); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - strlcpy(info.driver_name, hw_devicenames[idx], - sizeof(info.driver_name)); -#else - strlcpy(info.type, hw_devicenames[idx], sizeof(info.type)); -#endif - info.addr = hw_addrs[idx]; - for (i = 0; itv->i2c_clients[i] && i < I2C_CLIENTS_MAX; i++) {} - - if (i == I2C_CLIENTS_MAX) { - IVTV_ERR("insufficient room for new I2C client!\n"); - return -ENOMEM; + if (hw == IVTV_HW_TUNER) { + /* special tuner handling */ + sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + itv->card_i2c->radio); + if (sd) + sd->grp_id = 1 << idx; + sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + itv->card_i2c->demod); + if (sd) + sd->grp_id = 1 << idx; + sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + itv->card_i2c->tv); + if (sd) + sd->grp_id = 1 << idx; + return sd ? 0 : -1; } + if (!hw_addrs[idx]) + return -1; + if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { + unsigned short addrs[2] = { hw_addrs[idx], I2C_CLIENT_END }; - if (id != I2C_DRIVERID_TUNER) { - if (id == I2C_DRIVERID_UPD64031A || - id == I2C_DRIVERID_UPD64083) { - unsigned short addrs[2] = { info.addr, I2C_CLIENT_END }; - - c = i2c_new_probed_device(&itv->i2c_adap, &info, addrs); - } else - c = i2c_new_device(&itv->i2c_adap, &info); - if (c && c->driver == NULL) - i2c_unregister_device(c); - else if (c) - itv->i2c_clients[i] = c; - return itv->i2c_clients[i] ? 0 : -ENODEV; - } - - /* special tuner handling */ - c = i2c_new_probed_device(&itv->i2c_adap, &info, itv->card_i2c->radio); - if (c && c->driver == NULL) - i2c_unregister_device(c); - else if (c) - itv->i2c_clients[i++] = c; - c = i2c_new_probed_device(&itv->i2c_adap, &info, itv->card_i2c->demod); - if (c && c->driver == NULL) - i2c_unregister_device(c); - else if (c) - itv->i2c_clients[i++] = c; - c = i2c_new_probed_device(&itv->i2c_adap, &info, itv->card_i2c->tv); - if (c && c->driver == NULL) - i2c_unregister_device(c); - else if (c) - itv->i2c_clients[i++] = c; - return 0; -#else - return 0; -#endif -} - -static int attach_inform(struct i2c_client *client) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) - struct ivtv *itv = (struct ivtv *)i2c_get_adapdata(client->adapter); - int i; - - IVTV_DEBUG_I2C("i2c client attach\n"); - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (itv->i2c_clients[i] == NULL) { - itv->i2c_clients[i] = client; - break; - } - } - if (i == I2C_CLIENTS_MAX) { - IVTV_ERR("Insufficient room for new I2C client\n"); + sd = v4l2_i2c_new_probed_subdev(adap, mod, type, addrs); + } else { + sd = v4l2_i2c_new_subdev(adap, mod, type, hw_addrs[idx]); } -#endif - return 0; + if (sd) + sd->grp_id = 1 << idx; + return sd ? 0 : -1; } -static int detach_inform(struct i2c_client *client) +struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw) { - int i; - struct ivtv *itv = (struct ivtv *)i2c_get_adapdata(client->adapter); + struct v4l2_subdev *result = NULL; + struct v4l2_subdev *sd; - IVTV_DEBUG_I2C("i2c client detach\n"); - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (itv->i2c_clients[i] == client) { - itv->i2c_clients[i] = NULL; + spin_lock(&itv->device.lock); + v4l2_device_for_each_subdev(sd, &itv->device) { + if (sd->grp_id == hw) { + result = sd; break; } } - IVTV_DEBUG_I2C("i2c detach [client=%s,%s]\n", - client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); - - return 0; + spin_unlock(&itv->device.lock); + return result; } /* Set the serial clock line to the desired state */ @@ -522,7 +476,8 @@ static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, intervening stop condition */ static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { - struct ivtv *itv = i2c_get_adapdata(i2c_adap); + struct v4l2_device *drv = i2c_get_adapdata(i2c_adap); + struct ivtv *itv = to_ivtv(drv); int retval; int i; @@ -561,8 +516,6 @@ static struct i2c_adapter ivtv_i2c_adap_hw_template = { .id = I2C_HW_B_CX2341X, .algo = &ivtv_algo, .algo_data = NULL, /* filled from template */ - .client_register = attach_inform, - .client_unregister = detach_inform, .owner = THIS_MODULE, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .class = I2C_CLASS_TV_ANALOG, @@ -617,8 +570,6 @@ static struct i2c_adapter ivtv_i2c_adap_template = { .id = I2C_HW_B_CX2341X, .algo = NULL, /* set by i2c-algo-bit */ .algo_data = NULL, /* filled from template */ - .client_register = attach_inform, - .client_unregister = detach_inform, .owner = THIS_MODULE, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .class = I2C_CLASS_TV_ANALOG, @@ -638,160 +589,6 @@ static struct i2c_client ivtv_i2c_client_template = { .name = "ivtv internal", }; -int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg) -{ - struct i2c_client *client; - int retval; - int i; - - IVTV_DEBUG_I2C("call_i2c_client addr=%02x\n", addr); - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - client = itv->i2c_clients[i]; - if (client == NULL || client->driver == NULL || - client->driver->command == NULL) - continue; - if (addr == client->addr) { - retval = client->driver->command(client, cmd, arg); - return retval; - } - } - if (cmd != VIDIOC_G_CHIP_IDENT) - IVTV_ERR("i2c addr 0x%02x not found for command 0x%x\n", addr, cmd); - return -ENODEV; -} - -/* Find the i2c device based on the driver ID and return - its i2c address or -ENODEV if no matching device was found. */ -static int ivtv_i2c_id_addr(struct ivtv *itv, u32 id) -{ - struct i2c_client *client; - int retval = -ENODEV; - int i; - - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - client = itv->i2c_clients[i]; - if (client == NULL || client->driver == NULL) - continue; - if (id == client->driver->id) { - retval = client->addr; - break; - } - } - return retval; -} - -/* Find the i2c device name matching the DRIVERID */ -static const char *ivtv_i2c_id_name(u32 id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) - if (hw_driverids[i] == id) - return hw_devicenames[i]; - return "unknown device"; -} - -/* Find the i2c device name matching the IVTV_HW_ flag */ -static const char *ivtv_i2c_hw_name(u32 hw) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) - if (1 << i == hw) - return hw_devicenames[i]; - return "unknown device"; -} - -/* Find the i2c device matching the IVTV_HW_ flag and return - its i2c address or -ENODEV if no matching device was found. */ -int ivtv_i2c_hw_addr(struct ivtv *itv, u32 hw) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) - if (1 << i == hw) - return ivtv_i2c_id_addr(itv, hw_driverids[i]); - return -ENODEV; -} - -/* Calls i2c device based on IVTV_HW_ flag. If hw == 0, then do nothing. - If hw == IVTV_HW_GPIO then call the gpio handler. */ -int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg) -{ - int addr; - - if (hw == IVTV_HW_GPIO) - return ivtv_gpio(itv, cmd, arg); - if (hw == 0) - return 0; - - addr = ivtv_i2c_hw_addr(itv, hw); - if (addr < 0) { - IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x\n", - hw, ivtv_i2c_hw_name(hw), cmd); - return addr; - } - return ivtv_call_i2c_client(itv, addr, cmd, arg); -} - -/* Calls i2c device based on I2C driver ID. */ -int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg) -{ - int addr; - - addr = ivtv_i2c_id_addr(itv, id); - if (addr < 0) { - if (cmd != VIDIOC_G_CHIP_IDENT) - IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x\n", - id, ivtv_i2c_id_name(id), cmd); - return addr; - } - return ivtv_call_i2c_client(itv, addr, cmd, arg); -} - -int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg) -{ - return ivtv_call_i2c_client(itv, IVTV_CX25840_I2C_ADDR, cmd, arg); -} - -int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg) -{ - return ivtv_call_i2c_client(itv, IVTV_SAA7115_I2C_ADDR, cmd, arg); -} - -int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg) -{ - return ivtv_call_i2c_client(itv, IVTV_SAA7127_I2C_ADDR, cmd, arg); -} -EXPORT_SYMBOL(ivtv_saa7127); - -int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg) -{ - return ivtv_call_i2c_client(itv, IVTV_SAA717x_I2C_ADDR, cmd, arg); -} - -int ivtv_upd64031a(struct ivtv *itv, unsigned int cmd, void *arg) -{ - return ivtv_call_i2c_client(itv, IVTV_UPD64031A_I2C_ADDR, cmd, arg); -} - -int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg) -{ - return ivtv_call_i2c_client(itv, IVTV_UPD64083_I2C_ADDR, cmd, arg); -} - -/* broadcast cmd for all I2C clients and for the gpio subsystem */ -void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg) -{ - if (itv->i2c_adap.algo == NULL) { - IVTV_ERR("Adapter is not set"); - return; - } - i2c_clients_command(&itv->i2c_adap, cmd, arg); - if (itv->hw_flags & IVTV_HW_GPIO) - ivtv_gpio(itv, cmd, arg); -} - /* init + register i2c algo-bit adapter */ int init_ivtv_i2c(struct ivtv *itv) { @@ -800,10 +597,9 @@ int init_ivtv_i2c(struct ivtv *itv) /* Sanity checks for the I2C hardware arrays. They must be the * same size and GPIO must be the last entry. */ - if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) || - ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || - IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1)) || - hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) { + if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || + ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_modules) || + IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1))) { IVTV_ERR("Mismatched I2C hardware arrays\n"); return -ENODEV; } @@ -820,8 +616,8 @@ int init_ivtv_i2c(struct ivtv *itv) itv->i2c_adap.algo_data = &itv->i2c_algo; sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d", - itv->num); - i2c_set_adapdata(&itv->i2c_adap, itv); + itv->instance); + i2c_set_adapdata(&itv->i2c_adap, &itv->device); memcpy(&itv->i2c_client, &ivtv_i2c_client_template, sizeof(struct i2c_client)); diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.h b/linux/drivers/media/video/ivtv/ivtv-i2c.h index 022978cf5..396928a06 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.h +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.h @@ -21,19 +21,8 @@ #ifndef IVTV_I2C_H #define IVTV_I2C_H -int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg); -int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg); -int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg); -int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg); -int ivtv_upd64031a(struct ivtv *itv, unsigned int cmd, void *arg); -int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg); - -int ivtv_i2c_hw_addr(struct ivtv *itv, u32 hw); -int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg); -int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg); -int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg); -void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg); int ivtv_i2c_register(struct ivtv *itv, unsigned idx); +struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw); /* init + register i2c algo-bit adapter */ int init_ivtv_i2c(struct ivtv *itv); diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 4bae38d21..cd990a4b8 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -393,7 +393,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo return 0; } - itv->video_dec_func(itv, VIDIOC_G_FMT, fmt); + v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); vbifmt->service_set = ivtv_get_service_set(vbifmt); return 0; } @@ -581,7 +581,7 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f p->height = h; if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) fmt->fmt.pix.width /= 2; - itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); + v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); return ivtv_g_fmt_vid_cap(file, fh, fmt); } @@ -593,7 +593,7 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f return -EBUSY; itv->vbi.sliced_in->service_set = 0; itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; - itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); + v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); return ivtv_g_fmt_vbi_cap(file, fh, fmt); } @@ -611,7 +611,7 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) return -EBUSY; itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); + v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); return 0; } @@ -685,18 +685,17 @@ static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; return 0; } - if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) - return ivtv_i2c_id(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip); - if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR) - return ivtv_call_i2c_client(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip); - return -EINVAL; + if (chip->match_type != V4L2_CHIP_MATCH_I2C_DRIVER && + chip->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + /* TODO: is this correct? */ + return ivtv_call_all_err(itv, core, g_chip_ident, chip); } #ifdef CONFIG_VIDEO_ADV_DEBUG static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) { struct v4l2_register *regs = arg; - unsigned long flags; volatile u8 __iomem *reg_start; if (!capable(CAP_SYS_ADMIN)) @@ -711,12 +710,10 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) else return -EINVAL; - spin_lock_irqsave(&ivtv_cards_lock, flags); if (cmd == VIDIOC_DBG_G_REGISTER) regs->val = readl(regs->reg + reg_start); else writel(regs->val, regs->reg + reg_start); - spin_unlock_irqrestore(&ivtv_cards_lock, flags); return 0; } @@ -726,9 +723,10 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *re if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg); - if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) - return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg); - return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg); + /* TODO: subdev errors should not be ignored, this should become a + subdev helper function. */ + ivtv_call_all(itv, core, g_register, reg); + return 0; } static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg) @@ -737,9 +735,10 @@ static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *re if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg); - if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) - return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg); - return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg); + /* TODO: subdev errors should not be ignored, this should become a + subdev helper function. */ + ivtv_call_all(itv, core, s_register, reg); + return 0; } #endif @@ -884,12 +883,6 @@ static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) streamtype = id->type; - if (ivtv_debug & IVTV_DBGFLG_IOCTL) { - printk(KERN_INFO "ivtv%d ioctl: ", itv->num); - /* Should be replaced */ - /* v4l_printk_ioctl(VIDIOC_S_CROP); */ - } - if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { @@ -1050,7 +1043,7 @@ static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) itv->active_output = outp; route.input = SAA7127_INPUT_TYPE_NORMAL; route.output = itv->card->video_outputs[outp].video_output; - ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, &route); return 0; } @@ -1062,7 +1055,7 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency * if (vf->tuner != 0) return -EINVAL; - ivtv_call_i2c_clients(itv, VIDIOC_G_FREQUENCY, vf); + ivtv_call_all(itv, tuner, g_frequency, vf); return 0; } @@ -1075,7 +1068,7 @@ int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) ivtv_mute(itv); IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency); - ivtv_call_i2c_clients(itv, VIDIOC_S_FREQUENCY, vf); + ivtv_call_all(itv, tuner, s_frequency, vf); ivtv_unmute(itv); return 0; } @@ -1123,14 +1116,14 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std); /* Tuner */ - ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); + ivtv_call_all(itv, tuner, s_std, itv->std); if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { /* set display standard */ itv->std_out = *std; itv->is_out_60hz = itv->is_60hz; itv->is_out_50hz = itv->is_50hz; - ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out); + ivtv_call_all(itv, video, s_std_output, itv->std_out); ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); itv->main_rect.left = itv->main_rect.top = 0; itv->main_rect.width = 720; @@ -1154,7 +1147,7 @@ static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) if (vt->index != 0) return -EINVAL; - ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt); + ivtv_call_all(itv, tuner, s_tuner, vt); return 0; } @@ -1166,7 +1159,7 @@ static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) if (vt->index != 0) return -EINVAL; - ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt); + ivtv_call_all(itv, tuner, g_tuner, vt); if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); @@ -1444,14 +1437,15 @@ static int ivtv_log_status(struct file *file, void *fh) struct v4l2_audio audin; int i; - IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num); + IVTV_INFO("================= START STATUS CARD #%d =================\n", + itv->instance); IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); if (itv->hw_flags & IVTV_HW_TVEEPROM) { struct tveeprom tv; ivtv_read_eeprom(itv, &tv); } - ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL); + ivtv_call_all(itv, core, log_status); ivtv_get_input(itv, itv->active_input, &vidin); ivtv_get_audio_input(itv, itv->audio_input, &audin); IVTV_INFO("Video Input: %s\n", vidin.name); @@ -1518,7 +1512,7 @@ static int ivtv_log_status(struct file *file, void *fh) } IVTV_INFO("Tuner: %s\n", test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); - cx2341x_log_status(&itv->params, itv->name); + cx2341x_log_status(&itv->params, itv->device.name); IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); for (i = 0; i < IVTV_MAX_STREAMS; i++) { struct ivtv_stream *s = &itv->streams[i]; @@ -1530,8 +1524,11 @@ static int ivtv_log_status(struct file *file, void *fh) (s->buffers * s->buf_size) / 1024, s->buffers); } - IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted); - IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); + IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", + (long long)itv->mpg_data_received, + (long long)itv->vbi_data_inserted); + IVTV_INFO("================== END STATUS CARD #%d ==================\n", + itv->instance); return 0; } @@ -1736,7 +1733,7 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg) case VIDIOC_INT_S_AUDIO_ROUTING: { struct v4l2_routing *route = arg; - ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route); + ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, route); break; } @@ -1746,7 +1743,7 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg) if ((val == 0 && itv->options.newi2c) || (val & 0x01)) ivtv_reset_ir_gpio(itv); if (val & 0x02) - itv->video_dec_func(itv, cmd, NULL); + v4l2_subdev_call(itv->sd_video, core, reset, 0); break; } diff --git a/linux/drivers/media/video/ivtv/ivtv-routing.c b/linux/drivers/media/video/ivtv/ivtv-routing.c index 05564919b..3fd302294 100644 --- a/linux/drivers/media/video/ivtv/ivtv-routing.c +++ b/linux/drivers/media/video/ivtv/ivtv-routing.c @@ -47,13 +47,13 @@ void ivtv_audio_set_io(struct ivtv *itv) route.output = 0; if (itv->card->hw_muxer & IVTV_HW_M52790) route.output = M52790_OUT_STEREO; - ivtv_i2c_hw(itv, itv->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route); + v4l2_subdev_call(itv->sd_muxer, audio, s_routing, &route); route.input = in->audio_input; route.output = 0; if (itv->card->hw_audio & IVTV_HW_MSP34XX) route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); - ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, &route); + ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, &route); } /* Selects the video input and output according to the current @@ -66,7 +66,7 @@ void ivtv_video_set_io(struct ivtv *itv) route.input = itv->card->video_inputs[inp].video_input; route.output = 0; - itv->video_dec_func(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); + v4l2_subdev_call(itv->sd_video, video, s_routing, &route); type = itv->card->video_inputs[inp].video_type; @@ -79,7 +79,7 @@ void ivtv_video_set_io(struct ivtv *itv) } if (itv->card->hw_video & IVTV_HW_GPIO) - ivtv_gpio(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); + ivtv_call_hw(itv, IVTV_HW_GPIO, video, s_routing, &route); if (itv->card->hw_video & IVTV_HW_UPD64031A) { if (type == IVTV_CARD_INPUT_VID_TUNER || @@ -92,7 +92,7 @@ void ivtv_video_set_io(struct ivtv *itv) } route.input |= itv->card->gr_config; - ivtv_upd64031a(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); + ivtv_call_hw(itv, IVTV_HW_UPD64031A, video, s_routing, &route); } if (itv->card->hw_video & IVTV_HW_UPD6408X) { @@ -110,6 +110,6 @@ void ivtv_video_set_io(struct ivtv *itv) route.input |= UPD64083_EXT_Y_ADC; } } - ivtv_upd64083(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); + ivtv_call_hw(itv, IVTV_HW_UPD6408X, video, s_routing, &route); } } diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c index 9b7aa79eb..76279ed30 100644 --- a/linux/drivers/media/video/ivtv/ivtv-streams.c +++ b/linux/drivers/media/video/ivtv/ivtv-streams.c @@ -172,7 +172,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; int num_offset = ivtv_stream_info[type].num_offset; - int num = itv->num + ivtv_first_minor + num_offset; + int num = itv->instance + ivtv_first_minor + num_offset; /* These four fields are always initialized. If v4l2dev == NULL, then this stream is not in use. In that case no other fields but these @@ -205,8 +205,8 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) return -ENOMEM; } - snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", - itv->num, s->name); + snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "%s %s", + itv->device.name, s->name); s->v4l2dev->num = num; s->v4l2dev->parent = &itv->dev->dev; @@ -260,6 +260,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) if (s_mpg->v4l2dev) num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset; } + video_set_drvdata(s->v4l2dev, s); /* Register device. First try the desired minor, then any free one. */ if (video_register_device(s->v4l2dev, vfl_type, num)) { @@ -343,7 +344,7 @@ static void ivtv_vbi_setup(struct ivtv *itv) ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); /* setup VBI registers */ - itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); + v4l2_subdev_call(itv->sd_video, video, s_fmt, &itv->vbi.in); /* determine number of lines and total number of VBI bytes. A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1 @@ -577,10 +578,10 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) clear_bit(IVTV_F_I_EOS, &itv->i_flags); /* Initialize Digitizer for Capture */ - itv->video_dec_func(itv, VIDIOC_STREAMOFF, NULL); + v4l2_subdev_call(itv->sd_video, video, s_stream, 0); ivtv_msleep_timeout(300, 1); ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); - itv->video_dec_func(itv, VIDIOC_STREAMON, NULL); + v4l2_subdev_call(itv->sd_video, video, s_stream, 1); } /* begin_capture */ diff --git a/linux/drivers/media/video/ivtv/ivtv-vbi.c b/linux/drivers/media/video/ivtv/ivtv-vbi.c index 4a37a7d2e..5c5d1c462 100644 --- a/linux/drivers/media/video/ivtv/ivtv-vbi.c +++ b/linux/drivers/media/video/ivtv/ivtv-vbi.c @@ -21,6 +21,7 @@ #include "ivtv-i2c.h" #include "ivtv-ioctl.h" #include "ivtv-queue.h" +#include "ivtv-cards.h" #include "ivtv-vbi.h" static void ivtv_set_vps(struct ivtv *itv, int enabled) @@ -37,7 +38,7 @@ static void ivtv_set_vps(struct ivtv *itv, int enabled) data.data[9] = itv->vbi.vps_payload.data[2]; data.data[10] = itv->vbi.vps_payload.data[3]; data.data[11] = itv->vbi.vps_payload.data[4]; - ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); } static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) @@ -51,12 +52,12 @@ static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) data.line = (mode & 1) ? 21 : 0; data.data[0] = cc->odd[0]; data.data[1] = cc->odd[1]; - ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); data.field = 1; data.line = (mode & 2) ? 21 : 0; data.data[0] = cc->even[0]; data.data[1] = cc->even[1]; - ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); } static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) @@ -79,7 +80,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) data.line = enabled ? 23 : 0; data.data[0] = mode & 0xff; data.data[1] = (mode >> 8) & 0xff; - ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); } static int odd_parity(u8 c) @@ -313,7 +314,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 continue; } vbi.p = p + 4; - itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi); + v4l2_subdev_call(itv->sd_video, video, decode_vbi_line, &vbi); if (vbi.type && !(lines & (1 << vbi.line))) { lines |= 1 << vbi.line; itv->vbi.sliced_data[line].id = vbi.type; @@ -437,7 +438,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv) data.id = V4L2_SLICED_WSS_625; data.field = 0; - if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { + if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { ivtv_set_wss(itv, 1, data.data[0] & 0xf); vi->wss_missing_cnt = 0; } else if (vi->wss_missing_cnt == 4) { @@ -451,13 +452,13 @@ void ivtv_vbi_work_handler(struct ivtv *itv) data.id = V4L2_SLICED_CAPTION_525; data.field = 0; - if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { + if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { mode |= 1; cc.odd[0] = data.data[0]; cc.odd[1] = data.data[1]; } data.field = 1; - if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { + if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { mode |= 2; cc.even[0] = data.data[0]; cc.even[1] = data.data[1]; diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c index 5e3613d86..26b91d2c8 100644 --- a/linux/drivers/media/video/ivtv/ivtvfb.c +++ b/linux/drivers/media/video/ivtv/ivtvfb.c @@ -48,6 +48,7 @@ #endif #include "ivtv-driver.h" +#include "ivtv-cards.h" #include "ivtv-i2c.h" #include "ivtv-udma.h" #include "ivtv-mailbox.h" @@ -121,15 +122,15 @@ MODULE_LICENSE("GPL"); #define IVTVFB_DEBUG(x, type, fmt, args...) \ do { \ if ((x) & ivtvfb_debug) \ - printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->num , ## args); \ + printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \ } while (0) #define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args) #define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args) /* Standard kernel messages */ -#define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->num , ## args) -#define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->num , ## args) -#define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->num , ## args) +#define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->instance , ## args) +#define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->instance , ## args) +#define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args) /* --------------------------------------------------------------------- */ @@ -904,16 +905,16 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info) switch (blank_mode) { case FB_BLANK_UNBLANK: ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1); - ivtv_saa7127(itv, VIDIOC_STREAMON, NULL); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); break; case FB_BLANK_NORMAL: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_VSYNC_SUSPEND: ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); - ivtv_saa7127(itv, VIDIOC_STREAMON, NULL); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); break; case FB_BLANK_POWERDOWN: - ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); break; } @@ -1197,10 +1198,45 @@ static int ivtvfb_init_card(struct ivtv *itv) } +static int __init ivtvfb_callback_init(struct device *dev, void *p) +{ + struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); + struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device); + + if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { + if (ivtvfb_init_card(itv) == 0) { + IVTVFB_INFO("Framebuffer registered on %s\n", + itv->device.name); + (*(int *)p)++; + } + } + return 0; +} + +static int ivtvfb_callback_cleanup(struct device *dev, void *p) +{ + struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); + struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device); + + if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { + if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { + IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", + itv->instance); + return 0; + } + IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); + ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); + ivtvfb_release_buffers(itv); + itv->osd_video_pbase = 0; + } + return 0; +} + static int __init ivtvfb_init(void) { - struct ivtv *itv; - int i, registered = 0; + struct device_driver *drv; + int registered = 0; + int err; if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) { printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n", @@ -1208,20 +1244,11 @@ static int __init ivtvfb_init(void) return -EINVAL; } - /* Locate & initialise all cards supporting an OSD. */ - for (i = 0; i < ivtv_cards_active; i++) { - if (ivtvfb_card_id != -1 && i != ivtvfb_card_id) - continue; - itv = ivtv_cards[i]; - if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { - if (ivtvfb_init_card(itv) == 0) { - IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i); - registered++; - } - } - } + drv = driver_find("ivtv", &pci_bus_type); + err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); + put_driver(drv); if (!registered) { - printk(KERN_ERR "ivtvfb: no cards found"); + printk(KERN_ERR "ivtvfb: no cards found\n"); return -ENODEV; } return 0; @@ -1229,24 +1256,14 @@ static int __init ivtvfb_init(void) static void ivtvfb_cleanup(void) { - struct ivtv *itv; - int i; + struct device_driver *drv; + int err; printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n"); - for (i = 0; i < ivtv_cards_active; i++) { - itv = ivtv_cards[i]; - if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) { - if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { - IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i); - return; - } - IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i); - ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); - ivtvfb_release_buffers(itv); - itv->osd_video_pbase = 0; - } - } + drv = driver_find("ivtv", &pci_bus_type); + err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); + put_driver(drv); } module_init(ivtvfb_init); -- cgit v1.2.3 From 8bd850c491873395b5ec35921fca010bb2ae4f75 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 30 Nov 2008 08:01:21 -0500 Subject: cx18: cx18_writel_expect() should not declare success on a PCI read error From: Andy Walls cx18: cx18_writel_expect() should not declare success on a PCI read error. This removes the potential for cx18_write*_expect() calls to not accomplish a PCI write successfully as expected. The CX18-AV core uses the *expect() calls often and this may be the source of intermittent audio problems and standands switching problems. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-io.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/cx18/cx18-io.h b/linux/drivers/media/video/cx18/cx18-io.h index e6716dcb1..2635b3a8c 100644 --- a/linux/drivers/media/video/cx18/cx18-io.h +++ b/linux/drivers/media/video/cx18/cx18-io.h @@ -83,10 +83,14 @@ void cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, u32 eval, u32 mask) { int i; + u32 r; eval &= mask; for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) { cx18_writel_noretry(cx, val, addr); - if (eval == (cx18_readl(cx, addr) & mask)) + r = cx18_readl(cx, addr); + if (r == 0xffffffff && eval != 0xffffffff) + continue; + if (eval == (r & mask)) break; } } -- cgit v1.2.3 From 8bebedcb0a873713c1f1ec2b3c12bcee7116f723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 1 Dec 2008 07:32:59 +0100 Subject: Correct the name of the Pascal Stangs library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 3ca5a0218..def39d5bc 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -10,7 +10,7 @@ * v4l2 interface modeled after the V4L2 driver * for SN9C10x PC Camera Controllers * - * Register defines taken from Pascal Stangs Proxycon Armlib + * Register defines taken from Pascal Stangs Procyon Armlib * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as -- cgit v1.2.3 From fd3e91675d5c7b8c8a82af7f8e3c5d706e458791 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Mon, 1 Dec 2008 10:51:14 +0100 Subject: dib0700: Stop repeating after user stops pushing button From: Devin Heitmueller A user noticed that there would continue to be 4-6 keypresses even after the user stopped holding down the button. This was because we were not reading the bulk pipe faster than the firmware was injecting information, which would result in a backlog. Make the query interval faster, and increase the number of cycles before we start repeating to compensate. Thanks to Knud Poulsen for pointing this out. Priority: high Signed-off-by: Devin Heitmueller Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index f28d3ae59..391732788 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -446,13 +446,13 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) == NULL ? -ENODEV : 0; } -#define DEFAULT_RC_INTERVAL 150 +#define DEFAULT_RC_INTERVAL 50 static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; /* Number of keypresses to ignore before start repeating */ -#define RC_REPEAT_DELAY 2 -#define RC_REPEAT_DELAY_V1_20 5 +#define RC_REPEAT_DELAY 6 +#define RC_REPEAT_DELAY_V1_20 10 -- cgit v1.2.3 From 714df90d630e253a910741d99b28b96fbd56ed7d Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Mon, 1 Dec 2008 10:59:37 +0100 Subject: [PATCH] Cablestar 2 I2C retries (fix CableStar2 support) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Antti Seppälä At some point the Flexcop driver was changed to support newer Flexcop cards. These modifications however broke the detection of Cablestar 2 DVB-C cards. The reason is that the earlier version of the driver used to retry unsuccessful i2c operations. The demodulator of Cablestar 2 cards (stv0297) seems to be very dependent on these retries and adding them back fixes Cablestar detection. This patch restores this behaviour for the CableStar2. Priority: high Signed-off-by: Antti Seppälä Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 2 ++ linux/drivers/media/dvb/b2c2/flexcop-i2c.c | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index a127a4175..5cded3708 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -628,12 +628,14 @@ int flexcop_frontend_init(struct flexcop_device *fc) } /* try the cable dvb (stv0297) */ + fc->fc_i2c_adap[0].no_base_addr = 1; fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); if (fc->fe != NULL) { fc->dev_type = FC_CABLE; fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; goto fe_found; } + fc->fc_i2c_adap[0].no_base_addr = 0; /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ fc->fe = dvb_attach(mt312_attach, diff --git a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c index 05635c453..01d27613f 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -47,8 +47,12 @@ static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c, int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ ret; - r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; ret = flexcop_i2c_operation(i2c->fc, &r100); + if (ret != 0) { + deb_i2c("Retrying operation\n"); + r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; + ret = flexcop_i2c_operation(i2c->fc, &r100); + } if (ret != 0) { deb_i2c("read failed. %d\n", ret); return ret; -- cgit v1.2.3 From dbd5de8bd7cd16274c7b4ed29be253cf73bd3300 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 1 Dec 2008 13:44:48 +0100 Subject: Change power on/off sequence on ov772x Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 35 ++++++++++++++++++++++------------- 1 files changed, 22 insertions(+), 13 deletions(-) --- linux/drivers/media/video/ov772x.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 2ddc2ab70..cf1c7bcfc 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -593,12 +593,30 @@ static int ov772x_reset(struct i2c_client *client) static int ov772x_init(struct soc_camera_device *icd) { - return 0; + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + int ret = 0; + + if (priv->info->link.power) { + ret = priv->info->link.power(&priv->client->dev, 1); + if (ret < 0) + return ret; + } + + if (priv->info->link.reset) + ret = priv->info->link.reset(&priv->client->dev); + + return ret; } static int ov772x_release(struct soc_camera_device *icd) { - return 0; + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + int ret = 0; + + if (priv->info->link.power) + ret = priv->info->link.power(&priv->client->dev, 0); + + return ret; } static int ov772x_start_capture(struct soc_camera_device *icd) @@ -814,9 +832,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd) icd->formats = ov772x_fmt_lists; icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); - if (priv->info->link.power) - priv->info->link.power(&priv->client->dev, 1); - /* * check and show product ID and manufacturer ID */ @@ -824,8 +839,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd) ver = i2c_smbus_read_byte_data(priv->client, VER); if (pid != 0x77 || ver != 0x21) { - if (priv->info->link.power) - priv->info->link.power(&priv->client->dev, 0); + dev_err(&icd->dev, + "Product ID error %x:%x\n", pid, ver); return -ENODEV; } @@ -842,13 +857,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd) static void ov772x_video_remove(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - soc_camera_video_stop(icd); - - if (priv->info->link.power) - priv->info->link.power(&priv->client->dev, 0); - } static struct soc_camera_ops ov772x_ops = { -- cgit v1.2.3 From 64934a93ee0c4f6edf946a0c044ee7a0ec871a0c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 1 Dec 2008 13:44:51 +0100 Subject: Register name fix for ov772x driver Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 48 +++++++++++++++++++++--------------------- 1 files changed, 24 insertions(+), 24 deletions(-) --- linux/drivers/media/video/ov772x.c | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index cf1c7bcfc..bd6dd150c 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -112,34 +112,34 @@ #define AREF7 0x55 /* Analog reference control */ #define UFIX 0x60 /* U channel fixed value output */ #define VFIX 0x61 /* V channel fixed value output */ -#define AW_BB_BLK 0x62 /* AWB option for advanced AWB */ -#define AW_B_CTRL0 0x63 /* AWB control byte 0 */ +#define AWBB_BLK 0x62 /* AWB option for advanced AWB */ +#define AWB_CTRL0 0x63 /* AWB control byte 0 */ #define DSP_CTRL1 0x64 /* DSP control byte 1 */ #define DSP_CTRL2 0x65 /* DSP control byte 2 */ #define DSP_CTRL3 0x66 /* DSP control byte 3 */ #define DSP_CTRL4 0x67 /* DSP control byte 4 */ -#define AW_B_BIAS 0x68 /* AWB BLC level clip */ -#define AW_BCTRL1 0x69 /* AWB control 1 */ -#define AW_BCTRL2 0x6A /* AWB control 2 */ -#define AW_BCTRL3 0x6B /* AWB control 3 */ -#define AW_BCTRL4 0x6C /* AWB control 4 */ -#define AW_BCTRL5 0x6D /* AWB control 5 */ -#define AW_BCTRL6 0x6E /* AWB control 6 */ -#define AW_BCTRL7 0x6F /* AWB control 7 */ -#define AW_BCTRL8 0x70 /* AWB control 8 */ -#define AW_BCTRL9 0x71 /* AWB control 9 */ -#define AW_BCTRL10 0x72 /* AWB control 10 */ -#define AW_BCTRL11 0x73 /* AWB control 11 */ -#define AW_BCTRL12 0x74 /* AWB control 12 */ -#define AW_BCTRL13 0x75 /* AWB control 13 */ -#define AW_BCTRL14 0x76 /* AWB control 14 */ -#define AW_BCTRL15 0x77 /* AWB control 15 */ -#define AW_BCTRL16 0x78 /* AWB control 16 */ -#define AW_BCTRL17 0x79 /* AWB control 17 */ -#define AW_BCTRL18 0x7A /* AWB control 18 */ -#define AW_BCTRL19 0x7B /* AWB control 19 */ -#define AW_BCTRL20 0x7C /* AWB control 20 */ -#define AW_BCTRL21 0x7D /* AWB control 21 */ +#define AWB_BIAS 0x68 /* AWB BLC level clip */ +#define AWB_CTRL1 0x69 /* AWB control 1 */ +#define AWB_CTRL2 0x6A /* AWB control 2 */ +#define AWB_CTRL3 0x6B /* AWB control 3 */ +#define AWB_CTRL4 0x6C /* AWB control 4 */ +#define AWB_CTRL5 0x6D /* AWB control 5 */ +#define AWB_CTRL6 0x6E /* AWB control 6 */ +#define AWB_CTRL7 0x6F /* AWB control 7 */ +#define AWB_CTRL8 0x70 /* AWB control 8 */ +#define AWB_CTRL9 0x71 /* AWB control 9 */ +#define AWB_CTRL10 0x72 /* AWB control 10 */ +#define AWB_CTRL11 0x73 /* AWB control 11 */ +#define AWB_CTRL12 0x74 /* AWB control 12 */ +#define AWB_CTRL13 0x75 /* AWB control 13 */ +#define AWB_CTRL14 0x76 /* AWB control 14 */ +#define AWB_CTRL15 0x77 /* AWB control 15 */ +#define AWB_CTRL16 0x78 /* AWB control 16 */ +#define AWB_CTRL17 0x79 /* AWB control 17 */ +#define AWB_CTRL18 0x7A /* AWB control 18 */ +#define AWB_CTRL19 0x7B /* AWB control 19 */ +#define AWB_CTRL20 0x7C /* AWB control 20 */ +#define AWB_CTRL21 0x7D /* AWB control 21 */ #define GAM1 0x7E /* Gamma Curve 1st segment input end point */ #define GAM2 0x7F /* Gamma Curve 2nd segment input end point */ #define GAM3 0x80 /* Gamma Curve 3rd segment input end point */ -- cgit v1.2.3 From 0b36e297630eb11d129e39d264704119ef3e5bb6 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 1 Dec 2008 13:44:53 +0100 Subject: soc-camera: merge .try_bus_param() into .try_fmt_cap() .try_bus_param() method from struct soc_camera_host_ops is only called at one location immediately before .try_fmt_cap(), there is no value in keeping these two methods separate, merge them. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 6 +++++- drivers/media/video/sh_mobile_ceu_camera.c | 6 +++++- drivers/media/video/soc_camera.c | 5 ----- include/media/soc_camera.h | 1 - 4 files changed, 10 insertions(+), 8 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 6 +++++- linux/drivers/media/video/sh_mobile_ceu_camera.c | 6 +++++- linux/drivers/media/video/soc_camera.c | 5 ----- linux/include/media/soc_camera.h | 1 - 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 08723ed84..a585f4138 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -918,6 +918,11 @@ static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, struct v4l2_format *f) { + int ret = pxa_camera_try_bus_param(icd, f->fmt.pix.pixelformat); + + if (ret < 0) + return ret; + /* limit to pxa hardware capabilities */ if (f->fmt.pix.height < 32) f->fmt.pix.height = 32; @@ -1044,7 +1049,6 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .reqbufs = pxa_camera_reqbufs, .poll = pxa_camera_poll, .querycap = pxa_camera_querycap, - .try_bus_param = pxa_camera_try_bus_param, .set_bus_param = pxa_camera_set_bus_param, }; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 2fb8bee0b..0cfcc2fec 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -454,6 +454,11 @@ static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd, static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, struct v4l2_format *f) { + int ret = sh_mobile_ceu_try_bus_param(icd, f->fmt.pix.pixelformat); + + if (ret < 0) + return ret; + /* FIXME: calculate using depth and bus width */ if (f->fmt.pix.height < 4) @@ -541,7 +546,6 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .reqbufs = sh_mobile_ceu_reqbufs, .poll = sh_mobile_ceu_poll, .querycap = sh_mobile_ceu_querycap, - .try_bus_param = sh_mobile_ceu_try_bus_param, .set_bus_param = sh_mobile_ceu_set_bus_param, .init_videobuf = sh_mobile_ceu_init_videobuf, }; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 7a46697c4..1720f8463 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -78,11 +78,6 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - /* test physical bus parameters */ - ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat); - if (ret) - return ret; - /* limit format to hardware capabilities */ ret = ici->ops->try_fmt_cap(icd, f); diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 9231e2d90..ee0e6b4be 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -73,7 +73,6 @@ struct soc_camera_host_ops { struct soc_camera_device *); int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); - int (*try_bus_param)(struct soc_camera_device *, __u32); int (*set_bus_param)(struct soc_camera_device *, __u32); unsigned int (*poll)(struct file *, poll_table *); }; -- cgit v1.2.3 From a25098a0d06ad54e605ab676785dd412a00be9bc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 1 Dec 2008 13:44:56 +0100 Subject: soc-camera: formatting fixes Minor formatting fixes Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/soc_camera.c | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) --- linux/drivers/media/video/soc_camera.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 1720f8463..8730869a8 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -36,8 +36,8 @@ static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); static DEFINE_MUTEX(video_lock); -const static struct soc_camera_data_format* -format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) +const static struct soc_camera_data_format *format_by_fourcc( + struct soc_camera_device *icd, unsigned int fourcc) { unsigned int i; @@ -48,7 +48,7 @@ format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) } static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; @@ -261,7 +261,7 @@ static int soc_camera_close(struct inode *inode, struct file *file) } static ssize_t soc_camera_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; @@ -306,7 +306,6 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) return ici->ops->poll(file, pt); } - static struct file_operations soc_camera_fops = { .owner = THIS_MODULE, .open = soc_camera_open, @@ -318,9 +317,8 @@ static struct file_operations soc_camera_fops = { .llseek = no_llseek, }; - static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; @@ -367,7 +365,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, } static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) + struct v4l2_fmtdesc *f) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; @@ -386,7 +384,7 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, } static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; -- cgit v1.2.3 From 23c99ad0f49a1ec633853e1b2a265308c755abd0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 1 Dec 2008 13:44:59 +0100 Subject: soc-camera: let camera host drivers decide upon pixel format Pixel format requested by the user is not necessarily the same, as what a sensor driver provides. There are situations, when a camera host driver provides the required format, but requires a different format from the sensor. Further, the list of formats, supported by sensors is pretty static and can be pretty good described with a constant list of structures. Whereas decisions, made by camera host drivers to support requested formats can be quite complex, therefore it is better to let the host driver do the work. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 32 +++++++++++++++- drivers/media/video/sh_mobile_ceu_camera.c | 32 +++++++++++++++- drivers/media/video/soc_camera.c | 58 ++++++++++----------------- include/media/soc_camera.h | 3 + 4 files changed, 87 insertions(+), 38 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 32 ++++++++++++- linux/drivers/media/video/sh_mobile_ceu_camera.c | 32 ++++++++++++- linux/drivers/media/video/soc_camera.c | 58 +++++++++--------------- linux/include/media/soc_camera.h | 3 ++ 4 files changed, 87 insertions(+), 38 deletions(-) diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index a585f4138..4c206ac74 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -912,17 +912,43 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { - return icd->ops->set_fmt_cap(icd, pixfmt, rect); + const struct soc_camera_data_format *cam_fmt; + int ret; + + /* + * TODO: find a suitable supported by the SoC output format, check + * whether the sensor supports one of acceptable input formats. + */ + if (pixfmt) { + cam_fmt = soc_camera_format_by_fourcc(icd, pixfmt); + if (!cam_fmt) + return -EINVAL; + } + + ret = icd->ops->set_fmt_cap(icd, pixfmt, rect); + if (pixfmt && !ret) + icd->current_fmt = cam_fmt; + + return ret; } static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, struct v4l2_format *f) { + const struct soc_camera_data_format *cam_fmt; int ret = pxa_camera_try_bus_param(icd, f->fmt.pix.pixelformat); if (ret < 0) return ret; + /* + * TODO: find a suitable supported by the SoC output format, check + * whether the sensor supports one of acceptable input formats. + */ + cam_fmt = soc_camera_format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!cam_fmt) + return -EINVAL; + /* limit to pxa hardware capabilities */ if (f->fmt.pix.height < 32) f->fmt.pix.height = 32; @@ -934,6 +960,10 @@ static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, f->fmt.pix.width = 2048; f->fmt.pix.width &= ~0x01; + f->fmt.pix.bytesperline = f->fmt.pix.width * + DIV_ROUND_UP(cam_fmt->depth, 8); + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + /* limit to sensor capabilities */ return icd->ops->try_fmt_cap(icd, f); } diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 0cfcc2fec..8f42a1063 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -448,17 +448,43 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { - return icd->ops->set_fmt_cap(icd, pixfmt, rect); + const struct soc_camera_data_format *cam_fmt; + int ret; + + /* + * TODO: find a suitable supported by the SoC output format, check + * whether the sensor supports one of acceptable input formats. + */ + if (pixfmt) { + cam_fmt = soc_camera_format_by_fourcc(icd, pixfmt); + if (!cam_fmt) + return -EINVAL; + } + + ret = icd->ops->set_fmt_cap(icd, pixfmt, rect); + if (pixfmt && !ret) + icd->current_fmt = cam_fmt; + + return ret; } static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, struct v4l2_format *f) { + const struct soc_camera_data_format *cam_fmt; int ret = sh_mobile_ceu_try_bus_param(icd, f->fmt.pix.pixelformat); if (ret < 0) return ret; + /* + * TODO: find a suitable supported by the SoC output format, check + * whether the sensor supports one of acceptable input formats. + */ + cam_fmt = soc_camera_format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!cam_fmt) + return -EINVAL; + /* FIXME: calculate using depth and bus width */ if (f->fmt.pix.height < 4) @@ -472,6 +498,10 @@ static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, f->fmt.pix.width &= ~0x01; f->fmt.pix.height &= ~0x03; + f->fmt.pix.bytesperline = f->fmt.pix.width * + DIV_ROUND_UP(cam_fmt->depth, 8); + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + /* limit to sensor capabilities */ return icd->ops->try_fmt_cap(icd, f); } diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 8730869a8..0c9c86d8b 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -36,7 +36,7 @@ static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); static DEFINE_MUTEX(video_lock); -const static struct soc_camera_data_format *format_by_fourcc( +const struct soc_camera_data_format *soc_camera_format_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) { unsigned int i; @@ -46,6 +46,7 @@ const static struct soc_camera_data_format *format_by_fourcc( return icd->formats + i; return NULL; } +EXPORT_SYMBOL(soc_camera_format_by_fourcc); static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) @@ -55,25 +56,19 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); enum v4l2_field field; - const struct soc_camera_data_format *fmt; int ret; WARN_ON(priv != file->private_data); - fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); - if (!fmt) { - dev_dbg(&icd->dev, "invalid format 0x%08x\n", - f->fmt.pix.pixelformat); - return -EINVAL; - } - - dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc); - + /* + * TODO: this might also have to migrate to host-drivers, if anyone + * wishes to support other fields + */ field = f->fmt.pix.field; if (field == V4L2_FIELD_ANY) { - field = V4L2_FIELD_NONE; - } else if (V4L2_FIELD_NONE != field) { + f->fmt.pix.field = V4L2_FIELD_NONE; + } else if (field != V4L2_FIELD_NONE) { dev_err(&icd->dev, "Field type invalid.\n"); return -EINVAL; } @@ -81,13 +76,6 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, /* limit format to hardware capabilities */ ret = ici->ops->try_fmt_cap(icd, f); - /* calculate missing fields */ - f->fmt.pix.field = field; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - return ret; } @@ -326,18 +314,10 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, to_soc_camera_host(icd->dev.parent); int ret; struct v4l2_rect rect; - const static struct soc_camera_data_format *data_fmt; WARN_ON(priv != file->private_data); - data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); - if (!data_fmt) - return -EINVAL; - - /* buswidth may be further adjusted by the ici */ - icd->buswidth = data_fmt->depth; - - ret = soc_camera_try_fmt_vid_cap(file, icf, f); + ret = soc_camera_try_fmt_vid_cap(file, priv, f); if (ret < 0) return ret; @@ -346,14 +326,21 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, rect.width = f->fmt.pix.width; rect.height = f->fmt.pix.height; ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); - if (ret < 0) + if (ret < 0) { return ret; + } else if (!icd->current_fmt || + icd->current_fmt->fourcc != f->fmt.pix.pixelformat) { + dev_err(&ici->dev, "Host driver hasn't set up current " + "format correctly!\n"); + return -EINVAL; + } - icd->current_fmt = data_fmt; + /* buswidth may be further adjusted by the ici */ + icd->buswidth = icd->current_fmt->depth; icd->width = rect.width; icd->height = rect.height; icf->vb_vidq.field = f->fmt.pix.field; - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", f->type); @@ -395,10 +382,9 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.height = icd->height; f->fmt.pix.field = icf->vb_vidq.field; f->fmt.pix.pixelformat = icd->current_fmt->fourcc; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * icd->current_fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.bytesperline = f->fmt.pix.width * + DIV_ROUND_UP(icd->current_fmt->depth, 8); + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", icd->current_fmt->fourcc); return 0; diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index ee0e6b4be..8e8fcb75d 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -105,6 +105,9 @@ extern void soc_camera_device_unregister(struct soc_camera_device *icd); extern int soc_camera_video_start(struct soc_camera_device *icd); extern void soc_camera_video_stop(struct soc_camera_device *icd); +extern const struct soc_camera_data_format *soc_camera_format_by_fourcc( + struct soc_camera_device *icd, unsigned int fourcc); + struct soc_camera_data_format { const char *name; unsigned int depth; -- cgit v1.2.3 From 0245bbfa8052eabd0398e5b0d92345feabfcfafc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 1 Dec 2008 13:45:21 +0100 Subject: soc-camera: simplify naming We anyway don't follow the s_fmt_vid_cap / g_fmt_vid_cap / try_fmt_vid_cap naming, and soc-camera is so far only about video capture, let's simplify operation names a bit further. set_fmt_cap / try_fmt_cap wasn't a very good choice too. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m001.c | 14 +++++++------- drivers/media/video/mt9m111.c | 12 ++++++------ drivers/media/video/mt9v022.c | 14 +++++++------- drivers/media/video/ov772x.c | 14 +++++++------- drivers/media/video/pxa_camera.c | 16 ++++++++-------- drivers/media/video/sh_mobile_ceu_camera.c | 16 ++++++++-------- drivers/media/video/soc_camera.c | 6 +++--- drivers/media/video/soc_camera_platform.c | 12 ++++++------ include/media/soc_camera.h | 10 ++++------ 9 files changed, 56 insertions(+), 58 deletions(-) --- linux/drivers/media/video/mt9m001.c | 14 +++++++------- linux/drivers/media/video/mt9m111.c | 12 ++++++------ linux/drivers/media/video/mt9v022.c | 14 +++++++------- linux/drivers/media/video/ov772x.c | 14 +++++++------- linux/drivers/media/video/pxa_camera.c | 16 ++++++++-------- linux/drivers/media/video/sh_mobile_ceu_camera.c | 16 ++++++++-------- linux/drivers/media/video/soc_camera.c | 6 +++--- linux/drivers/media/video/soc_camera_platform.c | 12 ++++++------ linux/include/media/soc_camera.h | 10 ++++------ 9 files changed, 56 insertions(+), 58 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 228183c54..edacba723 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -285,8 +285,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) width_flag; } -static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9m001_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); int ret; @@ -298,7 +298,7 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); /* The caller provides a supported format, as verified per - * call to icd->try_fmt_cap() */ + * call to icd->try_fmt() */ if (!ret) ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); if (!ret) @@ -325,8 +325,8 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, return ret; } -static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m001_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) { if (f->fmt.pix.height < 32 + icd->y_skip_top) f->fmt.pix.height = 32 + icd->y_skip_top; @@ -447,8 +447,8 @@ static struct soc_camera_ops mt9m001_ops = { .release = mt9m001_release, .start_capture = mt9m001_start_capture, .stop_capture = mt9m001_stop_capture, - .set_fmt_cap = mt9m001_set_fmt_cap, - .try_fmt_cap = mt9m001_try_fmt_cap, + .set_fmt = mt9m001_set_fmt, + .try_fmt = mt9m001_try_fmt, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, .controls = mt9m001_controls, diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index ceff40edc..1fde94514 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -452,8 +452,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) return ret; } -static int mt9m111_set_fmt_cap(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9m111_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret; @@ -473,8 +473,8 @@ static int mt9m111_set_fmt_cap(struct soc_camera_device *icd, return ret; } -static int mt9m111_try_fmt_cap(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m111_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) { if (f->fmt.pix.height > MT9M111_MAX_HEIGHT) f->fmt.pix.height = MT9M111_MAX_HEIGHT; @@ -597,8 +597,8 @@ static struct soc_camera_ops mt9m111_ops = { .release = mt9m111_release, .start_capture = mt9m111_start_capture, .stop_capture = mt9m111_stop_capture, - .set_fmt_cap = mt9m111_set_fmt_cap, - .try_fmt_cap = mt9m111_try_fmt_cap, + .set_fmt = mt9m111_set_fmt, + .try_fmt = mt9m111_try_fmt, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, .controls = mt9m111_controls, diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index bea695a2c..1ca28c087 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -337,14 +337,14 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) width_flag; } -static int mt9v022_set_fmt_cap(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9v022_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); int ret; /* The caller provides a supported format, as verified per call to - * icd->try_fmt_cap(), datawidth is from our supported format list */ + * icd->try_fmt(), datawidth is from our supported format list */ switch (pixfmt) { case V4L2_PIX_FMT_GREY: case V4L2_PIX_FMT_Y16: @@ -400,8 +400,8 @@ static int mt9v022_set_fmt_cap(struct soc_camera_device *icd, return 0; } -static int mt9v022_try_fmt_cap(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9v022_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) { if (f->fmt.pix.height < 32 + icd->y_skip_top) f->fmt.pix.height = 32 + icd->y_skip_top; @@ -538,8 +538,8 @@ static struct soc_camera_ops mt9v022_ops = { .release = mt9v022_release, .start_capture = mt9v022_start_capture, .stop_capture = mt9v022_stop_capture, - .set_fmt_cap = mt9v022_set_fmt_cap, - .try_fmt_cap = mt9v022_try_fmt_cap, + .set_fmt = mt9v022_set_fmt, + .try_fmt = mt9v022_try_fmt, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, .controls = mt9v022_controls, diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index bd6dd150c..c023bbc84 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -755,9 +755,9 @@ static int ov772x_set_register(struct soc_camera_device *icd, } #endif -static int ov772x_set_fmt_cap(struct soc_camera_device *icd, - __u32 pixfmt, - struct v4l2_rect *rect) +static int ov772x_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, + struct v4l2_rect *rect) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); int ret = -EINVAL; @@ -778,8 +778,8 @@ static int ov772x_set_fmt_cap(struct soc_camera_device *icd, return ret; } -static int ov772x_try_fmt_cap(struct soc_camera_device *icd, - struct v4l2_format *f) +static int ov772x_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; struct ov772x_priv *priv; @@ -868,8 +868,8 @@ static struct soc_camera_ops ov772x_ops = { .release = ov772x_release, .start_capture = ov772x_start_capture, .stop_capture = ov772x_stop_capture, - .set_fmt_cap = ov772x_set_fmt_cap, - .try_fmt_cap = ov772x_try_fmt_cap, + .set_fmt = ov772x_set_fmt, + .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, .get_chip_id = ov772x_get_chip_id, diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 4c206ac74..1cdff7381 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -909,8 +909,8 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; } -static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int pxa_camera_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) { const struct soc_camera_data_format *cam_fmt; int ret; @@ -925,15 +925,15 @@ static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, return -EINVAL; } - ret = icd->ops->set_fmt_cap(icd, pixfmt, rect); + ret = icd->ops->set_fmt(icd, pixfmt, rect); if (pixfmt && !ret) icd->current_fmt = cam_fmt; return ret; } -static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, - struct v4l2_format *f) +static int pxa_camera_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) { const struct soc_camera_data_format *cam_fmt; int ret = pxa_camera_try_bus_param(icd, f->fmt.pix.pixelformat); @@ -965,7 +965,7 @@ static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; /* limit to sensor capabilities */ - return icd->ops->try_fmt_cap(icd, f); + return icd->ops->try_fmt(icd, f); } static int pxa_camera_reqbufs(struct soc_camera_file *icf, @@ -1073,8 +1073,8 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .remove = pxa_camera_remove_device, .suspend = pxa_camera_suspend, .resume = pxa_camera_resume, - .set_fmt_cap = pxa_camera_set_fmt_cap, - .try_fmt_cap = pxa_camera_try_fmt_cap, + .set_fmt = pxa_camera_set_fmt, + .try_fmt = pxa_camera_try_fmt, .init_videobuf = pxa_camera_init_videobuf, .reqbufs = pxa_camera_reqbufs, .poll = pxa_camera_poll, diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 8f42a1063..e2e816213 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -445,8 +445,8 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, return 0; } -static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) { const struct soc_camera_data_format *cam_fmt; int ret; @@ -461,15 +461,15 @@ static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd, return -EINVAL; } - ret = icd->ops->set_fmt_cap(icd, pixfmt, rect); + ret = icd->ops->set_fmt(icd, pixfmt, rect); if (pixfmt && !ret) icd->current_fmt = cam_fmt; return ret; } -static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, - struct v4l2_format *f) +static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) { const struct soc_camera_data_format *cam_fmt; int ret = sh_mobile_ceu_try_bus_param(icd, f->fmt.pix.pixelformat); @@ -503,7 +503,7 @@ static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; /* limit to sensor capabilities */ - return icd->ops->try_fmt_cap(icd, f); + return icd->ops->try_fmt(icd, f); } static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf, @@ -571,8 +571,8 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .owner = THIS_MODULE, .add = sh_mobile_ceu_add_device, .remove = sh_mobile_ceu_remove_device, - .set_fmt_cap = sh_mobile_ceu_set_fmt_cap, - .try_fmt_cap = sh_mobile_ceu_try_fmt_cap, + .set_fmt = sh_mobile_ceu_set_fmt, + .try_fmt = sh_mobile_ceu_try_fmt, .reqbufs = sh_mobile_ceu_reqbufs, .poll = sh_mobile_ceu_poll, .querycap = sh_mobile_ceu_querycap, diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 0c9c86d8b..5befc748e 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -74,7 +74,7 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, } /* limit format to hardware capabilities */ - ret = ici->ops->try_fmt_cap(icd, f); + ret = ici->ops->try_fmt(icd, f); return ret; } @@ -325,7 +325,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, rect.top = icd->y_current; rect.width = f->fmt.pix.width; rect.height = f->fmt.pix.height; - ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); + ret = ici->ops->set_fmt(icd, f->fmt.pix.pixelformat, &rect); if (ret < 0) { return ret; } else if (!icd->current_fmt || @@ -554,7 +554,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = ici->ops->set_fmt_cap(icd, 0, &a->c); + ret = ici->ops->set_fmt(icd, 0, &a->c); if (!ret) { icd->width = a->c.width; icd->height = a->c.height; diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index bb7a9d480..c23871e4c 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -79,14 +79,14 @@ soc_camera_platform_query_bus_param(struct soc_camera_device *icd) return p->bus_param; } -static int soc_camera_platform_set_fmt_cap(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int soc_camera_platform_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) { return 0; } -static int soc_camera_platform_try_fmt_cap(struct soc_camera_device *icd, - struct v4l2_format *f) +static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) { struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); @@ -124,8 +124,8 @@ static struct soc_camera_ops soc_camera_platform_ops = { .release = soc_camera_platform_release, .start_capture = soc_camera_platform_start_capture, .stop_capture = soc_camera_platform_stop_capture, - .set_fmt_cap = soc_camera_platform_set_fmt_cap, - .try_fmt_cap = soc_camera_platform_try_fmt_cap, + .set_fmt = soc_camera_platform_set_fmt, + .try_fmt = soc_camera_platform_try_fmt, .set_bus_param = soc_camera_platform_set_bus_param, .query_bus_param = soc_camera_platform_query_bus_param, }; diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 8e8fcb75d..b14f6ddc9 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -66,9 +66,8 @@ struct soc_camera_host_ops { void (*remove)(struct soc_camera_device *); int (*suspend)(struct soc_camera_device *, pm_message_t state); int (*resume)(struct soc_camera_device *); - int (*set_fmt_cap)(struct soc_camera_device *, __u32, - struct v4l2_rect *); - int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); + int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *); + int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); void (*init_videobuf)(struct videobuf_queue *, struct soc_camera_device *); int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); @@ -125,9 +124,8 @@ struct soc_camera_ops { int (*release)(struct soc_camera_device *); int (*start_capture)(struct soc_camera_device *); int (*stop_capture)(struct soc_camera_device *); - int (*set_fmt_cap)(struct soc_camera_device *, __u32, - struct v4l2_rect *); - int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); + int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *); + int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); unsigned long (*query_bus_param)(struct soc_camera_device *); int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*get_chip_id)(struct soc_camera_device *, -- cgit v1.2.3 From df64fb6c88d2244e8a6374b34ff395e31ec6ef4f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 1 Dec 2008 13:45:24 +0100 Subject: soc-camera: add a per-camera device host private data pointer This pointer will be used by pxa_camera.c to point to its pixel format data. Signed-off-by: Guennadi Liakhovetski --- include/media/soc_camera.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) --- linux/include/media/soc_camera.h | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index b14f6ddc9..dddaf45c9 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -42,6 +42,7 @@ struct soc_camera_device { const struct soc_camera_data_format *formats; int num_formats; struct module *owner; + void *host_priv; /* per-device host private data */ /* soc_camera.c private count. Only accessed with video_lock held */ int use_count; }; -- cgit v1.2.3 From 70459071e4ccc3617dc180337b15366b596f9047 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 1 Dec 2008 13:45:27 +0100 Subject: soc-camera: pixel format negotiation - core support Allocate and fill a list of formats, supported by this specific camera-host combination. Use it for format enumeration. Take care to stay backwards-compatible. Camera hosts rely on sensor formats available, as well as host specific translations. We add a structure so that hosts can define a translation table and use it for format check and setup. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Robert Jarzmik --- drivers/media/video/soc_camera.c | 93 +++++++++++++++++++++++++++++++++----- include/media/soc_camera.h | 25 ++++++++++- 2 files changed, 105 insertions(+), 13 deletions(-) --- linux/drivers/media/video/soc_camera.c | 93 +++++++++++++++++++++++++++++----- linux/include/media/soc_camera.h | 25 ++++++++- 2 files changed, 105 insertions(+), 13 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 5befc748e..4a9c52c37 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -48,6 +48,18 @@ const struct soc_camera_data_format *soc_camera_format_by_fourcc( } EXPORT_SYMBOL(soc_camera_format_by_fourcc); +const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( + struct soc_camera_device *icd, unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < icd->num_user_formats; i++) + if (icd->user_formats[i].host_fmt->fourcc == fourcc) + return icd->user_formats + i; + return NULL; +} +EXPORT_SYMBOL(soc_camera_xlate_by_fourcc); + static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { @@ -162,6 +174,59 @@ static int soc_camera_dqbuf(struct file *file, void *priv, return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); } +static int soc_camera_init_user_formats(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int i, fmts = 0; + + if (!ici->ops->get_formats) + /* + * Fallback mode - the host will have to serve all + * sensor-provided formats one-to-one to the user + */ + fmts = icd->num_formats; + else + /* + * First pass - only count formats this host-sensor + * configuration can provide + */ + for (i = 0; i < icd->num_formats; i++) + fmts += ici->ops->get_formats(icd, i, NULL); + + if (!fmts) + return -ENXIO; + + icd->user_formats = + vmalloc(fmts * sizeof(struct soc_camera_format_xlate)); + if (!icd->user_formats) + return -ENOMEM; + + icd->num_user_formats = fmts; + fmts = 0; + + dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); + + /* Second pass - actually fill data formats */ + for (i = 0; i < icd->num_formats; i++) + if (!ici->ops->get_formats) { + icd->user_formats[i].host_fmt = icd->formats + i; + icd->user_formats[i].cam_fmt = icd->formats + i; + icd->user_formats[i].buswidth = icd->formats[i].depth; + } else { + fmts += ici->ops->get_formats(icd, i, + &icd->user_formats[fmts]); + } + + icd->current_fmt = icd->user_formats[0].host_fmt; + + return 0; +} + +static void soc_camera_free_user_formats(struct soc_camera_device *icd) +{ + vfree(icd->user_formats); +} + static int soc_camera_open(struct inode *inode, struct file *file) { struct video_device *vdev; @@ -198,10 +263,12 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* Now we really have to activate the camera */ if (icd->use_count == 1) { + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eiufmt; ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); - icd->use_count--; goto eiciadd; } } @@ -217,6 +284,9 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* All errors are entered with the video_lock held */ eiciadd: + soc_camera_free_user_formats(icd); +eiufmt: + icd->use_count--; module_put(ici->ops->owner); emgi: module_put(icd->ops->owner); @@ -235,8 +305,10 @@ static int soc_camera_close(struct inode *inode, struct file *file) mutex_lock(&video_lock); icd->use_count--; - if (!icd->use_count) + if (!icd->use_count) { ici->ops->remove(icd); + soc_camera_free_user_formats(icd); + } module_put(icd->ops->owner); module_put(ici->ops->owner); mutex_unlock(&video_lock); @@ -312,6 +384,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + __u32 pixfmt = f->fmt.pix.pixelformat; int ret; struct v4l2_rect rect; @@ -329,14 +402,12 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, if (ret < 0) { return ret; } else if (!icd->current_fmt || - icd->current_fmt->fourcc != f->fmt.pix.pixelformat) { - dev_err(&ici->dev, "Host driver hasn't set up current " - "format correctly!\n"); + icd->current_fmt->fourcc != pixfmt) { + dev_err(&ici->dev, + "Host driver hasn't set up current format correctly!\n"); return -EINVAL; } - /* buswidth may be further adjusted by the ici */ - icd->buswidth = icd->current_fmt->depth; icd->width = rect.width; icd->height = rect.height; icf->vb_vidq.field = f->fmt.pix.field; @@ -348,7 +419,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, icd->width, icd->height); /* set physical bus parameters */ - return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat); + return ici->ops->set_bus_param(icd, pixfmt); } static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, @@ -360,10 +431,10 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, WARN_ON(priv != file->private_data); - if (f->index >= icd->num_formats) + if (f->index >= icd->num_user_formats) return -EINVAL; - format = &icd->formats[f->index]; + format = icd->user_formats[f->index].host_fmt; strlcpy(f->description, format->name, sizeof(f->description)); f->pixelformat = format->fourcc; @@ -920,8 +991,6 @@ int soc_camera_video_start(struct soc_camera_device *icd) vdev->minor = -1; vdev->tvnorms = V4L2_STD_UNKNOWN, - icd->current_fmt = &icd->formats[0]; - err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); if (err < 0) { dev_err(vdev->parent, "video_register_device failed\n"); diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index dddaf45c9..da57ffdae 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -41,6 +41,8 @@ struct soc_camera_device { const struct soc_camera_data_format *current_fmt; const struct soc_camera_data_format *formats; int num_formats; + struct soc_camera_format_xlate *user_formats; + int num_user_formats; struct module *owner; void *host_priv; /* per-device host private data */ /* soc_camera.c private count. Only accessed with video_lock held */ @@ -65,8 +67,10 @@ struct soc_camera_host_ops { struct module *owner; int (*add)(struct soc_camera_device *); void (*remove)(struct soc_camera_device *); - int (*suspend)(struct soc_camera_device *, pm_message_t state); + int (*suspend)(struct soc_camera_device *, pm_message_t); int (*resume)(struct soc_camera_device *); + int (*get_formats)(struct soc_camera_device *, int, + struct soc_camera_format_xlate *); int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *); int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); void (*init_videobuf)(struct videobuf_queue *, @@ -107,6 +111,8 @@ extern void soc_camera_video_stop(struct soc_camera_device *icd); extern const struct soc_camera_data_format *soc_camera_format_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc); +extern const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( + struct soc_camera_device *icd, unsigned int fourcc); struct soc_camera_data_format { const char *name; @@ -115,6 +121,23 @@ struct soc_camera_data_format { enum v4l2_colorspace colorspace; }; +/** + * struct soc_camera_format_xlate - match between host and sensor formats + * @cam_fmt: sensor format provided by the sensor + * @host_fmt: host format after host translation from cam_fmt + * @buswidth: bus width for this format + * + * Host and sensor translation structure. Used in table of host and sensor + * formats matchings in soc_camera_device. A host can override the generic list + * generation by implementing get_formats(), and use it for format checks and + * format setup. + */ +struct soc_camera_format_xlate { + const struct soc_camera_data_format *cam_fmt; + const struct soc_camera_data_format *host_fmt; + unsigned char buswidth; +}; + struct soc_camera_ops { struct module *owner; int (*probe)(struct soc_camera_device *); -- cgit v1.2.3 From e5d82c47206f8bd3ab34f728d8861a816f246d8a Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 1 Dec 2008 13:45:35 +0100 Subject: pxa-camera: pixel format negotiation Use the new format-negotiation infrastructure, support all four YUV422 packed and the planar formats. The new translation structure enables to build the format list with buswidth, depth, host format and camera format checked, so that it's not done anymore on try_fmt nor set_fmt. Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 207 ++++++++++++++++++++++++++++++-------- 1 files changed, 165 insertions(+), 42 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 207 ++++++++++++++++++++++++++------- 1 file changed, 165 insertions(+), 42 deletions(-) diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 1cdff7381..210a99780 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -770,6 +770,9 @@ static int test_platform_param(struct pxa_camera_dev *pcdev, if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)) return -EINVAL; *flags |= SOCAM_DATAWIDTH_8; + break; + default: + return -EINVAL; } return 0; @@ -828,12 +831,10 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) * We fix bit-per-pixel equal to data-width... */ switch (common_flags & SOCAM_DATAWIDTH_MASK) { case SOCAM_DATAWIDTH_10: - icd->buswidth = 10; dw = 4; bpp = 0x40; break; case SOCAM_DATAWIDTH_9: - icd->buswidth = 9; dw = 3; bpp = 0x20; break; @@ -841,7 +842,6 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) /* Actually it can only be 8 now, * default is just to silence compiler warnings */ case SOCAM_DATAWIDTH_8: - icd->buswidth = 8; dw = 2; bpp = 0; } @@ -867,7 +867,17 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) case V4L2_PIX_FMT_YUV422P: pcdev->channels = 3; cicr1 |= CICR1_YCBCR_F; + /* + * Normally, pxa bus wants as input UYVY format. We allow all + * reorderings of the YUV422 format, as no processing is done, + * and the YUV stream is just passed through without any + * transformation. Note that UYVY is the only format that + * should be used if pxa framebuffer Overlay2 is used. + */ + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: cicr1 |= CICR1_COLOR_SP_VAL(2); break; case V4L2_PIX_FMT_RGB555: @@ -893,13 +903,14 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) return 0; } -static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +static int pxa_camera_try_bus_param(struct soc_camera_device *icd, + unsigned char buswidth) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; unsigned long bus_flags, camera_flags; - int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); + int ret = test_platform_param(pcdev, buswidth, &bus_flags); if (ret < 0) return ret; @@ -909,25 +920,139 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; } +static const struct soc_camera_data_format pxa_camera_formats[] = { + { + .name = "Planar YUV422 16 bit", + .depth = 16, + .fourcc = V4L2_PIX_FMT_YUV422P, + .colorspace = V4L2_COLORSPACE_JPEG, + }, +}; + +static bool buswidth_supported(struct soc_camera_device *icd, int depth) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + + switch (depth) { + case 8: + return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8); + case 9: + return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9); + case 10: + return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10); + } + return false; +} + +static int required_buswidth(const struct soc_camera_data_format *fmt) +{ + switch (fmt->fourcc) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB555: + return 8; + default: + return fmt->depth; + } +} + +static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, + struct soc_camera_format_xlate *xlate) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int formats = 0, buswidth, ret; + + buswidth = required_buswidth(icd->formats + idx); + + if (!buswidth_supported(icd, buswidth)) + return 0; + + ret = pxa_camera_try_bus_param(icd, buswidth); + if (ret < 0) + return 0; + + switch (icd->formats[idx].fourcc) { + case V4L2_PIX_FMT_UYVY: + formats++; + if (xlate) { + xlate->host_fmt = &pxa_camera_formats[0]; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = buswidth; + xlate++; + dev_dbg(&ici->dev, "Providing format %s using %s\n", + pxa_camera_formats[0].name, + icd->formats[idx].name); + } + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB555: + formats++; + if (xlate) { + xlate->host_fmt = icd->formats + idx; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = buswidth; + xlate++; + dev_dbg(&ici->dev, "Providing format %s packed\n", + icd->formats[idx].name); + } + break; + default: + /* Generic pass-through */ + formats++; + if (xlate) { + xlate->host_fmt = icd->formats + idx; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = icd->formats[idx].depth; + xlate++; + dev_dbg(&ici->dev, + "Providing format %s in pass-through mode\n", + icd->formats[idx].name); + } + } + + return formats; +} + static int pxa_camera_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { - const struct soc_camera_data_format *cam_fmt; - int ret; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL; + const struct soc_camera_format_xlate *xlate; + int ret, buswidth; - /* - * TODO: find a suitable supported by the SoC output format, check - * whether the sensor supports one of acceptable input formats. - */ - if (pixfmt) { - cam_fmt = soc_camera_format_by_fourcc(icd, pixfmt); - if (!cam_fmt) - return -EINVAL; + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; } - ret = icd->ops->set_fmt(icd, pixfmt, rect); - if (pixfmt && !ret) - icd->current_fmt = cam_fmt; + buswidth = xlate->buswidth; + host_fmt = xlate->host_fmt; + cam_fmt = xlate->cam_fmt; + + switch (pixfmt) { + case 0: /* Only geometry change */ + ret = icd->ops->set_fmt(icd, pixfmt, rect); + break; + default: + ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect); + } + + if (ret < 0) + dev_warn(&ici->dev, "Failed to configure for format %x\n", + pixfmt); + + if (pixfmt && !ret) { + icd->buswidth = buswidth; + icd->current_fmt = host_fmt; + } return ret; } @@ -935,34 +1060,31 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, static int pxa_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - const struct soc_camera_data_format *cam_fmt; - int ret = pxa_camera_try_bus_param(icd, f->fmt.pix.pixelformat); - - if (ret < 0) - return ret; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + __u32 pixfmt = pix->pixelformat; - /* - * TODO: find a suitable supported by the SoC output format, check - * whether the sensor supports one of acceptable input formats. - */ - cam_fmt = soc_camera_format_by_fourcc(icd, f->fmt.pix.pixelformat); - if (!cam_fmt) + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; + } /* limit to pxa hardware capabilities */ - if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; - if (f->fmt.pix.height > 2048) - f->fmt.pix.height = 2048; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.width > 2048) - f->fmt.pix.width = 2048; - f->fmt.pix.width &= ~0x01; - - f->fmt.pix.bytesperline = f->fmt.pix.width * - DIV_ROUND_UP(cam_fmt->depth, 8); - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + if (pix->height < 32) + pix->height = 32; + if (pix->height > 2048) + pix->height = 2048; + if (pix->width < 48) + pix->width = 48; + if (pix->width > 2048) + pix->width = 2048; + pix->width &= ~0x01; + + pix->bytesperline = pix->width * + DIV_ROUND_UP(xlate->host_fmt->depth, 8); + pix->sizeimage = pix->height * pix->bytesperline; /* limit to sensor capabilities */ return icd->ops->try_fmt(icd, f); @@ -1073,6 +1195,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .remove = pxa_camera_remove_device, .suspend = pxa_camera_suspend, .resume = pxa_camera_resume, + .get_formats = pxa_camera_get_formats, .set_fmt = pxa_camera_set_fmt, .try_fmt = pxa_camera_try_fmt, .init_videobuf = pxa_camera_init_videobuf, -- cgit v1.2.3 From 7df653d0550763831781c8010ef17527b04a3010 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 1 Dec 2008 18:44:02 +0100 Subject: gspca: Webcam 06f8:3004 added in sonixj. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/sonixj.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index 4c96adc0b..8d0210b24 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -171,6 +171,7 @@ sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom spca506 06e1:a190 ADS Instant VCD ov534 06f8:3002 Hercules Blog Webcam ov534 06f8:3003 Hercules Dualpix HD Weblog +sonixj 06f8:3004 Hercules Classic Silver spca508 0733:0110 ViewQuest VQ110 spca508 0130:0130 Clone Digital Webcam 11043 spca501 0733:0401 Intel Create and Share diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 8037a4ec9..fb8b42daf 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1751,6 +1751,7 @@ static const __devinitdata struct usb_device_id device_table[] = { #endif {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)}, {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)}, + {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)}, /* bw600.inf: {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */ -- cgit v1.2.3 From 1c16293ac6a29e20be55c9d6ed97d9ce5970a3d9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 1 Dec 2008 19:40:09 +0100 Subject: omap2: add OMAP2 camera driver. From: Sakari Ailus Add a driver for the OMAP2 camera block. OMAP2 is used in e.g. Nokia N800/N810 internet tablet. This driver uses the V4L2 internal ioctl interface. Priority: normal Signed-off-by: Sakari Ailus Signed-off-by: Trilok Soni Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Kconfig | 7 + linux/drivers/media/video/Makefile | 3 + linux/drivers/media/video/omap24xxcam-dma.c | 601 +++++++++ linux/drivers/media/video/omap24xxcam.c | 1908 +++++++++++++++++++++++++++ linux/drivers/media/video/omap24xxcam.h | 593 +++++++++ 5 files changed, 3112 insertions(+) create mode 100644 linux/drivers/media/video/omap24xxcam-dma.c create mode 100644 linux/drivers/media/video/omap24xxcam.c create mode 100644 linux/drivers/media/video/omap24xxcam.h diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index c4ee10c37..91652d964 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -770,6 +770,13 @@ config VIDEO_SH_MOBILE_CEU ---help--- This is a v4l2 driver for the SuperH Mobile CEU Interface +config VIDEO_OMAP2 + tristate "OMAP2 Camera Capture Interface driver" + depends on VIDEO_DEV && ARCH_OMAP2 + select VIDEOBUF_DMA_SG + ---help--- + This is a v4l2 driver for the TI OMAP2 camera capture interface + # # USB Multimedia device configuration # diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 53d43f9e0..ac147b1ae 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -8,6 +8,8 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o stkwebcam-objs := stk-webcam.o stk-sensor.o +omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o + videodev-objs := v4l2-dev.o v4l2-ioctl.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-compat-ioctl32.o v4l2-int-device.o @@ -130,6 +132,7 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885/ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o +obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o diff --git a/linux/drivers/media/video/omap24xxcam-dma.c b/linux/drivers/media/video/omap24xxcam-dma.c new file mode 100644 index 000000000..1d54b86c9 --- /dev/null +++ b/linux/drivers/media/video/omap24xxcam-dma.c @@ -0,0 +1,601 @@ +/* + * drivers/media/video/omap24xxcam-dma.c + * + * Copyright (C) 2004 MontaVista Software, Inc. + * Copyright (C) 2004 Texas Instruments. + * Copyright (C) 2007 Nokia Corporation. + * + * Contact: Sakari Ailus + * + * Based on code from Andy Lowe and + * David Cohen . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include + +#include "omap24xxcam.h" + +/* + * + * DMA hardware. + * + */ + +/* Ack all interrupt on CSR and IRQSTATUS_L0 */ +static void omap24xxcam_dmahw_ack_all(unsigned long base) +{ + u32 csr; + int i; + + for (i = 0; i < NUM_CAMDMA_CHANNELS; ++i) { + csr = omap24xxcam_reg_in(base, CAMDMA_CSR(i)); + /* ack interrupt in CSR */ + omap24xxcam_reg_out(base, CAMDMA_CSR(i), csr); + } + omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, 0xf); +} + +/* Ack dmach on CSR and IRQSTATUS_L0 */ +static u32 omap24xxcam_dmahw_ack_ch(unsigned long base, int dmach) +{ + u32 csr; + + csr = omap24xxcam_reg_in(base, CAMDMA_CSR(dmach)); + /* ack interrupt in CSR */ + omap24xxcam_reg_out(base, CAMDMA_CSR(dmach), csr); + /* ack interrupt in IRQSTATUS */ + omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, (1 << dmach)); + + return csr; +} + +static int omap24xxcam_dmahw_running(unsigned long base, int dmach) +{ + return omap24xxcam_reg_in(base, CAMDMA_CCR(dmach)) & CAMDMA_CCR_ENABLE; +} + +static void omap24xxcam_dmahw_transfer_setup(unsigned long base, int dmach, + dma_addr_t start, u32 len) +{ + omap24xxcam_reg_out(base, CAMDMA_CCR(dmach), + CAMDMA_CCR_SEL_SRC_DST_SYNC + | CAMDMA_CCR_BS + | CAMDMA_CCR_DST_AMODE_POST_INC + | CAMDMA_CCR_SRC_AMODE_POST_INC + | CAMDMA_CCR_FS + | CAMDMA_CCR_WR_ACTIVE + | CAMDMA_CCR_RD_ACTIVE + | CAMDMA_CCR_SYNCHRO_CAMERA); + omap24xxcam_reg_out(base, CAMDMA_CLNK_CTRL(dmach), 0); + omap24xxcam_reg_out(base, CAMDMA_CEN(dmach), len); + omap24xxcam_reg_out(base, CAMDMA_CFN(dmach), 1); + omap24xxcam_reg_out(base, CAMDMA_CSDP(dmach), + CAMDMA_CSDP_WRITE_MODE_POSTED + | CAMDMA_CSDP_DST_BURST_EN_32 + | CAMDMA_CSDP_DST_PACKED + | CAMDMA_CSDP_SRC_BURST_EN_32 + | CAMDMA_CSDP_SRC_PACKED + | CAMDMA_CSDP_DATA_TYPE_8BITS); + omap24xxcam_reg_out(base, CAMDMA_CSSA(dmach), 0); + omap24xxcam_reg_out(base, CAMDMA_CDSA(dmach), start); + omap24xxcam_reg_out(base, CAMDMA_CSEI(dmach), 0); + omap24xxcam_reg_out(base, CAMDMA_CSFI(dmach), DMA_THRESHOLD); + omap24xxcam_reg_out(base, CAMDMA_CDEI(dmach), 0); + omap24xxcam_reg_out(base, CAMDMA_CDFI(dmach), 0); + omap24xxcam_reg_out(base, CAMDMA_CSR(dmach), + CAMDMA_CSR_MISALIGNED_ERR + | CAMDMA_CSR_SECURE_ERR + | CAMDMA_CSR_TRANS_ERR + | CAMDMA_CSR_BLOCK + | CAMDMA_CSR_DROP); + omap24xxcam_reg_out(base, CAMDMA_CICR(dmach), + CAMDMA_CICR_MISALIGNED_ERR_IE + | CAMDMA_CICR_SECURE_ERR_IE + | CAMDMA_CICR_TRANS_ERR_IE + | CAMDMA_CICR_BLOCK_IE + | CAMDMA_CICR_DROP_IE); +} + +static void omap24xxcam_dmahw_transfer_start(unsigned long base, int dmach) +{ + omap24xxcam_reg_out(base, CAMDMA_CCR(dmach), + CAMDMA_CCR_SEL_SRC_DST_SYNC + | CAMDMA_CCR_BS + | CAMDMA_CCR_DST_AMODE_POST_INC + | CAMDMA_CCR_SRC_AMODE_POST_INC + | CAMDMA_CCR_ENABLE + | CAMDMA_CCR_FS + | CAMDMA_CCR_SYNCHRO_CAMERA); +} + +static void omap24xxcam_dmahw_transfer_chain(unsigned long base, int dmach, + int free_dmach) +{ + int prev_dmach, ch; + + if (dmach == 0) + prev_dmach = NUM_CAMDMA_CHANNELS - 1; + else + prev_dmach = dmach - 1; + omap24xxcam_reg_out(base, CAMDMA_CLNK_CTRL(prev_dmach), + CAMDMA_CLNK_CTRL_ENABLE_LNK | dmach); + /* Did we chain the DMA transfer before the previous one + * finished? + */ + ch = (dmach + free_dmach) % NUM_CAMDMA_CHANNELS; + while (!(omap24xxcam_reg_in(base, CAMDMA_CCR(ch)) + & CAMDMA_CCR_ENABLE)) { + if (ch == dmach) { + /* The previous transfer has ended and this one + * hasn't started, so we must not have chained + * to the previous one in time. We'll have to + * start it now. + */ + omap24xxcam_dmahw_transfer_start(base, dmach); + break; + } else + ch = (ch + 1) % NUM_CAMDMA_CHANNELS; + } +} + +/* Abort all chained DMA transfers. After all transfers have been + * aborted and the DMA controller is idle, the completion routines for + * any aborted transfers will be called in sequence. The DMA + * controller may not be idle after this routine completes, because + * the completion routines might start new transfers. + */ +static void omap24xxcam_dmahw_abort_ch(unsigned long base, int dmach) +{ + /* mask all interrupts from this channel */ + omap24xxcam_reg_out(base, CAMDMA_CICR(dmach), 0); + /* unlink this channel */ + omap24xxcam_reg_merge(base, CAMDMA_CLNK_CTRL(dmach), 0, + CAMDMA_CLNK_CTRL_ENABLE_LNK); + /* disable this channel */ + omap24xxcam_reg_merge(base, CAMDMA_CCR(dmach), 0, CAMDMA_CCR_ENABLE); +} + +static void omap24xxcam_dmahw_init(unsigned long base) +{ + omap24xxcam_reg_out(base, CAMDMA_OCP_SYSCONFIG, + CAMDMA_OCP_SYSCONFIG_MIDLEMODE_FSTANDBY + | CAMDMA_OCP_SYSCONFIG_SIDLEMODE_FIDLE + | CAMDMA_OCP_SYSCONFIG_AUTOIDLE); + + omap24xxcam_reg_merge(base, CAMDMA_GCR, 0x10, + CAMDMA_GCR_MAX_CHANNEL_FIFO_DEPTH); + + omap24xxcam_reg_out(base, CAMDMA_IRQENABLE_L0, 0xf); +} + +/* + * + * Individual DMA channel handling. + * + */ + +/* Start a DMA transfer from the camera to memory. + * Returns zero if the transfer was successfully started, or non-zero if all + * DMA channels are already in use or starting is currently inhibited. + */ +static int omap24xxcam_dma_start(struct omap24xxcam_dma *dma, dma_addr_t start, + u32 len, dma_callback_t callback, void *arg) +{ + unsigned long flags; + int dmach; + + spin_lock_irqsave(&dma->lock, flags); + + if (!dma->free_dmach || atomic_read(&dma->dma_stop)) { + spin_unlock_irqrestore(&dma->lock, flags); + return -EBUSY; + } + + dmach = dma->next_dmach; + + dma->ch_state[dmach].callback = callback; + dma->ch_state[dmach].arg = arg; + + omap24xxcam_dmahw_transfer_setup(dma->base, dmach, start, len); + + /* We're ready to start the DMA transfer. */ + + if (dma->free_dmach < NUM_CAMDMA_CHANNELS) { + /* A transfer is already in progress, so try to chain to it. */ + omap24xxcam_dmahw_transfer_chain(dma->base, dmach, + dma->free_dmach); + } else { + /* No transfer is in progress, so we'll just start this one + * now. + */ + omap24xxcam_dmahw_transfer_start(dma->base, dmach); + } + + dma->next_dmach = (dma->next_dmach + 1) % NUM_CAMDMA_CHANNELS; + dma->free_dmach--; + + spin_unlock_irqrestore(&dma->lock, flags); + + return 0; +} + +/* Abort all chained DMA transfers. After all transfers have been + * aborted and the DMA controller is idle, the completion routines for + * any aborted transfers will be called in sequence. The DMA + * controller may not be idle after this routine completes, because + * the completion routines might start new transfers. + */ +static void omap24xxcam_dma_abort(struct omap24xxcam_dma *dma, u32 csr) +{ + unsigned long flags; + int dmach, i, free_dmach; + dma_callback_t callback; + void *arg; + + spin_lock_irqsave(&dma->lock, flags); + + /* stop any DMA transfers in progress */ + dmach = (dma->next_dmach + dma->free_dmach) % NUM_CAMDMA_CHANNELS; + for (i = 0; i < NUM_CAMDMA_CHANNELS; i++) { + omap24xxcam_dmahw_abort_ch(dma->base, dmach); + dmach = (dmach + 1) % NUM_CAMDMA_CHANNELS; + } + + /* We have to be careful here because the callback routine + * might start a new DMA transfer, and we only want to abort + * transfers that were started before this routine was called. + */ + free_dmach = dma->free_dmach; + while ((dma->free_dmach < NUM_CAMDMA_CHANNELS) && + (free_dmach < NUM_CAMDMA_CHANNELS)) { + dmach = (dma->next_dmach + dma->free_dmach) + % NUM_CAMDMA_CHANNELS; + callback = dma->ch_state[dmach].callback; + arg = dma->ch_state[dmach].arg; + dma->free_dmach++; + free_dmach++; + if (callback) { + /* leave interrupts disabled during callback */ + spin_unlock(&dma->lock); + (*callback) (dma, csr, arg); + spin_lock(&dma->lock); + } + } + + spin_unlock_irqrestore(&dma->lock, flags); +} + +/* Abort all chained DMA transfers. After all transfers have been + * aborted and the DMA controller is idle, the completion routines for + * any aborted transfers will be called in sequence. If the completion + * routines attempt to start a new DMA transfer it will fail, so the + * DMA controller will be idle after this routine completes. + */ +static void omap24xxcam_dma_stop(struct omap24xxcam_dma *dma, u32 csr) +{ + atomic_inc(&dma->dma_stop); + omap24xxcam_dma_abort(dma, csr); + atomic_dec(&dma->dma_stop); +} + +/* Camera DMA interrupt service routine. */ +void omap24xxcam_dma_isr(struct omap24xxcam_dma *dma) +{ + int dmach; + dma_callback_t callback; + void *arg; + u32 csr; + const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR + | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR + | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP; + + spin_lock(&dma->lock); + + if (dma->free_dmach == NUM_CAMDMA_CHANNELS) { + /* A camera DMA interrupt occurred while all channels + * are idle, so we'll acknowledge the interrupt in the + * IRQSTATUS register and exit. + */ + omap24xxcam_dmahw_ack_all(dma->base); + spin_unlock(&dma->lock); + return; + } + + while (dma->free_dmach < NUM_CAMDMA_CHANNELS) { + dmach = (dma->next_dmach + dma->free_dmach) + % NUM_CAMDMA_CHANNELS; + if (omap24xxcam_dmahw_running(dma->base, dmach)) { + /* This buffer hasn't finished yet, so we're done. */ + break; + } + csr = omap24xxcam_dmahw_ack_ch(dma->base, dmach); + if (csr & csr_error) { + /* A DMA error occurred, so stop all DMA + * transfers in progress. + */ + spin_unlock(&dma->lock); + omap24xxcam_dma_stop(dma, csr); + return; + } else { + callback = dma->ch_state[dmach].callback; + arg = dma->ch_state[dmach].arg; + dma->free_dmach++; + if (callback) { + spin_unlock(&dma->lock); + (*callback) (dma, csr, arg); + spin_lock(&dma->lock); + } + } + } + + spin_unlock(&dma->lock); + + omap24xxcam_sgdma_process( + container_of(dma, struct omap24xxcam_sgdma, dma)); +} + +void omap24xxcam_dma_hwinit(struct omap24xxcam_dma *dma) +{ + unsigned long flags; + + spin_lock_irqsave(&dma->lock, flags); + + omap24xxcam_dmahw_init(dma->base); + + spin_unlock_irqrestore(&dma->lock, flags); +} + +static void omap24xxcam_dma_init(struct omap24xxcam_dma *dma, + unsigned long base) +{ + int ch; + + /* group all channels on DMA IRQ0 and unmask irq */ + spin_lock_init(&dma->lock); + dma->base = base; + dma->free_dmach = NUM_CAMDMA_CHANNELS; + dma->next_dmach = 0; + for (ch = 0; ch < NUM_CAMDMA_CHANNELS; ch++) { + dma->ch_state[ch].callback = NULL; + dma->ch_state[ch].arg = NULL; + } +} + +/* + * + * Scatter-gather DMA. + * + * High-level DMA construct for transferring whole picture frames to + * memory that is discontinuous. + * + */ + +/* DMA completion routine for the scatter-gather DMA fragments. */ +static void omap24xxcam_sgdma_callback(struct omap24xxcam_dma *dma, u32 csr, + void *arg) +{ + struct omap24xxcam_sgdma *sgdma = + container_of(dma, struct omap24xxcam_sgdma, dma); + int sgslot = (int)arg; + struct sgdma_state *sg_state; + const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR + | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR + | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP; + + spin_lock(&sgdma->lock); + + /* We got an interrupt, we can remove the timer */ + del_timer(&sgdma->reset_timer); + + sg_state = sgdma->sg_state + sgslot; + if (!sg_state->queued_sglist) { + spin_unlock(&sgdma->lock); + printk(KERN_ERR "%s: sgdma completed when none queued!\n", + __func__); + return; + } + + sg_state->csr |= csr; + if (!--sg_state->queued_sglist) { + /* Queue for this sglist is empty, so check to see if we're + * done. + */ + if ((sg_state->next_sglist == sg_state->sglen) + || (sg_state->csr & csr_error)) { + sgdma_callback_t callback = sg_state->callback; + void *arg = sg_state->arg; + u32 sg_csr = sg_state->csr; + /* All done with this sglist */ + sgdma->free_sgdma++; + if (callback) { + spin_unlock(&sgdma->lock); + (*callback) (sgdma, sg_csr, arg); + return; + } + } + } + + spin_unlock(&sgdma->lock); +} + +/* Start queued scatter-gather DMA transfers. */ +void omap24xxcam_sgdma_process(struct omap24xxcam_sgdma *sgdma) +{ + unsigned long flags; + int queued_sgdma, sgslot; + struct sgdma_state *sg_state; + const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR + | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR + | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP; + + spin_lock_irqsave(&sgdma->lock, flags); + + queued_sgdma = NUM_SG_DMA - sgdma->free_sgdma; + sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA; + while (queued_sgdma > 0) { + sg_state = sgdma->sg_state + sgslot; + while ((sg_state->next_sglist < sg_state->sglen) && + !(sg_state->csr & csr_error)) { + const struct scatterlist *sglist; + unsigned int len; + + sglist = sg_state->sglist + sg_state->next_sglist; + /* try to start the next DMA transfer */ + if (sg_state->next_sglist + 1 == sg_state->sglen) { + /* + * On the last sg, we handle the case where + * cam->img.pix.sizeimage % PAGE_ALIGN != 0 + */ + len = sg_state->len - sg_state->bytes_read; + } else { + len = sg_dma_len(sglist); + } + + if (omap24xxcam_dma_start(&sgdma->dma, + sg_dma_address(sglist), + len, + omap24xxcam_sgdma_callback, + (void *)sgslot)) { + /* DMA start failed */ + spin_unlock_irqrestore(&sgdma->lock, flags); + return; + } else { + unsigned long expires; + /* DMA start was successful */ + sg_state->next_sglist++; + sg_state->bytes_read += len; + sg_state->queued_sglist++; + + /* We start the reset timer */ + expires = jiffies + HZ; + mod_timer(&sgdma->reset_timer, expires); + } + } + queued_sgdma--; + sgslot = (sgslot + 1) % NUM_SG_DMA; + } + + spin_unlock_irqrestore(&sgdma->lock, flags); +} + +/* + * Queue a scatter-gather DMA transfer from the camera to memory. + * Returns zero if the transfer was successfully queued, or non-zero + * if all of the scatter-gather slots are already in use. + */ +int omap24xxcam_sgdma_queue(struct omap24xxcam_sgdma *sgdma, + const struct scatterlist *sglist, int sglen, + int len, sgdma_callback_t callback, void *arg) +{ + unsigned long flags; + struct sgdma_state *sg_state; + + if ((sglen < 0) || ((sglen > 0) & !sglist)) + return -EINVAL; + + spin_lock_irqsave(&sgdma->lock, flags); + + if (!sgdma->free_sgdma) { + spin_unlock_irqrestore(&sgdma->lock, flags); + return -EBUSY; + } + + sg_state = sgdma->sg_state + sgdma->next_sgdma; + + sg_state->sglist = sglist; + sg_state->sglen = sglen; + sg_state->next_sglist = 0; + sg_state->bytes_read = 0; + sg_state->len = len; + sg_state->queued_sglist = 0; + sg_state->csr = 0; + sg_state->callback = callback; + sg_state->arg = arg; + + sgdma->next_sgdma = (sgdma->next_sgdma + 1) % NUM_SG_DMA; + sgdma->free_sgdma--; + + spin_unlock_irqrestore(&sgdma->lock, flags); + + omap24xxcam_sgdma_process(sgdma); + + return 0; +} + +/* Sync scatter-gather DMA by aborting any DMA transfers currently in progress. + * Any queued scatter-gather DMA transactions that have not yet been started + * will remain queued. The DMA controller will be idle after this routine + * completes. When the scatter-gather queue is restarted, the next + * scatter-gather DMA transfer will begin at the start of a new transaction. + */ +void omap24xxcam_sgdma_sync(struct omap24xxcam_sgdma *sgdma) +{ + unsigned long flags; + int sgslot; + struct sgdma_state *sg_state; + u32 csr = CAMDMA_CSR_TRANS_ERR; + + /* stop any DMA transfers in progress */ + omap24xxcam_dma_stop(&sgdma->dma, csr); + + spin_lock_irqsave(&sgdma->lock, flags); + + if (sgdma->free_sgdma < NUM_SG_DMA) { + sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA; + sg_state = sgdma->sg_state + sgslot; + if (sg_state->next_sglist != 0) { + /* This DMA transfer was in progress, so abort it. */ + sgdma_callback_t callback = sg_state->callback; + void *arg = sg_state->arg; + sgdma->free_sgdma++; + if (callback) { + /* leave interrupts masked */ + spin_unlock(&sgdma->lock); + (*callback) (sgdma, csr, arg); + spin_lock(&sgdma->lock); + } + } + } + + spin_unlock_irqrestore(&sgdma->lock, flags); +} + +void omap24xxcam_sgdma_init(struct omap24xxcam_sgdma *sgdma, + unsigned long base, + void (*reset_callback)(unsigned long data), + unsigned long reset_callback_data) +{ + int sg; + + spin_lock_init(&sgdma->lock); + sgdma->free_sgdma = NUM_SG_DMA; + sgdma->next_sgdma = 0; + for (sg = 0; sg < NUM_SG_DMA; sg++) { + sgdma->sg_state[sg].sglen = 0; + sgdma->sg_state[sg].next_sglist = 0; + sgdma->sg_state[sg].bytes_read = 0; + sgdma->sg_state[sg].queued_sglist = 0; + sgdma->sg_state[sg].csr = 0; + sgdma->sg_state[sg].callback = NULL; + sgdma->sg_state[sg].arg = NULL; + } + + omap24xxcam_dma_init(&sgdma->dma, base); + setup_timer(&sgdma->reset_timer, reset_callback, reset_callback_data); +} diff --git a/linux/drivers/media/video/omap24xxcam.c b/linux/drivers/media/video/omap24xxcam.c new file mode 100644 index 000000000..85c3c7c92 --- /dev/null +++ b/linux/drivers/media/video/omap24xxcam.c @@ -0,0 +1,1908 @@ +/* + * drivers/media/video/omap24xxcam.c + * + * OMAP 2 camera block driver. + * + * Copyright (C) 2004 MontaVista Software, Inc. + * Copyright (C) 2004 Texas Instruments. + * Copyright (C) 2007-2008 Nokia Corporation. + * + * Contact: Sakari Ailus + * + * Based on code from Andy Lowe + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include /* needed for videobufs */ +#include +#include +#include +#include + +#include +#include + +#include "omap24xxcam.h" + +#define OMAP24XXCAM_VERSION KERNEL_VERSION(0, 0, 0) + +#define RESET_TIMEOUT_NS 10000 + +static void omap24xxcam_reset(struct omap24xxcam_device *cam); +static int omap24xxcam_sensor_if_enable(struct omap24xxcam_device *cam); +static void omap24xxcam_device_unregister(struct v4l2_int_device *s); +static int omap24xxcam_remove(struct platform_device *pdev); + +/* module parameters */ +static int video_nr = -1; /* video device minor (-1 ==> auto assign) */ +/* + * Maximum amount of memory to use for capture buffers. + * Default is 4800KB, enough to double-buffer SXGA. + */ +static int capture_mem = 1280 * 960 * 2 * 2; + +static struct v4l2_int_device omap24xxcam; + +/* + * + * Clocks. + * + */ + +static void omap24xxcam_clock_put(struct omap24xxcam_device *cam) +{ + if (cam->ick != NULL && !IS_ERR(cam->ick)) + clk_put(cam->ick); + if (cam->fck != NULL && !IS_ERR(cam->fck)) + clk_put(cam->fck); + + cam->ick = cam->fck = NULL; +} + +static int omap24xxcam_clock_get(struct omap24xxcam_device *cam) +{ + int rval = 0; + + cam->fck = clk_get(cam->dev, "cam_fck"); + if (IS_ERR(cam->fck)) { + dev_err(cam->dev, "can't get cam_fck"); + rval = PTR_ERR(cam->fck); + omap24xxcam_clock_put(cam); + return rval; + } + + cam->ick = clk_get(cam->dev, "cam_ick"); + if (IS_ERR(cam->ick)) { + dev_err(cam->dev, "can't get cam_ick"); + rval = PTR_ERR(cam->ick); + omap24xxcam_clock_put(cam); + } + + return rval; +} + +static void omap24xxcam_clock_on(struct omap24xxcam_device *cam) +{ + clk_enable(cam->fck); + clk_enable(cam->ick); +} + +static void omap24xxcam_clock_off(struct omap24xxcam_device *cam) +{ + clk_disable(cam->fck); + clk_disable(cam->ick); +} + +/* + * + * Camera core + * + */ + +/* + * Set xclk. + * + * To disable xclk, use value zero. + */ +static void omap24xxcam_core_xclk_set(const struct omap24xxcam_device *cam, + u32 xclk) +{ + if (xclk) { + u32 divisor = CAM_MCLK / xclk; + + if (divisor == 1) + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, + CC_CTRL_XCLK, + CC_CTRL_XCLK_DIV_BYPASS); + else + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, + CC_CTRL_XCLK, divisor); + } else + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, + CC_CTRL_XCLK, CC_CTRL_XCLK_DIV_STABLE_LOW); +} + +static void omap24xxcam_core_hwinit(const struct omap24xxcam_device *cam) +{ + /* + * Setting the camera core AUTOIDLE bit causes problems with frame + * synchronization, so we will clear the AUTOIDLE bit instead. + */ + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_SYSCONFIG, + CC_SYSCONFIG_AUTOIDLE); + + /* program the camera interface DMA packet size */ + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_CTRL_DMA, + CC_CTRL_DMA_EN | (DMA_THRESHOLD / 4 - 1)); + + /* enable camera core error interrupts */ + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_IRQENABLE, + CC_IRQENABLE_FW_ERR_IRQ + | CC_IRQENABLE_FSC_ERR_IRQ + | CC_IRQENABLE_SSC_ERR_IRQ + | CC_IRQENABLE_FIFO_OF_IRQ); +} + +/* + * Enable the camera core. + * + * Data transfer to the camera DMA starts from next starting frame. + */ +static void omap24xxcam_core_enable(const struct omap24xxcam_device *cam) +{ + + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_CTRL, + cam->cc_ctrl); +} + +/* + * Disable camera core. + * + * The data transfer will be stopped immediately (CC_CTRL_CC_RST). The + * core internal state machines will be reset. Use + * CC_CTRL_CC_FRAME_TRIG instead if you want to transfer the current + * frame completely. + */ +static void omap24xxcam_core_disable(const struct omap24xxcam_device *cam) +{ + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_CTRL, + CC_CTRL_CC_RST); +} + +/* Interrupt service routine for camera core interrupts. */ +static void omap24xxcam_core_isr(struct omap24xxcam_device *cam) +{ + u32 cc_irqstatus; + const u32 cc_irqstatus_err = + CC_IRQSTATUS_FW_ERR_IRQ + | CC_IRQSTATUS_FSC_ERR_IRQ + | CC_IRQSTATUS_SSC_ERR_IRQ + | CC_IRQSTATUS_FIFO_UF_IRQ + | CC_IRQSTATUS_FIFO_OF_IRQ; + + cc_irqstatus = omap24xxcam_reg_in(cam->mmio_base + CC_REG_OFFSET, + CC_IRQSTATUS); + omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_IRQSTATUS, + cc_irqstatus); + + if (cc_irqstatus & cc_irqstatus_err + && !atomic_read(&cam->in_reset)) { + dev_dbg(cam->dev, "resetting camera, cc_irqstatus 0x%x\n", + cc_irqstatus); + omap24xxcam_reset(cam); + } +} + +/* + * + * videobuf_buffer handling. + * + * Memory for mmapped videobuf_buffers is not allocated + * conventionally, but by several kmalloc allocations and then + * creating the scatterlist on our own. User-space buffers are handled + * normally. + * + */ + +/* + * Free the memory-mapped buffer memory allocated for a + * videobuf_buffer and the associated scatterlist. + */ +static void omap24xxcam_vbq_free_mmap_buffer(struct videobuf_buffer *vb) +{ + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + size_t alloc_size; + struct page *page; + int i; + + if (dma->sglist == NULL) + return; + + i = dma->sglen; + while (i) { + i--; + alloc_size = sg_dma_len(&dma->sglist[i]); + page = sg_page(&dma->sglist[i]); + do { + ClearPageReserved(page++); + } while (alloc_size -= PAGE_SIZE); + __free_pages(sg_page(&dma->sglist[i]), + get_order(sg_dma_len(&dma->sglist[i]))); + } + + kfree(dma->sglist); + dma->sglist = NULL; +} + +/* Release all memory related to the videobuf_queue. */ +static void omap24xxcam_vbq_free_mmap_buffers(struct videobuf_queue *vbq) +{ + int i; + + mutex_lock(&vbq->vb_lock); + + for (i = 0; i < VIDEO_MAX_FRAME; i++) { + if (NULL == vbq->bufs[i]) + continue; + if (V4L2_MEMORY_MMAP != vbq->bufs[i]->memory) + continue; + vbq->ops->buf_release(vbq, vbq->bufs[i]); + omap24xxcam_vbq_free_mmap_buffer(vbq->bufs[i]); + kfree(vbq->bufs[i]); + vbq->bufs[i] = NULL; + } + + mutex_unlock(&vbq->vb_lock); + + videobuf_mmap_free(vbq); +} + +/* + * Allocate physically as contiguous as possible buffer for video + * frame and allocate and build DMA scatter-gather list for it. + */ +static int omap24xxcam_vbq_alloc_mmap_buffer(struct videobuf_buffer *vb) +{ + unsigned int order; + size_t alloc_size, size = vb->bsize; /* vb->bsize is page aligned */ + struct page *page; + int max_pages, err = 0, i = 0; + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + + /* + * allocate maximum size scatter-gather list. Note this is + * overhead. We may not use as many entries as we allocate + */ + max_pages = vb->bsize >> PAGE_SHIFT; + dma->sglist = kcalloc(max_pages, sizeof(*dma->sglist), GFP_KERNEL); + if (dma->sglist == NULL) { + err = -ENOMEM; + goto out; + } + + while (size) { + order = get_order(size); + /* + * do not over-allocate even if we would get larger + * contiguous chunk that way + */ + if ((PAGE_SIZE << order) > size) + order--; + + /* try to allocate as many contiguous pages as possible */ + page = alloc_pages(GFP_KERNEL | GFP_DMA, order); + /* if allocation fails, try to allocate smaller amount */ + while (page == NULL) { + order--; + page = alloc_pages(GFP_KERNEL | GFP_DMA, order); + if (page == NULL && !order) { + err = -ENOMEM; + goto out; + } + } + size -= (PAGE_SIZE << order); + + /* append allocated chunk of pages into scatter-gather list */ + sg_set_page(&dma->sglist[i], page, PAGE_SIZE << order, 0); + dma->sglen++; + i++; + + alloc_size = (PAGE_SIZE << order); + + /* clear pages before giving them to user space */ + memset(page_address(page), 0, alloc_size); + + /* mark allocated pages reserved */ + do { + SetPageReserved(page++); + } while (alloc_size -= PAGE_SIZE); + } + /* + * REVISIT: not fully correct to assign nr_pages == sglen but + * video-buf is passing nr_pages for e.g. unmap_sg calls + */ + dma->nr_pages = dma->sglen; + dma->direction = PCI_DMA_FROMDEVICE; + + return 0; + +out: + omap24xxcam_vbq_free_mmap_buffer(vb); + return err; +} + +static int omap24xxcam_vbq_alloc_mmap_buffers(struct videobuf_queue *vbq, + unsigned int count) +{ + int i, err = 0; + struct omap24xxcam_fh *fh = + container_of(vbq, struct omap24xxcam_fh, vbq); + + mutex_lock(&vbq->vb_lock); + + for (i = 0; i < count; i++) { + err = omap24xxcam_vbq_alloc_mmap_buffer(vbq->bufs[i]); + if (err) + goto out; + dev_dbg(fh->cam->dev, "sglen is %d for buffer %d\n", + videobuf_to_dma(vbq->bufs[i])->sglen, i); + } + + mutex_unlock(&vbq->vb_lock); + + return 0; +out: + while (i) { + i--; + omap24xxcam_vbq_free_mmap_buffer(vbq->bufs[i]); + } + + mutex_unlock(&vbq->vb_lock); + + return err; +} + +/* + * This routine is called from interrupt context when a scatter-gather DMA + * transfer of a videobuf_buffer completes. + */ +static void omap24xxcam_vbq_complete(struct omap24xxcam_sgdma *sgdma, + u32 csr, void *arg) +{ + struct omap24xxcam_device *cam = + container_of(sgdma, struct omap24xxcam_device, sgdma); + struct omap24xxcam_fh *fh = cam->streaming->private_data; + struct videobuf_buffer *vb = (struct videobuf_buffer *)arg; + const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR + | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR + | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP; + unsigned long flags; + + spin_lock_irqsave(&cam->core_enable_disable_lock, flags); + if (--cam->sgdma_in_queue == 0) + omap24xxcam_core_disable(cam); + spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags); + + do_gettimeofday(&vb->ts); + vb->field_count = atomic_add_return(2, &fh->field_count); + if (csr & csr_error) { + vb->state = VIDEOBUF_ERROR; + if (!atomic_read(&fh->cam->in_reset)) { + dev_dbg(cam->dev, "resetting camera, csr 0x%x\n", csr); + omap24xxcam_reset(cam); + } + } else + vb->state = VIDEOBUF_DONE; + wake_up(&vb->done); +} + +static void omap24xxcam_vbq_release(struct videobuf_queue *vbq, + struct videobuf_buffer *vb) +{ + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + + /* wait for buffer, especially to get out of the sgdma queue */ + videobuf_waiton(vb, 0, 0); + if (vb->memory == V4L2_MEMORY_MMAP) { + dma_unmap_sg(vbq->dev, dma->sglist, dma->sglen, + dma->direction); + dma->direction = DMA_NONE; + } else { + videobuf_dma_unmap(vbq, videobuf_to_dma(vb)); + videobuf_dma_free(videobuf_to_dma(vb)); + } + + vb->state = VIDEOBUF_NEEDS_INIT; +} + +/* + * Limit the number of available kernel image capture buffers based on the + * number requested, the currently selected image size, and the maximum + * amount of memory permitted for kernel capture buffers. + */ +static int omap24xxcam_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt, + unsigned int *size) +{ + struct omap24xxcam_fh *fh = vbq->priv_data; + + if (*cnt <= 0) + *cnt = VIDEO_MAX_FRAME; /* supply a default number of buffers */ + + if (*cnt > VIDEO_MAX_FRAME) + *cnt = VIDEO_MAX_FRAME; + + *size = fh->pix.sizeimage; + + /* accessing fh->cam->capture_mem is ok, it's constant */ + while (*size * *cnt > fh->cam->capture_mem) + (*cnt)--; + + return 0; +} + +static int omap24xxcam_dma_iolock(struct videobuf_queue *vbq, + struct videobuf_dmabuf *dma) +{ + int err = 0; + + dma->direction = PCI_DMA_FROMDEVICE; + if (!dma_map_sg(vbq->dev, dma->sglist, dma->sglen, dma->direction)) { + kfree(dma->sglist); + dma->sglist = NULL; + dma->sglen = 0; + err = -EIO; + } + + return err; +} + +static int omap24xxcam_vbq_prepare(struct videobuf_queue *vbq, + struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct omap24xxcam_fh *fh = vbq->priv_data; + int err = 0; + + /* + * Accessing pix here is okay since it's constant while + * streaming is on (and we only get called then). + */ + if (vb->baddr) { + /* This is a userspace buffer. */ + if (fh->pix.sizeimage > vb->bsize) { + /* The buffer isn't big enough. */ + err = -EINVAL; + } else + vb->size = fh->pix.sizeimage; + } else { + if (vb->state != VIDEOBUF_NEEDS_INIT) { + /* + * We have a kernel bounce buffer that has + * already been allocated. + */ + if (fh->pix.sizeimage > vb->size) { + /* + * The image size has been changed to + * a larger size since this buffer was + * allocated, so we need to free and + * reallocate it. + */ + omap24xxcam_vbq_release(vbq, vb); + vb->size = fh->pix.sizeimage; + } + } else { + /* We need to allocate a new kernel bounce buffer. */ + vb->size = fh->pix.sizeimage; + } + } + + if (err) + return err; + + vb->width = fh->pix.width; + vb->height = fh->pix.height; + vb->field = field; + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + if (vb->memory == V4L2_MEMORY_MMAP) + /* + * we have built the scatter-gather list by ourself so + * do the scatter-gather mapping as well + */ + err = omap24xxcam_dma_iolock(vbq, videobuf_to_dma(vb)); + else + err = videobuf_iolock(vbq, vb, NULL); + } + + if (!err) + vb->state = VIDEOBUF_PREPARED; + else + omap24xxcam_vbq_release(vbq, vb); + + return err; +} + +static void omap24xxcam_vbq_queue(struct videobuf_queue *vbq, + struct videobuf_buffer *vb) +{ + struct omap24xxcam_fh *fh = vbq->priv_data; + struct omap24xxcam_device *cam = fh->cam; + enum videobuf_state state = vb->state; + unsigned long flags; + int err; + + /* + * FIXME: We're marking the buffer active since we have no + * pretty way of marking it active exactly when the + * scatter-gather transfer starts. + */ + vb->state = VIDEOBUF_ACTIVE; + + err = omap24xxcam_sgdma_queue(&fh->cam->sgdma, + videobuf_to_dma(vb)->sglist, + videobuf_to_dma(vb)->sglen, vb->size, + omap24xxcam_vbq_complete, vb); + + if (!err) { + spin_lock_irqsave(&cam->core_enable_disable_lock, flags); + if (++cam->sgdma_in_queue == 1 + && !atomic_read(&cam->in_reset)) + omap24xxcam_core_enable(cam); + spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags); + } else { + /* + * Oops. We're not supposed to get any errors here. + * The only way we could get an error is if we ran out + * of scatter-gather DMA slots, but we are supposed to + * have at least as many scatter-gather DMA slots as + * video buffers so that can't happen. + */ + dev_err(cam->dev, "failed to queue a video buffer for dma!\n"); + dev_err(cam->dev, "likely a bug in the driver!\n"); + vb->state = state; + } +} + +static struct videobuf_queue_ops omap24xxcam_vbq_ops = { + .buf_setup = omap24xxcam_vbq_setup, + .buf_prepare = omap24xxcam_vbq_prepare, + .buf_queue = omap24xxcam_vbq_queue, + .buf_release = omap24xxcam_vbq_release, +}; + +/* + * + * OMAP main camera system + * + */ + +/* + * Reset camera block to power-on state. + */ +static void omap24xxcam_poweron_reset(struct omap24xxcam_device *cam) +{ + int max_loop = RESET_TIMEOUT_NS; + + /* Reset whole camera subsystem */ + omap24xxcam_reg_out(cam->mmio_base, + CAM_SYSCONFIG, + CAM_SYSCONFIG_SOFTRESET); + + /* Wait till it's finished */ + while (!(omap24xxcam_reg_in(cam->mmio_base, CAM_SYSSTATUS) + & CAM_SYSSTATUS_RESETDONE) + && --max_loop) { + ndelay(1); + } + + if (!(omap24xxcam_reg_in(cam->mmio_base, CAM_SYSSTATUS) + & CAM_SYSSTATUS_RESETDONE)) + dev_err(cam->dev, "camera soft reset timeout\n"); +} + +/* + * (Re)initialise the camera block. + */ +static void omap24xxcam_hwinit(struct omap24xxcam_device *cam) +{ + omap24xxcam_poweron_reset(cam); + + /* set the camera subsystem autoidle bit */ + omap24xxcam_reg_out(cam->mmio_base, CAM_SYSCONFIG, + CAM_SYSCONFIG_AUTOIDLE); + + /* set the camera MMU autoidle bit */ + omap24xxcam_reg_out(cam->mmio_base, + CAMMMU_REG_OFFSET + CAMMMU_SYSCONFIG, + CAMMMU_SYSCONFIG_AUTOIDLE); + + omap24xxcam_core_hwinit(cam); + + omap24xxcam_dma_hwinit(&cam->sgdma.dma); +} + +/* + * Callback for dma transfer stalling. + */ +static void omap24xxcam_stalled_dma_reset(unsigned long data) +{ + struct omap24xxcam_device *cam = (struct omap24xxcam_device *)data; + + if (!atomic_read(&cam->in_reset)) { + dev_dbg(cam->dev, "dma stalled, resetting camera\n"); + omap24xxcam_reset(cam); + } +} + +/* + * Stop capture. Mark we're doing a reset, stop DMA transfers and + * core. (No new scatter-gather transfers will be queued whilst + * in_reset is non-zero.) + * + * If omap24xxcam_capture_stop is called from several places at + * once, only the first call will have an effect. Similarly, the last + * call omap24xxcam_streaming_cont will have effect. + * + * Serialisation is ensured by using cam->core_enable_disable_lock. + */ +static void omap24xxcam_capture_stop(struct omap24xxcam_device *cam) +{ + unsigned long flags; + + spin_lock_irqsave(&cam->core_enable_disable_lock, flags); + + if (atomic_inc_return(&cam->in_reset) != 1) { + spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags); + return; + } + + omap24xxcam_core_disable(cam); + + spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags); + + omap24xxcam_sgdma_sync(&cam->sgdma); +} + +/* + * Reset and continue streaming. + * + * Note: Resetting the camera FIFO via the CC_RST bit in the CC_CTRL + * register is supposed to be sufficient to recover from a camera + * interface error, but it doesn't seem to be enough. If we only do + * that then subsequent image captures are out of sync by either one + * or two times DMA_THRESHOLD bytes. Resetting and re-initializing the + * entire camera subsystem prevents the problem with frame + * synchronization. + */ +static void omap24xxcam_capture_cont(struct omap24xxcam_device *cam) +{ + unsigned long flags; + + spin_lock_irqsave(&cam->core_enable_disable_lock, flags); + + if (atomic_read(&cam->in_reset) != 1) + goto out; + + omap24xxcam_hwinit(cam); + + omap24xxcam_sensor_if_enable(cam); + + omap24xxcam_sgdma_process(&cam->sgdma); + + if (cam->sgdma_in_queue) + omap24xxcam_core_enable(cam); + +out: + atomic_dec(&cam->in_reset); + spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags); +} + +static ssize_t +omap24xxcam_streaming_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct omap24xxcam_device *cam = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", cam->streaming ? "active" : "inactive"); +} +static DEVICE_ATTR(streaming, S_IRUGO, omap24xxcam_streaming_show, NULL); + +/* + * Stop capture and restart it. I.e. reset the camera during use. + */ +static void omap24xxcam_reset(struct omap24xxcam_device *cam) +{ + omap24xxcam_capture_stop(cam); + omap24xxcam_capture_cont(cam); +} + +/* + * The main interrupt handler. + */ +static irqreturn_t omap24xxcam_isr(int irq, void *arg) +{ + struct omap24xxcam_device *cam = (struct omap24xxcam_device *)arg; + u32 irqstatus; + unsigned int irqhandled = 0; + + irqstatus = omap24xxcam_reg_in(cam->mmio_base, CAM_IRQSTATUS); + + if (irqstatus & + (CAM_IRQSTATUS_DMA_IRQ2 | CAM_IRQSTATUS_DMA_IRQ1 + | CAM_IRQSTATUS_DMA_IRQ0)) { + omap24xxcam_dma_isr(&cam->sgdma.dma); + irqhandled = 1; + } + if (irqstatus & CAM_IRQSTATUS_CC_IRQ) { + omap24xxcam_core_isr(cam); + irqhandled = 1; + } + if (irqstatus & CAM_IRQSTATUS_MMU_IRQ) + dev_err(cam->dev, "unhandled camera MMU interrupt!\n"); + + return IRQ_RETVAL(irqhandled); +} + +/* + * + * Sensor handling. + * + */ + +/* + * Enable the external sensor interface. Try to negotiate interface + * parameters with the sensor and start using the new ones. The calls + * to sensor_if_enable and sensor_if_disable need not to be balanced. + */ +static int omap24xxcam_sensor_if_enable(struct omap24xxcam_device *cam) +{ + int rval; + struct v4l2_ifparm p; + + rval = vidioc_int_g_ifparm(cam->sdev, &p); + if (rval) { + dev_err(cam->dev, "vidioc_int_g_ifparm failed with %d\n", rval); + return rval; + } + + cam->if_type = p.if_type; + + cam->cc_ctrl = CC_CTRL_CC_EN; + + switch (p.if_type) { + case V4L2_IF_TYPE_BT656: + if (p.u.bt656.frame_start_on_rising_vs) + cam->cc_ctrl |= CC_CTRL_NOBT_SYNCHRO; + if (p.u.bt656.bt_sync_correct) + cam->cc_ctrl |= CC_CTRL_BT_CORRECT; + if (p.u.bt656.swap) + cam->cc_ctrl |= CC_CTRL_PAR_ORDERCAM; + if (p.u.bt656.latch_clk_inv) + cam->cc_ctrl |= CC_CTRL_PAR_CLK_POL; + if (p.u.bt656.nobt_hs_inv) + cam->cc_ctrl |= CC_CTRL_NOBT_HS_POL; + if (p.u.bt656.nobt_vs_inv) + cam->cc_ctrl |= CC_CTRL_NOBT_VS_POL; + + switch (p.u.bt656.mode) { + case V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT: + cam->cc_ctrl |= CC_CTRL_PAR_MODE_NOBT8; + break; + case V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT: + cam->cc_ctrl |= CC_CTRL_PAR_MODE_NOBT10; + break; + case V4L2_IF_TYPE_BT656_MODE_NOBT_12BIT: + cam->cc_ctrl |= CC_CTRL_PAR_MODE_NOBT12; + break; + case V4L2_IF_TYPE_BT656_MODE_BT_8BIT: + cam->cc_ctrl |= CC_CTRL_PAR_MODE_BT8; + break; + case V4L2_IF_TYPE_BT656_MODE_BT_10BIT: + cam->cc_ctrl |= CC_CTRL_PAR_MODE_BT10; + break; + default: + dev_err(cam->dev, + "bt656 interface mode %d not supported\n", + p.u.bt656.mode); + return -EINVAL; + } + /* + * The clock rate that the sensor wants has changed. + * We have to adjust the xclk from OMAP 2 side to + * match the sensor's wish as closely as possible. + */ + if (p.u.bt656.clock_curr != cam->if_u.bt656.xclk) { + u32 xclk = p.u.bt656.clock_curr; + u32 divisor; + + if (xclk == 0) + return -EINVAL; + + if (xclk > CAM_MCLK) + xclk = CAM_MCLK; + + divisor = CAM_MCLK / xclk; + if (divisor * xclk < CAM_MCLK) + divisor++; + if (CAM_MCLK / divisor < p.u.bt656.clock_min + && divisor > 1) + divisor--; + if (divisor > 30) + divisor = 30; + + xclk = CAM_MCLK / divisor; + + if (xclk < p.u.bt656.clock_min + || xclk > p.u.bt656.clock_max) + return -EINVAL; + + cam->if_u.bt656.xclk = xclk; + } + omap24xxcam_core_xclk_set(cam, cam->if_u.bt656.xclk); + break; + default: + /* FIXME: how about other interfaces? */ + dev_err(cam->dev, "interface type %d not supported\n", + p.if_type); + return -EINVAL; + } + + return 0; +} + +static void omap24xxcam_sensor_if_disable(const struct omap24xxcam_device *cam) +{ + switch (cam->if_type) { + case V4L2_IF_TYPE_BT656: + omap24xxcam_core_xclk_set(cam, 0); + break; + } +} + +/* + * Initialise the sensor hardware. + */ +static int omap24xxcam_sensor_init(struct omap24xxcam_device *cam) +{ + int err = 0; + struct v4l2_int_device *sdev = cam->sdev; + + omap24xxcam_clock_on(cam); + err = omap24xxcam_sensor_if_enable(cam); + if (err) { + dev_err(cam->dev, "sensor interface could not be enabled at " + "initialisation, %d\n", err); + cam->sdev = NULL; + goto out; + } + + /* power up sensor during sensor initialization */ + vidioc_int_s_power(sdev, 1); + + err = vidioc_int_dev_init(sdev); + if (err) { + dev_err(cam->dev, "cannot initialize sensor, error %d\n", err); + /* Sensor init failed --- it's nonexistent to us! */ + cam->sdev = NULL; + goto out; + } + + dev_info(cam->dev, "sensor is %s\n", sdev->name); + +out: + omap24xxcam_sensor_if_disable(cam); + omap24xxcam_clock_off(cam); + + vidioc_int_s_power(sdev, 0); + + return err; +} + +static void omap24xxcam_sensor_exit(struct omap24xxcam_device *cam) +{ + if (cam->sdev) + vidioc_int_dev_exit(cam->sdev); +} + +static void omap24xxcam_sensor_disable(struct omap24xxcam_device *cam) +{ + omap24xxcam_sensor_if_disable(cam); + omap24xxcam_clock_off(cam); + vidioc_int_s_power(cam->sdev, 0); +} + +/* + * Power-up and configure camera sensor. It's ready for capturing now. + */ +static int omap24xxcam_sensor_enable(struct omap24xxcam_device *cam) +{ + int rval; + + omap24xxcam_clock_on(cam); + + omap24xxcam_sensor_if_enable(cam); + + rval = vidioc_int_s_power(cam->sdev, 1); + if (rval) + goto out; + + rval = vidioc_int_init(cam->sdev); + if (rval) + goto out; + + return 0; + +out: + omap24xxcam_sensor_disable(cam); + + return rval; +} + +static void omap24xxcam_sensor_reset_work(struct work_struct *work) +{ + struct omap24xxcam_device *cam = + container_of(work, struct omap24xxcam_device, + sensor_reset_work); + + if (atomic_read(&cam->reset_disable)) + return; + + omap24xxcam_capture_stop(cam); + + if (vidioc_int_reset(cam->sdev) == 0) { + vidioc_int_init(cam->sdev); + } else { + /* Can't reset it by vidioc_int_reset. */ + omap24xxcam_sensor_disable(cam); + omap24xxcam_sensor_enable(cam); + } + + omap24xxcam_capture_cont(cam); +} + +/* + * + * IOCTL interface. + * + */ + +static int vidioc_querycap(struct file *file, void *fh, + struct v4l2_capability *cap) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + + strlcpy(cap->driver, CAM_NAME, sizeof(cap->driver)); + strlcpy(cap->card, cam->vfd->name, sizeof(cap->card)); + cap->version = OMAP24XXCAM_VERSION; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + rval = vidioc_int_enum_fmt_cap(cam->sdev, f); + + return rval; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + mutex_lock(&cam->mutex); + rval = vidioc_int_g_fmt_cap(cam->sdev, f); + mutex_unlock(&cam->mutex); + + return rval; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + mutex_lock(&cam->mutex); + if (cam->streaming) { + rval = -EBUSY; + goto out; + } + + rval = vidioc_int_s_fmt_cap(cam->sdev, f); + +out: + mutex_unlock(&cam->mutex); + + if (!rval) { + mutex_lock(&ofh->vbq.vb_lock); + ofh->pix = f->fmt.pix; + mutex_unlock(&ofh->vbq.vb_lock); + } + + memset(f, 0, sizeof(*f)); + vidioc_g_fmt_vid_cap(file, fh, f); + + return rval; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + mutex_lock(&cam->mutex); + rval = vidioc_int_try_fmt_cap(cam->sdev, f); + mutex_unlock(&cam->mutex); + + return rval; +} + +static int vidioc_reqbufs(struct file *file, void *fh, + struct v4l2_requestbuffers *b) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + mutex_lock(&cam->mutex); + if (cam->streaming) { + mutex_unlock(&cam->mutex); + return -EBUSY; + } + + omap24xxcam_vbq_free_mmap_buffers(&ofh->vbq); + mutex_unlock(&cam->mutex); + + rval = videobuf_reqbufs(&ofh->vbq, b); + + /* + * Either videobuf_reqbufs failed or the buffers are not + * memory-mapped (which would need special attention). + */ + if (rval < 0 || b->memory != V4L2_MEMORY_MMAP) + goto out; + + rval = omap24xxcam_vbq_alloc_mmap_buffers(&ofh->vbq, rval); + if (rval) + omap24xxcam_vbq_free_mmap_buffers(&ofh->vbq); + +out: + return rval; +} + +static int vidioc_querybuf(struct file *file, void *fh, + struct v4l2_buffer *b) +{ + struct omap24xxcam_fh *ofh = fh; + + return videobuf_querybuf(&ofh->vbq, b); +} + +static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) +{ + struct omap24xxcam_fh *ofh = fh; + + return videobuf_qbuf(&ofh->vbq, b); +} + +static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + struct videobuf_buffer *vb; + int rval; + +videobuf_dqbuf_again: + rval = videobuf_dqbuf(&ofh->vbq, b, file->f_flags & O_NONBLOCK); + if (rval) + goto out; + + vb = ofh->vbq.bufs[b->index]; + + mutex_lock(&cam->mutex); + /* _needs_reset returns -EIO if reset is required. */ + rval = vidioc_int_g_needs_reset(cam->sdev, (void *)vb->baddr); + mutex_unlock(&cam->mutex); + if (rval == -EIO) + schedule_work(&cam->sensor_reset_work); + else + rval = 0; + +out: + /* + * This is a hack. We don't want to show -EIO to the user + * space. Requeue the buffer and try again if we're not doing + * this in non-blocking mode. + */ + if (rval == -EIO) { + videobuf_qbuf(&ofh->vbq, b); + if (!(file->f_flags & O_NONBLOCK)) + goto videobuf_dqbuf_again; + /* + * We don't have a videobuf_buffer now --- maybe next + * time... + */ + rval = -EAGAIN; + } + + return rval; +} + +static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + mutex_lock(&cam->mutex); + if (cam->streaming) { + rval = -EBUSY; + goto out; + } + + rval = omap24xxcam_sensor_if_enable(cam); + if (rval) { + dev_dbg(cam->dev, "vidioc_int_g_ifparm failed\n"); + goto out; + } + + rval = videobuf_streamon(&ofh->vbq); + if (!rval) { + cam->streaming = file; + sysfs_notify(&cam->dev->kobj, NULL, "streaming"); + } + +out: + mutex_unlock(&cam->mutex); + + return rval; +} + +static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + struct videobuf_queue *q = &ofh->vbq; + int rval; + + atomic_inc(&cam->reset_disable); + + flush_scheduled_work(); + + rval = videobuf_streamoff(q); + if (!rval) { + mutex_lock(&cam->mutex); + cam->streaming = NULL; + mutex_unlock(&cam->mutex); + sysfs_notify(&cam->dev->kobj, NULL, "streaming"); + } + + atomic_dec(&cam->reset_disable); + + return rval; +} + +static int vidioc_enum_input(struct file *file, void *fh, + struct v4l2_input *inp) +{ + if (inp->index > 0) + return -EINVAL; + + strlcpy(inp->name, "camera", sizeof(inp->name)); + inp->type = V4L2_INPUT_TYPE_CAMERA; + + return 0; +} + +static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) +{ + *i = 0; + + return 0; +} + +static int vidioc_s_input(struct file *file, void *fh, unsigned int i) +{ + if (i > 0) + return -EINVAL; + + return 0; +} + +static int vidioc_queryctrl(struct file *file, void *fh, + struct v4l2_queryctrl *a) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + rval = vidioc_int_queryctrl(cam->sdev, a); + + return rval; +} + +static int vidioc_g_ctrl(struct file *file, void *fh, + struct v4l2_control *a) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + mutex_lock(&cam->mutex); + rval = vidioc_int_g_ctrl(cam->sdev, a); + mutex_unlock(&cam->mutex); + + return rval; +} + +static int vidioc_s_ctrl(struct file *file, void *fh, + struct v4l2_control *a) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + mutex_lock(&cam->mutex); + rval = vidioc_int_s_ctrl(cam->sdev, a); + mutex_unlock(&cam->mutex); + + return rval; +} + +static int vidioc_g_parm(struct file *file, void *fh, + struct v4l2_streamparm *a) { + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + int rval; + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + mutex_lock(&cam->mutex); + rval = vidioc_int_g_parm(cam->sdev, a); + mutex_unlock(&cam->mutex); + + return rval; +} + +static int vidioc_s_parm(struct file *file, void *fh, + struct v4l2_streamparm *a) +{ + struct omap24xxcam_fh *ofh = fh; + struct omap24xxcam_device *cam = ofh->cam; + struct v4l2_streamparm old_streamparm; + int rval; + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + mutex_lock(&cam->mutex); + if (cam->streaming) { + rval = -EBUSY; + goto out; + } + + old_streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + rval = vidioc_int_g_parm(cam->sdev, &old_streamparm); + if (rval) + goto out; + + rval = vidioc_int_s_parm(cam->sdev, a); + if (rval) + goto out; + + rval = omap24xxcam_sensor_if_enable(cam); + /* + * Revert to old streaming parameters if enabling sensor + * interface with the new ones failed. + */ + if (rval) + vidioc_int_s_parm(cam->sdev, &old_streamparm); + +out: + mutex_unlock(&cam->mutex); + + return rval; +} + +/* + * + * File operations. + * + */ + +static unsigned int omap24xxcam_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct omap24xxcam_fh *fh = file->private_data; + struct omap24xxcam_device *cam = fh->cam; + struct videobuf_buffer *vb; + + mutex_lock(&cam->mutex); + if (cam->streaming != file) { + mutex_unlock(&cam->mutex); + return POLLERR; + } + mutex_unlock(&cam->mutex); + + mutex_lock(&fh->vbq.vb_lock); + if (list_empty(&fh->vbq.stream)) { + mutex_unlock(&fh->vbq.vb_lock); + return POLLERR; + } + vb = list_entry(fh->vbq.stream.next, struct videobuf_buffer, stream); + mutex_unlock(&fh->vbq.vb_lock); + + poll_wait(file, &vb->done, wait); + + if (vb->state == VIDEOBUF_DONE || vb->state == VIDEOBUF_ERROR) + return POLLIN | POLLRDNORM; + + return 0; +} + +static int omap24xxcam_mmap_buffers(struct file *file, + struct vm_area_struct *vma) +{ + struct omap24xxcam_fh *fh = file->private_data; + struct omap24xxcam_device *cam = fh->cam; + struct videobuf_queue *vbq = &fh->vbq; + unsigned int first, last, size, i, j; + int err = 0; + + mutex_lock(&cam->mutex); + if (cam->streaming) { + mutex_unlock(&cam->mutex); + return -EBUSY; + } + mutex_unlock(&cam->mutex); + mutex_lock(&vbq->vb_lock); + + /* look for first buffer to map */ + for (first = 0; first < VIDEO_MAX_FRAME; first++) { + if (NULL == vbq->bufs[first]) + continue; + if (V4L2_MEMORY_MMAP != vbq->bufs[first]->memory) + continue; + if (vbq->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) + break; + } + + /* look for last buffer to map */ + for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) { + if (NULL == vbq->bufs[last]) + continue; + if (V4L2_MEMORY_MMAP != vbq->bufs[last]->memory) + continue; + size += vbq->bufs[last]->bsize; + if (size == (vma->vm_end - vma->vm_start)) + break; + } + + size = 0; + for (i = first; i <= last; i++) { + struct videobuf_dmabuf *dma = videobuf_to_dma(vbq->bufs[i]); + + for (j = 0; j < dma->sglen; j++) { + err = remap_pfn_range( + vma, vma->vm_start + size, + page_to_pfn(sg_page(&dma->sglist[j])), + sg_dma_len(&dma->sglist[j]), vma->vm_page_prot); + if (err) + goto out; + size += sg_dma_len(&dma->sglist[j]); + } + } + +out: + mutex_unlock(&vbq->vb_lock); + + return err; +} + +static int omap24xxcam_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct omap24xxcam_fh *fh = file->private_data; + int rval; + + /* let the video-buf mapper check arguments and set-up structures */ + rval = videobuf_mmap_mapper(&fh->vbq, vma); + if (rval) + return rval; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* do mapping to our allocated buffers */ + rval = omap24xxcam_mmap_buffers(file, vma); + /* + * In case of error, free vma->vm_private_data allocated by + * videobuf_mmap_mapper. + */ + if (rval) + kfree(vma->vm_private_data); + + return rval; +} + +static int omap24xxcam_open(struct inode *inode, struct file *file) +{ + int minor = iminor(inode); + struct omap24xxcam_device *cam = omap24xxcam.priv; + struct omap24xxcam_fh *fh; + struct v4l2_format format; + + if (!cam || !cam->vfd || (cam->vfd->minor != minor)) + return -ENODEV; + + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (fh == NULL) + return -ENOMEM; + + mutex_lock(&cam->mutex); + if (cam->sdev == NULL || !try_module_get(cam->sdev->module)) { + mutex_unlock(&cam->mutex); + goto out_try_module_get; + } + + if (atomic_inc_return(&cam->users) == 1) { + omap24xxcam_hwinit(cam); + if (omap24xxcam_sensor_enable(cam)) { + mutex_unlock(&cam->mutex); + goto out_omap24xxcam_sensor_enable; + } + } + mutex_unlock(&cam->mutex); + + fh->cam = cam; + mutex_lock(&cam->mutex); + vidioc_int_g_fmt_cap(cam->sdev, &format); + mutex_unlock(&cam->mutex); + /* FIXME: how about fh->pix when there are more users? */ + fh->pix = format.fmt.pix; + + file->private_data = fh; + + spin_lock_init(&fh->vbq_lock); + + videobuf_queue_sg_init(&fh->vbq, &omap24xxcam_vbq_ops, NULL, + &fh->vbq_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_NONE, + sizeof(struct videobuf_buffer), fh); + + return 0; + +out_omap24xxcam_sensor_enable: + omap24xxcam_poweron_reset(cam); + module_put(cam->sdev->module); + +out_try_module_get: + kfree(fh); + + return -ENODEV; +} + +static int omap24xxcam_release(struct inode *inode, struct file *file) +{ + struct omap24xxcam_fh *fh = file->private_data; + struct omap24xxcam_device *cam = fh->cam; + + atomic_inc(&cam->reset_disable); + + flush_scheduled_work(); + + /* stop streaming capture */ + videobuf_streamoff(&fh->vbq); + + mutex_lock(&cam->mutex); + if (cam->streaming == file) { + cam->streaming = NULL; + mutex_unlock(&cam->mutex); + sysfs_notify(&cam->dev->kobj, NULL, "streaming"); + } else { + mutex_unlock(&cam->mutex); + } + + atomic_dec(&cam->reset_disable); + + omap24xxcam_vbq_free_mmap_buffers(&fh->vbq); + + /* + * Make sure the reset work we might have scheduled is not + * pending! It may be run *only* if we have users. (And it may + * not be scheduled anymore since streaming is already + * disabled.) + */ + flush_scheduled_work(); + + mutex_lock(&cam->mutex); + if (atomic_dec_return(&cam->users) == 0) { + omap24xxcam_sensor_disable(cam); + omap24xxcam_poweron_reset(cam); + } + mutex_unlock(&cam->mutex); + + file->private_data = NULL; + + module_put(cam->sdev->module); + kfree(fh); + + return 0; +} + +static struct file_operations omap24xxcam_fops = { + .llseek = no_llseek, + .ioctl = video_ioctl2, + .poll = omap24xxcam_poll, + .mmap = omap24xxcam_mmap, + .open = omap24xxcam_open, + .release = omap24xxcam_release, +}; + +/* + * + * Power management. + * + */ + +#ifdef CONFIG_PM +static int omap24xxcam_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct omap24xxcam_device *cam = platform_get_drvdata(pdev); + + if (atomic_read(&cam->users) == 0) + return 0; + + if (!atomic_read(&cam->reset_disable)) + omap24xxcam_capture_stop(cam); + + omap24xxcam_sensor_disable(cam); + omap24xxcam_poweron_reset(cam); + + return 0; +} + +static int omap24xxcam_resume(struct platform_device *pdev) +{ + struct omap24xxcam_device *cam = platform_get_drvdata(pdev); + + if (atomic_read(&cam->users) == 0) + return 0; + + omap24xxcam_hwinit(cam); + omap24xxcam_sensor_enable(cam); + + if (!atomic_read(&cam->reset_disable)) + omap24xxcam_capture_cont(cam); + + return 0; +} +#endif /* CONFIG_PM */ + +static const struct v4l2_ioctl_ops omap24xxcam_ioctl_fops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_parm = vidioc_g_parm, + .vidioc_s_parm = vidioc_s_parm, +}; + +/* + * + * Camera device (i.e. /dev/video). + * + */ + +static int omap24xxcam_device_register(struct v4l2_int_device *s) +{ + struct omap24xxcam_device *cam = s->u.slave->master->priv; + struct video_device *vfd; + int rval; + + /* We already have a slave. */ + if (cam->sdev) + return -EBUSY; + + cam->sdev = s; + + if (device_create_file(cam->dev, &dev_attr_streaming) != 0) { + dev_err(cam->dev, "could not register sysfs entry\n"); + rval = -EBUSY; + goto err; + } + + /* initialize the video_device struct */ + vfd = cam->vfd = video_device_alloc(); + if (!vfd) { + dev_err(cam->dev, "could not allocate video device struct\n"); + rval = -ENOMEM; + goto err; + } + vfd->release = video_device_release; + + vfd->parent = cam->dev; + + strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name)); + vfd->vfl_type = VID_TYPE_CAPTURE | VID_TYPE_CHROMAKEY; + vfd->fops = &omap24xxcam_fops; + vfd->minor = -1; + vfd->ioctl_ops = &omap24xxcam_ioctl_fops; + + omap24xxcam_hwinit(cam); + + rval = omap24xxcam_sensor_init(cam); + if (rval) + goto err; + + if (video_register_device(vfd, VFL_TYPE_GRABBER, video_nr) < 0) { + dev_err(cam->dev, "could not register V4L device\n"); + vfd->minor = -1; + rval = -EBUSY; + goto err; + } + + omap24xxcam_poweron_reset(cam); + + dev_info(cam->dev, "registered device video%d\n", vfd->minor); + + return 0; + +err: + omap24xxcam_device_unregister(s); + + return rval; +} + +static void omap24xxcam_device_unregister(struct v4l2_int_device *s) +{ + struct omap24xxcam_device *cam = s->u.slave->master->priv; + + omap24xxcam_sensor_exit(cam); + + if (cam->vfd) { + if (cam->vfd->minor == -1) { + /* + * The device was never registered, so release the + * video_device struct directly. + */ + video_device_release(cam->vfd); + } else { + /* + * The unregister function will release the + * video_device struct as well as + * unregistering it. + */ + video_unregister_device(cam->vfd); + } + cam->vfd = NULL; + } + + device_remove_file(cam->dev, &dev_attr_streaming); + + cam->sdev = NULL; +} + +static struct v4l2_int_master omap24xxcam_master = { + .attach = omap24xxcam_device_register, + .detach = omap24xxcam_device_unregister, +}; + +static struct v4l2_int_device omap24xxcam = { + .module = THIS_MODULE, + .name = CAM_NAME, + .type = v4l2_int_type_master, + .u = { + .master = &omap24xxcam_master + }, +}; + +/* + * + * Driver initialisation and deinitialisation. + * + */ + +static int __init omap24xxcam_probe(struct platform_device *pdev) +{ + struct omap24xxcam_device *cam; + struct resource *mem; + int irq; + + cam = kzalloc(sizeof(*cam), GFP_KERNEL); + if (!cam) { + dev_err(&pdev->dev, "could not allocate memory\n"); + goto err; + } + + platform_set_drvdata(pdev, cam); + + cam->dev = &pdev->dev; + + /* + * Impose a lower limit on the amount of memory allocated for + * capture. We require at least enough memory to double-buffer + * QVGA (300KB). + */ + if (capture_mem < 320 * 240 * 2 * 2) + capture_mem = 320 * 240 * 2 * 2; + cam->capture_mem = capture_mem; + + /* request the mem region for the camera registers */ + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(cam->dev, "no mem resource?\n"); + goto err; + } + if (!request_mem_region(mem->start, (mem->end - mem->start) + 1, + pdev->name)) { + dev_err(cam->dev, + "cannot reserve camera register I/O region\n"); + goto err; + } + cam->mmio_base_phys = mem->start; + cam->mmio_size = (mem->end - mem->start) + 1; + + /* map the region */ + cam->mmio_base = (unsigned long) + ioremap_nocache(cam->mmio_base_phys, cam->mmio_size); + if (!cam->mmio_base) { + dev_err(cam->dev, "cannot map camera register I/O region\n"); + goto err; + } + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(cam->dev, "no irq for camera?\n"); + goto err; + } + + /* install the interrupt service routine */ + if (request_irq(irq, omap24xxcam_isr, 0, CAM_NAME, cam)) { + dev_err(cam->dev, + "could not install interrupt service routine\n"); + goto err; + } + cam->irq = irq; + + if (omap24xxcam_clock_get(cam)) + goto err; + + INIT_WORK(&cam->sensor_reset_work, omap24xxcam_sensor_reset_work); + + mutex_init(&cam->mutex); + spin_lock_init(&cam->core_enable_disable_lock); + + omap24xxcam_sgdma_init(&cam->sgdma, + cam->mmio_base + CAMDMA_REG_OFFSET, + omap24xxcam_stalled_dma_reset, + (unsigned long)cam); + + omap24xxcam.priv = cam; + + if (v4l2_int_device_register(&omap24xxcam)) + goto err; + + return 0; + +err: + omap24xxcam_remove(pdev); + return -ENODEV; +} + +static int omap24xxcam_remove(struct platform_device *pdev) +{ + struct omap24xxcam_device *cam = platform_get_drvdata(pdev); + + if (!cam) + return 0; + + if (omap24xxcam.priv != NULL) + v4l2_int_device_unregister(&omap24xxcam); + omap24xxcam.priv = NULL; + + omap24xxcam_clock_put(cam); + + if (cam->irq) { + free_irq(cam->irq, cam); + cam->irq = 0; + } + + if (cam->mmio_base) { + iounmap((void *)cam->mmio_base); + cam->mmio_base = 0; + } + + if (cam->mmio_base_phys) { + release_mem_region(cam->mmio_base_phys, cam->mmio_size); + cam->mmio_base_phys = 0; + } + + kfree(cam); + + return 0; +} + +static struct platform_driver omap24xxcam_driver = { + .probe = omap24xxcam_probe, + .remove = omap24xxcam_remove, +#ifdef CONFIG_PM + .suspend = omap24xxcam_suspend, + .resume = omap24xxcam_resume, +#endif + .driver = { + .name = CAM_NAME, + .owner = THIS_MODULE, + }, +}; + +/* + * + * Module initialisation and deinitialisation + * + */ + +static int __init omap24xxcam_init(void) +{ + return platform_driver_register(&omap24xxcam_driver); +} + +static void __exit omap24xxcam_cleanup(void) +{ + platform_driver_unregister(&omap24xxcam_driver); +} + +MODULE_AUTHOR("Sakari Ailus "); +MODULE_DESCRIPTION("OMAP24xx Video for Linux camera driver"); +MODULE_LICENSE("GPL"); +module_param(video_nr, int, 0); +MODULE_PARM_DESC(video_nr, + "Minor number for video device (-1 ==> auto assign)"); +module_param(capture_mem, int, 0); +MODULE_PARM_DESC(capture_mem, "Maximum amount of memory for capture " + "buffers (default 4800kiB)"); + +module_init(omap24xxcam_init); +module_exit(omap24xxcam_cleanup); diff --git a/linux/drivers/media/video/omap24xxcam.h b/linux/drivers/media/video/omap24xxcam.h new file mode 100644 index 000000000..2ce67f5a4 --- /dev/null +++ b/linux/drivers/media/video/omap24xxcam.h @@ -0,0 +1,593 @@ +/* + * drivers/media/video/omap24xxcam.h + * + * Copyright (C) 2004 MontaVista Software, Inc. + * Copyright (C) 2004 Texas Instruments. + * Copyright (C) 2007 Nokia Corporation. + * + * Contact: Sakari Ailus + * + * Based on code from Andy Lowe . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef OMAP24XXCAM_H +#define OMAP24XXCAM_H + +#include +#include + +/* + * + * General driver related definitions. + * + */ + +#define CAM_NAME "omap24xxcam" + +#define CAM_MCLK 96000000 + +/* number of bytes transferred per DMA request */ +#define DMA_THRESHOLD 32 + +/* + * NUM_CAMDMA_CHANNELS is the number of logical channels provided by + * the camera DMA controller. + */ +#define NUM_CAMDMA_CHANNELS 4 + +/* + * NUM_SG_DMA is the number of scatter-gather DMA transfers that can + * be queued. (We don't have any overlay sglists now.) + */ +#define NUM_SG_DMA (VIDEO_MAX_FRAME) + +/* + * + * Register definitions. + * + */ + +/* subsystem register block offsets */ +#define CC_REG_OFFSET 0x00000400 +#define CAMDMA_REG_OFFSET 0x00000800 +#define CAMMMU_REG_OFFSET 0x00000C00 + +/* define camera subsystem register offsets */ +#define CAM_REVISION 0x000 +#define CAM_SYSCONFIG 0x010 +#define CAM_SYSSTATUS 0x014 +#define CAM_IRQSTATUS 0x018 +#define CAM_GPO 0x040 +#define CAM_GPI 0x050 + +/* define camera core register offsets */ +#define CC_REVISION 0x000 +#define CC_SYSCONFIG 0x010 +#define CC_SYSSTATUS 0x014 +#define CC_IRQSTATUS 0x018 +#define CC_IRQENABLE 0x01C +#define CC_CTRL 0x040 +#define CC_CTRL_DMA 0x044 +#define CC_CTRL_XCLK 0x048 +#define CC_FIFODATA 0x04C +#define CC_TEST 0x050 +#define CC_GENPAR 0x054 +#define CC_CCPFSCR 0x058 +#define CC_CCPFECR 0x05C +#define CC_CCPLSCR 0x060 +#define CC_CCPLECR 0x064 +#define CC_CCPDFR 0x068 + +/* define camera dma register offsets */ +#define CAMDMA_REVISION 0x000 +#define CAMDMA_IRQSTATUS_L0 0x008 +#define CAMDMA_IRQSTATUS_L1 0x00C +#define CAMDMA_IRQSTATUS_L2 0x010 +#define CAMDMA_IRQSTATUS_L3 0x014 +#define CAMDMA_IRQENABLE_L0 0x018 +#define CAMDMA_IRQENABLE_L1 0x01C +#define CAMDMA_IRQENABLE_L2 0x020 +#define CAMDMA_IRQENABLE_L3 0x024 +#define CAMDMA_SYSSTATUS 0x028 +#define CAMDMA_OCP_SYSCONFIG 0x02C +#define CAMDMA_CAPS_0 0x064 +#define CAMDMA_CAPS_2 0x06C +#define CAMDMA_CAPS_3 0x070 +#define CAMDMA_CAPS_4 0x074 +#define CAMDMA_GCR 0x078 +#define CAMDMA_CCR(n) (0x080 + (n)*0x60) +#define CAMDMA_CLNK_CTRL(n) (0x084 + (n)*0x60) +#define CAMDMA_CICR(n) (0x088 + (n)*0x60) +#define CAMDMA_CSR(n) (0x08C + (n)*0x60) +#define CAMDMA_CSDP(n) (0x090 + (n)*0x60) +#define CAMDMA_CEN(n) (0x094 + (n)*0x60) +#define CAMDMA_CFN(n) (0x098 + (n)*0x60) +#define CAMDMA_CSSA(n) (0x09C + (n)*0x60) +#define CAMDMA_CDSA(n) (0x0A0 + (n)*0x60) +#define CAMDMA_CSEI(n) (0x0A4 + (n)*0x60) +#define CAMDMA_CSFI(n) (0x0A8 + (n)*0x60) +#define CAMDMA_CDEI(n) (0x0AC + (n)*0x60) +#define CAMDMA_CDFI(n) (0x0B0 + (n)*0x60) +#define CAMDMA_CSAC(n) (0x0B4 + (n)*0x60) +#define CAMDMA_CDAC(n) (0x0B8 + (n)*0x60) +#define CAMDMA_CCEN(n) (0x0BC + (n)*0x60) +#define CAMDMA_CCFN(n) (0x0C0 + (n)*0x60) +#define CAMDMA_COLOR(n) (0x0C4 + (n)*0x60) + +/* define camera mmu register offsets */ +#define CAMMMU_REVISION 0x000 +#define CAMMMU_SYSCONFIG 0x010 +#define CAMMMU_SYSSTATUS 0x014 +#define CAMMMU_IRQSTATUS 0x018 +#define CAMMMU_IRQENABLE 0x01C +#define CAMMMU_WALKING_ST 0x040 +#define CAMMMU_CNTL 0x044 +#define CAMMMU_FAULT_AD 0x048 +#define CAMMMU_TTB 0x04C +#define CAMMMU_LOCK 0x050 +#define CAMMMU_LD_TLB 0x054 +#define CAMMMU_CAM 0x058 +#define CAMMMU_RAM 0x05C +#define CAMMMU_GFLUSH 0x060 +#define CAMMMU_FLUSH_ENTRY 0x064 +#define CAMMMU_READ_CAM 0x068 +#define CAMMMU_READ_RAM 0x06C +#define CAMMMU_EMU_FAULT_AD 0x070 + +/* Define bit fields within selected registers */ +#define CAM_REVISION_MAJOR (15 << 4) +#define CAM_REVISION_MAJOR_SHIFT 4 +#define CAM_REVISION_MINOR (15 << 0) +#define CAM_REVISION_MINOR_SHIFT 0 + +#define CAM_SYSCONFIG_SOFTRESET (1 << 1) +#define CAM_SYSCONFIG_AUTOIDLE (1 << 0) + +#define CAM_SYSSTATUS_RESETDONE (1 << 0) + +#define CAM_IRQSTATUS_CC_IRQ (1 << 4) +#define CAM_IRQSTATUS_MMU_IRQ (1 << 3) +#define CAM_IRQSTATUS_DMA_IRQ2 (1 << 2) +#define CAM_IRQSTATUS_DMA_IRQ1 (1 << 1) +#define CAM_IRQSTATUS_DMA_IRQ0 (1 << 0) + +#define CAM_GPO_CAM_S_P_EN (1 << 1) +#define CAM_GPO_CAM_CCP_MODE (1 << 0) + +#define CAM_GPI_CC_DMA_REQ1 (1 << 24) +#define CAP_GPI_CC_DMA_REQ0 (1 << 23) +#define CAP_GPI_CAM_MSTANDBY (1 << 21) +#define CAP_GPI_CAM_WAIT (1 << 20) +#define CAP_GPI_CAM_S_DATA (1 << 17) +#define CAP_GPI_CAM_S_CLK (1 << 16) +#define CAP_GPI_CAM_P_DATA (0xFFF << 3) +#define CAP_GPI_CAM_P_DATA_SHIFT 3 +#define CAP_GPI_CAM_P_VS (1 << 2) +#define CAP_GPI_CAM_P_HS (1 << 1) +#define CAP_GPI_CAM_P_CLK (1 << 0) + +#define CC_REVISION_MAJOR (15 << 4) +#define CC_REVISION_MAJOR_SHIFT 4 +#define CC_REVISION_MINOR (15 << 0) +#define CC_REVISION_MINOR_SHIFT 0 + +#define CC_SYSCONFIG_SIDLEMODE (3 << 3) +#define CC_SYSCONFIG_SIDLEMODE_FIDLE (0 << 3) +#define CC_SYSCONFIG_SIDLEMODE_NIDLE (1 << 3) +#define CC_SYSCONFIG_SOFTRESET (1 << 1) +#define CC_SYSCONFIG_AUTOIDLE (1 << 0) + +#define CC_SYSSTATUS_RESETDONE (1 << 0) + +#define CC_IRQSTATUS_FS_IRQ (1 << 19) +#define CC_IRQSTATUS_LE_IRQ (1 << 18) +#define CC_IRQSTATUS_LS_IRQ (1 << 17) +#define CC_IRQSTATUS_FE_IRQ (1 << 16) +#define CC_IRQSTATUS_FW_ERR_IRQ (1 << 10) +#define CC_IRQSTATUS_FSC_ERR_IRQ (1 << 9) +#define CC_IRQSTATUS_SSC_ERR_IRQ (1 << 8) +#define CC_IRQSTATUS_FIFO_NOEMPTY_IRQ (1 << 4) +#define CC_IRQSTATUS_FIFO_FULL_IRQ (1 << 3) +#define CC_IRQSTATUS_FIFO_THR_IRQ (1 << 2) +#define CC_IRQSTATUS_FIFO_OF_IRQ (1 << 1) +#define CC_IRQSTATUS_FIFO_UF_IRQ (1 << 0) + +#define CC_IRQENABLE_FS_IRQ (1 << 19) +#define CC_IRQENABLE_LE_IRQ (1 << 18) +#define CC_IRQENABLE_LS_IRQ (1 << 17) +#define CC_IRQENABLE_FE_IRQ (1 << 16) +#define CC_IRQENABLE_FW_ERR_IRQ (1 << 10) +#define CC_IRQENABLE_FSC_ERR_IRQ (1 << 9) +#define CC_IRQENABLE_SSC_ERR_IRQ (1 << 8) +#define CC_IRQENABLE_FIFO_NOEMPTY_IRQ (1 << 4) +#define CC_IRQENABLE_FIFO_FULL_IRQ (1 << 3) +#define CC_IRQENABLE_FIFO_THR_IRQ (1 << 2) +#define CC_IRQENABLE_FIFO_OF_IRQ (1 << 1) +#define CC_IRQENABLE_FIFO_UF_IRQ (1 << 0) + +#define CC_CTRL_CC_ONE_SHOT (1 << 20) +#define CC_CTRL_CC_IF_SYNCHRO (1 << 19) +#define CC_CTRL_CC_RST (1 << 18) +#define CC_CTRL_CC_FRAME_TRIG (1 << 17) +#define CC_CTRL_CC_EN (1 << 16) +#define CC_CTRL_NOBT_SYNCHRO (1 << 13) +#define CC_CTRL_BT_CORRECT (1 << 12) +#define CC_CTRL_PAR_ORDERCAM (1 << 11) +#define CC_CTRL_PAR_CLK_POL (1 << 10) +#define CC_CTRL_NOBT_HS_POL (1 << 9) +#define CC_CTRL_NOBT_VS_POL (1 << 8) +#define CC_CTRL_PAR_MODE (7 << 1) +#define CC_CTRL_PAR_MODE_SHIFT 1 +#define CC_CTRL_PAR_MODE_NOBT8 (0 << 1) +#define CC_CTRL_PAR_MODE_NOBT10 (1 << 1) +#define CC_CTRL_PAR_MODE_NOBT12 (2 << 1) +#define CC_CTRL_PAR_MODE_BT8 (4 << 1) +#define CC_CTRL_PAR_MODE_BT10 (5 << 1) +#define CC_CTRL_PAR_MODE_FIFOTEST (7 << 1) +#define CC_CTRL_CCP_MODE (1 << 0) + +#define CC_CTRL_DMA_EN (1 << 8) +#define CC_CTRL_DMA_FIFO_THRESHOLD (0x7F << 0) +#define CC_CTRL_DMA_FIFO_THRESHOLD_SHIFT 0 + +#define CC_CTRL_XCLK_DIV (0x1F << 0) +#define CC_CTRL_XCLK_DIV_SHIFT 0 +#define CC_CTRL_XCLK_DIV_STABLE_LOW (0 << 0) +#define CC_CTRL_XCLK_DIV_STABLE_HIGH (1 << 0) +#define CC_CTRL_XCLK_DIV_BYPASS (31 << 0) + +#define CC_TEST_FIFO_RD_POINTER (0xFF << 24) +#define CC_TEST_FIFO_RD_POINTER_SHIFT 24 +#define CC_TEST_FIFO_WR_POINTER (0xFF << 16) +#define CC_TEST_FIFO_WR_POINTER_SHIFT 16 +#define CC_TEST_FIFO_LEVEL (0xFF << 8) +#define CC_TEST_FIFO_LEVEL_SHIFT 8 +#define CC_TEST_FIFO_LEVEL_PEAK (0xFF << 0) +#define CC_TEST_FIFO_LEVEL_PEAK_SHIFT 0 + +#define CC_GENPAR_FIFO_DEPTH (7 << 0) +#define CC_GENPAR_FIFO_DEPTH_SHIFT 0 + +#define CC_CCPDFR_ALPHA (0xFF << 8) +#define CC_CCPDFR_ALPHA_SHIFT 8 +#define CC_CCPDFR_DATAFORMAT (15 << 0) +#define CC_CCPDFR_DATAFORMAT_SHIFT 0 +#define CC_CCPDFR_DATAFORMAT_YUV422BE (0 << 0) +#define CC_CCPDFR_DATAFORMAT_YUV422 (1 << 0) +#define CC_CCPDFR_DATAFORMAT_YUV420 (2 << 0) +#define CC_CCPDFR_DATAFORMAT_RGB444 (4 << 0) +#define CC_CCPDFR_DATAFORMAT_RGB565 (5 << 0) +#define CC_CCPDFR_DATAFORMAT_RGB888NDE (6 << 0) +#define CC_CCPDFR_DATAFORMAT_RGB888 (7 << 0) +#define CC_CCPDFR_DATAFORMAT_RAW8NDE (8 << 0) +#define CC_CCPDFR_DATAFORMAT_RAW8 (9 << 0) +#define CC_CCPDFR_DATAFORMAT_RAW10NDE (10 << 0) +#define CC_CCPDFR_DATAFORMAT_RAW10 (11 << 0) +#define CC_CCPDFR_DATAFORMAT_RAW12NDE (12 << 0) +#define CC_CCPDFR_DATAFORMAT_RAW12 (13 << 0) +#define CC_CCPDFR_DATAFORMAT_JPEG8 (15 << 0) + +#define CAMDMA_REVISION_MAJOR (15 << 4) +#define CAMDMA_REVISION_MAJOR_SHIFT 4 +#define CAMDMA_REVISION_MINOR (15 << 0) +#define CAMDMA_REVISION_MINOR_SHIFT 0 + +#define CAMDMA_OCP_SYSCONFIG_MIDLEMODE (3 << 12) +#define CAMDMA_OCP_SYSCONFIG_MIDLEMODE_FSTANDBY (0 << 12) +#define CAMDMA_OCP_SYSCONFIG_MIDLEMODE_NSTANDBY (1 << 12) +#define CAMDMA_OCP_SYSCONFIG_MIDLEMODE_SSTANDBY (2 << 12) +#define CAMDMA_OCP_SYSCONFIG_FUNC_CLOCK (1 << 9) +#define CAMDMA_OCP_SYSCONFIG_OCP_CLOCK (1 << 8) +#define CAMDMA_OCP_SYSCONFIG_EMUFREE (1 << 5) +#define CAMDMA_OCP_SYSCONFIG_SIDLEMODE (3 << 3) +#define CAMDMA_OCP_SYSCONFIG_SIDLEMODE_FIDLE (0 << 3) +#define CAMDMA_OCP_SYSCONFIG_SIDLEMODE_NIDLE (1 << 3) +#define CAMDMA_OCP_SYSCONFIG_SIDLEMODE_SIDLE (2 << 3) +#define CAMDMA_OCP_SYSCONFIG_SOFTRESET (1 << 1) +#define CAMDMA_OCP_SYSCONFIG_AUTOIDLE (1 << 0) + +#define CAMDMA_SYSSTATUS_RESETDONE (1 << 0) + +#define CAMDMA_GCR_ARBITRATION_RATE (0xFF << 16) +#define CAMDMA_GCR_ARBITRATION_RATE_SHIFT 16 +#define CAMDMA_GCR_MAX_CHANNEL_FIFO_DEPTH (0xFF << 0) +#define CAMDMA_GCR_MAX_CHANNEL_FIFO_DEPTH_SHIFT 0 + +#define CAMDMA_CCR_SEL_SRC_DST_SYNC (1 << 24) +#define CAMDMA_CCR_PREFETCH (1 << 23) +#define CAMDMA_CCR_SUPERVISOR (1 << 22) +#define CAMDMA_CCR_SECURE (1 << 21) +#define CAMDMA_CCR_BS (1 << 18) +#define CAMDMA_CCR_TRANSPARENT_COPY_ENABLE (1 << 17) +#define CAMDMA_CCR_CONSTANT_FILL_ENABLE (1 << 16) +#define CAMDMA_CCR_DST_AMODE (3 << 14) +#define CAMDMA_CCR_DST_AMODE_CONST_ADDR (0 << 14) +#define CAMDMA_CCR_DST_AMODE_POST_INC (1 << 14) +#define CAMDMA_CCR_DST_AMODE_SGL_IDX (2 << 14) +#define CAMDMA_CCR_DST_AMODE_DBL_IDX (3 << 14) +#define CAMDMA_CCR_SRC_AMODE (3 << 12) +#define CAMDMA_CCR_SRC_AMODE_CONST_ADDR (0 << 12) +#define CAMDMA_CCR_SRC_AMODE_POST_INC (1 << 12) +#define CAMDMA_CCR_SRC_AMODE_SGL_IDX (2 << 12) +#define CAMDMA_CCR_SRC_AMODE_DBL_IDX (3 << 12) +#define CAMDMA_CCR_WR_ACTIVE (1 << 10) +#define CAMDMA_CCR_RD_ACTIVE (1 << 9) +#define CAMDMA_CCR_SUSPEND_SENSITIVE (1 << 8) +#define CAMDMA_CCR_ENABLE (1 << 7) +#define CAMDMA_CCR_PRIO (1 << 6) +#define CAMDMA_CCR_FS (1 << 5) +#define CAMDMA_CCR_SYNCHRO ((3 << 19) | (31 << 0)) +#define CAMDMA_CCR_SYNCHRO_CAMERA 0x01 + +#define CAMDMA_CLNK_CTRL_ENABLE_LNK (1 << 15) +#define CAMDMA_CLNK_CTRL_NEXTLCH_ID (0x1F << 0) +#define CAMDMA_CLNK_CTRL_NEXTLCH_ID_SHIFT 0 + +#define CAMDMA_CICR_MISALIGNED_ERR_IE (1 << 11) +#define CAMDMA_CICR_SUPERVISOR_ERR_IE (1 << 10) +#define CAMDMA_CICR_SECURE_ERR_IE (1 << 9) +#define CAMDMA_CICR_TRANS_ERR_IE (1 << 8) +#define CAMDMA_CICR_PACKET_IE (1 << 7) +#define CAMDMA_CICR_BLOCK_IE (1 << 5) +#define CAMDMA_CICR_LAST_IE (1 << 4) +#define CAMDMA_CICR_FRAME_IE (1 << 3) +#define CAMDMA_CICR_HALF_IE (1 << 2) +#define CAMDMA_CICR_DROP_IE (1 << 1) + +#define CAMDMA_CSR_MISALIGNED_ERR (1 << 11) +#define CAMDMA_CSR_SUPERVISOR_ERR (1 << 10) +#define CAMDMA_CSR_SECURE_ERR (1 << 9) +#define CAMDMA_CSR_TRANS_ERR (1 << 8) +#define CAMDMA_CSR_PACKET (1 << 7) +#define CAMDMA_CSR_SYNC (1 << 6) +#define CAMDMA_CSR_BLOCK (1 << 5) +#define CAMDMA_CSR_LAST (1 << 4) +#define CAMDMA_CSR_FRAME (1 << 3) +#define CAMDMA_CSR_HALF (1 << 2) +#define CAMDMA_CSR_DROP (1 << 1) + +#define CAMDMA_CSDP_SRC_ENDIANNESS (1 << 21) +#define CAMDMA_CSDP_SRC_ENDIANNESS_LOCK (1 << 20) +#define CAMDMA_CSDP_DST_ENDIANNESS (1 << 19) +#define CAMDMA_CSDP_DST_ENDIANNESS_LOCK (1 << 18) +#define CAMDMA_CSDP_WRITE_MODE (3 << 16) +#define CAMDMA_CSDP_WRITE_MODE_WRNP (0 << 16) +#define CAMDMA_CSDP_WRITE_MODE_POSTED (1 << 16) +#define CAMDMA_CSDP_WRITE_MODE_POSTED_LAST_WRNP (2 << 16) +#define CAMDMA_CSDP_DST_BURST_EN (3 << 14) +#define CAMDMA_CSDP_DST_BURST_EN_1 (0 << 14) +#define CAMDMA_CSDP_DST_BURST_EN_16 (1 << 14) +#define CAMDMA_CSDP_DST_BURST_EN_32 (2 << 14) +#define CAMDMA_CSDP_DST_BURST_EN_64 (3 << 14) +#define CAMDMA_CSDP_DST_PACKED (1 << 13) +#define CAMDMA_CSDP_WR_ADD_TRSLT (15 << 9) +#define CAMDMA_CSDP_WR_ADD_TRSLT_ENABLE_MREQADD (3 << 9) +#define CAMDMA_CSDP_SRC_BURST_EN (3 << 7) +#define CAMDMA_CSDP_SRC_BURST_EN_1 (0 << 7) +#define CAMDMA_CSDP_SRC_BURST_EN_16 (1 << 7) +#define CAMDMA_CSDP_SRC_BURST_EN_32 (2 << 7) +#define CAMDMA_CSDP_SRC_BURST_EN_64 (3 << 7) +#define CAMDMA_CSDP_SRC_PACKED (1 << 6) +#define CAMDMA_CSDP_RD_ADD_TRSLT (15 << 2) +#define CAMDMA_CSDP_RD_ADD_TRSLT_ENABLE_MREQADD (3 << 2) +#define CAMDMA_CSDP_DATA_TYPE (3 << 0) +#define CAMDMA_CSDP_DATA_TYPE_8BITS (0 << 0) +#define CAMDMA_CSDP_DATA_TYPE_16BITS (1 << 0) +#define CAMDMA_CSDP_DATA_TYPE_32BITS (2 << 0) + +#define CAMMMU_SYSCONFIG_AUTOIDLE (1 << 0) + +/* + * + * Declarations. + * + */ + +/* forward declarations */ +struct omap24xxcam_sgdma; +struct omap24xxcam_dma; + +typedef void (*sgdma_callback_t)(struct omap24xxcam_sgdma *cam, + u32 status, void *arg); +typedef void (*dma_callback_t)(struct omap24xxcam_dma *cam, + u32 status, void *arg); + +struct channel_state { + dma_callback_t callback; + void *arg; +}; + +/* sgdma state for each of the possible videobuf_buffers + 2 overlays */ +struct sgdma_state { + const struct scatterlist *sglist; + int sglen; /* number of sglist entries */ + int next_sglist; /* index of next sglist entry to process */ + unsigned int bytes_read; /* number of bytes read */ + unsigned int len; /* total length of sglist (excluding + * bytes due to page alignment) */ + int queued_sglist; /* number of sglist entries queued for DMA */ + u32 csr; /* DMA return code */ + sgdma_callback_t callback; + void *arg; +}; + +/* physical DMA channel management */ +struct omap24xxcam_dma { + spinlock_t lock; /* Lock for the whole structure. */ + + unsigned long base; /* base address for dma controller */ + + /* While dma_stop!=0, an attempt to start a new DMA transfer will + * fail. + */ + atomic_t dma_stop; + int free_dmach; /* number of dma channels free */ + int next_dmach; /* index of next dma channel to use */ + struct channel_state ch_state[NUM_CAMDMA_CHANNELS]; +}; + +/* scatter-gather DMA (scatterlist stuff) management */ +struct omap24xxcam_sgdma { + struct omap24xxcam_dma dma; + + spinlock_t lock; /* Lock for the fields below. */ + int free_sgdma; /* number of free sg dma slots */ + int next_sgdma; /* index of next sg dma slot to use */ + struct sgdma_state sg_state[NUM_SG_DMA]; + + /* Reset timer data */ + struct timer_list reset_timer; +}; + +/* per-device data structure */ +struct omap24xxcam_device { + /*** mutex ***/ + /* + * mutex serialises access to this structure. Also camera + * opening and releasing is synchronised by this. + */ + struct mutex mutex; + + /*** general driver state information ***/ + atomic_t users; + /* + * Lock to serialise core enabling and disabling and access to + * sgdma_in_queue. + */ + spinlock_t core_enable_disable_lock; + /* + * Number or sgdma requests in scatter-gather queue, protected + * by the lock above. + */ + int sgdma_in_queue; + /* + * Sensor interface parameters: interface type, CC_CTRL + * register value and interface specific data. + */ + int if_type; + union { + struct parallel { + u32 xclk; + } bt656; + } if_u; + u32 cc_ctrl; + + /*** subsystem structures ***/ + struct omap24xxcam_sgdma sgdma; + + /*** hardware resources ***/ + unsigned int irq; + unsigned long mmio_base; + unsigned long mmio_base_phys; + unsigned long mmio_size; + + /*** interfaces and device ***/ + struct v4l2_int_device *sdev; + struct device *dev; + struct video_device *vfd; + + /*** camera and sensor reset related stuff ***/ + struct work_struct sensor_reset_work; + /* + * We're in the middle of a reset. Don't enable core if this + * is non-zero! This exists to help decisionmaking in a case + * where videobuf_qbuf is called while we are in the middle of + * a reset. + */ + atomic_t in_reset; + /* + * Non-zero if we don't want any resets for now. Used to + * prevent reset work to run when we're about to stop + * streaming. + */ + atomic_t reset_disable; + + /*** video device parameters ***/ + int capture_mem; + + /*** camera module clocks ***/ + struct clk *fck; + struct clk *ick; + + /*** capture data ***/ + /* file handle, if streaming is on */ + struct file *streaming; +}; + +/* Per-file handle data. */ +struct omap24xxcam_fh { + spinlock_t vbq_lock; /* spinlock for the videobuf queue */ + struct videobuf_queue vbq; + struct v4l2_pix_format pix; /* serialise pix by vbq->lock */ + atomic_t field_count; /* field counter for videobuf_buffer */ + /* accessing cam here doesn't need serialisation: it's constant */ + struct omap24xxcam_device *cam; +}; + +/* + * + * Register I/O functions. + * + */ + +static inline u32 omap24xxcam_reg_in(unsigned long base, u32 offset) +{ + return readl(base + offset); +} + +static inline u32 omap24xxcam_reg_out(unsigned long base, u32 offset, + u32 val) +{ + writel(val, base + offset); + return val; +} + +static inline u32 omap24xxcam_reg_merge(unsigned long base, u32 offset, + u32 val, u32 mask) +{ + u32 addr = base + offset; + u32 new_val = (readl(addr) & ~mask) | (val & mask); + + writel(new_val, addr); + return new_val; +} + +/* + * + * Function prototypes. + * + */ + +/* dma prototypes */ + +void omap24xxcam_dma_hwinit(struct omap24xxcam_dma *dma); +void omap24xxcam_dma_isr(struct omap24xxcam_dma *dma); + +/* sgdma prototypes */ + +void omap24xxcam_sgdma_process(struct omap24xxcam_sgdma *sgdma); +int omap24xxcam_sgdma_queue(struct omap24xxcam_sgdma *sgdma, + const struct scatterlist *sglist, int sglen, + int len, sgdma_callback_t callback, void *arg); +void omap24xxcam_sgdma_sync(struct omap24xxcam_sgdma *sgdma); +void omap24xxcam_sgdma_init(struct omap24xxcam_sgdma *sgdma, + unsigned long base, + void (*reset_callback)(unsigned long data), + unsigned long reset_callback_data); +void omap24xxcam_sgdma_exit(struct omap24xxcam_sgdma *sgdma); + +#endif -- cgit v1.2.3 From dc1b57bb7e3d558107e4706599fa76dcb3165977 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 1 Dec 2008 22:01:04 -0200 Subject: em28xx: Add specific entry for WinTV-HVR 850 From: Douglas Schilling Landgraf Added specific entry for WinTV-HVR 850 Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/Documentation/video4linux/CARDLIST.em28xx | 3 ++- linux/drivers/media/video/em28xx/em28xx-cards.c | 32 +++++++++++++++++++++++-- linux/drivers/media/video/em28xx/em28xx-dvb.c | 1 + linux/drivers/media/video/em28xx/em28xx.h | 1 + 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index ea537f5ae..a6734eb7b 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -14,7 +14,7 @@ 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) [eb1a:2821] 15 -> V-Gear PocketTV (em2800) - 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b,2040:651f] + 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b] 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227] 18 -> Hauppauge WinTV HVR 900 (R2) (em2880) [2040:6502] 19 -> PointNix Intra-Oral Camera (em2860) @@ -58,3 +58,4 @@ 57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316] 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] 59 -> Pinnacle PCTV HD Mini (em2874) [2304:023f] + 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index d38b3ba72..2ecc98af7 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -687,6 +687,32 @@ struct em28xx_board em28xx_boards[] = { .gpio = hauppauge_wintv_hvr_900_analog, } }, }, + [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850] = { + .name = "Hauppauge WinTV HVR 850", + .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, + .mts_firmware = 1, + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, + .ir_codes = ir_codes_hauppauge_new, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, + } }, + }, [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = { .name = "Hauppauge WinTV HVR 950", .tuner_type = TUNER_XC2028, @@ -1354,8 +1380,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, { USB_DEVICE(0x2040, 0x651b), /* RP HVR-950 */ .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, - { USB_DEVICE(0x2040, 0x651f), /* HCW HVR-850 */ - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, + { USB_DEVICE(0x2040, 0x651f), + .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, { USB_DEVICE(0x0438, 0xb002), .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, { USB_DEVICE(0x2001, 0xf112), @@ -1575,6 +1601,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ctl->demod = XC3028_FE_DEFAULT; ctl->fname = XC3028L_DEFAULT_FIRMWARE; break; + case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: /* FIXME: Better to specify the needed IF */ @@ -1759,6 +1786,7 @@ void em28xx_card_setup(struct em28xx *dev) case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: + case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: { struct tveeprom tv; diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index a06659f28..ddc4f6a99 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -410,6 +410,7 @@ static int dvb_init(struct em28xx *dev) em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { + case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 667cb70cf..4de9a8190 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -99,6 +99,7 @@ #define EM2883_BOARD_KWORLD_HYBRID_A316 57 #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 #define EM2874_BOARD_PINNACLE_PCTV_80E 59 +#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From ce9193f864e672d15847eac5e1c86e9c4094904d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 2 Dec 2008 10:56:47 +0100 Subject: gspca: Add the webcam 0c45:613a in the gspca documentation. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index 8d0210b24..acf6c9f8e 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -257,6 +257,7 @@ sonixj 0c45:612a Avant Camera sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix sonixj 0c45:6130 Sonix Pccam sonixj 0c45:6138 Sn9c120 Mo4000 +sonixj 0c45:613a Microdia Sonix PC Camera sonixj 0c45:613b Surfer SN-206 sonixj 0c45:613c Sonix Pccam168 sonixj 0c45:6143 Sonix Pccam168 -- cgit v1.2.3 From 18a1649ef4ce188d4f62e37be85055bdfa5d6c97 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 2 Dec 2008 10:58:57 +0100 Subject: gspca: Bad color control in sonixj. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index fb8b42daf..a0ff265cd 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1220,17 +1220,17 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i, v; - __u8 rega0[12]; /* U & V gains */ + __u8 reg8a[12]; /* U & V gains */ static __s16 uv[6] = { /* same as reg84 in signed decimal */ -24, -38, 64, /* UR UG UB */ 62, -51, -9 /* VR VG VB */ }; for (i = 0; i < 6; i++) { v = uv[i] * sd->colors / COLOR_DEF; - rega0[i * 2] = v; - rega0[i * 2 + 1] = (v >> 8) & 0x0f; + reg8a[i * 2] = v; + reg8a[i * 2 + 1] = (v >> 8) & 0x0f; } - reg_w(gspca_dev, 0x84, rega0, sizeof rega0); + reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a); } static void setredblue(struct gspca_dev *gspca_dev) -- cgit v1.2.3 From b999679a2733164c8241db55370190c699fd55fd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 2 Dec 2008 19:00:57 +0100 Subject: gspca: Fix image problem at low resolutions with ov7660 in sonixj. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index a0ff265cd..368382cf7 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1394,19 +1394,15 @@ static int sd_start(struct gspca_dev *gspca_dev) default: /* case SENSOR_OV7660: */ ov7660_InitSensor(gspca_dev); - if (mode) { -/* reg17 = 0x21; * 320 */ -/* reg1 = 0x44; */ -/* reg1 = 0x46; (done) */ - } else { /* 640 */ - if (sd->bridge == BRIDGE_SN9C120) { + if (sd->bridge == BRIDGE_SN9C120) { + if (mode) { /* 320x240 - 160x120 */ reg17 = 0xa2; reg1 = 0x44; /* 48 Mhz, video trf eneble */ - } else { - reg17 = 0x22; - reg1 = 0x06; /* 24 Mhz, video trf eneble - * inverse power down */ } + } else { + reg17 = 0x22; + reg1 = 0x06; /* 24 Mhz, video trf eneble + * inverse power down */ } break; } -- cgit v1.2.3 From 5be2df264845a545c345c924c23153459140a308 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 2 Dec 2008 22:34:52 +0000 Subject: drivers/media/video/cx88/cx88-alsa.c: Adjust error-handling code From: Julia Lawall In the function cx88_audio_initdev, the value card has been created using snd_card_new. The other error handling code in this function frees the value using snd_card_free. I have thus changed the first error case to do the same. On the other hand, it may be that card is not sufficiently initialized at this point to use snd_card_free, in which case something else should be done to free the memory in the error case. In the function snd_cx88_create the call kfree(chip) in one error case looks suspicious, both because it is not done in the other error code, and because chip points into the middle of the memory allocated by snd_card_new, ie it is not itself associated with a separate kmalloc. Therefore I have removed it. The semantic match that finds the first problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S,S1; position p1,p2,p3; expression E,E1; type T,T1; expression *ptr != NULL; @@ ( if ((x@p1 = snd_card_new(...)) == NULL) S | x@p1 = snd_card_new(...); ) ... when != snd_card_free(...,(T)x,...) when != if (...) { <+... snd_card_free(...,(T)x,...) ...+> } when != true x == NULL || ... when != x = E when != E = (T)x when any ( if (x == NULL || ...) S1 | if@p2 (...) { ... when != snd_card_free(...,(T1)x,...) when != if (...) { <+... snd_card_free(...,(T1)x,...) ...+> } when != x = E1 when != E1 = (T1)x ( return \(0\|<+...x...+>\|ptr\); | return@p3 ...; ) } ) @ script:python @ p1 << r.p1; p3 << r.p3; @@ print "* file: %s snd_card_new: %s return: %s" % (p1[0].file,p1[0].line,p3[0].line) // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-alsa.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index 3dd2f6629..f7171586d 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -795,7 +795,6 @@ static int __devinit snd_cx88_create(struct snd_card *card, core = cx88_core_get(pci); if (NULL == core) { err = -EINVAL; - kfree (chip); return err; } @@ -872,7 +871,7 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, err = snd_cx88_create(card, pci, &chip); if (err < 0) - return (err); + goto error; err = snd_cx88_pcm(chip, 0, "CX88 Digital"); if (err < 0) -- cgit v1.2.3 From 26a19b1a88a4f99ab366bfd80734b34453b35a8b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Dec 2008 11:19:22 +0100 Subject: gspca: Webcam 093a:2622 added in pac7311. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/pac7311.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index acf6c9f8e..72d31bd64 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -217,6 +217,7 @@ pac7311 093a:2608 Trust WB-3300p pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 pac7311 093a:260f SnakeCam pac7311 093a:2621 PAC731x +pac7311 093a:2622 Genius Eye 312 pac7311 093a:2624 PAC7302 pac7311 093a:2626 Labtec 2200 pac7311 093a:262a Webcam 300k diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index f443df77e..b0a9d0687 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -1079,6 +1079,7 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, + {USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302}, -- cgit v1.2.3 From 21f9b7166963112dcef346971b1ba1df42014c79 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Dec 2008 11:29:26 +0100 Subject: gspca: Add the webcam 0c45:60fe in the gspca documentation. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index 72d31bd64..a38c87246 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -253,6 +253,7 @@ sonixj 0c45:60c0 Sangha Sn535 sonixj 0c45:60ec SN9C105+MO4000 sonixj 0c45:60fb Surfer NoName sonixj 0c45:60fc LG-LIC300 +sonixj 0c45:60fe Microdia Audio sonixj 0c45:6128 Microdia/Sonix SNP325 sonixj 0c45:612a Avant Camera sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix -- cgit v1.2.3 From 5b67d9e00e803d51963fb07cd32160f3314abfaa Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Dec 2008 18:01:54 +0100 Subject: gspca: Simplify frame rate setting and debug in ov534. From: Antonio Ospite Priority: normal Signed-off-by: Antonio Ospite Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index a574be09b..b26faae8d 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -48,7 +48,6 @@ static int frame_rate; /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u8 frame_rate; }; /* V4L2 controls supported by the driver */ @@ -358,45 +357,38 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *)gspca_dev; - ov534_setup(gspca_dev->dev); + int fr; - if (frame_rate > 0) - sd->frame_rate = frame_rate; + ov534_setup(gspca_dev->dev); - PDEBUG(D_PROBE, "frame_rate = %d", sd->frame_rate); + fr = frame_rate; - switch (sd->frame_rate) { + switch (fr) { case 50: sccb_reg_write(gspca_dev->dev, 0x11, 0x01); - sccb_check_status(gspca_dev->dev); sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); - sccb_check_status(gspca_dev->dev); ov534_reg_verify_write(gspca_dev->dev, 0xe5, 0x02); break; case 40: sccb_reg_write(gspca_dev->dev, 0x11, 0x02); - sccb_check_status(gspca_dev->dev); sccb_reg_write(gspca_dev->dev, 0x0d, 0xc1); - sccb_check_status(gspca_dev->dev); ov534_reg_verify_write(gspca_dev->dev, 0xe5, 0x04); break; - case 30: +/* case 30: */ default: + fr = 30; sccb_reg_write(gspca_dev->dev, 0x11, 0x04); - sccb_check_status(gspca_dev->dev); sccb_reg_write(gspca_dev->dev, 0x0d, 0x81); - sccb_check_status(gspca_dev->dev); ov534_reg_verify_write(gspca_dev->dev, 0xe5, 0x02); break; case 15: sccb_reg_write(gspca_dev->dev, 0x11, 0x03); - sccb_check_status(gspca_dev->dev); sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); - sccb_check_status(gspca_dev->dev); ov534_reg_verify_write(gspca_dev->dev, 0xe5, 0x04); break; - }; + } + + PDEBUG(D_PROBE, "frame_rate: %d", fr); return 0; } -- cgit v1.2.3 From ae07805bc9b851fe075b043bd085d234a7c786fb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Dec 2008 18:10:01 +0100 Subject: gspca: Use u8 values for USB control messages in ov534. From: Antonio Ospite Priority: normal Signed-off-by: Antonio Ospite Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index b26faae8d..530f0b712 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -62,12 +62,12 @@ static struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; -static void ov534_reg_write(struct usb_device *udev, u16 reg, u16 val) +static void ov534_reg_write(struct usb_device *udev, u16 reg, u8 val) { - u16 data = val; + u8 data = val; int ret; - PDEBUG(D_USBO, "reg=0x%04x, val=0%04x", reg, val); + PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val); ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x1, @@ -77,9 +77,9 @@ static void ov534_reg_write(struct usb_device *udev, u16 reg, u16 val) PDEBUG(D_ERR, "write failed"); } -static u16 ov534_reg_read(struct usb_device *udev, u16 reg) +static u8 ov534_reg_read(struct usb_device *udev, u16 reg) { - u16 data; + u8 data; int ret; ret = usb_control_msg(udev, @@ -87,21 +87,21 @@ static u16 ov534_reg_read(struct usb_device *udev, u16 reg) 0x1, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0, reg, &data, 1, CTRL_TIMEOUT); - PDEBUG(D_USBI, "reg=0x%04x, data=0x%04x", reg, data); + PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, data); if (ret < 0) PDEBUG(D_ERR, "read failed"); return data; } -static void ov534_reg_verify_write(struct usb_device *udev, u16 reg, u16 val) +static void ov534_reg_verify_write(struct usb_device *udev, u16 reg, u8 val) { - u16 data; + u8 data; ov534_reg_write(udev, reg, val); data = ov534_reg_read(udev, reg); if (data != val) { PDEBUG(D_ERR | D_USBO, - "unexpected result from read: 0x%04x != 0x%04x", val, + "unexpected result from read: 0x%02x != 0x%02x", val, data); } } @@ -110,7 +110,7 @@ static void ov534_reg_verify_write(struct usb_device *udev, u16 reg, u16 val) * (direction and output)? */ static void ov534_set_led(struct usb_device *udev, int status) { - u16 data; + u8 data; PDEBUG(D_CONF, "led status: %d", status); @@ -129,13 +129,13 @@ static void ov534_set_led(struct usb_device *udev, int status) static int sccb_check_status(struct usb_device *udev) { - u16 data; + u8 data; int i; for (i = 0; i < 5; i++) { data = ov534_reg_read(udev, OV534_REG_STATUS); - switch (data & 0xFF) { + switch (data) { case 0x00: return 1; case 0x04: @@ -150,9 +150,9 @@ static int sccb_check_status(struct usb_device *udev) return 0; } -static void sccb_reg_write(struct usb_device *udev, u16 reg, u16 val) +static void sccb_reg_write(struct usb_device *udev, u16 reg, u8 val) { - PDEBUG(D_USBO, "reg: 0x%04x, val: 0x%04x", reg, val); + PDEBUG(D_USBO, "reg: 0x%04x, val: 0x%02x", reg, val); ov534_reg_write(udev, OV534_REG_SUBADDR, reg); ov534_reg_write(udev, OV534_REG_WRITE, val); ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_WRITE_3); -- cgit v1.2.3 From c1e15caf1b787cceea76c8a1868516001f1e4588 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Dec 2008 20:21:08 +0100 Subject: gspca: Use smaller chunks for urb buffer in ov534. From: Antonio Ospite Priority: normal Signed-off-by: Antonio Ospite Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 51 ++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 530f0b712..f86158dd1 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -346,7 +346,14 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - cam->bulk_size = vga_mode[0].sizeimage; + /* + * On some architectures we need contiguous memory for urb buffers, and + * in low memory situation 'sizeimage' can be too much. + * 16kiB chunks should be available even when we are low in memory. + * TODO: CHECK this description: is the problem arch-dependent or more + * general? + */ + cam->bulk_size = 16 * 1024; cam->bulk_nurbs = 2; PDEBUG(D_PROBE, "bulk_size = %d", cam->bulk_size); @@ -395,15 +402,19 @@ static int sd_init(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { - PDEBUG(D_PROBE, "width = %d, height = %d", - gspca_dev->width, gspca_dev->height); - - gspca_dev->cam.bulk_size = gspca_dev->width * gspca_dev->height * 2; + struct gspca_frame *frame; /* start streaming data */ ov534_set_led(gspca_dev->dev, 1); ov534_reg_write(gspca_dev->dev, 0xe0, 0x00); + frame = gspca_get_i_frame(gspca_dev); + if (frame == NULL) { + PDEBUG(D_ERR, "NULL frame!"); + return -1; + } + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, gspca_dev->usb_buf, 0); + return 0; } @@ -421,18 +432,26 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, * The current camera setup doesn't stream the last pixel, so we set it * to a dummy value */ - __u8 last_pixel[4] = { 0, 0, 0, 0 }; - int framesize = gspca_dev->cam.bulk_size; - - if (len == framesize - 4) { - frame = - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); - frame = - gspca_frame_add(gspca_dev, LAST_PACKET, frame, last_pixel, - 4); + __u8 last[4] = { 0, 0, 0, 0 }; + int framesize = frame->v4l2_buf.length; + + PDEBUG(D_PACK, ""); + PDEBUG(D_PACK, "** packet len = %d, framesize = %d", len, framesize); + PDEBUG(D_PACK, "** frame->data_end - frame->data + len = %d", + frame->data_end - frame->data + len); + +#if 0 + /* Can this check mask some tranfer errors? */ + if (len < gspca_dev->cam.bulk_size) { +#else + if (frame->data_end - frame->data + len == framesize - 4) { +#endif + PDEBUG(D_PACK, " end of frame!"); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, last, 4); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); } else - PDEBUG(D_PACK, "packet len = %d, framesize = %d", len, - framesize); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } /* sub-driver description */ -- cgit v1.2.3 From a31709b99b19630a583553b1b0dd95f862579258 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 4 Dec 2008 08:28:27 +0100 Subject: gspca - ov534: Initialization cleanup. From: Jim Paris Priority: normal Signed-off-by: Jim Paris Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 337 +++++++++++++++----------------- 1 file changed, 159 insertions(+), 178 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index f86158dd1..f0b096612 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -93,19 +93,6 @@ static u8 ov534_reg_read(struct usb_device *udev, u16 reg) return data; } -static void ov534_reg_verify_write(struct usb_device *udev, u16 reg, u8 val) -{ - u8 data; - - ov534_reg_write(udev, reg, val); - data = ov534_reg_read(udev, reg); - if (data != val) { - PDEBUG(D_ERR | D_USBO, - "unexpected result from read: 0x%02x != 0x%02x", val, - data); - } -} - /* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. * (direction and output)? */ static void ov534_set_led(struct usb_device *udev, int status) @@ -161,174 +148,168 @@ static void sccb_reg_write(struct usb_device *udev, u16 reg, u8 val) PDEBUG(D_ERR, "sccb_reg_write failed"); } -/* setup method */ -static void ov534_setup(struct usb_device *udev) -{ - ov534_reg_verify_write(udev, 0xe7, 0x3a); - - ov534_reg_write(udev, OV534_REG_ADDRESS, 0x60); - ov534_reg_write(udev, OV534_REG_ADDRESS, 0x60); - ov534_reg_write(udev, OV534_REG_ADDRESS, 0x60); - ov534_reg_write(udev, OV534_REG_ADDRESS, 0x42); - - ov534_reg_verify_write(udev, 0xc2, 0x0c); - ov534_reg_verify_write(udev, 0x88, 0xf8); - ov534_reg_verify_write(udev, 0xc3, 0x69); - ov534_reg_verify_write(udev, 0x89, 0xff); - ov534_reg_verify_write(udev, 0x76, 0x03); - ov534_reg_verify_write(udev, 0x92, 0x01); - ov534_reg_verify_write(udev, 0x93, 0x18); - ov534_reg_verify_write(udev, 0x94, 0x10); - ov534_reg_verify_write(udev, 0x95, 0x10); - ov534_reg_verify_write(udev, 0xe2, 0x00); - ov534_reg_verify_write(udev, 0xe7, 0x3e); - - ov534_reg_write(udev, 0x1c, 0x0a); - ov534_reg_write(udev, 0x1d, 0x22); - ov534_reg_write(udev, 0x1d, 0x06); - - ov534_reg_verify_write(udev, 0x96, 0x00); - - ov534_reg_write(udev, 0x97, 0x20); - ov534_reg_write(udev, 0x97, 0x20); - ov534_reg_write(udev, 0x97, 0x20); - ov534_reg_write(udev, 0x97, 0x0a); - ov534_reg_write(udev, 0x97, 0x3f); - ov534_reg_write(udev, 0x97, 0x4a); - ov534_reg_write(udev, 0x97, 0x20); - ov534_reg_write(udev, 0x97, 0x15); - ov534_reg_write(udev, 0x97, 0x0b); - - ov534_reg_verify_write(udev, 0x8e, 0x40); - ov534_reg_verify_write(udev, 0x1f, 0x81); - ov534_reg_verify_write(udev, 0x34, 0x05); - ov534_reg_verify_write(udev, 0xe3, 0x04); - ov534_reg_verify_write(udev, 0x88, 0x00); - ov534_reg_verify_write(udev, 0x89, 0x00); - ov534_reg_verify_write(udev, 0x76, 0x00); - ov534_reg_verify_write(udev, 0xe7, 0x2e); - ov534_reg_verify_write(udev, 0x31, 0xf9); - ov534_reg_verify_write(udev, 0x25, 0x42); - ov534_reg_verify_write(udev, 0x21, 0xf0); - - ov534_reg_write(udev, 0x1c, 0x00); - ov534_reg_write(udev, 0x1d, 0x40); - ov534_reg_write(udev, 0x1d, 0x02); - ov534_reg_write(udev, 0x1d, 0x00); - ov534_reg_write(udev, 0x1d, 0x02); - ov534_reg_write(udev, 0x1d, 0x57); - ov534_reg_write(udev, 0x1d, 0xff); - - ov534_reg_verify_write(udev, 0x8d, 0x1c); - ov534_reg_verify_write(udev, 0x8e, 0x80); - ov534_reg_verify_write(udev, 0xe5, 0x04); - - ov534_set_led(udev, 1); - - sccb_reg_write(udev, 0x12, 0x80); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x11, 0x01); - - ov534_set_led(udev, 0); - - sccb_reg_write(udev, 0x3d, 0x03); - sccb_reg_write(udev, 0x17, 0x26); - sccb_reg_write(udev, 0x18, 0xa0); - sccb_reg_write(udev, 0x19, 0x07); - sccb_reg_write(udev, 0x1a, 0xf0); - sccb_reg_write(udev, 0x32, 0x00); - sccb_reg_write(udev, 0x29, 0xa0); - sccb_reg_write(udev, 0x2c, 0xf0); - sccb_reg_write(udev, 0x65, 0x20); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x42, 0x7f); - sccb_reg_write(udev, 0x63, 0xe0); - sccb_reg_write(udev, 0x64, 0xff); - sccb_reg_write(udev, 0x66, 0x00); - sccb_reg_write(udev, 0x13, 0xf0); - sccb_reg_write(udev, 0x0d, 0x41); - sccb_reg_write(udev, 0x0f, 0xc5); - sccb_reg_write(udev, 0x14, 0x11); - - ov534_set_led(udev, 1); - - sccb_reg_write(udev, 0x22, 0x7f); - sccb_reg_write(udev, 0x23, 0x03); - sccb_reg_write(udev, 0x24, 0x40); - sccb_reg_write(udev, 0x25, 0x30); - sccb_reg_write(udev, 0x26, 0xa1); - sccb_reg_write(udev, 0x2a, 0x00); - sccb_reg_write(udev, 0x2b, 0x00); - sccb_reg_write(udev, 0x6b, 0xaa); - sccb_reg_write(udev, 0x13, 0xff); +static const __u8 ov534_reg_initdata[][2] = { + { 0xe7, 0x3a }, + + { OV534_REG_ADDRESS, 0x42 }, /* select OV772x sensor */ + + { 0xc2, 0x0c }, + { 0x88, 0xf8 }, + { 0xc3, 0x69 }, + { 0x89, 0xff }, + { 0x76, 0x03 }, + { 0x92, 0x01 }, + { 0x93, 0x18 }, + { 0x94, 0x10 }, + { 0x95, 0x10 }, + { 0xe2, 0x00 }, + { 0xe7, 0x3e }, + + { 0x1c, 0x0a }, + { 0x1d, 0x22 }, + { 0x1d, 0x06 }, + + { 0x96, 0x00 }, + + { 0x97, 0x20 }, + { 0x97, 0x20 }, + { 0x97, 0x20 }, + { 0x97, 0x0a }, + { 0x97, 0x3f }, + { 0x97, 0x4a }, + { 0x97, 0x20 }, + { 0x97, 0x15 }, + { 0x97, 0x0b }, + + { 0x8e, 0x40 }, + { 0x1f, 0x81 }, + { 0x34, 0x05 }, + { 0xe3, 0x04 }, + { 0x88, 0x00 }, + { 0x89, 0x00 }, + { 0x76, 0x00 }, + { 0xe7, 0x2e }, + { 0x31, 0xf9 }, + { 0x25, 0x42 }, + { 0x21, 0xf0 }, + + { 0x1c, 0x00 }, + { 0x1d, 0x40 }, + { 0x1d, 0x02 }, + { 0x1d, 0x00 }, + { 0x1d, 0x02 }, + { 0x1d, 0x57 }, + { 0x1d, 0xff }, + + { 0x8d, 0x1c }, + { 0x8e, 0x80 }, + { 0xe5, 0x04 }, + + { 0xc0, 0x50 }, + { 0xc1, 0x3c }, + { 0xc2, 0x0c }, +}; - ov534_set_led(udev, 0); +static const __u8 ov772x_reg_initdata[][2] = { + { 0x12, 0x80 }, + { 0x11, 0x01 }, + + { 0x3d, 0x03 }, + { 0x17, 0x26 }, + { 0x18, 0xa0 }, + { 0x19, 0x07 }, + { 0x1a, 0xf0 }, + { 0x32, 0x00 }, + { 0x29, 0xa0 }, + { 0x2c, 0xf0 }, + { 0x65, 0x20 }, + { 0x11, 0x01 }, + { 0x42, 0x7f }, + { 0x63, 0xe0 }, + { 0x64, 0xff }, + { 0x66, 0x00 }, + { 0x13, 0xf0 }, + { 0x0d, 0x41 }, + { 0x0f, 0xc5 }, + { 0x14, 0x11 }, + + { 0x22, 0x7f }, + { 0x23, 0x03 }, + { 0x24, 0x40 }, + { 0x25, 0x30 }, + { 0x26, 0xa1 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x6b, 0xaa }, + { 0x13, 0xff }, + + { 0x90, 0x05 }, + { 0x91, 0x01 }, + { 0x92, 0x03 }, + { 0x93, 0x00 }, + { 0x94, 0x60 }, + { 0x95, 0x3c }, + { 0x96, 0x24 }, + { 0x97, 0x1e }, + { 0x98, 0x62 }, + { 0x99, 0x80 }, + { 0x9a, 0x1e }, + { 0x9b, 0x08 }, + { 0x9c, 0x20 }, + { 0x9e, 0x81 }, + + { 0xa6, 0x04 }, + { 0x7e, 0x0c }, + { 0x7f, 0x16 }, + { 0x80, 0x2a }, + { 0x81, 0x4e }, + { 0x82, 0x61 }, + { 0x83, 0x6f }, + { 0x84, 0x7b }, + { 0x85, 0x86 }, + { 0x86, 0x8e }, + { 0x87, 0x97 }, + { 0x88, 0xa4 }, + { 0x89, 0xaf }, + { 0x8a, 0xc5 }, + { 0x8b, 0xd7 }, + { 0x8c, 0xe8 }, + { 0x8d, 0x20 }, + + { 0x0c, 0x90 }, + + { 0x2b, 0x00 }, + { 0x22, 0x7f }, + { 0x23, 0x03 }, + { 0x11, 0x01 }, + { 0x0c, 0xd0 }, + { 0x64, 0xff }, + { 0x0d, 0x41 }, + + { 0x14, 0x41 }, + { 0x0e, 0xcd }, + { 0xac, 0xbf }, + { 0x8e, 0x00 }, + { 0x0c, 0xd0 } +}; - sccb_reg_write(udev, 0x90, 0x05); - sccb_reg_write(udev, 0x91, 0x01); - sccb_reg_write(udev, 0x92, 0x03); - sccb_reg_write(udev, 0x93, 0x00); - sccb_reg_write(udev, 0x94, 0x60); - sccb_reg_write(udev, 0x95, 0x3c); - sccb_reg_write(udev, 0x96, 0x24); - sccb_reg_write(udev, 0x97, 0x1e); - sccb_reg_write(udev, 0x98, 0x62); - sccb_reg_write(udev, 0x99, 0x80); - sccb_reg_write(udev, 0x9a, 0x1e); - sccb_reg_write(udev, 0x9b, 0x08); - sccb_reg_write(udev, 0x9c, 0x20); - sccb_reg_write(udev, 0x9e, 0x81); - ov534_set_led(udev, 1); +/* setup method */ +static void ov534_setup(struct usb_device *udev) +{ + int i; - sccb_reg_write(udev, 0xa6, 0x04); - sccb_reg_write(udev, 0x7e, 0x0c); - sccb_reg_write(udev, 0x7f, 0x16); - sccb_reg_write(udev, 0x80, 0x2a); - sccb_reg_write(udev, 0x81, 0x4e); - sccb_reg_write(udev, 0x82, 0x61); - sccb_reg_write(udev, 0x83, 0x6f); - sccb_reg_write(udev, 0x84, 0x7b); - sccb_reg_write(udev, 0x85, 0x86); - sccb_reg_write(udev, 0x86, 0x8e); - sccb_reg_write(udev, 0x87, 0x97); - sccb_reg_write(udev, 0x88, 0xa4); - sccb_reg_write(udev, 0x89, 0xaf); - sccb_reg_write(udev, 0x8a, 0xc5); - sccb_reg_write(udev, 0x8b, 0xd7); - sccb_reg_write(udev, 0x8c, 0xe8); - sccb_reg_write(udev, 0x8d, 0x20); - - sccb_reg_write(udev, 0x0c, 0x90); - - ov534_reg_verify_write(udev, 0xc0, 0x50); - ov534_reg_verify_write(udev, 0xc1, 0x3c); - ov534_reg_verify_write(udev, 0xc2, 0x0c); + /* Initialize bridge chip */ + for (i = 0; i < ARRAY_SIZE(ov534_reg_initdata); i++) + ov534_reg_write(udev, ov534_reg_initdata[i][0], + ov534_reg_initdata[i][1]); ov534_set_led(udev, 1); - sccb_reg_write(udev, 0x2b, 0x00); - sccb_reg_write(udev, 0x22, 0x7f); - sccb_reg_write(udev, 0x23, 0x03); - sccb_reg_write(udev, 0x11, 0x01); - sccb_reg_write(udev, 0x0c, 0xd0); - sccb_reg_write(udev, 0x64, 0xff); - sccb_reg_write(udev, 0x0d, 0x41); - - sccb_reg_write(udev, 0x14, 0x41); - sccb_reg_write(udev, 0x0e, 0xcd); - sccb_reg_write(udev, 0xac, 0xbf); - sccb_reg_write(udev, 0x8e, 0x00); - sccb_reg_write(udev, 0x0c, 0xd0); + /* Initialize sensor */ + for (i = 0; i < ARRAY_SIZE(ov772x_reg_initdata); i++) + sccb_reg_write(udev, ov772x_reg_initdata[i][0], + ov772x_reg_initdata[i][1]); ov534_reg_write(udev, 0xe0, 0x09); ov534_set_led(udev, 0); @@ -374,24 +355,24 @@ static int sd_init(struct gspca_dev *gspca_dev) case 50: sccb_reg_write(gspca_dev->dev, 0x11, 0x01); sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); - ov534_reg_verify_write(gspca_dev->dev, 0xe5, 0x02); + ov534_reg_write(gspca_dev->dev, 0xe5, 0x02); break; case 40: sccb_reg_write(gspca_dev->dev, 0x11, 0x02); sccb_reg_write(gspca_dev->dev, 0x0d, 0xc1); - ov534_reg_verify_write(gspca_dev->dev, 0xe5, 0x04); + ov534_reg_write(gspca_dev->dev, 0xe5, 0x04); break; /* case 30: */ default: fr = 30; sccb_reg_write(gspca_dev->dev, 0x11, 0x04); sccb_reg_write(gspca_dev->dev, 0x0d, 0x81); - ov534_reg_verify_write(gspca_dev->dev, 0xe5, 0x02); + ov534_reg_write(gspca_dev->dev, 0xe5, 0x02); break; case 15: sccb_reg_write(gspca_dev->dev, 0x11, 0x03); sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); - ov534_reg_verify_write(gspca_dev->dev, 0xe5, 0x04); + ov534_reg_write(gspca_dev->dev, 0xe5, 0x04); break; } -- cgit v1.2.3 From 813bf1a92a9d665e013b0c0a52450d68af7ae80c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 4 Dec 2008 08:36:14 +0100 Subject: gspca - ov534: Fix frame size so we don't miss the last pixel. From: Jim Paris The frame size is too small, so we lose the last YUYV pixel. Fix the setup and remove the last_pixel hack. Priority: normal Signed-off-by: Jim Paris Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index f0b096612..79bb6241d 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -197,9 +197,9 @@ static const __u8 ov534_reg_initdata[][2] = { { 0x1d, 0x40 }, { 0x1d, 0x02 }, { 0x1d, 0x00 }, - { 0x1d, 0x02 }, - { 0x1d, 0x57 }, - { 0x1d, 0xff }, + { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ + { 0x1d, 0x58 }, /* frame size */ + { 0x1d, 0x00 }, /* frame size */ { 0x8d, 0x1c }, { 0x8e, 0x80 }, @@ -409,30 +409,15 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, __u8 *data, int len) { - /* - * The current camera setup doesn't stream the last pixel, so we set it - * to a dummy value - */ - __u8 last[4] = { 0, 0, 0, 0 }; int framesize = frame->v4l2_buf.length; - PDEBUG(D_PACK, ""); - PDEBUG(D_PACK, "** packet len = %d, framesize = %d", len, framesize); - PDEBUG(D_PACK, "** frame->data_end - frame->data + len = %d", - frame->data_end - frame->data + len); - -#if 0 - /* Can this check mask some tranfer errors? */ - if (len < gspca_dev->cam.bulk_size) { -#else - if (frame->data_end - frame->data + len == framesize - 4) { -#endif - PDEBUG(D_PACK, " end of frame!"); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, last, 4); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); + if (len == framesize) { + frame = gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + data, len); + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); } else - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + PDEBUG(D_PACK, "packet len = %d, framesize = %d", len, + framesize); } /* sub-driver description */ -- cgit v1.2.3 From 8b10a9746fefdebe48ea6080a647adfe08be3338 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 4 Dec 2008 08:52:40 +0100 Subject: gspca - ov534: Frame transfer improvements. From: Jim Paris The indirect registers at 0x1c/0x1d control frame settings. If we leave the values at 0x0a and 0x0b at their reset-time defaults, frame data from the camera matches the UVC payload format. This lets us better reassemble the data into frames and know when data was lost. This also lets us relax the bulk_size requirement from 600K to 2K, which should help systems on with limited RAM (like the PS3). Priority: normal Signed-off-by: Jim Paris Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 103 ++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 79bb6241d..e02c8f70f 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -165,10 +165,6 @@ static const __u8 ov534_reg_initdata[][2] = { { 0xe2, 0x00 }, { 0xe7, 0x3e }, - { 0x1c, 0x0a }, - { 0x1d, 0x22 }, - { 0x1d, 0x06 }, - { 0x96, 0x00 }, { 0x97, 0x20 }, @@ -327,18 +323,9 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - /* - * On some architectures we need contiguous memory for urb buffers, and - * in low memory situation 'sizeimage' can be too much. - * 16kiB chunks should be available even when we are low in memory. - * TODO: CHECK this description: is the problem arch-dependent or more - * general? - */ - cam->bulk_size = 16 * 1024; + cam->bulk_size = 2048; cam->bulk_nurbs = 2; - PDEBUG(D_PROBE, "bulk_size = %d", cam->bulk_size); - return 0; } @@ -383,19 +370,10 @@ static int sd_init(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { - struct gspca_frame *frame; - /* start streaming data */ ov534_set_led(gspca_dev->dev, 1); ov534_reg_write(gspca_dev->dev, 0xe0, 0x00); - frame = gspca_get_i_frame(gspca_dev); - if (frame == NULL) { - PDEBUG(D_ERR, "NULL frame!"); - return -1; - } - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, gspca_dev->usb_buf, 0); - return 0; } @@ -406,18 +384,79 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ov534_set_led(gspca_dev->dev, 0); } +/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ +#define UVC_STREAM_EOH (1 << 7) +#define UVC_STREAM_ERR (1 << 6) +#define UVC_STREAM_STI (1 << 5) +#define UVC_STREAM_RES (1 << 4) +#define UVC_STREAM_SCR (1 << 3) +#define UVC_STREAM_PTS (1 << 2) +#define UVC_STREAM_EOF (1 << 1) +#define UVC_STREAM_FID (1 << 0) + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, __u8 *data, int len) { - int framesize = frame->v4l2_buf.length; - - if (len == framesize) { - frame = gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - data, len); - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); - } else - PDEBUG(D_PACK, "packet len = %d, framesize = %d", len, - framesize); + static __u32 last_pts; + __u32 this_pts; + static int last_fid; + int this_fid; + + /* Payloads are prefixed with a the UVC-style header. We + consider a frame to start when the FID toggles, or the PTS + changes. A frame ends when EOF is set, and we've received + the correct number of bytes. */ + + /* Verify UVC header. Header length is always 12 */ + if (data[0] != 12 || len < 12) { + PDEBUG(D_PACK, "bad header"); + goto discard; + } + + /* Check errors */ + if (data[1] & UVC_STREAM_ERR) { + PDEBUG(D_PACK, "payload error"); + goto discard; + } + + /* Extract PTS and FID */ + if (!(data[1] & UVC_STREAM_PTS)) { + PDEBUG(D_PACK, "PTS not present"); + goto discard; + } + this_pts = (data[5] << 24) | (data[4] << 16) | (data[3] << 8) | data[2]; + this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; + + /* If PTS or FID has changed, start a new frame. */ + if (this_pts != last_pts || this_fid != last_fid) { + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + last_pts = this_pts; + last_fid = this_fid; + } + + /* Add the data from this payload */ + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data + 12, len - 12); + + /* If this packet is marked as EOF, end the frame */ + if (data[1] & UVC_STREAM_EOF) { + last_pts = 0; + + if ((frame->data_end - frame->data) != + (gspca_dev->width * gspca_dev->height * 2)) { + PDEBUG(D_PACK, "short frame"); + goto discard; + } + + gspca_frame_add(gspca_dev, LAST_PACKET, frame, NULL, 0); + } + + /* Done */ + return; + +discard: + /* Discard data until a new frame starts. */ + gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); } /* sub-driver description */ -- cgit v1.2.3 From a9c96b1af32e0ce19b406f21d9ee63a9b6883d33 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 4 Dec 2008 09:06:08 +0100 Subject: gspca - ov534: Accept many simultaneous webcams. From: Jean-Francois Moine This patch moves the last fid and pts from static to the sd structure. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index e02c8f70f..28a798279 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -48,6 +48,8 @@ static int frame_rate; /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ + __u32 last_fid; + __u32 last_pts; }; /* V4L2 controls supported by the driver */ @@ -397,9 +399,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, __u8 *data, int len) { - static __u32 last_pts; + struct sd *sd = (struct sd *) gspca_dev; __u32 this_pts; - static int last_fid; int this_fid; /* Payloads are prefixed with a the UVC-style header. We @@ -428,10 +429,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; /* If PTS or FID has changed, start a new frame. */ - if (this_pts != last_pts || this_fid != last_fid) { + if (this_pts != sd->last_pts || this_fid != sd->last_fid) { gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); - last_pts = this_pts; - last_fid = this_fid; + sd->last_pts = this_pts; + sd->last_fid = this_fid; } /* Add the data from this payload */ @@ -440,7 +441,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* If this packet is marked as EOF, end the frame */ if (data[1] & UVC_STREAM_EOF) { - last_pts = 0; + sd->last_pts = 0; if ((frame->data_end - frame->data) != (gspca_dev->width * gspca_dev->height * 2)) { -- cgit v1.2.3 From e9548d6c7e62b32a90ad51b519844be602571b9d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Dec 2008 15:49:23 +0000 Subject: Fix stv0299 support in dw2102 USB DVB-S/S2 driver From: Igor M. Liplianin register 0x00 contains 0xa1 for STV0299 and STV0299B register 0x00 might contain 0x80 when returning from standby Signed-off-by: Igor M. Liplianin Acked-by: Sergey Silkin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dw2102.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c index 9b32c9c0a..2b8ee587b 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.c +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c @@ -672,7 +672,7 @@ static int dw2102_load_firmware(struct usb_device *dev, /* check STV0299 frontend */ dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2, DW210X_READ_MSG); - if (reset16[0] == 0xa1) { + if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) { dw2102_properties.i2c_algo = &dw2102_i2c_algo; dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach; break; -- cgit v1.2.3 From 798b92bbda5976e2ca0fca8ca21ef0c11757a244 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 5 Dec 2008 10:18:37 +0100 Subject: gspca - sonixj: Cleanup / simplify code. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 70 ++++++++++++++++---------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 368382cf7..ff94cd639 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -37,26 +37,26 @@ struct sd { atomic_t avg_lum; unsigned int exposure; - unsigned short brightness; - unsigned char contrast; - unsigned char colors; - unsigned char autogain; + __u16 brightness; + __u8 contrast; + __u8 colors; + __u8 autogain; __u8 blue; __u8 red; __u8 vflip; /* ov7630 only */ __u8 infrared; /* mi0360 only */ - signed char ag_cnt; + __s8 ag_cnt; #define AG_CNT_START 13 - char qindex; - unsigned char bridge; + __u8 qindex; + __u8 bridge; #define BRIDGE_SN9C102P 0 #define BRIDGE_SN9C105 1 #define BRIDGE_SN9C110 2 #define BRIDGE_SN9C120 3 #define BRIDGE_SN9C325 4 - char sensor; /* Type of image sensor chip */ + __u8 sensor; /* Type of image sensor chip */ #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 #define SENSOR_MO4000 2 @@ -64,7 +64,7 @@ struct sd { #define SENSOR_OV7630 4 #define SENSOR_OV7648 5 #define SENSOR_OV7660 6 - unsigned char i2c_base; + __u8 i2c_base; }; /* V4L2 controls supported by the driver */ @@ -207,6 +207,24 @@ static struct ctrl sd_ctrls[] = { }, }; +/* table of the disabled controls */ +static __u32 ctrl_dis[] = { + (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + /* SENSOR_HV7131R 0 */ + (1 << VFLIP_IDX), + /* SENSOR_MI0360 1 */ + (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + /* SENSOR_MO4000 2 */ + (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + /* SENSOR_OM6802 3 */ + (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX), + /* SENSOR_OV7630 4 */ + (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + /* SENSOR_OV7648 5 */ + (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + /* SENSOR_OV7660 6 */ +}; + static struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 160, @@ -801,8 +819,6 @@ static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg) static int probesensor(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; - i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ msleep(10); reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ @@ -814,8 +830,7 @@ static int probesensor(struct gspca_dev *gspca_dev) && gspca_dev->usb_buf[3] == 0x00 && gspca_dev->usb_buf[4] == 0x00) { PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R"); - sd->sensor = SENSOR_HV7131R; - return SENSOR_HV7131R; + return 0; } PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x", gspca_dev->usb_buf[0], gspca_dev->usb_buf[1], @@ -1030,17 +1045,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->vflip = VFLIP_DEF; sd->infrared = INFRARED_DEF; - switch (sd->sensor) { - case SENSOR_OV7630: - case SENSOR_OV7648: - case SENSOR_OV7660: - gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX); - break; - } - if (sd->sensor != SENSOR_OV7630) - gspca_dev->ctrl_dis |= (1 << VFLIP_IDX); - if (sd->sensor != SENSOR_MI0360) - gspca_dev->ctrl_dis |= (1 << INFRARED_IDX); + gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; return 0; } @@ -1048,7 +1053,6 @@ static int sd_config(struct gspca_dev *gspca_dev, static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; -/* const __u8 *sn9c1xx; */ __u8 regGpio[] = { 0x29, 0x74 }; __u8 regF1; @@ -1087,12 +1091,7 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0xf1, 0x01); -#if 1 /*jfm: from win trace*/ return 0; -#else - sn9c1xx = sn_tb[(int) sd->sensor]; - return configure_gpio(gspca_dev, sn9c1xx); -#endif } static unsigned int setexposure(struct gspca_dev *gspca_dev, @@ -1207,13 +1206,16 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 k2; - __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 }; + __u8 contrast[6]; k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10; /* 10..40 */ contrast[0] = (k2 + 1) / 2; /* red */ + contrast[1] = 0; contrast[2] = k2; /* green */ + contrast[3] = 0; contrast[4] = (k2 + 1) / 5; /* blue */ - reg_w(gspca_dev, 0x84, contrast, 6); + contrast[5] = 0; + reg_w(gspca_dev, 0x84, contrast, sizeof contrast); } static void setcolors(struct gspca_dev *gspca_dev) @@ -1386,10 +1388,6 @@ static int sd_start(struct gspca_dev *gspca_dev) ov7648_InitSensor(gspca_dev); reg17 = 0x21; /* reg1 = 0x42; * 42 - 46? */ -/* if (mode) - ; * 320x2... - else - ; * 640x... */ break; default: /* case SENSOR_OV7660: */ -- cgit v1.2.3 From b4bd1e6e9284910c01185a58e17ce30342ecfd3d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 5 Dec 2008 10:25:26 +0100 Subject: gspca - ov519: Change copyright information. From: Romain Beauxis Priority: normal Signed-off-by: Romain Beauxis Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov519.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index b18d98191..5fb519da2 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -3,7 +3,18 @@ * * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) * - * (This module is adapted from the ov51x-jpeg package) + * This module is adapted from the ov51x-jpeg package, which itself + * was adapted from the ov511 driver. + * + * Original copyright for the ov511 driver is: + * + * Copyright (c) 1999-2004 Mark W. McClelland + * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach + * + * ov51x-jpeg original copyright is: + * + * Copyright (c) 2004-2007 Romain Beauxis + * Support for OV7670 sensors was contributed by Sam Skipsey * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From 638261a778c7bf8bea3491501854038d0a524dbe Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 5 Dec 2008 14:13:40 +0100 Subject: v4l2-int-if: add three new ioctls for std handling and routing From: Vaibhav Hiremath These changes are needed for the new TVP514x driver. Priority: normal Signed-off-by: Brijesh Jadav Signed-off-by: Hardik Shah Signed-off-by: Manjunath Hadli Signed-off-by: R Sivaraj Signed-off-by: Vaibhav Hiremath Signed-off-by: Karicheri Muralidharan Signed-off-by: Hans Verkuil --- linux/include/media/v4l2-int-device.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/include/media/v4l2-int-device.h b/linux/include/media/v4l2-int-device.h index 9c2df41db..ecda3c725 100644 --- a/linux/include/media/v4l2-int-device.h +++ b/linux/include/media/v4l2-int-device.h @@ -183,6 +183,9 @@ enum v4l2_int_ioctl_num { vidioc_int_s_crop_num, vidioc_int_g_parm_num, vidioc_int_s_parm_num, + vidioc_int_querystd_num, + vidioc_int_s_std_num, + vidioc_int_s_video_routing_num, /* * @@ -284,6 +287,9 @@ V4L2_INT_WRAPPER_1(g_crop, struct v4l2_crop, *); V4L2_INT_WRAPPER_1(s_crop, struct v4l2_crop, *); V4L2_INT_WRAPPER_1(g_parm, struct v4l2_streamparm, *); V4L2_INT_WRAPPER_1(s_parm, struct v4l2_streamparm, *); +V4L2_INT_WRAPPER_1(querystd, v4l2_std_id, *); +V4L2_INT_WRAPPER_1(s_std, v4l2_std_id, *); +V4L2_INT_WRAPPER_1(s_video_routing, struct v4l2_routing, *); V4L2_INT_WRAPPER_0(dev_init); V4L2_INT_WRAPPER_0(dev_exit); -- cgit v1.2.3 From c3e98daadb06990a815e0bd027c2d578c1e2ffee Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 5 Dec 2008 14:19:36 +0100 Subject: v4l: add new tvp514x I2C video decoder driver From: Vaibhav Hiremath Priority: normal Signed-off-by: Brijesh Jadav Signed-off-by: Hardik Shah Signed-off-by: Manjunath Hadli Signed-off-by: R Sivaraj Signed-off-by: Vaibhav Hiremath Signed-off-by: Karicheri Muralidharan Signed-off-by: Hans Verkuil Reviewed-by: Hans Verkuil Reviewed-by: David Brownell --- linux/drivers/media/video/Kconfig | 11 + linux/drivers/media/video/Makefile | 1 + linux/drivers/media/video/tvp514x.c | 1569 ++++++++++++++++++++++++++++++ linux/drivers/media/video/tvp514x_regs.h | 297 ++++++ linux/include/media/tvp514x.h | 118 +++ 5 files changed, 1996 insertions(+) create mode 100644 linux/drivers/media/video/tvp514x.c create mode 100644 linux/drivers/media/video/tvp514x_regs.h create mode 100644 linux/include/media/tvp514x.h diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 91652d964..cc224744b 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -361,6 +361,17 @@ config VIDEO_SAA7191 To compile this driver as a module, choose M here: the module will be called saa7191. +config VIDEO_TVP514X + tristate "Texas Instruments TVP514x video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + This is a Video4Linux2 sensor-level driver for the TI TVP5146/47 + decoder. It is currently working with the TI OMAP3 camera + controller. + + To compile this driver as a module, choose M here: the + module will be called tvp514x. + config VIDEO_TVP5150 tristate "Texas Instruments TVP5150 video decoder" depends on VIDEO_V4L2 && I2C diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index ac147b1ae..492ab3dce 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o +obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o obj-$(CONFIG_VIDEO_CS5345) += cs5345.o diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c new file mode 100644 index 000000000..ac9aa40d0 --- /dev/null +++ b/linux/drivers/media/video/tvp514x.c @@ -0,0 +1,1569 @@ +/* + * drivers/media/video/tvp514x.c + * + * TI TVP5146/47 decoder driver + * + * Copyright (C) 2008 Texas Instruments Inc + * Author: Vaibhav Hiremath + * + * Contributors: + * Sivaraj R + * Brijesh R Jadav + * Hardik Shah + * Manjunath Hadli + * Karicheri Muralidharan + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include + +#include "tvp514x_regs.h" + +/* Module Name */ +#define TVP514X_MODULE_NAME "tvp514x" + +/* Private macros for TVP */ +#define I2C_RETRY_COUNT (5) +#define LOCK_RETRY_COUNT (5) +#define LOCK_RETRY_DELAY (200) + +/* Debug functions */ +static int debug; +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +#define dump_reg(client, reg, val) \ + do { \ + val = tvp514x_read_reg(client, reg); \ + v4l_info(client, "Reg(0x%.2X): 0x%.2X\n", reg, val); \ + } while (0) + +/** + * enum tvp514x_std - enum for supported standards + */ +enum tvp514x_std { + STD_NTSC_MJ = 0, + STD_PAL_BDGHIN, + STD_INVALID +}; + +/** + * enum tvp514x_state - enum for different decoder states + */ +enum tvp514x_state { + STATE_NOT_DETECTED, + STATE_DETECTED +}; + +/** + * struct tvp514x_std_info - Structure to store standard informations + * @width: Line width in pixels + * @height:Number of active lines + * @video_std: Value to write in REG_VIDEO_STD register + * @standard: v4l2 standard structure information + */ +struct tvp514x_std_info { + unsigned long width; + unsigned long height; + u8 video_std; + struct v4l2_standard standard; +}; + +/** + * struct tvp514x_decoded - TVP5146/47 decoder object + * @v4l2_int_device: Slave handle + * @pdata: Board specific + * @client: I2C client data + * @id: Entry from I2C table + * @ver: Chip version + * @state: TVP5146/47 decoder state - detected or not-detected + * @pix: Current pixel format + * @num_fmts: Number of formats + * @fmt_list: Format list + * @current_std: Current standard + * @num_stds: Number of standards + * @std_list: Standards list + * @route: input and output routing at chip level + */ +struct tvp514x_decoder { + struct v4l2_int_device *v4l2_int_device; + const struct tvp514x_platform_data *pdata; + struct i2c_client *client; + + struct i2c_device_id *id; + + int ver; + enum tvp514x_state state; + + struct v4l2_pix_format pix; + int num_fmts; + const struct v4l2_fmtdesc *fmt_list; + + enum tvp514x_std current_std; + int num_stds; + struct tvp514x_std_info *std_list; + + struct v4l2_routing route; +}; + +/* TVP514x default register values */ +static struct tvp514x_reg tvp514x_reg_list[] = { + {TOK_WRITE, REG_INPUT_SEL, 0x05}, /* Composite selected */ + {TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F}, + {TOK_WRITE, REG_VIDEO_STD, 0x00}, /* Auto mode */ + {TOK_WRITE, REG_OPERATION_MODE, 0x00}, + {TOK_SKIP, REG_AUTOSWITCH_MASK, 0x3F}, + {TOK_WRITE, REG_COLOR_KILLER, 0x10}, + {TOK_WRITE, REG_LUMA_CONTROL1, 0x00}, + {TOK_WRITE, REG_LUMA_CONTROL2, 0x00}, + {TOK_WRITE, REG_LUMA_CONTROL3, 0x02}, + {TOK_WRITE, REG_BRIGHTNESS, 0x80}, + {TOK_WRITE, REG_CONTRAST, 0x80}, + {TOK_WRITE, REG_SATURATION, 0x80}, + {TOK_WRITE, REG_HUE, 0x00}, + {TOK_WRITE, REG_CHROMA_CONTROL1, 0x00}, + {TOK_WRITE, REG_CHROMA_CONTROL2, 0x0E}, + {TOK_SKIP, 0x0F, 0x00}, /* Reserved */ + {TOK_WRITE, REG_COMP_PR_SATURATION, 0x80}, + {TOK_WRITE, REG_COMP_Y_CONTRAST, 0x80}, + {TOK_WRITE, REG_COMP_PB_SATURATION, 0x80}, + {TOK_SKIP, 0x13, 0x00}, /* Reserved */ + {TOK_WRITE, REG_COMP_Y_BRIGHTNESS, 0x80}, + {TOK_SKIP, 0x15, 0x00}, /* Reserved */ + {TOK_SKIP, REG_AVID_START_PIXEL_LSB, 0x55}, /* NTSC timing */ + {TOK_SKIP, REG_AVID_START_PIXEL_MSB, 0x00}, + {TOK_SKIP, REG_AVID_STOP_PIXEL_LSB, 0x25}, + {TOK_SKIP, REG_AVID_STOP_PIXEL_MSB, 0x03}, + {TOK_SKIP, REG_HSYNC_START_PIXEL_LSB, 0x00}, /* NTSC timing */ + {TOK_SKIP, REG_HSYNC_START_PIXEL_MSB, 0x00}, + {TOK_SKIP, REG_HSYNC_STOP_PIXEL_LSB, 0x40}, + {TOK_SKIP, REG_HSYNC_STOP_PIXEL_MSB, 0x00}, + {TOK_SKIP, REG_VSYNC_START_LINE_LSB, 0x04}, /* NTSC timing */ + {TOK_SKIP, REG_VSYNC_START_LINE_MSB, 0x00}, + {TOK_SKIP, REG_VSYNC_STOP_LINE_LSB, 0x07}, + {TOK_SKIP, REG_VSYNC_STOP_LINE_MSB, 0x00}, + {TOK_SKIP, REG_VBLK_START_LINE_LSB, 0x01}, /* NTSC timing */ + {TOK_SKIP, REG_VBLK_START_LINE_MSB, 0x00}, + {TOK_SKIP, REG_VBLK_STOP_LINE_LSB, 0x15}, + {TOK_SKIP, REG_VBLK_STOP_LINE_MSB, 0x00}, + {TOK_SKIP, 0x26, 0x00}, /* Reserved */ + {TOK_SKIP, 0x27, 0x00}, /* Reserved */ + {TOK_SKIP, REG_FAST_SWTICH_CONTROL, 0xCC}, + {TOK_SKIP, 0x29, 0x00}, /* Reserved */ + {TOK_SKIP, REG_FAST_SWTICH_SCART_DELAY, 0x00}, + {TOK_SKIP, 0x2B, 0x00}, /* Reserved */ + {TOK_SKIP, REG_SCART_DELAY, 0x00}, + {TOK_SKIP, REG_CTI_DELAY, 0x00}, + {TOK_SKIP, REG_CTI_CONTROL, 0x00}, + {TOK_SKIP, 0x2F, 0x00}, /* Reserved */ + {TOK_SKIP, 0x30, 0x00}, /* Reserved */ + {TOK_SKIP, 0x31, 0x00}, /* Reserved */ + {TOK_WRITE, REG_SYNC_CONTROL, 0x00}, /* HS, VS active high */ + {TOK_WRITE, REG_OUTPUT_FORMATTER1, 0x00}, /* 10-bit BT.656 */ + {TOK_WRITE, REG_OUTPUT_FORMATTER2, 0x11}, /* Enable clk & data */ + {TOK_WRITE, REG_OUTPUT_FORMATTER3, 0xEE}, /* Enable AVID & FLD */ + {TOK_WRITE, REG_OUTPUT_FORMATTER4, 0xAF}, /* Enable VS & HS */ + {TOK_WRITE, REG_OUTPUT_FORMATTER5, 0xFF}, + {TOK_WRITE, REG_OUTPUT_FORMATTER6, 0xFF}, + {TOK_WRITE, REG_CLEAR_LOST_LOCK, 0x01}, /* Clear status */ + {TOK_TERM, 0, 0}, +}; + +/* List of image formats supported by TVP5146/47 decoder + * Currently we are using 8 bit mode only, but can be + * extended to 10/20 bit mode. + */ +static const struct v4l2_fmtdesc tvp514x_fmt_list[] = { + { + .index = 0, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .flags = 0, + .description = "8-bit UYVY 4:2:2 Format", + .pixelformat = V4L2_PIX_FMT_UYVY, + }, +}; + +/* + * Supported standards - + * + * Currently supports two standards only, need to add support for rest of the + * modes, like SECAM, etc... + */ +static struct tvp514x_std_info tvp514x_std_list[] = { + /* Standard: STD_NTSC_MJ */ + [STD_NTSC_MJ] = { + .width = NTSC_NUM_ACTIVE_PIXELS, + .height = NTSC_NUM_ACTIVE_LINES, + .video_std = VIDEO_STD_NTSC_MJ_BIT, + .standard = { + .index = 0, + .id = V4L2_STD_NTSC, + .name = "NTSC", + .frameperiod = {1001, 30000}, + .framelines = 525 + }, + /* Standard: STD_PAL_BDGHIN */ + }, + [STD_PAL_BDGHIN] = { + .width = PAL_NUM_ACTIVE_PIXELS, + .height = PAL_NUM_ACTIVE_LINES, + .video_std = VIDEO_STD_PAL_BDGHIN_BIT, + .standard = { + .index = 1, + .id = V4L2_STD_PAL, + .name = "PAL", + .frameperiod = {1, 25}, + .framelines = 625 + }, + }, + /* Standard: need to add for additional standard */ +}; +/* + * Control structure for Auto Gain + * This is temporary data, will get replaced once + * v4l2_ctrl_query_fill supports it. + */ +static const struct v4l2_queryctrl tvp514x_autogain_ctrl = { + .id = V4L2_CID_AUTOGAIN, + .name = "Gain, Automatic", + .type = V4L2_CTRL_TYPE_BOOLEAN, + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, +}; + +/* + * Read a value from a register in an TVP5146/47 decoder device. + * Returns value read if successful, or non-zero (-1) otherwise. + */ +static int tvp514x_read_reg(struct i2c_client *client, u8 reg) +{ + int err; + int retry = 0; +read_again: + + err = i2c_smbus_read_byte_data(client, reg); + if (err == -1) { + if (retry <= I2C_RETRY_COUNT) { + v4l_warn(client, "Read: retry ... %d\n", retry); + retry++; + msleep_interruptible(10); + goto read_again; + } + } + + return err; +} + +/* + * Write a value to a register in an TVP5146/47 decoder device. + * Returns zero if successful, or non-zero otherwise. + */ +static int tvp514x_write_reg(struct i2c_client *client, u8 reg, u8 val) +{ + int err; + int retry = 0; +write_again: + + err = i2c_smbus_write_byte_data(client, reg, val); + if (err) { + if (retry <= I2C_RETRY_COUNT) { + v4l_warn(client, "Write: retry ... %d\n", retry); + retry++; + msleep_interruptible(10); + goto write_again; + } + } + + return err; +} + +/* + * tvp514x_write_regs : Initializes a list of TVP5146/47 registers + * if token is TOK_TERM, then entire write operation terminates + * if token is TOK_DELAY, then a delay of 'val' msec is introduced + * if token is TOK_SKIP, then the register write is skipped + * if token is TOK_WRITE, then the register write is performed + * + * reglist - list of registers to be written + * Returns zero if successful, or non-zero otherwise. + */ +static int tvp514x_write_regs(struct i2c_client *client, + const struct tvp514x_reg reglist[]) +{ + int err; + const struct tvp514x_reg *next = reglist; + + for (; next->token != TOK_TERM; next++) { + if (next->token == TOK_DELAY) { + msleep(next->val); + continue; + } + + if (next->token == TOK_SKIP) + continue; + + err = tvp514x_write_reg(client, next->reg, (u8) next->val); + if (err) { + v4l_err(client, "Write failed. Err[%d]\n", err); + return err; + } + } + return 0; +} + +/* + * tvp514x_get_current_std: + * Returns the current standard detected by TVP5146/47 + */ +static enum tvp514x_std tvp514x_get_current_std(struct tvp514x_decoder + *decoder) +{ + u8 std, std_status; + + std = tvp514x_read_reg(decoder->client, REG_VIDEO_STD); + if ((std & VIDEO_STD_MASK) == VIDEO_STD_AUTO_SWITCH_BIT) { + /* use the standard status register */ + std_status = tvp514x_read_reg(decoder->client, + REG_VIDEO_STD_STATUS); + } else + std_status = std; /* use the standard register itself */ + + switch (std_status & VIDEO_STD_MASK) { + case VIDEO_STD_NTSC_MJ_BIT: + return STD_NTSC_MJ; + + case VIDEO_STD_PAL_BDGHIN_BIT: + return STD_PAL_BDGHIN; + + default: + return STD_INVALID; + } + + return STD_INVALID; +} + +/* + * TVP5146/47 register dump function + */ +static void tvp514x_reg_dump(struct tvp514x_decoder *decoder) +{ + u8 value; + + dump_reg(decoder->client, REG_INPUT_SEL, value); + dump_reg(decoder->client, REG_AFE_GAIN_CTRL, value); + dump_reg(decoder->client, REG_VIDEO_STD, value); + dump_reg(decoder->client, REG_OPERATION_MODE, value); + dump_reg(decoder->client, REG_COLOR_KILLER, value); + dump_reg(decoder->client, REG_LUMA_CONTROL1, value); + dump_reg(decoder->client, REG_LUMA_CONTROL2, value); + dump_reg(decoder->client, REG_LUMA_CONTROL3, value); + dump_reg(decoder->client, REG_BRIGHTNESS, value); + dump_reg(decoder->client, REG_CONTRAST, value); + dump_reg(decoder->client, REG_SATURATION, value); + dump_reg(decoder->client, REG_HUE, value); + dump_reg(decoder->client, REG_CHROMA_CONTROL1, value); + dump_reg(decoder->client, REG_CHROMA_CONTROL2, value); + dump_reg(decoder->client, REG_COMP_PR_SATURATION, value); + dump_reg(decoder->client, REG_COMP_Y_CONTRAST, value); + dump_reg(decoder->client, REG_COMP_PB_SATURATION, value); + dump_reg(decoder->client, REG_COMP_Y_BRIGHTNESS, value); + dump_reg(decoder->client, REG_AVID_START_PIXEL_LSB, value); + dump_reg(decoder->client, REG_AVID_START_PIXEL_MSB, value); + dump_reg(decoder->client, REG_AVID_STOP_PIXEL_LSB, value); + dump_reg(decoder->client, REG_AVID_STOP_PIXEL_MSB, value); + dump_reg(decoder->client, REG_HSYNC_START_PIXEL_LSB, value); + dump_reg(decoder->client, REG_HSYNC_START_PIXEL_MSB, value); + dump_reg(decoder->client, REG_HSYNC_STOP_PIXEL_LSB, value); + dump_reg(decoder->client, REG_HSYNC_STOP_PIXEL_MSB, value); + dump_reg(decoder->client, REG_VSYNC_START_LINE_LSB, value); + dump_reg(decoder->client, REG_VSYNC_START_LINE_MSB, value); + dump_reg(decoder->client, REG_VSYNC_STOP_LINE_LSB, value); + dump_reg(decoder->client, REG_VSYNC_STOP_LINE_MSB, value); + dump_reg(decoder->client, REG_VBLK_START_LINE_LSB, value); + dump_reg(decoder->client, REG_VBLK_START_LINE_MSB, value); + dump_reg(decoder->client, REG_VBLK_STOP_LINE_LSB, value); + dump_reg(decoder->client, REG_VBLK_STOP_LINE_MSB, value); + dump_reg(decoder->client, REG_SYNC_CONTROL, value); + dump_reg(decoder->client, REG_OUTPUT_FORMATTER1, value); + dump_reg(decoder->client, REG_OUTPUT_FORMATTER2, value); + dump_reg(decoder->client, REG_OUTPUT_FORMATTER3, value); + dump_reg(decoder->client, REG_OUTPUT_FORMATTER4, value); + dump_reg(decoder->client, REG_OUTPUT_FORMATTER5, value); + dump_reg(decoder->client, REG_OUTPUT_FORMATTER6, value); + dump_reg(decoder->client, REG_CLEAR_LOST_LOCK, value); +} + +/* + * Configure the TVP5146/47 with the current register settings + * Returns zero if successful, or non-zero otherwise. + */ +static int tvp514x_configure(struct tvp514x_decoder *decoder) +{ + int err; + + /* common register initialization */ + err = + tvp514x_write_regs(decoder->client, tvp514x_reg_list); + if (err) + return err; + + if (debug) + tvp514x_reg_dump(decoder); + + return 0; +} + +/* + * Detect if an tvp514x is present, and if so which revision. + * A device is considered to be detected if the chip ID (LSB and MSB) + * registers match the expected values. + * Any value of the rom version register is accepted. + * Returns ENODEV error number if no device is detected, or zero + * if a device is detected. + */ +static int tvp514x_detect(struct tvp514x_decoder *decoder) +{ + u8 chip_id_msb, chip_id_lsb, rom_ver; + + chip_id_msb = tvp514x_read_reg(decoder->client, REG_CHIP_ID_MSB); + chip_id_lsb = tvp514x_read_reg(decoder->client, REG_CHIP_ID_LSB); + rom_ver = tvp514x_read_reg(decoder->client, REG_ROM_VERSION); + + v4l_dbg(1, debug, decoder->client, + "chip id detected msb:0x%x lsb:0x%x rom version:0x%x\n", + chip_id_msb, chip_id_lsb, rom_ver); + if ((chip_id_msb != TVP514X_CHIP_ID_MSB) + || ((chip_id_lsb != TVP5146_CHIP_ID_LSB) + && (chip_id_lsb != TVP5147_CHIP_ID_LSB))) { + /* We didn't read the values we expected, so this must not be + * an TVP5146/47. + */ + v4l_err(decoder->client, + "chip id mismatch msb:0x%x lsb:0x%x\n", + chip_id_msb, chip_id_lsb); + return -ENODEV; + } + + decoder->ver = rom_ver; + decoder->state = STATE_DETECTED; + + v4l_info(decoder->client, + "%s found at 0x%x (%s)\n", decoder->client->name, + decoder->client->addr << 1, + decoder->client->adapter->name); + return 0; +} + +/* + * Following are decoder interface functions implemented by + * TVP5146/47 decoder driver. + */ + +/** + * ioctl_querystd - V4L2 decoder interface handler for VIDIOC_QUERYSTD ioctl + * @s: pointer to standard V4L2 device structure + * @std_id: standard V4L2 std_id ioctl enum + * + * Returns the current standard detected by TVP5146/47. If no active input is + * detected, returns -EINVAL + */ +static int ioctl_querystd(struct v4l2_int_device *s, v4l2_std_id *std_id) +{ + struct tvp514x_decoder *decoder = s->priv; + enum tvp514x_std current_std; + enum tvp514x_input input_sel; + u8 sync_lock_status, lock_mask; + + if (std_id == NULL) + return -EINVAL; + + /* get the current standard */ + current_std = tvp514x_get_current_std(decoder); + if (current_std == STD_INVALID) + return -EINVAL; + + input_sel = decoder->route.input; + + switch (input_sel) { + case INPUT_CVBS_VI1A: + case INPUT_CVBS_VI1B: + case INPUT_CVBS_VI1C: + case INPUT_CVBS_VI2A: + case INPUT_CVBS_VI2B: + case INPUT_CVBS_VI2C: + case INPUT_CVBS_VI3A: + case INPUT_CVBS_VI3B: + case INPUT_CVBS_VI3C: + case INPUT_CVBS_VI4A: + lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT | + STATUS_HORZ_SYNC_LOCK_BIT | + STATUS_VIRT_SYNC_LOCK_BIT; + break; + + case INPUT_SVIDEO_VI2A_VI1A: + case INPUT_SVIDEO_VI2B_VI1B: + case INPUT_SVIDEO_VI2C_VI1C: + case INPUT_SVIDEO_VI2A_VI3A: + case INPUT_SVIDEO_VI2B_VI3B: + case INPUT_SVIDEO_VI2C_VI3C: + case INPUT_SVIDEO_VI4A_VI1A: + case INPUT_SVIDEO_VI4A_VI1B: + case INPUT_SVIDEO_VI4A_VI1C: + case INPUT_SVIDEO_VI4A_VI3A: + case INPUT_SVIDEO_VI4A_VI3B: + case INPUT_SVIDEO_VI4A_VI3C: + lock_mask = STATUS_HORZ_SYNC_LOCK_BIT | + STATUS_VIRT_SYNC_LOCK_BIT; + break; + /*Need to add other interfaces*/ + default: + return -EINVAL; + } + /* check whether signal is locked */ + sync_lock_status = tvp514x_read_reg(decoder->client, REG_STATUS1); + if (lock_mask != (sync_lock_status & lock_mask)) + return -EINVAL; /* No input detected */ + + decoder->current_std = current_std; + *std_id = decoder->std_list[current_std].standard.id; + + v4l_dbg(1, debug, decoder->client, "Current STD: %s", + decoder->std_list[current_std].standard.name); + return 0; +} + +/** + * ioctl_s_std - V4L2 decoder interface handler for VIDIOC_S_STD ioctl + * @s: pointer to standard V4L2 device structure + * @std_id: standard V4L2 v4l2_std_id ioctl enum + * + * If std_id is supported, sets the requested standard. Otherwise, returns + * -EINVAL + */ +static int ioctl_s_std(struct v4l2_int_device *s, v4l2_std_id *std_id) +{ + struct tvp514x_decoder *decoder = s->priv; + int err, i; + + if (std_id == NULL) + return -EINVAL; + + for (i = 0; i < decoder->num_stds; i++) + if (*std_id & decoder->std_list[i].standard.id) + break; + + if ((i == decoder->num_stds) || (i == STD_INVALID)) + return -EINVAL; + + err = tvp514x_write_reg(decoder->client, REG_VIDEO_STD, + decoder->std_list[i].video_std); + if (err) + return err; + + decoder->current_std = i; + tvp514x_reg_list[REG_VIDEO_STD].val = decoder->std_list[i].video_std; + + v4l_dbg(1, debug, decoder->client, "Standard set to: %s", + decoder->std_list[i].standard.name); + return 0; +} + +/** + * ioctl_s_routing - V4L2 decoder interface handler for VIDIOC_S_INPUT ioctl + * @s: pointer to standard V4L2 device structure + * @index: number of the input + * + * If index is valid, selects the requested input. Otherwise, returns -EINVAL if + * the input is not supported or there is no active signal present in the + * selected input. + */ +static int ioctl_s_routing(struct v4l2_int_device *s, + struct v4l2_routing *route) +{ + struct tvp514x_decoder *decoder = s->priv; + int err; + enum tvp514x_input input_sel; + enum tvp514x_output output_sel; + enum tvp514x_std current_std = STD_INVALID; + u8 sync_lock_status, lock_mask; + int try_count = LOCK_RETRY_COUNT; + + if ((!route) || (route->input >= INPUT_INVALID) || + (route->output >= OUTPUT_INVALID)) + return -EINVAL; /* Index out of bound */ + + input_sel = route->input; + output_sel = route->output; + + err = tvp514x_write_reg(decoder->client, REG_INPUT_SEL, input_sel); + if (err) + return err; + + output_sel |= tvp514x_read_reg(decoder->client, + REG_OUTPUT_FORMATTER1) & 0x7; + err = tvp514x_write_reg(decoder->client, REG_OUTPUT_FORMATTER1, + output_sel); + if (err) + return err; + + tvp514x_reg_list[REG_INPUT_SEL].val = input_sel; + tvp514x_reg_list[REG_OUTPUT_FORMATTER1].val = output_sel; + + /* Clear status */ + msleep(LOCK_RETRY_DELAY); + err = + tvp514x_write_reg(decoder->client, REG_CLEAR_LOST_LOCK, 0x01); + if (err) + return err; + + switch (input_sel) { + case INPUT_CVBS_VI1A: + case INPUT_CVBS_VI1B: + case INPUT_CVBS_VI1C: + case INPUT_CVBS_VI2A: + case INPUT_CVBS_VI2B: + case INPUT_CVBS_VI2C: + case INPUT_CVBS_VI3A: + case INPUT_CVBS_VI3B: + case INPUT_CVBS_VI3C: + case INPUT_CVBS_VI4A: + lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT | + STATUS_HORZ_SYNC_LOCK_BIT | + STATUS_VIRT_SYNC_LOCK_BIT; + break; + + case INPUT_SVIDEO_VI2A_VI1A: + case INPUT_SVIDEO_VI2B_VI1B: + case INPUT_SVIDEO_VI2C_VI1C: + case INPUT_SVIDEO_VI2A_VI3A: + case INPUT_SVIDEO_VI2B_VI3B: + case INPUT_SVIDEO_VI2C_VI3C: + case INPUT_SVIDEO_VI4A_VI1A: + case INPUT_SVIDEO_VI4A_VI1B: + case INPUT_SVIDEO_VI4A_VI1C: + case INPUT_SVIDEO_VI4A_VI3A: + case INPUT_SVIDEO_VI4A_VI3B: + case INPUT_SVIDEO_VI4A_VI3C: + lock_mask = STATUS_HORZ_SYNC_LOCK_BIT | + STATUS_VIRT_SYNC_LOCK_BIT; + break; + /*Need to add other interfaces*/ + default: + return -EINVAL; + } + + while (try_count-- > 0) { + /* Allow decoder to sync up with new input */ + msleep(LOCK_RETRY_DELAY); + + /* get the current standard for future reference */ + current_std = tvp514x_get_current_std(decoder); + if (current_std == STD_INVALID) + continue; + + sync_lock_status = tvp514x_read_reg(decoder->client, + REG_STATUS1); + if (lock_mask == (sync_lock_status & lock_mask)) + break; /* Input detected */ + } + + if ((current_std == STD_INVALID) || (try_count < 0)) + return -EINVAL; + + decoder->current_std = current_std; + decoder->route.input = route->input; + decoder->route.output = route->output; + + v4l_dbg(1, debug, decoder->client, + "Input set to: %d, std : %d", + input_sel, current_std); + + return 0; +} + +/** + * ioctl_queryctrl - V4L2 decoder interface handler for VIDIOC_QUERYCTRL ioctl + * @s: pointer to standard V4L2 device structure + * @qctrl: standard V4L2 v4l2_queryctrl structure + * + * If the requested control is supported, returns the control information. + * Otherwise, returns -EINVAL if the control is not supported. + */ +static int +ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qctrl) +{ + struct tvp514x_decoder *decoder = s->priv; + int err = -EINVAL; + + if (qctrl == NULL) + return err; + + switch (qctrl->id) { + case V4L2_CID_BRIGHTNESS: + /* Brightness supported is same as standard one (0-255), + * so make use of standard API provided. + */ + err = v4l2_ctrl_query_fill_std(qctrl); + break; + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + /* Saturation and Contrast supported is - + * Contrast: 0 - 255 (Default - 128) + * Saturation: 0 - 255 (Default - 128) + */ + err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); + break; + case V4L2_CID_HUE: + /* Hue Supported is - + * Hue - -180 - +180 (Default - 0, Step - +180) + */ + err = v4l2_ctrl_query_fill(qctrl, -180, 180, 180, 0); + break; + case V4L2_CID_AUTOGAIN: + /* Autogain is either 0 or 1*/ + memcpy(qctrl, &tvp514x_autogain_ctrl, + sizeof(struct v4l2_queryctrl)); + err = 0; + break; + default: + v4l_err(decoder->client, + "invalid control id %d\n", qctrl->id); + return err; + } + + v4l_dbg(1, debug, decoder->client, + "Query Control: %s : Min - %d, Max - %d, Def - %d", + qctrl->name, + qctrl->minimum, + qctrl->maximum, + qctrl->default_value); + + return err; +} + +/** + * ioctl_g_ctrl - V4L2 decoder interface handler for VIDIOC_G_CTRL ioctl + * @s: pointer to standard V4L2 device structure + * @ctrl: pointer to v4l2_control structure + * + * If the requested control is supported, returns the control's current + * value from the decoder. Otherwise, returns -EINVAL if the control is not + * supported. + */ +static int +ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) +{ + struct tvp514x_decoder *decoder = s->priv; + + if (ctrl == NULL) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = tvp514x_reg_list[REG_BRIGHTNESS].val; + break; + case V4L2_CID_CONTRAST: + ctrl->value = tvp514x_reg_list[REG_CONTRAST].val; + break; + case V4L2_CID_SATURATION: + ctrl->value = tvp514x_reg_list[REG_SATURATION].val; + break; + case V4L2_CID_HUE: + ctrl->value = tvp514x_reg_list[REG_HUE].val; + if (ctrl->value == 0x7F) + ctrl->value = 180; + else if (ctrl->value == 0x80) + ctrl->value = -180; + else + ctrl->value = 0; + + break; + case V4L2_CID_AUTOGAIN: + ctrl->value = tvp514x_reg_list[REG_AFE_GAIN_CTRL].val; + if ((ctrl->value & 0x3) == 3) + ctrl->value = 1; + else + ctrl->value = 0; + + break; + default: + v4l_err(decoder->client, + "invalid control id %d\n", ctrl->id); + return -EINVAL; + } + + v4l_dbg(1, debug, decoder->client, + "Get Control: ID - %d - %d", + ctrl->id, ctrl->value); + return 0; +} + +/** + * ioctl_s_ctrl - V4L2 decoder interface handler for VIDIOC_S_CTRL ioctl + * @s: pointer to standard V4L2 device structure + * @ctrl: pointer to v4l2_control structure + * + * If the requested control is supported, sets the control's current + * value in HW. Otherwise, returns -EINVAL if the control is not supported. + */ +static int +ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) +{ + struct tvp514x_decoder *decoder = s->priv; + int err = -EINVAL, value; + + if (ctrl == NULL) + return err; + + value = (__s32) ctrl->value; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value < 0 || ctrl->value > 255) { + v4l_err(decoder->client, + "invalid brightness setting %d\n", + ctrl->value); + return -ERANGE; + } + err = tvp514x_write_reg(decoder->client, REG_BRIGHTNESS, + value); + if (err) + return err; + tvp514x_reg_list[REG_BRIGHTNESS].val = value; + break; + case V4L2_CID_CONTRAST: + if (ctrl->value < 0 || ctrl->value > 255) { + v4l_err(decoder->client, + "invalid contrast setting %d\n", + ctrl->value); + return -ERANGE; + } + err = tvp514x_write_reg(decoder->client, REG_CONTRAST, + value); + if (err) + return err; + tvp514x_reg_list[REG_CONTRAST].val = value; + break; + case V4L2_CID_SATURATION: + if (ctrl->value < 0 || ctrl->value > 255) { + v4l_err(decoder->client, + "invalid saturation setting %d\n", + ctrl->value); + return -ERANGE; + } + err = tvp514x_write_reg(decoder->client, REG_SATURATION, + value); + if (err) + return err; + tvp514x_reg_list[REG_SATURATION].val = value; + break; + case V4L2_CID_HUE: + if (value == 180) + value = 0x7F; + else if (value == -180) + value = 0x80; + else if (value == 0) + value = 0; + else { + v4l_err(decoder->client, + "invalid hue setting %d\n", + ctrl->value); + return -ERANGE; + } + err = tvp514x_write_reg(decoder->client, REG_HUE, + value); + if (err) + return err; + tvp514x_reg_list[REG_HUE].val = value; + break; + case V4L2_CID_AUTOGAIN: + if (value == 1) + value = 0x0F; + else if (value == 0) + value = 0x0C; + else { + v4l_err(decoder->client, + "invalid auto gain setting %d\n", + ctrl->value); + return -ERANGE; + } + err = tvp514x_write_reg(decoder->client, REG_AFE_GAIN_CTRL, + value); + if (err) + return err; + tvp514x_reg_list[REG_AFE_GAIN_CTRL].val = value; + break; + default: + v4l_err(decoder->client, + "invalid control id %d\n", ctrl->id); + return err; + } + + v4l_dbg(1, debug, decoder->client, + "Set Control: ID - %d - %d", + ctrl->id, ctrl->value); + + return err; +} + +/** + * ioctl_enum_fmt_cap - Implement the CAPTURE buffer VIDIOC_ENUM_FMT ioctl + * @s: pointer to standard V4L2 device structure + * @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure + * + * Implement the VIDIOC_ENUM_FMT ioctl to enumerate supported formats + */ +static int +ioctl_enum_fmt_cap(struct v4l2_int_device *s, struct v4l2_fmtdesc *fmt) +{ + struct tvp514x_decoder *decoder = s->priv; + int index; + + if (fmt == NULL) + return -EINVAL; + + index = fmt->index; + if ((index >= decoder->num_fmts) || (index < 0)) + return -EINVAL; /* Index out of bound */ + + if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; /* only capture is supported */ + + memcpy(fmt, &decoder->fmt_list[index], + sizeof(struct v4l2_fmtdesc)); + + v4l_dbg(1, debug, decoder->client, + "Current FMT: index - %d (%s)", + decoder->fmt_list[index].index, + decoder->fmt_list[index].description); + return 0; +} + +/** + * ioctl_try_fmt_cap - Implement the CAPTURE buffer VIDIOC_TRY_FMT ioctl + * @s: pointer to standard V4L2 device structure + * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure + * + * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This + * ioctl is used to negotiate the image capture size and pixel format + * without actually making it take effect. + */ +static int +ioctl_try_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) +{ + struct tvp514x_decoder *decoder = s->priv; + int ifmt; + struct v4l2_pix_format *pix; + enum tvp514x_std current_std; + + if (f == NULL) + return -EINVAL; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + pix = &f->fmt.pix; + + /* Calculate height and width based on current standard */ + current_std = tvp514x_get_current_std(decoder); + if (current_std == STD_INVALID) + return -EINVAL; + + decoder->current_std = current_std; + pix->width = decoder->std_list[current_std].width; + pix->height = decoder->std_list[current_std].height; + + for (ifmt = 0; ifmt < decoder->num_fmts; ifmt++) { + if (pix->pixelformat == + decoder->fmt_list[ifmt].pixelformat) + break; + } + if (ifmt == decoder->num_fmts) + ifmt = 0; /* None of the format matched, select default */ + pix->pixelformat = decoder->fmt_list[ifmt].pixelformat; + + pix->field = V4L2_FIELD_INTERLACED; + pix->bytesperline = pix->width * 2; + pix->sizeimage = pix->bytesperline * pix->height; + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; + pix->priv = 0; + + v4l_dbg(1, debug, decoder->client, + "Try FMT: pixelformat - %s, bytesperline - %d" + "Width - %d, Height - %d", + decoder->fmt_list[ifmt].description, pix->bytesperline, + pix->width, pix->height); + return 0; +} + +/** + * ioctl_s_fmt_cap - V4L2 decoder interface handler for VIDIOC_S_FMT ioctl + * @s: pointer to standard V4L2 device structure + * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure + * + * If the requested format is supported, configures the HW to use that + * format, returns error code if format not supported or HW can't be + * correctly configured. + */ +static int +ioctl_s_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) +{ + struct tvp514x_decoder *decoder = s->priv; + struct v4l2_pix_format *pix; + int rval; + + if (f == NULL) + return -EINVAL; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; /* only capture is supported */ + + pix = &f->fmt.pix; + rval = ioctl_try_fmt_cap(s, f); + if (rval) + return rval; + + decoder->pix = *pix; + + return rval; +} + +/** + * ioctl_g_fmt_cap - V4L2 decoder interface handler for ioctl_g_fmt_cap + * @s: pointer to standard V4L2 device structure + * @f: pointer to standard V4L2 v4l2_format structure + * + * Returns the decoder's current pixel format in the v4l2_format + * parameter. + */ +static int +ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) +{ + struct tvp514x_decoder *decoder = s->priv; + + if (f == NULL) + return -EINVAL; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; /* only capture is supported */ + + f->fmt.pix = decoder->pix; + + v4l_dbg(1, debug, decoder->client, + "Current FMT: bytesperline - %d" + "Width - %d, Height - %d", + decoder->pix.bytesperline, + decoder->pix.width, decoder->pix.height); + return 0; +} + +/** + * ioctl_g_parm - V4L2 decoder interface handler for VIDIOC_G_PARM ioctl + * @s: pointer to standard V4L2 device structure + * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure + * + * Returns the decoder's video CAPTURE parameters. + */ +static int +ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) +{ + struct tvp514x_decoder *decoder = s->priv; + struct v4l2_captureparm *cparm; + enum tvp514x_std current_std; + + if (a == NULL) + return -EINVAL; + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; /* only capture is supported */ + + memset(a, 0, sizeof(*a)); + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + /* get the current standard */ + current_std = tvp514x_get_current_std(decoder); + if (current_std == STD_INVALID) + return -EINVAL; + + decoder->current_std = current_std; + + cparm = &a->parm.capture; + cparm->capability = V4L2_CAP_TIMEPERFRAME; + cparm->timeperframe = + decoder->std_list[current_std].standard.frameperiod; + + return 0; +} + +/** + * ioctl_s_parm - V4L2 decoder interface handler for VIDIOC_S_PARM ioctl + * @s: pointer to standard V4L2 device structure + * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure + * + * Configures the decoder to use the input parameters, if possible. If + * not possible, returns the appropriate error code. + */ +static int +ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) +{ + struct tvp514x_decoder *decoder = s->priv; + struct v4l2_fract *timeperframe; + enum tvp514x_std current_std; + + if (a == NULL) + return -EINVAL; + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; /* only capture is supported */ + + timeperframe = &a->parm.capture.timeperframe; + + /* get the current standard */ + current_std = tvp514x_get_current_std(decoder); + if (current_std == STD_INVALID) + return -EINVAL; + + decoder->current_std = current_std; + + *timeperframe = + decoder->std_list[current_std].standard.frameperiod; + + return 0; +} + +/** + * ioctl_g_ifparm - V4L2 decoder interface handler for vidioc_int_g_ifparm_num + * @s: pointer to standard V4L2 device structure + * @p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure + * + * Gets slave interface parameters. + * Calculates the required xclk value to support the requested + * clock parameters in p. This value is returned in the p + * parameter. + */ +static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) +{ + struct tvp514x_decoder *decoder = s->priv; + int rval; + + if (p == NULL) + return -EINVAL; + + if (NULL == decoder->pdata->ifparm) + return -EINVAL; + + rval = decoder->pdata->ifparm(p); + if (rval) { + v4l_err(decoder->client, "g_ifparm.Err[%d]\n", rval); + return rval; + } + + p->u.bt656.clock_curr = TVP514X_XCLK_BT656; + + return 0; +} + +/** + * ioctl_g_priv - V4L2 decoder interface handler for vidioc_int_g_priv_num + * @s: pointer to standard V4L2 device structure + * @p: void pointer to hold decoder's private data address + * + * Returns device's (decoder's) private data area address in p parameter + */ +static int ioctl_g_priv(struct v4l2_int_device *s, void *p) +{ + struct tvp514x_decoder *decoder = s->priv; + + if (NULL == decoder->pdata->priv_data_set) + return -EINVAL; + + return decoder->pdata->priv_data_set(p); +} + +/** + * ioctl_s_power - V4L2 decoder interface handler for vidioc_int_s_power_num + * @s: pointer to standard V4L2 device structure + * @on: power state to which device is to be set + * + * Sets devices power state to requrested state, if possible. + */ +static int ioctl_s_power(struct v4l2_int_device *s, enum v4l2_power on) +{ + struct tvp514x_decoder *decoder = s->priv; + int err = 0; + + switch (on) { + case V4L2_POWER_OFF: + /* Power Down Sequence */ + err = + tvp514x_write_reg(decoder->client, REG_OPERATION_MODE, + 0x01); + /* Disable mux for TVP5146/47 decoder data path */ + if (decoder->pdata->power_set) + err |= decoder->pdata->power_set(on); + decoder->state = STATE_NOT_DETECTED; + break; + + case V4L2_POWER_STANDBY: + if (decoder->pdata->power_set) + err = decoder->pdata->power_set(on); + break; + + case V4L2_POWER_ON: + /* Enable mux for TVP5146/47 decoder data path */ + if ((decoder->pdata->power_set) && + (decoder->state == STATE_NOT_DETECTED)) { + int i; + struct tvp514x_init_seq *int_seq = + (struct tvp514x_init_seq *) + decoder->id->driver_data; + + err = decoder->pdata->power_set(on); + + /* Power Up Sequence */ + for (i = 0; i < int_seq->no_regs; i++) { + err |= tvp514x_write_reg(decoder->client, + int_seq->init_reg_seq[i].reg, + int_seq->init_reg_seq[i].val); + } + /* Detect the sensor is not already detected */ + err |= tvp514x_detect(decoder); + if (err) { + v4l_err(decoder->client, + "Unable to detect decoder\n"); + return err; + } + } + err |= tvp514x_configure(decoder); + break; + + default: + err = -ENODEV; + break; + } + + return err; +} + +/** + * ioctl_init - V4L2 decoder interface handler for VIDIOC_INT_INIT + * @s: pointer to standard V4L2 device structure + * + * Initialize the decoder device (calls tvp514x_configure()) + */ +static int ioctl_init(struct v4l2_int_device *s) +{ + struct tvp514x_decoder *decoder = s->priv; + + /* Set default standard to auto */ + tvp514x_reg_list[REG_VIDEO_STD].val = + VIDEO_STD_AUTO_SWITCH_BIT; + + return tvp514x_configure(decoder); +} + +/** + * ioctl_dev_exit - V4L2 decoder interface handler for vidioc_int_dev_exit_num + * @s: pointer to standard V4L2 device structure + * + * Delinitialise the dev. at slave detach. The complement of ioctl_dev_init. + */ +static int ioctl_dev_exit(struct v4l2_int_device *s) +{ + return 0; +} + +/** + * ioctl_dev_init - V4L2 decoder interface handler for vidioc_int_dev_init_num + * @s: pointer to standard V4L2 device structure + * + * Initialise the device when slave attaches to the master. Returns 0 if + * TVP5146/47 device could be found, otherwise returns appropriate error. + */ +static int ioctl_dev_init(struct v4l2_int_device *s) +{ + struct tvp514x_decoder *decoder = s->priv; + int err; + + err = tvp514x_detect(decoder); + if (err < 0) { + v4l_err(decoder->client, + "Unable to detect decoder\n"); + return err; + } + + v4l_info(decoder->client, + "chip version 0x%.2x detected\n", decoder->ver); + + return 0; +} + +static struct v4l2_int_ioctl_desc tvp514x_ioctl_desc[] = { + {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*) ioctl_dev_init}, + {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func*) ioctl_dev_exit}, + {vidioc_int_s_power_num, (v4l2_int_ioctl_func*) ioctl_s_power}, + {vidioc_int_g_priv_num, (v4l2_int_ioctl_func*) ioctl_g_priv}, + {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*) ioctl_g_ifparm}, + {vidioc_int_init_num, (v4l2_int_ioctl_func*) ioctl_init}, + {vidioc_int_enum_fmt_cap_num, + (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, + {vidioc_int_try_fmt_cap_num, + (v4l2_int_ioctl_func *) ioctl_try_fmt_cap}, + {vidioc_int_g_fmt_cap_num, + (v4l2_int_ioctl_func *) ioctl_g_fmt_cap}, + {vidioc_int_s_fmt_cap_num, + (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, + {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm}, + {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm}, + {vidioc_int_queryctrl_num, + (v4l2_int_ioctl_func *) ioctl_queryctrl}, + {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl}, + {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl}, + {vidioc_int_querystd_num, (v4l2_int_ioctl_func *) ioctl_querystd}, + {vidioc_int_s_std_num, (v4l2_int_ioctl_func *) ioctl_s_std}, + {vidioc_int_s_video_routing_num, + (v4l2_int_ioctl_func *) ioctl_s_routing}, +}; + +static struct v4l2_int_slave tvp514x_slave = { + .ioctls = tvp514x_ioctl_desc, + .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc), +}; + +static struct tvp514x_decoder tvp514x_dev = { + .state = STATE_NOT_DETECTED, + + .fmt_list = tvp514x_fmt_list, + .num_fmts = ARRAY_SIZE(tvp514x_fmt_list), + + .pix = { /* Default to NTSC 8-bit YUV 422 */ + .width = NTSC_NUM_ACTIVE_PIXELS, + .height = NTSC_NUM_ACTIVE_LINES, + .pixelformat = V4L2_PIX_FMT_UYVY, + .field = V4L2_FIELD_INTERLACED, + .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2, + .sizeimage = + NTSC_NUM_ACTIVE_PIXELS * 2 * NTSC_NUM_ACTIVE_LINES, + .colorspace = V4L2_COLORSPACE_SMPTE170M, + }, + + .current_std = STD_NTSC_MJ, + .std_list = tvp514x_std_list, + .num_stds = ARRAY_SIZE(tvp514x_std_list), + +}; + +static struct v4l2_int_device tvp514x_int_device = { + .module = THIS_MODULE, + .name = TVP514X_MODULE_NAME, + .priv = &tvp514x_dev, + .type = v4l2_int_type_slave, + .u = { + .slave = &tvp514x_slave, + }, +}; + +/** + * tvp514x_probe - decoder driver i2c probe handler + * @client: i2c driver client device structure + * + * Register decoder as an i2c client device and V4L2 + * device. + */ +static int +tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct tvp514x_decoder *decoder = &tvp514x_dev; + int err; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + decoder->pdata = client->dev.platform_data; + if (!decoder->pdata) { + v4l_err(client, "No platform data\n!!"); + return -ENODEV; + } + /* + * Fetch platform specific data, and configure the + * tvp514x_reg_list[] accordingly. Since this is one + * time configuration, no need to preserve. + */ + tvp514x_reg_list[REG_OUTPUT_FORMATTER2].val |= + (decoder->pdata->clk_polarity << 1); + tvp514x_reg_list[REG_SYNC_CONTROL].val |= + ((decoder->pdata->hs_polarity << 2) | + (decoder->pdata->vs_polarity << 3)); + /* + * Save the id data, required for power up sequence + */ + decoder->id = (struct i2c_device_id *)id; + /* Attach to Master */ + strcpy(tvp514x_int_device.u.slave->attach_to, decoder->pdata->master); + decoder->v4l2_int_device = &tvp514x_int_device; + decoder->client = client; + i2c_set_clientdata(client, decoder); + + /* Register with V4L2 layer as slave device */ + err = v4l2_int_device_register(decoder->v4l2_int_device); + if (err) { + i2c_set_clientdata(client, NULL); + v4l_err(client, + "Unable to register to v4l2. Err[%d]\n", err); + + } else + v4l_info(client, "Registered to v4l2 master %s!!\n", + decoder->pdata->master); + + return 0; +} + +/** + * tvp514x_remove - decoder driver i2c remove handler + * @client: i2c driver client device structure + * + * Unregister decoder as an i2c client device and V4L2 + * device. Complement of tvp514x_probe(). + */ +static int __exit tvp514x_remove(struct i2c_client *client) +{ + struct tvp514x_decoder *decoder = i2c_get_clientdata(client); + + if (!client->adapter) + return -ENODEV; /* our client isn't attached */ + + v4l2_int_device_unregister(decoder->v4l2_int_device); + i2c_set_clientdata(client, NULL); + + return 0; +} +/* + * TVP5146 Init/Power on Sequence + */ +static const struct tvp514x_reg tvp5146_init_reg_seq[] = { + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80}, + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, + {TOK_WRITE, REG_OPERATION_MODE, 0x01}, + {TOK_WRITE, REG_OPERATION_MODE, 0x00}, +}; +static const struct tvp514x_init_seq tvp5146_init = { + .no_regs = ARRAY_SIZE(tvp5146_init_reg_seq), + .init_reg_seq = tvp5146_init_reg_seq, +}; +/* + * TVP5147 Init/Power on Sequence + */ +static const struct tvp514x_reg tvp5147_init_reg_seq[] = { + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80}, + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x16}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xA0}, + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x16}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, + {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, + {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, + {TOK_WRITE, REG_OPERATION_MODE, 0x01}, + {TOK_WRITE, REG_OPERATION_MODE, 0x00}, +}; +static const struct tvp514x_init_seq tvp5147_init = { + .no_regs = ARRAY_SIZE(tvp5147_init_reg_seq), + .init_reg_seq = tvp5147_init_reg_seq, +}; +/* + * TVP5146M2/TVP5147M1 Init/Power on Sequence + */ +static const struct tvp514x_reg tvp514xm_init_reg_seq[] = { + {TOK_WRITE, REG_OPERATION_MODE, 0x01}, + {TOK_WRITE, REG_OPERATION_MODE, 0x00}, +}; +static const struct tvp514x_init_seq tvp514xm_init = { + .no_regs = ARRAY_SIZE(tvp514xm_init_reg_seq), + .init_reg_seq = tvp514xm_init_reg_seq, +}; +/* + * I2C Device Table - + * + * name - Name of the actual device/chip. + * driver_data - Driver data + */ +static const struct i2c_device_id tvp514x_id[] = { + {"tvp5146", (unsigned long)&tvp5146_init}, + {"tvp5146m2", (unsigned long)&tvp514xm_init}, + {"tvp5147", (unsigned long)&tvp5147_init}, + {"tvp5147m1", (unsigned long)&tvp514xm_init}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, tvp514x_id); + +static struct i2c_driver tvp514x_i2c_driver = { + .driver = { + .name = TVP514X_MODULE_NAME, + .owner = THIS_MODULE, + }, + .probe = tvp514x_probe, + .remove = __exit_p(tvp514x_remove), + .id_table = tvp514x_id, +}; + +/** + * tvp514x_init + * + * Module init function + */ +static int __init tvp514x_init(void) +{ + return i2c_add_driver(&tvp514x_i2c_driver); +} + +/** + * tvp514x_cleanup + * + * Module exit function + */ +static void __exit tvp514x_cleanup(void) +{ + i2c_del_driver(&tvp514x_i2c_driver); +} + +module_init(tvp514x_init); +module_exit(tvp514x_cleanup); + +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("TVP514X linux decoder driver"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/video/tvp514x_regs.h b/linux/drivers/media/video/tvp514x_regs.h new file mode 100644 index 000000000..351620aee --- /dev/null +++ b/linux/drivers/media/video/tvp514x_regs.h @@ -0,0 +1,297 @@ +/* + * drivers/media/video/tvp514x_regs.h + * + * Copyright (C) 2008 Texas Instruments Inc + * Author: Vaibhav Hiremath + * + * Contributors: + * Sivaraj R + * Brijesh R Jadav + * Hardik Shah + * Manjunath Hadli + * Karicheri Muralidharan + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _TVP514X_REGS_H +#define _TVP514X_REGS_H + +/* + * TVP5146/47 registers + */ +#define REG_INPUT_SEL (0x00) +#define REG_AFE_GAIN_CTRL (0x01) +#define REG_VIDEO_STD (0x02) +#define REG_OPERATION_MODE (0x03) +#define REG_AUTOSWITCH_MASK (0x04) + +#define REG_COLOR_KILLER (0x05) +#define REG_LUMA_CONTROL1 (0x06) +#define REG_LUMA_CONTROL2 (0x07) +#define REG_LUMA_CONTROL3 (0x08) + +#define REG_BRIGHTNESS (0x09) +#define REG_CONTRAST (0x0A) +#define REG_SATURATION (0x0B) +#define REG_HUE (0x0C) + +#define REG_CHROMA_CONTROL1 (0x0D) +#define REG_CHROMA_CONTROL2 (0x0E) + +/* 0x0F Reserved */ + +#define REG_COMP_PR_SATURATION (0x10) +#define REG_COMP_Y_CONTRAST (0x11) +#define REG_COMP_PB_SATURATION (0x12) + +/* 0x13 Reserved */ + +#define REG_COMP_Y_BRIGHTNESS (0x14) + +/* 0x15 Reserved */ + +#define REG_AVID_START_PIXEL_LSB (0x16) +#define REG_AVID_START_PIXEL_MSB (0x17) +#define REG_AVID_STOP_PIXEL_LSB (0x18) +#define REG_AVID_STOP_PIXEL_MSB (0x19) + +#define REG_HSYNC_START_PIXEL_LSB (0x1A) +#define REG_HSYNC_START_PIXEL_MSB (0x1B) +#define REG_HSYNC_STOP_PIXEL_LSB (0x1C) +#define REG_HSYNC_STOP_PIXEL_MSB (0x1D) + +#define REG_VSYNC_START_LINE_LSB (0x1E) +#define REG_VSYNC_START_LINE_MSB (0x1F) +#define REG_VSYNC_STOP_LINE_LSB (0x20) +#define REG_VSYNC_STOP_LINE_MSB (0x21) + +#define REG_VBLK_START_LINE_LSB (0x22) +#define REG_VBLK_START_LINE_MSB (0x23) +#define REG_VBLK_STOP_LINE_LSB (0x24) +#define REG_VBLK_STOP_LINE_MSB (0x25) + +/* 0x26 - 0x27 Reserved */ + +#define REG_FAST_SWTICH_CONTROL (0x28) + +/* 0x29 Reserved */ + +#define REG_FAST_SWTICH_SCART_DELAY (0x2A) + +/* 0x2B Reserved */ + +#define REG_SCART_DELAY (0x2C) +#define REG_CTI_DELAY (0x2D) +#define REG_CTI_CONTROL (0x2E) + +/* 0x2F - 0x31 Reserved */ + +#define REG_SYNC_CONTROL (0x32) +#define REG_OUTPUT_FORMATTER1 (0x33) +#define REG_OUTPUT_FORMATTER2 (0x34) +#define REG_OUTPUT_FORMATTER3 (0x35) +#define REG_OUTPUT_FORMATTER4 (0x36) +#define REG_OUTPUT_FORMATTER5 (0x37) +#define REG_OUTPUT_FORMATTER6 (0x38) +#define REG_CLEAR_LOST_LOCK (0x39) + +#define REG_STATUS1 (0x3A) +#define REG_STATUS2 (0x3B) + +#define REG_AGC_GAIN_STATUS_LSB (0x3C) +#define REG_AGC_GAIN_STATUS_MSB (0x3D) + +/* 0x3E Reserved */ + +#define REG_VIDEO_STD_STATUS (0x3F) +#define REG_GPIO_INPUT1 (0x40) +#define REG_GPIO_INPUT2 (0x41) + +/* 0x42 - 0x45 Reserved */ + +#define REG_AFE_COARSE_GAIN_CH1 (0x46) +#define REG_AFE_COARSE_GAIN_CH2 (0x47) +#define REG_AFE_COARSE_GAIN_CH3 (0x48) +#define REG_AFE_COARSE_GAIN_CH4 (0x49) + +#define REG_AFE_FINE_GAIN_PB_B_LSB (0x4A) +#define REG_AFE_FINE_GAIN_PB_B_MSB (0x4B) +#define REG_AFE_FINE_GAIN_Y_G_CHROMA_LSB (0x4C) +#define REG_AFE_FINE_GAIN_Y_G_CHROMA_MSB (0x4D) +#define REG_AFE_FINE_GAIN_PR_R_LSB (0x4E) +#define REG_AFE_FINE_GAIN_PR_R_MSB (0x4F) +#define REG_AFE_FINE_GAIN_CVBS_LUMA_LSB (0x50) +#define REG_AFE_FINE_GAIN_CVBS_LUMA_MSB (0x51) + +/* 0x52 - 0x68 Reserved */ + +#define REG_FBIT_VBIT_CONTROL1 (0x69) + +/* 0x6A - 0x6B Reserved */ + +#define REG_BACKEND_AGC_CONTROL (0x6C) + +/* 0x6D - 0x6E Reserved */ + +#define REG_AGC_DECREMENT_SPEED_CONTROL (0x6F) +#define REG_ROM_VERSION (0x70) + +/* 0x71 - 0x73 Reserved */ + +#define REG_AGC_WHITE_PEAK_PROCESSING (0x74) +#define REG_FBIT_VBIT_CONTROL2 (0x75) +#define REG_VCR_TRICK_MODE_CONTROL (0x76) +#define REG_HORIZONTAL_SHAKE_INCREMENT (0x77) +#define REG_AGC_INCREMENT_SPEED (0x78) +#define REG_AGC_INCREMENT_DELAY (0x79) + +/* 0x7A - 0x7F Reserved */ + +#define REG_CHIP_ID_MSB (0x80) +#define REG_CHIP_ID_LSB (0x81) + +/* 0x82 Reserved */ + +#define REG_CPLL_SPEED_CONTROL (0x83) + +/* 0x84 - 0x96 Reserved */ + +#define REG_STATUS_REQUEST (0x97) + +/* 0x98 - 0x99 Reserved */ + +#define REG_VERTICAL_LINE_COUNT_LSB (0x9A) +#define REG_VERTICAL_LINE_COUNT_MSB (0x9B) + +/* 0x9C - 0x9D Reserved */ + +#define REG_AGC_DECREMENT_DELAY (0x9E) + +/* 0x9F - 0xB0 Reserved */ + +#define REG_VDP_TTX_FILTER_1_MASK1 (0xB1) +#define REG_VDP_TTX_FILTER_1_MASK2 (0xB2) +#define REG_VDP_TTX_FILTER_1_MASK3 (0xB3) +#define REG_VDP_TTX_FILTER_1_MASK4 (0xB4) +#define REG_VDP_TTX_FILTER_1_MASK5 (0xB5) +#define REG_VDP_TTX_FILTER_2_MASK1 (0xB6) +#define REG_VDP_TTX_FILTER_2_MASK2 (0xB7) +#define REG_VDP_TTX_FILTER_2_MASK3 (0xB8) +#define REG_VDP_TTX_FILTER_2_MASK4 (0xB9) +#define REG_VDP_TTX_FILTER_2_MASK5 (0xBA) +#define REG_VDP_TTX_FILTER_CONTROL (0xBB) +#define REG_VDP_FIFO_WORD_COUNT (0xBC) +#define REG_VDP_FIFO_INTERRUPT_THRLD (0xBD) + +/* 0xBE Reserved */ + +#define REG_VDP_FIFO_RESET (0xBF) +#define REG_VDP_FIFO_OUTPUT_CONTROL (0xC0) +#define REG_VDP_LINE_NUMBER_INTERRUPT (0xC1) +#define REG_VDP_PIXEL_ALIGNMENT_LSB (0xC2) +#define REG_VDP_PIXEL_ALIGNMENT_MSB (0xC3) + +/* 0xC4 - 0xD5 Reserved */ + +#define REG_VDP_LINE_START (0xD6) +#define REG_VDP_LINE_STOP (0xD7) +#define REG_VDP_GLOBAL_LINE_MODE (0xD8) +#define REG_VDP_FULL_FIELD_ENABLE (0xD9) +#define REG_VDP_FULL_FIELD_MODE (0xDA) + +/* 0xDB - 0xDF Reserved */ + +#define REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR (0xE0) +#define REG_VBUS_DATA_ACCESS_VBUS_ADDR_INCR (0xE1) +#define REG_FIFO_READ_DATA (0xE2) + +/* 0xE3 - 0xE7 Reserved */ + +#define REG_VBUS_ADDRESS_ACCESS1 (0xE8) +#define REG_VBUS_ADDRESS_ACCESS2 (0xE9) +#define REG_VBUS_ADDRESS_ACCESS3 (0xEA) + +/* 0xEB - 0xEF Reserved */ + +#define REG_INTERRUPT_RAW_STATUS0 (0xF0) +#define REG_INTERRUPT_RAW_STATUS1 (0xF1) +#define REG_INTERRUPT_STATUS0 (0xF2) +#define REG_INTERRUPT_STATUS1 (0xF3) +#define REG_INTERRUPT_MASK0 (0xF4) +#define REG_INTERRUPT_MASK1 (0xF5) +#define REG_INTERRUPT_CLEAR0 (0xF6) +#define REG_INTERRUPT_CLEAR1 (0xF7) + +/* 0xF8 - 0xFF Reserved */ + +/* + * Mask and bit definitions of TVP5146/47 registers + */ +/* The ID values we are looking for */ +#define TVP514X_CHIP_ID_MSB (0x51) +#define TVP5146_CHIP_ID_LSB (0x46) +#define TVP5147_CHIP_ID_LSB (0x47) + +#define VIDEO_STD_MASK (0x07) +#define VIDEO_STD_AUTO_SWITCH_BIT (0x00) +#define VIDEO_STD_NTSC_MJ_BIT (0x01) +#define VIDEO_STD_PAL_BDGHIN_BIT (0x02) +#define VIDEO_STD_PAL_M_BIT (0x03) +#define VIDEO_STD_PAL_COMBINATION_N_BIT (0x04) +#define VIDEO_STD_NTSC_4_43_BIT (0x05) +#define VIDEO_STD_SECAM_BIT (0x06) +#define VIDEO_STD_PAL_60_BIT (0x07) + +/* + * Status bit + */ +#define STATUS_TV_VCR_BIT (1<<0) +#define STATUS_HORZ_SYNC_LOCK_BIT (1<<1) +#define STATUS_VIRT_SYNC_LOCK_BIT (1<<2) +#define STATUS_CLR_SUBCAR_LOCK_BIT (1<<3) +#define STATUS_LOST_LOCK_DETECT_BIT (1<<4) +#define STATUS_FEILD_RATE_BIT (1<<5) +#define STATUS_LINE_ALTERNATING_BIT (1<<6) +#define STATUS_PEAK_WHITE_DETECT_BIT (1<<7) + +/* Tokens for register write */ +#define TOK_WRITE (0) /* token for write operation */ +#define TOK_TERM (1) /* terminating token */ +#define TOK_DELAY (2) /* delay token for reg list */ +#define TOK_SKIP (3) /* token to skip a register */ +/** + * struct tvp514x_reg - Structure for TVP5146/47 register initialization values + * @token - Token: TOK_WRITE, TOK_TERM etc.. + * @reg - Register offset + * @val - Register Value for TOK_WRITE or delay in ms for TOK_DELAY + */ +struct tvp514x_reg { + u8 token; + u8 reg; + u32 val; +}; + +/** + * struct tvp514x_init_seq - Structure for TVP5146/47/46M2/47M1 power up + * Sequence. + * @ no_regs - Number of registers to write for power up sequence. + * @ init_reg_seq - Array of registers and respective value to write. + */ +struct tvp514x_init_seq { + unsigned int no_regs; + const struct tvp514x_reg *init_reg_seq; +}; +#endif /* ifndef _TVP514X_REGS_H */ diff --git a/linux/include/media/tvp514x.h b/linux/include/media/tvp514x.h new file mode 100644 index 000000000..5e7ee968c --- /dev/null +++ b/linux/include/media/tvp514x.h @@ -0,0 +1,118 @@ +/* + * drivers/media/video/tvp514x.h + * + * Copyright (C) 2008 Texas Instruments Inc + * Author: Vaibhav Hiremath + * + * Contributors: + * Sivaraj R + * Brijesh R Jadav + * Hardik Shah + * Manjunath Hadli + * Karicheri Muralidharan + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _TVP514X_H +#define _TVP514X_H + +/* + * Other macros + */ +#define TVP514X_MODULE_NAME "tvp514x" + +#define TVP514X_XCLK_BT656 (27000000) + +/* Number of pixels and number of lines per frame for different standards */ +#define NTSC_NUM_ACTIVE_PIXELS (720) +#define NTSC_NUM_ACTIVE_LINES (480) +#define PAL_NUM_ACTIVE_PIXELS (720) +#define PAL_NUM_ACTIVE_LINES (576) + +/** + * enum tvp514x_input - enum for different decoder input pin + * configuration. + */ +enum tvp514x_input { + /* + * CVBS input selection + */ + INPUT_CVBS_VI1A = 0x0, + INPUT_CVBS_VI1B, + INPUT_CVBS_VI1C, + INPUT_CVBS_VI2A = 0x04, + INPUT_CVBS_VI2B, + INPUT_CVBS_VI2C, + INPUT_CVBS_VI3A = 0x08, + INPUT_CVBS_VI3B, + INPUT_CVBS_VI3C, + INPUT_CVBS_VI4A = 0x0C, + /* + * S-Video input selection + */ + INPUT_SVIDEO_VI2A_VI1A = 0x44, + INPUT_SVIDEO_VI2B_VI1B, + INPUT_SVIDEO_VI2C_VI1C, + INPUT_SVIDEO_VI2A_VI3A = 0x54, + INPUT_SVIDEO_VI2B_VI3B, + INPUT_SVIDEO_VI2C_VI3C, + INPUT_SVIDEO_VI4A_VI1A = 0x4C, + INPUT_SVIDEO_VI4A_VI1B, + INPUT_SVIDEO_VI4A_VI1C, + INPUT_SVIDEO_VI4A_VI3A = 0x5C, + INPUT_SVIDEO_VI4A_VI3B, + INPUT_SVIDEO_VI4A_VI3C, + + /* Need to add entries for + * RGB, YPbPr and SCART. + */ + INPUT_INVALID +}; + +/** + * enum tvp514x_output - enum for output format + * supported. + * + */ +enum tvp514x_output { + OUTPUT_10BIT_422_EMBEDDED_SYNC = 0, + OUTPUT_20BIT_422_SEPERATE_SYNC, + OUTPUT_10BIT_422_SEPERATE_SYNC = 3, + OUTPUT_INVALID +}; + +/** + * struct tvp514x_platform_data - Platform data values and access functions. + * @power_set: Power state access function, zero is off, non-zero is on. + * @ifparm: Interface parameters access function. + * @priv_data_set: Device private data (pointer) access function. + * @clk_polarity: Clock polarity of the current interface. + * @ hs_polarity: HSYNC Polarity configuration for current interface. + * @ vs_polarity: VSYNC Polarity configuration for current interface. + */ +struct tvp514x_platform_data { + char *master; + int (*power_set) (enum v4l2_power on); + int (*ifparm) (struct v4l2_ifparm *p); + int (*priv_data_set) (void *); + /* Interface control params */ + bool clk_polarity; + bool hs_polarity; + bool vs_polarity; +}; + + +#endif /* ifndef _TVP514X_H */ -- cgit v1.2.3 From e743836c92c2f0fb9bf167dc094bb22ebbded955 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Dec 2008 11:31:16 -0200 Subject: tuner-xc2028: powers device of when not used From: Mauro Carvalho Chehab Since the firmware load is now fast on most boards, better to keep the tuner off by default. A modprobe parameter were added to keep the old behavior, to be used by old devices. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c index 7f43272ca..c7ed924df 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -32,6 +32,12 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); +static int no_poweroff; +module_param(no_poweroff, int, 0644); +MODULE_PARM_DESC(debug, "0 (default) powers device off when not used.\n" + "1 keep device energized and with tuner ready all the times.\n" + " Faster, but consumes more power and keeps the device hotter\n"); + static char audio_std[8]; module_param_string(audio_std, audio_std, sizeof(audio_std), 0); MODULE_PARM_DESC(audio_std, @@ -1095,16 +1101,16 @@ static int xc2028_set_params(struct dvb_frontend *fe, T_DIGITAL_TV, type, 0, demod); } -#if 0 -/* This is needed at sleep (S1/S3), but not at fe_standby. Otherwise, - firmware will be loaded on every open() - */ static int xc2028_sleep(struct dvb_frontend *fe) { struct xc2028_data *priv = fe->tuner_priv; int rc = 0; - tuner_dbg("%s called\n", __func__); + /* Avoid firmware reload on slow devices */ + if (no_poweroff) + return; + + tuner_dbg("Putting xc2028/3028 into poweroff mode.\n"); mutex_lock(&priv->lock); @@ -1119,7 +1125,6 @@ static int xc2028_sleep(struct dvb_frontend *fe) return rc; } -#endif static int xc2028_dvb_release(struct dvb_frontend *fe) { @@ -1200,9 +1205,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = { .get_frequency = xc2028_get_frequency, .get_rf_strength = xc2028_signal, .set_params = xc2028_set_params, -#if 0 .sleep = xc2028_sleep, -#endif #if 0 int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); int (*get_status)(struct dvb_frontend *fe, u32 *status); -- cgit v1.2.3 From 53f02dd170952065cf1c6c18fefa194bd403c4ee Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Dec 2008 11:39:12 -0200 Subject: em28xx: turn off tuner when not used From: Mauro Carvalho Chehab em28xx devices generally get hot when xc3028 tuner is powered on. This patch solves this by turning power off when the device is not used, at the expense of having a higher load time, when calling a TV application. Since firmware load happens on 1 or 2 seconds on most devices, this is not a pain. Also, it helps to save the planet by saving some power :) Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 00d49c45f..ff960f90c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1758,6 +1758,9 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) return 0; } + /* Save some power by putting tuner to sleep */ + em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + /* do this before setting alternate! */ em28xx_uninit_isoc(dev); em28xx_set_mode(dev, EM28XX_SUSPEND); @@ -2203,6 +2206,9 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, mutex_unlock(&em28xx_extension_devlist_lock); mutex_unlock(&em28xx_devlist_mutex); + /* Save some power by putting tuner to sleep */ + em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + return 0; fail_reg_devices: -- cgit v1.2.3 From 929fe04b1e4235f1078c9ecbc1824e9ba43baba4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Dec 2008 11:49:53 -0200 Subject: tuner-xc2028: fix a small warning From: Mauro Carvalho Chehab /home/mauro/v4l-dvb/v4l/tuner-xc2028.c: In function 'xc2028_sleep': /home/mauro/v4l-dvb/v4l/tuner-xc2028.c:1111: warning: 'return' with no value, in function returning non-void Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c index c7ed924df..9536e3d3b 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -1108,7 +1108,7 @@ static int xc2028_sleep(struct dvb_frontend *fe) /* Avoid firmware reload on slow devices */ if (no_poweroff) - return; + return 0; tuner_dbg("Putting xc2028/3028 into poweroff mode.\n"); -- cgit v1.2.3 From 499a1c5e7f4f6f5918e0c0e39860cd6f5630e799 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Dec 2008 22:49:34 +0000 Subject: saa7134: add analog and DVB-T support for Medion/Creatix CTX946 From: Hermann Pitton How to enable the mpeg encoder is not found yet. The card comes up with gpio 0x0820000 for DVB-T. Priority: normal Signed-off-by: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.saa7134 | 2 +- linux/drivers/media/video/saa7134/saa7134-cards.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index dd979dca8..335aef4dc 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -10,7 +10,7 @@ 9 -> Medion 5044 10 -> Kworld/KuroutoShikou SAA7130-TVPCI 11 -> Terratec Cinergy 600 TV [153b:1143] - 12 -> Medion 7134 [16be:0003] + 12 -> Medion 7134 [16be:0003,16be:5000] 13 -> Typhoon TV+Radio 90031 14 -> ELSA EX-VISION 300TV [1048:226b] 15 -> ELSA EX-VISION 500TV [1048:226a] diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index e2dc0822b..54be8314f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4811,6 +4811,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x0003, .driver_data = SAA7134_BOARD_MD7134, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x16be, /* CTX946 analog TV, HW mpeg, DVB-T */ + .subdevice = 0x5000, /* only analog TV and DVB-T for now */ + .driver_data = SAA7134_BOARD_MD7134, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x1048, -- cgit v1.2.3 From 7820558f98ad177a1b4db0882e9f49cc93200aa6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Dec 2008 11:29:33 +0100 Subject: v4l2-ctl: List device links as such From: Jean Delvare Improvement to --list-devices: when a device node is actually a link to another device node, display it as such. Priority: normal Signed-off-by: Jean Delvare Signed-off-by: Hans Verkuil --- v4l2-apps/util/v4l2-ctl.cpp | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index 417721c57..7d5988571 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -1096,6 +1096,7 @@ static void list_devices() DIR *dp; struct dirent *ep; dev_vec files; + dev_map links; dev_map cards; struct v4l2_capability vcap; @@ -1119,6 +1120,37 @@ static void list_devices() } #endif + /* Find device nodes which are links to other device nodes */ + for (dev_vec::iterator iter = files.begin(); + iter != files.end(); ) { + char link[64+1]; + int link_len; + std::string target; + + link_len = readlink(iter->c_str(), link, 64); + if (link_len < 0) { /* Not a link or error */ + iter++; + continue; + } + link[link_len] = '\0'; + + /* Only remove from files list if target itself is in list */ + if (link[0] != '/') /* Relative link */ + target = std::string("/dev/"); + target += link; + if (find(files.begin(), files.end(), target) == files.end()) { + iter++; + continue; + } + + /* Move the device node from files to links */ + if (links[target].empty()) + links[target] = *iter; + else + links[target] += ", " + *iter; + files.erase(iter); + } + std::sort(files.begin(), files.end(), sort_on_device_name); for (dev_vec::iterator iter = files.begin(); @@ -1133,7 +1165,10 @@ static void list_devices() bus_info = (const char *)vcap.bus_info; if (cards[bus_info].empty()) cards[bus_info] += std::string((char *)vcap.card) + " (" + bus_info + "):\n"; - cards[bus_info] += "\t" + (*iter) + "\n"; + cards[bus_info] += "\t" + (*iter); + if (!(links[*iter].empty())) + cards[bus_info] += " <- " + links[*iter]; + cards[bus_info] += "\n"; } for (dev_map::iterator iter = cards.begin(); iter != cards.end(); ++iter) { -- cgit v1.2.3 From 3ccc9245fe4ae35845a4d5ed89581bf56165ae78 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 6 Dec 2008 20:25:14 +0100 Subject: uvcvideo: Add nodrop module parameter to turn incomplete frame drop off. From: Laurent Pinchart The driver drops incomplete uncompressed video frames to avoid confusing userspace with corrupt data. Add a nodrop module parameter to turn that behaviour off and make all frames available to userspace. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 3 +++ linux/drivers/media/video/uvc/uvc_video.c | 3 ++- linux/drivers/media/video/uvc/uvcvideo.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 0a0ef6611..424a02965 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -44,6 +44,7 @@ #define DRIVER_VERSION "v0.1.0" #endif +unsigned int uvc_no_drop_param; static unsigned int uvc_quirks_param; unsigned int uvc_trace_param; @@ -1945,6 +1946,8 @@ static void __exit uvc_cleanup(void) module_init(uvc_init); module_exit(uvc_cleanup); +module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(quirks, "Forced device quirks"); module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 3be776a47..b19e91dd5 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -1007,7 +1007,8 @@ int uvc_video_enable(struct uvc_video_device *video, int enable) return 0; } - if (video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) + if ((video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) || + uvc_no_drop_param) video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; else video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 09b169b69..4533e34ef 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -683,6 +683,7 @@ struct uvc_driver { #define UVC_WARN_MINMAX 0 #define UVC_WARN_PROBE_DEF 1 +extern unsigned int uvc_no_drop_param; extern unsigned int uvc_trace_param; #define uvc_trace(flag, msg...) \ -- cgit v1.2.3 From ed31b2b95aaeb2d32f11053cc521b798b3280195 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 6 Dec 2008 21:43:40 +0100 Subject: uvcvideo: Add a device quirk to prune bogus controls. From: Laurent Pinchart Bogus controls currently include processing unit auto controls for which no corresponding manual control is available. Such auto controls make little sense if any, and are known to crash at least the SiGma Micro webcam. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_ctrl.c | 57 ++++++++++++++++++++++++++++-- linux/drivers/media/video/uvc/uvc_driver.c | 3 +- linux/drivers/media/video/uvc/uvcvideo.h | 1 + 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 9de8a1db5..01c72935d 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -545,11 +545,16 @@ static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) return ctrl->data + id * ctrl->info->size; } -static inline int uvc_get_bit(const __u8 *data, int bit) +static inline int uvc_test_bit(const __u8 *data, int bit) { return (data[bit >> 3] >> (bit & 7)) & 1; } +static inline void uvc_clear_bit(__u8 *data, int bit) +{ + data[bit >> 3] &= ~(1 << (bit & 7)); +} + /* Extract the bit string specified by mapping->offset and mapping->size * from the little-endian data stored at 'data' and return the result as * a signed 32bit integer. Sign extension will be performed if the mapping @@ -1307,6 +1312,51 @@ end: return ret; } +/* + * Prune an entity of its bogus controls. This currently includes processing + * unit auto controls for which no corresponding manual control is available. + * Such auto controls make little sense if any, and are known to crash at + * least the SiGma Micro webcam. + */ +static void +uvc_ctrl_prune_entity(struct uvc_entity *entity) +{ + static const struct { + u8 idx_manual; + u8 idx_auto; + } blacklist[] = { + { 2, 11 }, /* Hue */ + { 6, 12 }, /* White Balance Temperature */ + { 7, 13 }, /* White Balance Component */ + }; + + u8 *controls; + unsigned int size; + unsigned int i; + + if (UVC_ENTITY_TYPE(entity) != VC_PROCESSING_UNIT) + return; + + controls = entity->processing.bmControls; + size = entity->processing.bControlSize; + + for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { + if (blacklist[i].idx_auto >= 8 * size || + blacklist[i].idx_manual >= 8 * size) + continue; + + if (!uvc_test_bit(controls, blacklist[i].idx_auto) || + uvc_test_bit(controls, blacklist[i].idx_manual)) + continue; + + uvc_trace(UVC_TRACE_CONTROL, "Auto control %u/%u has no " + "matching manual control, removing it.\n", entity->id, + blacklist[i].idx_auto); + + uvc_clear_bit(controls, blacklist[i].idx_auto); + } +} + /* * Initialize device controls. */ @@ -1333,6 +1383,9 @@ int uvc_ctrl_init_device(struct uvc_device *dev) bControlSize = entity->camera.bControlSize; } + if (dev->quirks & UVC_QUIRK_PRUNE_CONTROLS) + uvc_ctrl_prune_entity(entity); + for (i = 0; i < bControlSize; ++i) ncontrols += hweight8(bmControls[i]); @@ -1347,7 +1400,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev) ctrl = entity->controls; for (i = 0; i < bControlSize * 8; ++i) { - if (uvc_get_bit(bmControls, i) == 0) + if (uvc_test_bit(bmControls, i) == 0) continue; ctrl->entity = entity; diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 424a02965..343792f0f 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1896,7 +1896,8 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX - | UVC_QUIRK_IGNORE_SELECTOR_UNIT}, + | UVC_QUIRK_IGNORE_SELECTOR_UNIT + | UVC_QUIRK_PRUNE_CONTROLS }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, {} diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 4533e34ef..a699c0bb1 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -316,6 +316,7 @@ struct uvc_xu_control { #define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008 #define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 +#define UVC_QUIRK_PRUNE_CONTROLS 0x00000040 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 -- cgit v1.2.3 From 60738570eec2254bed5147ebd299cc8c408f365e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 7 Dec 2008 14:19:29 -0200 Subject: saa7134: Add support for Kworld Plus TV Analog Lite PCI From: Mauro Carvalho Chehab Thanks to Sistema Fenix (http://www.sistemafenix.com.br/) for sponsoring this development. Signed-off-by: Gilberto Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.saa7134 | 1 + linux/drivers/media/common/ir-keymaps.c | 61 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-cards.c | 44 ++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-input.c | 14 ++++++ linux/drivers/media/video/saa7134/saa7134.h | 1 + linux/include/media/ir-common.h | 1 + 6 files changed, 122 insertions(+) diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index dc67eef38..dd979dca8 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -151,3 +151,4 @@ 150 -> Zogis Real Angel 220 151 -> ADS Tech Instant HDTV [1421:0380] 152 -> Asus Tiger Rev:1.00 [1043:4857] +153 -> Kworld Plus TV Analog Lite PCI [17de:7128] diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 6c0a80f45..ee9931f56 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2441,6 +2441,67 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel); +/* Kworld Plus TV Analog Lite PCI IR + Mauro Carvalho Chehab + */ +IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { + [0x0c] = KEY_PROG1, /* Kworld key */ + [0x16] = KEY_CLOSECD, /* -> ) */ + [0x1d] = KEY_POWER2, + + [0x00] = KEY_1, + [0x01] = KEY_2, + [0x02] = KEY_3, /* Two keys have the same code: 3 and left */ + [0x03] = KEY_4, /* Two keys have the same code: 3 and right */ + [0x04] = KEY_5, + [0x05] = KEY_6, + [0x06] = KEY_7, + [0x07] = KEY_8, + [0x08] = KEY_9, + [0x0a] = KEY_0, + + [0x09] = KEY_AGAIN, + [0x14] = KEY_MUTE, + + [0x20] = KEY_UP, + [0x21] = KEY_DOWN, + [0x0b] = KEY_ENTER, + + [0x10] = KEY_CHANNELUP, + [0x11] = KEY_CHANNELDOWN, + + /* Couldn't map key left/key right since those + conflict with '3' and '4' scancodes + I dunno what the original driver does + */ + + [0x13] = KEY_VOLUMEUP, + [0x12] = KEY_VOLUMEDOWN, + + /* The lower part of the IR + There are several duplicated keycodes there. + Most of them conflict with digits. + Add mappings just to the unused scancodes. + Somehow, the original driver has a way to know, + but this doesn't seem to be on some GPIO. + Also, it is not related to the time between keyup + and keydown. + */ + [0x19] = KEY_PAUSE, /* Timeshift */ + [0x1a] = KEY_STOP, + [0x1b] = KEY_RECORD, + + [0x22] = KEY_TEXT, + + [0x15] = KEY_AUDIO, /* ((*)) */ + [0x0f] = KEY_ZOOM, + [0x1c] = KEY_SHUFFLE, /* snapshot */ + + [0x18] = KEY_RED, /* B */ + [0x23] = KEY_GREEN, /* C */ +}; +EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog); + IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { [0x20] = KEY_LIST, [0x00] = KEY_POWER, diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index d4c432cb3..e2dc0822b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4645,6 +4645,43 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG] = { + .name = "Kworld Plus TV Analog Lite PCI", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_YMEC_TVF_5533MF, + .radio_type = TUNER_TEA5767, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x80000700, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + .gpio = 0x100, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x200, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x200, + } }, + .radio = { + .name = name_radio, + .vmux = 1, + .amux = LINE1, + .gpio = 0x100, + }, + .mute = { + .name = name_mute, + .vmux = 8, + .amux = 2, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5691,6 +5728,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1043, .subdevice = 0x4878, /* REV:1.02G */ .driver_data = SAA7134_BOARD_ASUSTeK_TIGER_3IN1, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x17de, + .subdevice = 0x7128, + .driver_data = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG, }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -5979,6 +6022,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_507_9FM: case SAA7134_BOARD_GENIUS_TVGO_A11MCE: case SAA7134_BOARD_REAL_ANGEL_220: + case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 1c4bd413e..272490b92 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -97,6 +97,15 @@ static int build_key(struct saa7134_dev *dev) dprintk("build_key gpio=0x%x mask=0x%x data=%d\n", gpio, ir->mask_keycode, data); + switch (dev->board) { + case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: + if (data == ir->mask_keycode) + ir_input_nokey(ir->dev, &ir->ir); + else + ir_input_keydown(ir->dev, &ir->ir, data, data); + return 0; + } + if (ir->polling) { if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { @@ -586,6 +595,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x4000; polling = 50; /* ms */ break; + case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: + ir_codes = ir_codes_kworld_plus_tv_analog; + mask_keycode = 0x7f; + polling = 40; /* ms */ + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 82f9a889a..3bb599673 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -276,6 +276,7 @@ struct saa7134_format { #define SAA7134_BOARD_REAL_ANGEL_220 150 #define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151 #define SAA7134_BOARD_ASUSTeK_TIGER 152 +#define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h index 3a88e13a2..5bf2ea006 100644 --- a/linux/include/media/ir-common.h +++ b/linux/include/media/ir-common.h @@ -158,6 +158,7 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE]; #endif /* -- cgit v1.2.3 From 981e24fc10ca11ec7c751ed1c639ac72fa37d1c7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 8 Dec 2008 00:01:57 -0200 Subject: tda827x: fix printk message when in FM mode From: Mauro Carvalho Chehab CC: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tda827x.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/common/tuners/tda827x.c b/linux/drivers/media/common/tuners/tda827x.c index 83a017c53..501b05ba1 100644 --- a/linux/drivers/media/common/tuners/tda827x.c +++ b/linux/drivers/media/common/tuners/tda827x.c @@ -81,10 +81,11 @@ static void tda827x_set_std(struct dvb_frontend *fe, mode = "xx"; } - if (params->mode == V4L2_TUNER_RADIO) + if (params->mode == V4L2_TUNER_RADIO) { priv->sgIF = 88; /* if frequency is 5.5 MHz */ - - dprintk("setting tda827x to system %s\n", mode); + dprintk("setting tda827x to radio FM\n"); + } else + dprintk("setting tda827x to system %s\n", mode); } -- cgit v1.2.3 From 1d0ec557faade5b5844db7b6996e118080a87db3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 8 Dec 2008 01:49:33 -0200 Subject: tda827x: fix returned frequency From: Mauro Carvalho Chehab Probably due to a removed code, tda827x were doing some wrong calculus at the returned frequency. I suspect that the original idea were to return the programmed divisor converted into frequency again. However, the current code is sometimes multiplying the programmed frequency by 62500, and, on other cases, like radio, it dividing it by 1000. Instead of doing such math, let's just store the frequency value as requested by the caller module. CC: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tda827x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/common/tuners/tda827x.c b/linux/drivers/media/common/tuners/tda827x.c index 501b05ba1..a14fe817d 100644 --- a/linux/drivers/media/common/tuners/tda827x.c +++ b/linux/drivers/media/common/tuners/tda827x.c @@ -201,7 +201,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe, fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(priv->i2c_adap, &msg, 1); - priv->frequency = tuner_freq - if_freq; // FIXME + priv->frequency = params->frequency; priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; return 0; @@ -306,7 +306,7 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe, reg2[1] = 0x08; /* Vsync en */ i2c_transfer(priv->i2c_adap, &msg, 1); - priv->frequency = freq * 62500; + priv->frequency = params->frequency; return 0; } @@ -593,7 +593,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(priv->i2c_adap, &msg, 1); - priv->frequency = tuner_freq - if_freq; // FIXME + priv->frequency = params->frequency; priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; return 0; @@ -693,7 +693,7 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, tuner_reg[1] = 0x19 + (priv->lpsel << 1); i2c_transfer(priv->i2c_adap, &msg, 1); - priv->frequency = freq * 62500; + priv->frequency = params->frequency; return 0; } -- cgit v1.2.3 From ddfa62c7544e846044782ec43aad56cc331c69a9 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 8 Dec 2008 08:48:21 +0100 Subject: gspca - vc032x: Bad check of the sensor mi0360. From: Jean-Francois Moine Error was due to bad variable names. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index db5deb957..7c0586fe6 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -1456,7 +1456,7 @@ static const struct sensor_info sensor_info_data[] = { {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, /* (tested in vc032x_probe_sensor) */ -/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x4382, 0x24, 0x25, 0x01}, */ +/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ }; /* read 'len' bytes in gspca_dev->usb_buf */ @@ -1513,18 +1513,18 @@ static void read_sensor_register(struct gspca_dev *gspca_dev, msleep(1); } reg_r(gspca_dev, 0xa1, 0xb33e, 1); - hdata = gspca_dev->usb_buf[0]; + ldata = gspca_dev->usb_buf[0]; reg_r(gspca_dev, 0xa1, 0xb33d, 1); mdata = gspca_dev->usb_buf[0]; reg_r(gspca_dev, 0xa1, 0xb33c, 1); - ldata = gspca_dev->usb_buf[0]; - PDEBUG(D_PROBE, "Read Sensor %02x %02x%02x", + hdata = gspca_dev->usb_buf[0]; + PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x", hdata, mdata, ldata); reg_r(gspca_dev, 0xa1, 0xb334, 1); if (gspca_dev->usb_buf[0] == 0x02) - *value = (ldata << 8) + mdata; + *value = (hdata << 8) + mdata; else - *value = ldata; + *value = hdata; } static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) @@ -1551,7 +1551,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) /* special case for MI0360 */ if (ptsensor_info->sensorId == SENSOR_MI1310_SOC - && value == 0x4382) + && value == 0x8243) return ptsensor_info->sensorId; } return -1; -- cgit v1.2.3 From 1ae43e8ab9d6411a573a667d5dab1f36faa95c65 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 8 Dec 2008 09:13:53 +0100 Subject: gspca - vc032x: V and H flips added for sensors ov7660 and 7670. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 137 +++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 7c0586fe6..7b899a735 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -32,8 +32,10 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned char autogain; - unsigned char lightfreq; + __u8 autogain; + __u8 hflip; + __u8 vflip; + __u8 lightfreq; char qindex; char bridge; @@ -52,6 +54,10 @@ struct sd { /* V4L2 controls supported by the driver */ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); +static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); @@ -70,7 +76,38 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, -#define LIGHTFREQ_IDX 1 +/* next 2 controls work with ov7660 and ov7670 only */ +#define HFLIP_IDX 1 + { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mirror", + .minimum = 0, + .maximum = 1, + .step = 1, +#define HFLIP_DEF 0 + .default_value = HFLIP_DEF, + }, + .set = sd_sethflip, + .get = sd_gethflip, + }, +#define VFLIP_IDX 2 + { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Vflip", + .minimum = 0, + .maximum = 1, + .step = 1, +#define VFLIP_DEF 0 + .default_value = VFLIP_DEF, + }, + .set = sd_setvflip, + .get = sd_getvflip, + }, +#define LIGHTFREQ_IDX 3 { { .id = V4L2_CID_POWER_LINE_FREQUENCY, @@ -112,6 +149,11 @@ static struct v4l2_pix_format vc0323_mode[] = { .priv = 0}, }; +/* OV7660/7670 registers */ +#define OV7660_REG_MVFP 0x1e +#define OV7660_MVFP_MIRROR 0x20 +#define OV7660_MVFP_VFLIP 0x10 + static const __u8 mi0360_matrix[9] = { 0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50 }; @@ -1057,7 +1099,7 @@ static const __u8 ov7660_initVGA_data[][4] = { {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa}, {0x00, 0x12, 0x80, 0xaa}, {0x00, 0x12, 0x05, 0xaa}, - {0x00, 0x1e, 0x01, 0xaa}, + {0x00, 0x1e, 0x01, 0xaa}, /* MVFP */ {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */ {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */ {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa}, @@ -1111,7 +1153,7 @@ static const __u8 ov7660_initQVGA_data[][4] = { {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x8f, 0x50, 0xcc}, {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa}, {0x00, 0x12, 0x80, 0xaa}, {0x00, 0x12, 0x05, 0xaa}, - {0x00, 0x1e, 0x01, 0xaa}, + {0x00, 0x1e, 0x01, 0xaa}, /* MVFP */ {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */ {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */ {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa}, @@ -1217,7 +1259,8 @@ static const __u8 ov7670_initVGA_JPG[][4] = { {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa}, {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa}, {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x1e, 0x07, 0xaa}, {0x00, 0x21, 0x02, 0xaa}, + {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ + {0x00, 0x21, 0x02, 0xaa}, {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa}, {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa}, {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa}, @@ -1282,7 +1325,8 @@ static const __u8 ov7670_initVGA_JPG[][4] = { {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa}, {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa}, {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, - {0x00, 0x1e, 0x37, 0xaa}, {0x00, 0xaa, 0x14, 0xaa}, + {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ + {0x00, 0xaa, 0x14, 0xaa}, {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa}, {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa}, {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa}, @@ -1344,7 +1388,8 @@ static const __u8 ov7670_initQVGA_JPG[][4] = { {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa}, {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa}, {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x1e, 0x07, 0xaa}, {0x00, 0x21, 0x02, 0xaa}, + {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ + {0x00, 0x21, 0x02, 0xaa}, {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa}, {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa}, {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa}, @@ -1409,7 +1454,8 @@ static const __u8 ov7670_initQVGA_JPG[][4] = { {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa}, {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa}, {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, - {0x00, 0x1e, 0x37, 0xaa}, {0x00, 0xaa, 0x14, 0xaa}, + {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ + {0x00, 0xaa, 0x14, 0xaa}, {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa}, {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa}, {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa}, @@ -1695,10 +1741,25 @@ static int sd_config(struct gspca_dev *gspca_dev, } sd->qindex = 7; + sd->hflip = HFLIP_DEF; + sd->vflip = VFLIP_DEF; + if (sd->sensor == SENSOR_OV7670) { + sd->hflip = 1; + sd->vflip = 1; + } sd->autogain = AUTOGAIN_DEF; sd->lightfreq = FREQ_DEF; if (sd->sensor != SENSOR_OV7670) gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV7670: + break; + default: + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) + | (1 << VFLIP_IDX); + break; + } if (sd->bridge == BRIDGE_VC0321) { reg_r(gspca_dev, 0x8a, 0, 3); @@ -1727,6 +1788,27 @@ static void setquality(struct gspca_dev *gspca_dev) #endif } +/* for OV7660 and OV7670 only */ +static void sethvflip(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 data; + + switch (sd->sensor) { + case SENSOR_OV7660: + data = 1; + break; + case SENSOR_OV7670: + data = 7; + break; + default: + return; + } + data |= OV7660_MVFP_MIRROR * sd->hflip + | OV7660_MVFP_VFLIP * sd->vflip; + i2c_write(gspca_dev, OV7660_REG_MVFP, &data, 1); +} + static void setautogain(struct gspca_dev *gspca_dev) { #if 0 @@ -1880,6 +1962,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); msleep(100); setquality(gspca_dev); + sethvflip(gspca_dev); setautogain(gspca_dev); setlightfreq(gspca_dev); } @@ -1948,6 +2031,42 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->hflip = val; + if (gspca_dev->streaming) + sethvflip(gspca_dev); + return 0; +} + +static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->hflip; + return 0; +} + +static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->vflip = val; + if (gspca_dev->streaming) + sethvflip(gspca_dev); + return 0; +} + +static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->vflip; + return 0; +} + static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From 4b21644e75fa6a4ac9284d07045c28ac414a8f1d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 8 Dec 2008 09:17:32 +0100 Subject: gspca - vc032x: Remove the autogain control. From: Jean-Francois Moine This control was not coded. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 57 ++------------------------------ 1 file changed, 3 insertions(+), 54 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 7b899a735..244f30fc6 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -32,7 +32,6 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u8 autogain; __u8 hflip; __u8 vflip; __u8 lightfreq; @@ -52,8 +51,6 @@ struct sd { }; /* V4L2 controls supported by the driver */ -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); @@ -62,22 +59,8 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { - { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto Gain", - .minimum = 0, - .maximum = 1, - .step = 1, -#define AUTOGAIN_DEF 1 - .default_value = AUTOGAIN_DEF, - }, - .set = sd_setautogain, - .get = sd_getautogain, - }, /* next 2 controls work with ov7660 and ov7670 only */ -#define HFLIP_IDX 1 +#define HFLIP_IDX 0 { { .id = V4L2_CID_HFLIP, @@ -92,7 +75,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_sethflip, .get = sd_gethflip, }, -#define VFLIP_IDX 2 +#define VFLIP_IDX 1 { { .id = V4L2_CID_VFLIP, @@ -107,7 +90,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setvflip, .get = sd_getvflip, }, -#define LIGHTFREQ_IDX 3 +#define LIGHTFREQ_IDX 2 { { .id = V4L2_CID_POWER_LINE_FREQUENCY, @@ -1747,7 +1730,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->hflip = 1; sd->vflip = 1; } - sd->autogain = AUTOGAIN_DEF; sd->lightfreq = FREQ_DEF; if (sd->sensor != SENSOR_OV7670) gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); @@ -1809,20 +1791,6 @@ static void sethvflip(struct gspca_dev *gspca_dev) i2c_write(gspca_dev, OV7660_REG_MVFP, &data, 1); } -static void setautogain(struct gspca_dev *gspca_dev) -{ -#if 0 - struct sd *sd = (struct sd *) gspca_dev; - __u8 autoval; - - if (sd->autogain) - autoval = 0x42; - else - autoval = 0x02; - reg_w(gspca_dev->dev, 0xa0, autoval, 0x0180); -#endif -} - static void setlightfreq(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1963,7 +1931,6 @@ static int sd_start(struct gspca_dev *gspca_dev) msleep(100); setquality(gspca_dev); sethvflip(gspca_dev); - setautogain(gspca_dev); setlightfreq(gspca_dev); } return 0; @@ -2013,24 +1980,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->autogain = val; - if (gspca_dev->streaming) - setautogain(gspca_dev); - return 0; -} - -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->autogain; - return 0; -} - static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From 603200bf18af9978fc1d1f81485d51aa2b9ec05c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 8 Dec 2008 10:25:40 +0100 Subject: gspca - zc3xx: Remove the duplicated register names From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/zc3xx-reg.h | 8 ---- linux/drivers/media/video/gspca/zc3xx.c | 72 ++++++++++++++--------------- 2 files changed, 36 insertions(+), 44 deletions(-) diff --git a/linux/drivers/media/video/gspca/zc3xx-reg.h b/linux/drivers/media/video/gspca/zc3xx-reg.h index f52e09c2c..bfb559c3b 100644 --- a/linux/drivers/media/video/gspca/zc3xx-reg.h +++ b/linux/drivers/media/video/gspca/zc3xx-reg.h @@ -244,14 +244,6 @@ #define ZC3XX_R1CA_SHARPNESS04 0x01ca #define ZC3XX_R1CB_SHARPNESS05 0x01cb -/* Synchronization */ -#define ZC3XX_R190_SYNC00LOW 0x0190 -#define ZC3XX_R191_SYNC00MID 0x0191 -#define ZC3XX_R192_SYNC00HIGH 0x0192 -#define ZC3XX_R195_SYNC01LOW 0x0195 -#define ZC3XX_R196_SYNC01MID 0x0196 -#define ZC3XX_R197_SYNC01HIGH 0x0197 - /* Dead pixels */ #define ZC3XX_R250_DEADPIXELSMODE 0x0250 diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index ae4e30b52..210ac4979 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -2368,12 +2368,12 @@ static const struct usb_action hv7131b_50HZ[] = { /* 640x480*/ {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */ {0xaa, 0x22, 0x001b}, /* 00,22,1b,aa */ {0xaa, 0x23, 0x00fc}, /* 00,23,fc,aa */ - {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */ - {0xa0, 0x9b, ZC3XX_R191_SYNC00MID}, /* 01,91,9b,cc */ - {0xa0, 0x80, ZC3XX_R192_SYNC00HIGH}, /* 01,92,80,cc */ - {0xa0, 0x00, ZC3XX_R195_SYNC01LOW}, /* 01,95,00,cc */ - {0xa0, 0xea, ZC3XX_R196_SYNC01MID}, /* 01,96,ea,cc */ - {0xa0, 0x60, ZC3XX_R197_SYNC01HIGH}, /* 01,97,60,cc */ + {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ + {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,9b,cc */ + {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,ea,cc */ + {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,60,cc */ {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */ {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */ {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */ @@ -2393,12 +2393,12 @@ static const struct usb_action hv7131b_50HZScale[] = { /* 320x240 */ {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */ {0xaa, 0x22, 0x0012}, /* 00,22,12,aa */ {0xaa, 0x23, 0x0080}, /* 00,23,80,aa */ - {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */ - {0xa0, 0x9b, ZC3XX_R191_SYNC00MID}, /* 01,91,9b,cc */ - {0xa0, 0x80, ZC3XX_R192_SYNC00HIGH}, /* 01,92,80,cc */ - {0xa0, 0x01, ZC3XX_R195_SYNC01LOW}, /* 01,95,01,cc */ - {0xa0, 0xd4, ZC3XX_R196_SYNC01MID}, /* 01,96,d4,cc */ - {0xa0, 0xc0, ZC3XX_R197_SYNC01HIGH}, /* 01,97,c0,cc */ + {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ + {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,9b,cc */ + {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */ + {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,01,cc */ + {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,d4,cc */ + {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,c0,cc */ {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */ {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */ {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */ @@ -2418,12 +2418,12 @@ static const struct usb_action hv7131b_60HZ[] = { /* 640x480*/ {0xaa, 0x21, 0x0040}, /* 00,21,40,aa */ {0xaa, 0x22, 0x0013}, /* 00,22,13,aa */ {0xaa, 0x23, 0x004c}, /* 00,23,4c,aa */ - {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */ - {0xa0, 0x4d, ZC3XX_R191_SYNC00MID}, /* 01,91,4d,cc */ - {0xa0, 0x60, ZC3XX_R192_SYNC00HIGH}, /* 01,92,60,cc */ - {0xa0, 0x00, ZC3XX_R195_SYNC01LOW}, /* 01,95,00,cc */ - {0xa0, 0xc3, ZC3XX_R196_SYNC01MID}, /* 01,96,c3,cc */ - {0xa0, 0x50, ZC3XX_R197_SYNC01HIGH}, /* 01,97,50,cc */ + {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ + {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,4d,cc */ + {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,60,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,c3,cc */ + {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,50,cc */ {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */ {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */ {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */ @@ -2443,12 +2443,12 @@ static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */ {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */ {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */ {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */ - {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */ - {0xa0, 0x4d, ZC3XX_R191_SYNC00MID}, /* 01,91,4d,cc */ - {0xa0, 0x60, ZC3XX_R192_SYNC00HIGH}, /* 01,92,60,cc */ - {0xa0, 0x01, ZC3XX_R195_SYNC01LOW}, /* 01,95,01,cc */ - {0xa0, 0x86, ZC3XX_R196_SYNC01MID}, /* 01,96,86,cc */ - {0xa0, 0xa0, ZC3XX_R197_SYNC01HIGH}, /* 01,97,a0,cc */ + {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ + {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,4d,cc */ + {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,60,cc */ + {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,01,cc */ + {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,86,cc */ + {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,a0,cc */ {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */ {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */ {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */ @@ -2468,12 +2468,12 @@ static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/ {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */ {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */ {0xaa, 0x23, 0x0003}, /* 00,23,03,aa */ - {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */ - {0xa0, 0xf8, ZC3XX_R191_SYNC00MID}, /* 01,91,f8,cc */ - {0xa0, 0x00, ZC3XX_R192_SYNC00HIGH}, /* 01,92,00,cc */ - {0xa0, 0x00, ZC3XX_R195_SYNC01LOW}, /* 01,95,00,cc */ - {0xa0, 0x02, ZC3XX_R196_SYNC01MID}, /* 01,96,02,cc */ - {0xa0, 0x00, ZC3XX_R197_SYNC01HIGH}, /* 01,97,00,cc */ + {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ + {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,f8,cc */ + {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,00,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,02,cc */ + {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,00,cc */ {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ @@ -2493,12 +2493,12 @@ static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */ {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */ {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */ {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */ - {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */ - {0xa0, 0xf8, ZC3XX_R191_SYNC00MID}, /* 01,91,f8,cc */ - {0xa0, 0x00, ZC3XX_R192_SYNC00HIGH}, /* 01,92,00,cc */ - {0xa0, 0x00, ZC3XX_R195_SYNC01LOW}, /* 01,95,00,cc */ - {0xa0, 0x02, ZC3XX_R196_SYNC01MID}, /* 01,96,02,cc */ - {0xa0, 0x00, ZC3XX_R197_SYNC01HIGH}, /* 01,97,00,cc */ + {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ + {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,f8,cc */ + {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,00,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,02,cc */ + {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,00,cc */ {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ -- cgit v1.2.3 From 37fbb382d3b08a70e2c0b8b33734f5e88132efe6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 8 Dec 2008 10:41:04 +0100 Subject: gspca - zc3xx: Change the USB exchanges for the sensor pas202b. From: Jean-Francois Moine This sensor was declared as hdcs2020. The new exchanges have been extracted from the ms-win file usbvm31b.inf. The light frequency control has been added. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/zc3xx.c | 727 ++++++++++++++++---------------- 1 file changed, 352 insertions(+), 375 deletions(-) diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index 210ac4979..678070b93 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -51,16 +51,16 @@ struct sd { #define SENSOR_CS2102 0 #define SENSOR_CS2102K 1 #define SENSOR_GC0305 2 -#define SENSOR_HDCS2020 3 -#define SENSOR_HDCS2020b 4 -#define SENSOR_HV7131B 5 -#define SENSOR_HV7131C 6 -#define SENSOR_ICM105A 7 -#define SENSOR_MC501CB 8 -#define SENSOR_OV7620 9 -/*#define SENSOR_OV7648 9 - same values */ -#define SENSOR_OV7630C 10 -#define SENSOR_PAS106 11 +#define SENSOR_HDCS2020b 3 +#define SENSOR_HV7131B 4 +#define SENSOR_HV7131C 5 +#define SENSOR_ICM105A 6 +#define SENSOR_MC501CB 7 +#define SENSOR_OV7620 8 +/*#define SENSOR_OV7648 8 - same values */ +#define SENSOR_OV7630C 9 +#define SENSOR_PAS106 10 +#define SENSOR_PAS202B 11 #define SENSOR_PB0330 12 #define SENSOR_PO2030 13 #define SENSOR_TAS5130CK 14 @@ -1653,295 +1653,6 @@ static const struct usb_action gc0305_NoFliker[] = { {} }; -/* play poker with registers at your own risk !! */ -static const struct usb_action hdcs2020xx_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, - /* D0 ?? E0 did not start */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, - {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, - {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xaa, 0x02, 0x0002}, - {0xaa, 0x07, 0x0006}, - {0xaa, 0x08, 0x0002}, - {0xaa, 0x09, 0x0006}, - {0xaa, 0x0a, 0x0001}, - {0xaa, 0x0b, 0x0001}, - {0xaa, 0x0c, 0x0008}, - {0xaa, 0x0d, 0x0000}, - {0xaa, 0x10, 0x0000}, - {0xaa, 0x12, 0x0005}, - {0xaa, 0x13, 0x0063}, - {0xaa, 0x15, 0x0070}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x04, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x07, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x11, ZC3XX_R120_GAMMA00}, /* gamma ~4 */ - {0xa0, 0x37, ZC3XX_R121_GAMMA01}, - {0xa0, 0x58, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x91, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa6, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb8, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc7, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd3, ZC3XX_R128_GAMMA08}, - {0xa0, 0xde, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe6, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xed, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf3, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf8, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfb, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x23, ZC3XX_R131_GAMMA11}, - {0xa0, 0x20, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, - {0xa0, 0x16, ZC3XX_R134_GAMMA14}, - {0xa0, 0x13, ZC3XX_R135_GAMMA15}, - {0xa0, 0x10, ZC3XX_R136_GAMMA16}, - {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, - - {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf5, ZC3XX_R10B_RGB01}, - {0xa0, 0xff, ZC3XX_R10C_RGB02}, - {0xa0, 0xf9, ZC3XX_R10D_RGB10}, - {0xa0, 0x51, ZC3XX_R10E_RGB11}, - {0xa0, 0xf5, ZC3XX_R10F_RGB12}, - {0xa0, 0xfb, ZC3XX_R110_RGB20}, - {0xa0, 0xed, ZC3XX_R111_RGB21}, - {0xa0, 0x5f, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, - {0xaa, 0x20, 0x0004}, - {0xaa, 0x21, 0x003d}, - {0xaa, 0x03, 0x0041}, - {0xaa, 0x04, 0x0010}, - {0xaa, 0x05, 0x003d}, - {0xaa, 0x0e, 0x0001}, - {0xaa, 0x0f, 0x0000}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0195}, - {0xa1, 0x01, 0x0196}, - {0xa1, 0x01, 0x0197}, - {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x1d, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x85, ZC3XX_R118_BGAIN}, - {0xa1, 0x01, 0x0116}, - {0xa1, 0x01, 0x0118}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x1d, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x85, ZC3XX_R118_BGAIN}, - {0xa1, 0x01, 0x0116}, - {0xa1, 0x01, 0x0118}, -/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */ - {0xa0, 0x00, 0x0007}, - {} -}; - -static const struct usb_action hdcs2020xx_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, - {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, - {0xaa, 0x02, 0x0002}, - {0xaa, 0x07, 0x0006}, - {0xaa, 0x08, 0x0002}, - {0xaa, 0x09, 0x0006}, - {0xaa, 0x0a, 0x0001}, - {0xaa, 0x0b, 0x0001}, - {0xaa, 0x0c, 0x0008}, - {0xaa, 0x0d, 0x0000}, - {0xaa, 0x10, 0x0000}, - {0xaa, 0x12, 0x0005}, - {0xaa, 0x13, 0x0063}, - {0xaa, 0x15, 0x0070}, - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x04, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x07, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x11, ZC3XX_R120_GAMMA00}, /* gamma ~4*/ - {0xa0, 0x37, ZC3XX_R121_GAMMA01}, - {0xa0, 0x58, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x91, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa6, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb8, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc7, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd3, ZC3XX_R128_GAMMA08}, - {0xa0, 0xde, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe6, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xed, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf3, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf8, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfb, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x23, ZC3XX_R131_GAMMA11}, - {0xa0, 0x20, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, - {0xa0, 0x16, ZC3XX_R134_GAMMA14}, - {0xa0, 0x13, ZC3XX_R135_GAMMA15}, - {0xa0, 0x10, ZC3XX_R136_GAMMA16}, - {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xff, ZC3XX_R10B_RGB01}, - {0xa0, 0xff, ZC3XX_R10C_RGB02}, - {0xa0, 0xff, ZC3XX_R10D_RGB10}, - {0xa0, 0x60, ZC3XX_R10E_RGB11}, - {0xa0, 0xff, ZC3XX_R10F_RGB12}, - {0xa0, 0xff, ZC3XX_R110_RGB20}, - {0xa0, 0xff, ZC3XX_R111_RGB21}, - {0xa0, 0x60, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, - {0xaa, 0x20, 0x0002}, - {0xaa, 0x21, 0x001b}, - {0xaa, 0x03, 0x0044}, - {0xaa, 0x04, 0x0008}, - {0xaa, 0x05, 0x001b}, - {0xaa, 0x0e, 0x0001}, - {0xaa, 0x0f, 0x0000}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xeb, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0195}, - {0xa1, 0x01, 0x0196}, - {0xa1, 0x01, 0x0197}, - {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x1d, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x99, ZC3XX_R118_BGAIN}, - {0xa1, 0x01, 0x0116}, - {0xa1, 0x01, 0x0118}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x1d, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x99, ZC3XX_R118_BGAIN}, -/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */ - {0xa0, 0x00, 0x0007}, -/* {0xa0, 0x18, 0x00fe}, */ - {} -}; static const struct usb_action hdcs2020xb_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, @@ -4424,6 +4135,270 @@ static const struct usb_action pas106b_NoFliker[] = { {} }; +/* from usbvm31b.inf */ +static const struct usb_action pas202b_Initial[] = { /* 640x480 */ + {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ + {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ + {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ + {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ + {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ + {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ + {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ + {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */ + {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ + {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ + {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ + {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */ + {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ + {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,03,cc */ + {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ + {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,03,cc */ + {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ + {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */ + {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ + {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */ + {0xaa, 0x02, 0x0002}, /* 00,02,04,aa --> 02 */ + {0xaa, 0x07, 0x0006}, /* 00,07,06,aa */ + {0xaa, 0x08, 0x0002}, /* 00,08,02,aa */ + {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ + {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ + {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ + {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ + {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ + {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ + {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ + {0xaa, 0x13, 0x0063}, /* 00,13,63,aa */ + {0xaa, 0x15, 0x0070}, /* 00,15,70,aa */ + {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */ + {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ + {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ + {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */ + {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ + {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ + {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ + {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ + {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */ + {} +}; +static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ + {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ + {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ + {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ + {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ + {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ + {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ + {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ + {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */ + {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ + {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ + {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ + {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */ + {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,08,cc */ + {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,02,cc */ + {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */ + {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */ + {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ + {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */ + {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ + {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ + {0xaa, 0x02, 0x0002}, /* 00,02,02,aa */ + {0xaa, 0x07, 0x0006}, /* 00,07,06,aa */ + {0xaa, 0x08, 0x0002}, /* 00,08,02,aa */ + {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ + {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ + {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ + {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ + {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ + {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ + {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ + {0xaa, 0x13, 0x0063}, /* 00,13,63,aa */ + {0xaa, 0x15, 0x0070}, /* 00,15,70,aa */ + {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ + {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ + {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ + {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */ + {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ + {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ + {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ + {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ + {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */ + {} +}; +static const struct usb_action pas202b_50HZ[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ + {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ + {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ + {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ + {0xaa, 0x21, 0x0068}, /* 00,21,68,aa */ + {0xaa, 0x03, 0x0044}, /* 00,03,44,aa */ + {0xaa, 0x04, 0x0009}, /* 00,04,09,aa */ + {0xaa, 0x05, 0x0028}, /* 00,05,28,aa */ + {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ + {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ + {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,d2,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ + {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */ + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ + {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */ + {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ + {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ + {0xa0, 0xeb, ZC3XX_R020_HSYNC_3}, /* 00,20,eb,cc */ + {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ + {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ + {} +}; +static const struct usb_action pas202b_50HZScale[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ + {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ + {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ + {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ + {0xaa, 0x21, 0x006c}, /* 00,21,6c,aa */ + {0xaa, 0x03, 0x0041}, /* 00,03,41,aa */ + {0xaa, 0x04, 0x0009}, /* 00,04,09,aa */ + {0xaa, 0x05, 0x002c}, /* 00,05,2c,aa */ + {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ + {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ + {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ + {0xa0, 0xbe, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,be,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ + {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */ + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ + {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */ + {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ + {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ + {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ + {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ + {} +}; +static const struct usb_action pas202b_60HZ[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ + {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ + {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ + {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ + {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */ + {0xaa, 0x03, 0x0045}, /* 00,03,45,aa */ + {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ + {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ + {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ + {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ + {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,c0,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ + {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */ + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ + {0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */ + {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */ + {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */ + {0xa0, 0xf5, ZC3XX_R020_HSYNC_3}, /* 00,20,f5,cc */ + {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ + {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ + {} +}; +static const struct usb_action pas202b_60HZScale[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ + {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ + {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ + {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ + {0xaa, 0x21, 0x0004}, /* 00,21,04,aa */ + {0xaa, 0x03, 0x0042}, /* 00,03,42,aa */ + {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ + {0xaa, 0x05, 0x0004}, /* 00,05,04,aa */ + {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ + {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ + {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ + {0xa0, 0x9f, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,9f,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ + {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */ + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ + {0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */ + {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ + {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */ + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ + {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ + {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ + {} +}; +static const struct usb_action pas202b_NoFliker[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ + {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ + {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ + {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ + {0xaa, 0x21, 0x0020}, /* 00,21,20,aa */ + {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ + {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ + {0xaa, 0x05, 0x0020}, /* 00,05,20,aa */ + {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ + {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ + {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ + {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ + {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ + {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ + {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ + {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ + {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ + {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ + {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ + {} +}; +static const struct usb_action pas202b_NoFlikerScale[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ + {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ + {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ + {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ + {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */ + {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ + {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ + {0xaa, 0x05, 0x0010}, /* 00,05,10,aa */ + {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ + {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ + {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ + {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ + {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ + {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ + {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ + {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ + {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ + {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ + {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ + {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ + {} +}; + static const struct usb_action pb03303x_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, @@ -6338,7 +6313,7 @@ static __u8 i2c_write(struct gspca_dev *gspca_dev, reg_w_i(gspca_dev->dev, valL, 0x93); reg_w_i(gspca_dev->dev, valH, 0x94); reg_w_i(gspca_dev->dev, 0x01, 0x90); /* <- write command */ - msleep(5); + msleep(15); retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", reg, valH, valL, retbyte); @@ -6381,31 +6356,35 @@ static void setmatrix(struct gspca_dev *gspca_dev) {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50}; static const __u8 ov7620_matrix[9] = {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58}; + static const __u8 pas202b_matrix[9] = + {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f}; static const __u8 po2030_matrix[9] = {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; static const __u8 vf0250_matrix[9] = {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; + static const __u8 *matrix_tb[SENSOR_MAX] = { + NULL, /* SENSOR_CS2102 0 */ + NULL, /* SENSOR_CS2102K 1 */ + gc0305_matrix, /* SENSOR_GC0305 2 */ + NULL, /* SENSOR_HDCS2020b 3 */ + NULL, /* SENSOR_HV7131B 4 */ + NULL, /* SENSOR_HV7131C 5 */ + NULL, /* SENSOR_ICM105A 6 */ + NULL, /* SENSOR_MC501CB 7 */ + ov7620_matrix, /* SENSOR_OV7620 8 */ + NULL, /* SENSOR_OV7630C 9 */ + NULL, /* SENSOR_PAS106 10 */ + pas202b_matrix, /* SENSOR_PAS202B 11 */ + NULL, /* SENSOR_PB0330 12 */ + po2030_matrix, /* SENSOR_PO2030 13 */ + NULL, /* SENSOR_TAS5130CK 14 */ + NULL, /* SENSOR_TAS5130CXX 15 */ + vf0250_matrix, /* SENSOR_TAS5130C_VF0250 16 */ + }; - switch (sd->sensor) { - case SENSOR_GC0305: - case SENSOR_HV7131B: - matrix = gc0305_matrix; - break; - case SENSOR_MC501CB: - return; /* no matrix? */ - case SENSOR_OV7620: -/* case SENSOR_OV7648: */ - matrix = ov7620_matrix; - break; - case SENSOR_PO2030: - matrix = po2030_matrix; - break; - case SENSOR_TAS5130C_VF0250: - matrix = vf0250_matrix; - break; - default: /* matrix already loaded */ - return; - } + matrix = matrix_tb[sd->sensor]; + if (matrix == NULL) + return; /* matrix already loaded */ for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++) reg_w(gspca_dev->dev, matrix[i], 0x010a + i); } @@ -6621,42 +6600,42 @@ static int setlightfreq(struct gspca_dev *gspca_dev) {gc0305_NoFliker, gc0305_NoFliker, gc0305_50HZ, gc0305_50HZ, gc0305_60HZ, gc0305_60HZ}, -/* SENSOR_HDCS2020 3 */ - {NULL, NULL, - NULL, NULL, - NULL, NULL}, -/* SENSOR_HDCS2020b 4 */ +/* SENSOR_HDCS2020b 3 */ {hdcs2020b_NoFliker, hdcs2020b_NoFliker, hdcs2020b_50HZ, hdcs2020b_50HZ, hdcs2020b_60HZ, hdcs2020b_60HZ}, -/* SENSOR_HV7131B 5 */ +/* SENSOR_HV7131B 4 */ {hv7131b_NoFlikerScale, hv7131b_NoFliker, hv7131b_50HZScale, hv7131b_50HZ, hv7131b_60HZScale, hv7131b_60HZ}, -/* SENSOR_HV7131C 6 */ +/* SENSOR_HV7131C 5 */ {NULL, NULL, NULL, NULL, NULL, NULL}, -/* SENSOR_ICM105A 7 */ +/* SENSOR_ICM105A 6 */ {icm105a_NoFliker, icm105a_NoFlikerScale, icm105a_50HZ, icm105a_50HZScale, icm105a_60HZ, icm105a_60HZScale}, -/* SENSOR_MC501CB 8 */ +/* SENSOR_MC501CB 7 */ {MC501CB_NoFliker, MC501CB_NoFlikerScale, MC501CB_50HZ, MC501CB_50HZScale, MC501CB_60HZ, MC501CB_60HZScale}, -/* SENSOR_OV7620 9 */ +/* SENSOR_OV7620 8 */ {OV7620_NoFliker, OV7620_NoFliker, OV7620_50HZ, OV7620_50HZ, OV7620_60HZ, OV7620_60HZ}, -/* SENSOR_OV7630C 10 */ +/* SENSOR_OV7630C 9 */ {NULL, NULL, NULL, NULL, NULL, NULL}, -/* SENSOR_PAS106 11 */ +/* SENSOR_PAS106 10 */ {pas106b_NoFliker, pas106b_NoFliker, pas106b_50HZ, pas106b_50HZ, pas106b_60HZ, pas106b_60HZ}, +/* SENSOR_PAS202B 11 */ + {pas202b_NoFlikerScale, pas202b_NoFliker, + pas202b_50HZScale, pas202b_50HZ, + pas202b_60HZScale, pas202b_60HZ}, /* SENSOR_PB0330 12 */ {pb0330_NoFliker, pb0330_NoFlikerScale, pb0330_50HZ, pb0330_50HZScale, @@ -7038,15 +7017,15 @@ static int sd_config(struct gspca_dev *gspca_dev, 5, /* SENSOR_CS2102 0 */ 5, /* SENSOR_CS2102K 1 */ 4, /* SENSOR_GC0305 2 */ - 4, /* SENSOR_HDCS2020 3 */ - 4, /* SENSOR_HDCS2020b 4 */ - 4, /* SENSOR_HV7131B 5 */ - 4, /* SENSOR_HV7131C 6 */ - 4, /* SENSOR_ICM105A 7 */ - 4, /* SENSOR_MC501CB 8 */ - 3, /* SENSOR_OV7620 9 */ - 4, /* SENSOR_OV7630C 10 */ - 4, /* SENSOR_PAS106 11 */ + 4, /* SENSOR_HDCS2020b 3 */ + 4, /* SENSOR_HV7131B 4 */ + 4, /* SENSOR_HV7131C 5 */ + 4, /* SENSOR_ICM105A 6 */ + 4, /* SENSOR_MC501CB 7 */ + 3, /* SENSOR_OV7620 8 */ + 4, /* SENSOR_OV7630C 9 */ + 4, /* SENSOR_PAS106 10 */ + 4, /* SENSOR_PAS202B 11 */ 4, /* SENSOR_PB0330 12 */ 4, /* SENSOR_PO2030 13 */ 4, /* SENSOR_TAS5130CK 14 */ @@ -7102,8 +7081,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = SENSOR_ICM105A; break; case 0x0e: - PDEBUG(D_PROBE, "Find Sensor HDCS2020"); - sd->sensor = SENSOR_HDCS2020; + PDEBUG(D_PROBE, "Find Sensor PAS202B"); + sd->sensor = SENSOR_PAS202B; sd->sharpness = 1; break; case 0x0f: @@ -7196,7 +7175,6 @@ static int sd_config(struct gspca_dev *gspca_dev, case SENSOR_PO2030: gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); break; - case SENSOR_HDCS2020: case SENSOR_HV7131B: case SENSOR_HV7131C: case SENSOR_OV7630C: @@ -7226,15 +7204,15 @@ static int sd_start(struct gspca_dev *gspca_dev) {cs2102_InitialScale, cs2102_Initial}, /* 0 */ {cs2102K_InitialScale, cs2102K_Initial}, /* 1 */ {gc0305_Initial, gc0305_InitialScale}, /* 2 */ - {hdcs2020xx_InitialScale, hdcs2020xx_Initial}, /* 3 */ - {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 4 */ - {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 5 */ - {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */ - {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */ - {MC501CB_InitialScale, MC501CB_Initial}, /* 9 */ - {OV7620_mode0, OV7620_mode1}, /* 9 */ - {ov7630c_InitialScale, ov7630c_Initial}, /* 10 */ - {pas106b_InitialScale, pas106b_Initial}, /* 11 */ + {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 3 */ + {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 4 */ + {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 5 */ + {icm105axx_InitialScale, icm105axx_Initial}, /* 6 */ + {MC501CB_InitialScale, MC501CB_Initial}, /* 7 */ + {OV7620_mode0, OV7620_mode1}, /* 8 */ + {ov7630c_InitialScale, ov7630c_Initial}, /* 9 */ + {pas106b_InitialScale, pas106b_Initial}, /* 10 */ + {pas202b_Initial, pas202b_InitialScale}, /* 11 */ {pb0330xx_InitialScale, pb0330xx_Initial}, /* 12 */ /* or {pb03303x_InitialScale, pb03303x_Initial}, */ {PO2030_mode0, PO2030_mode1}, /* 13 */ @@ -7291,6 +7269,11 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_r(gspca_dev, 0x0008); reg_w(dev, 0x00, 0x0008); break; + case SENSOR_PAS202B: +#if 0/*fixme*/ + reg_r(gspca_dev, ZC3XX_R002_CLOCKSELECT); + /* fall thru */ +#endif case SENSOR_GC0305: reg_r(gspca_dev, 0x0008); /* fall thru */ @@ -7304,7 +7287,6 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_CS2102: /* gamma set in xxx_Initial */ case SENSOR_CS2102K: - case SENSOR_HDCS2020: case SENSOR_HDCS2020b: case SENSOR_PB0330: /* pb with chip_revision - see above */ case SENSOR_OV7630C: @@ -7317,6 +7299,7 @@ static int sd_start(struct gspca_dev *gspca_dev) setmatrix(gspca_dev); /* one more time? */ switch (sd->sensor) { case SENSOR_OV7620: + case SENSOR_PAS202B: reg_r(gspca_dev, 0x0180); /* from win */ reg_w(dev, 0x00, 0x0180); break; @@ -7328,37 +7311,29 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_GC0305: - case SENSOR_OV7620: reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ reg_w(dev, 0x15, 0x01ae); - sd->autogain = 0; - break; + /* fall thru */ + case SENSOR_PAS202B: case SENSOR_PO2030: - reg_w(dev, 0x40, 0x0117); /* (from win traces) */ - reg_r(gspca_dev, 0x0180); - break; - } - - setautogain(gspca_dev); - switch (sd->sensor) { - case SENSOR_GC0305: -/* setlightfreq(gspca_dev); ?? (end: 80 -> [18d]) */ - reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ - reg_w(dev, 0x15, 0x01ae); - reg_w(dev, 0x40, 0x0180); - reg_w(dev, 0x40, 0x0117); +/* reg_w(dev, 0x40, ZC3XX_R117_GGAIN); * (from win traces) */ reg_r(gspca_dev, 0x0180); - sd->autogain = 1; - setautogain(gspca_dev); break; case SENSOR_OV7620: + reg_w(dev, 0x09, 0x01ad); + reg_w(dev, 0x15, 0x01ae); i2c_read(gspca_dev, 0x13); /*fixme: returns 0xa3 */ i2c_write(gspca_dev, 0x13, 0xa3, 0x00); /*fixme: returned value to send? */ - reg_w(dev, 0x40, 0x0117); /* (from win traces) */ + reg_w(dev, 0x40, 0x0117); reg_r(gspca_dev, 0x0180); - setautogain(gspca_dev); - msleep(500); + break; + } + + setautogain(gspca_dev); + switch (sd->sensor) { + case SENSOR_PAS202B: + reg_w(dev, 0x00, 0x0007); /* (from win traces) */ break; case SENSOR_PO2030: msleep(500); @@ -7368,6 +7343,8 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(dev, 0x02, 0x0008); break; } + if (sd->sensor == SENSOR_PAS202B) + reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); return 0; } -- cgit v1.2.3 From f604f345801f710bdeeb769a51b4e203c91e5f24 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 8 Dec 2008 11:36:57 -0200 Subject: tda8290: fix FM radio From: Mauro Carvalho Chehab tda8290 were using some random video standard for FM. This results on random errors. Instead, program tda8290 in expert mode, using a configuration near the one specified on NXP datasheet for tda8295 (available on their site). Also, properly display that the device is on radio mode. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tda8290.c | 63 ++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/common/tuners/tda8290.c b/linux/drivers/media/common/tuners/tda8290.c index 637849ec8..6eaaacca0 100644 --- a/linux/drivers/media/common/tuners/tda8290.c +++ b/linux/drivers/media/common/tuners/tda8290.c @@ -33,6 +33,9 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); +static int deemphasis_50; +MODULE_PARM_DESC(deemphasis_50, "0 - 75us deemphasis; 1 - 50us deemphasis"); + /* ---------------------------------------------------------------------- */ struct tda8290_priv { @@ -162,9 +165,34 @@ static void set_audio(struct dvb_frontend *fe, mode = "xx"; } - tuner_dbg("setting tda829x to system %s\n", mode); + if (params->mode == V4L2_TUNER_RADIO) { + priv->tda8290_easy_mode = 0x01; /* Start with MN values */ + tuner_dbg("setting to radio FM\n"); + } else { + tuner_dbg("setting tda829x to system %s\n", mode); + } } +struct { + unsigned char seq[2]; +} fm_mode[] = { + { { 0x01, 0x81} }, /* Put device into expert mode */ + { { 0x03, 0x48} }, /* Disable NOTCH and VIDEO filters */ + { { 0x04, 0x04} }, /* Disable color carrier filter (SSIF) */ + { { 0x05, 0x04} }, /* ADC headroom */ + { { 0x06, 0x10} }, /* group delay flat */ + + { { 0x07, 0x00} }, /* use the same radio DTO values as a tda8295 */ + { { 0x08, 0x00} }, + { { 0x09, 0x80} }, + { { 0x0a, 0xda} }, + { { 0x0b, 0x4b} }, + { { 0x0c, 0x68} }, + + { { 0x0d, 0x00} }, /* PLL off, no video carrier detect */ + { { 0x14, 0x00} }, /* disable auto mute if no video */ +}; + static void tda8290_set_params(struct dvb_frontend *fe, struct analog_parameters *params) { @@ -201,15 +229,30 @@ static void tda8290_set_params(struct dvb_frontend *fe, tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); msleep(1); - expert_mode[1] = priv->tda8290_easy_mode + 0x80; - tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2); - tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2); - tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2); - if (priv->tda8290_easy_mode & 0x60) - tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2); - else - tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); - tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); + if (params->mode == V4L2_TUNER_RADIO) { + int i; + unsigned char deemphasis[] = { 0x13, 1 }; + + /* FIXME: allow using a different deemphasis */ + + if (deemphasis_50) + deemphasis[1] = 2; + + for (i = 0; i < ARRAY_SIZE(fm_mode); i++) + tuner_i2c_xfer_send(&priv->i2c_props, fm_mode[i].seq, 2); + + tuner_i2c_xfer_send(&priv->i2c_props, deemphasis, 2); + } else { + expert_mode[1] = priv->tda8290_easy_mode + 0x80; + tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2); + tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2); + tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2); + if (priv->tda8290_easy_mode & 0x60) + tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2); + else + tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); + tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); + } tda8290_i2c_bridge(fe, 1); -- cgit v1.2.3 From 97b478e31ccddc358a73628542bb2d32983abeac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Dec 2008 16:43:10 -0200 Subject: em28xx: fix Kworld Hybrid 330 (A316) support From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 8 +++----- linux/drivers/media/video/em28xx/em28xx-dvb.c | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 2ecc98af7..23d3820a2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1238,19 +1238,17 @@ struct em28xx_board em28xx_boards[] = { }, [EM2883_BOARD_KWORLD_HYBRID_A316] = { .name = "Kworld PlusTV HD Hybrid 330", - .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, -#if 0 /* FIXME: add an entry at em28xx-dvb */ + .mts_firmware = 1, .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, -#endif + .dvb_gpio = default_digital, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, + .gpio = default_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index ddc4f6a99..8d3ed7dc8 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -413,6 +413,7 @@ static int dvb_init(struct em28xx *dev) case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: + case EM2883_BOARD_KWORLD_HYBRID_A316: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: dvb->frontend = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, -- cgit v1.2.3 From 08ec824664f6a447c209655719260db8b329576a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Dec 2008 09:06:13 +0100 Subject: gspca - vc032x: Webcam 15b8:6002 and sensor po1200 added. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/vc032x.c | 331 +++++++++++++++++++++++++++++- 2 files changed, 324 insertions(+), 8 deletions(-) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index a38c87246..81d7d891c 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -271,6 +271,7 @@ spca561 10fd:7e50 FlyCam Usb 100 zc3xx 10fd:8050 Typhoon Webshot II USB 300k ov534 1415:2000 Sony HD Eye for PS3 (SLEH 00201) pac207 145f:013a Trust WB-1300N +vc032x 15b8:6002 HP 2.0 Megapixel rz406aa spca501 1776:501c Arowana 300K CMOS Camera t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 244f30fc6..b898f6def 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -47,7 +47,8 @@ struct sd { #define SENSOR_MI1310_SOC 3 #define SENSOR_OV7660 4 #define SENSOR_OV7670 5 -#define SENSOR_PO3130NC 6 +#define SENSOR_PO1200 6 +#define SENSOR_PO3130NC 7 }; /* V4L2 controls supported by the driver */ @@ -132,6 +133,14 @@ static struct v4l2_pix_format vc0323_mode[] = { .priv = 0}, }; +static struct v4l2_pix_format svga_mode[] = { + {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 800, + .sizeimage = 800 * 600 * 1 / 4 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0}, +}; + /* OV7660/7670 registers */ #define OV7660_REG_MVFP 0x1e #define OV7660_MVFP_MIRROR 0x20 @@ -1466,6 +1475,293 @@ static const __u8 ov7670_initQVGA_JPG[][4] = { {0x00, 0x77, 0x05, 0xaa }, {}, }; + +/* PO1200 - values from usbvm326.inf and ms-win trace */ +static const __u8 po1200_gamma[17] = { +#if 1 + 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, + 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff +#else +/*ms-win trace*/ + 0x01, 0x0b, 0x1e, 0x38, 0x51, 0x6b, 0x83, 0x9a, 0xaf, + 0xc1, 0xd0, 0xdd, 0xe8, 0xf2, 0xf9, 0xff, 0xff +#endif +}; +static const __u8 po1200_matrix[9] = { + 0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e +}; +static const __u8 po1200_initVGA_data[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, /* reset? */ +#if 0 + {0x00, 0x00, 0x64, 0xdd}, + {0xb3, 0x49, 0x11, 0xcc}, + {0x00, 0x00, 0x33, 0xdd}, +/*read b349*/ +#endif + {0xb0, 0x03, 0x19, 0xcc}, +/* {0x00, 0x00, 0x33, 0xdd}, */ + {0xb0, 0x04, 0x02, 0xcc}, + {0xb0, 0x02, 0x02, 0xcc}, + {0xb3, 0x5d, 0x00, 0xcc}, + {0xb3, 0x01, 0x01, 0xcc}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x65, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x02, 0xb2, 0xcc}, + {0xb3, 0x03, 0x18, 0xcc}, + {0xb3, 0x04, 0x15, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x02, 0xcc}, + {0xb3, 0x23, 0x58, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x03, 0xcc}, + {0xb3, 0x17, 0x1f, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb0, 0x54, 0x13, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x34, 0x01, 0xcc}, + {0xb3, 0x35, 0xdc, 0xcc}, + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x12, 0x05, 0xaa}, + {0x00, 0x13, 0x02, 0xaa}, + {0x00, 0x1e, 0xc6, 0xaa}, + {0x00, 0x21, 0x00, 0xaa}, + {0x00, 0x25, 0x02, 0xaa}, + {0x00, 0x3c, 0x4f, 0xaa}, + {0x00, 0x3f, 0xe0, 0xaa}, + {0x00, 0x42, 0xff, 0xaa}, + {0x00, 0x45, 0x34, 0xaa}, + {0x00, 0x55, 0xfe, 0xaa}, + {0x00, 0x59, 0xd3, 0xaa}, + {0x00, 0x5e, 0x04, 0xaa}, + {0x00, 0x61, 0xb8, 0xaa}, + {0x00, 0x62, 0x02, 0xaa}, + {0x00, 0xa7, 0x31, 0xaa}, + {0x00, 0xa9, 0x66, 0xaa}, + {0x00, 0xb0, 0x00, 0xaa}, + {0x00, 0xb1, 0x00, 0xaa}, + {0x00, 0xb3, 0x11, 0xaa}, + {0x00, 0xb6, 0x26, 0xaa}, + {0x00, 0xb7, 0x20, 0xaa}, + {0x00, 0xba, 0x04, 0xaa}, + {0x00, 0x88, 0x42, 0xaa}, + {0x00, 0x89, 0x9a, 0xaa}, + {0x00, 0x8a, 0x88, 0xaa}, + {0x00, 0x8b, 0x8e, 0xaa}, + {0x00, 0x8c, 0x3e, 0xaa}, + {0x00, 0x8d, 0x90, 0xaa}, + {0x00, 0x8e, 0x87, 0xaa}, + {0x00, 0x8f, 0x96, 0xaa}, + {0x00, 0x90, 0x3d, 0xaa}, + {0x00, 0x64, 0x00, 0xaa}, + {0x00, 0x65, 0x10, 0xaa}, + {0x00, 0x66, 0x20, 0xaa}, + {0x00, 0x67, 0x2b, 0xaa}, + {0x00, 0x68, 0x36, 0xaa}, + {0x00, 0x69, 0x49, 0xaa}, + {0x00, 0x6a, 0x5a, 0xaa}, + {0x00, 0x6b, 0x7f, 0xaa}, + {0x00, 0x6c, 0x9b, 0xaa}, + {0x00, 0x6d, 0xba, 0xaa}, + {0x00, 0x6e, 0xd4, 0xaa}, + {0x00, 0x6f, 0xea, 0xaa}, + {0x00, 0x70, 0x00, 0xaa}, + {0x00, 0x71, 0x10, 0xaa}, + {0x00, 0x72, 0x20, 0xaa}, + {0x00, 0x73, 0x2b, 0xaa}, + {0x00, 0x74, 0x36, 0xaa}, + {0x00, 0x75, 0x49, 0xaa}, + {0x00, 0x76, 0x5a, 0xaa}, + {0x00, 0x77, 0x7f, 0xaa}, + {0x00, 0x78, 0x9b, 0xaa}, + {0x00, 0x79, 0xba, 0xaa}, + {0x00, 0x7a, 0xd4, 0xaa}, + {0x00, 0x7b, 0xea, 0xaa}, + {0x00, 0x7c, 0x00, 0xaa}, + {0x00, 0x7d, 0x10, 0xaa}, + {0x00, 0x7e, 0x20, 0xaa}, + {0x00, 0x7f, 0x2b, 0xaa}, + {0x00, 0x80, 0x36, 0xaa}, + {0x00, 0x81, 0x49, 0xaa}, + {0x00, 0x82, 0x5a, 0xaa}, + {0x00, 0x83, 0x7f, 0xaa}, + {0x00, 0x84, 0x9b, 0xaa}, + {0x00, 0x85, 0xba, 0xaa}, + {0x00, 0x86, 0xd4, 0xaa}, + {0x00, 0x87, 0xea, 0xaa}, + {0x00, 0x57, 0x2a, 0xaa}, + {0x00, 0x03, 0x01, 0xaa}, + {0x00, 0x04, 0x10, 0xaa}, + {0x00, 0x05, 0x10, 0xaa}, + {0x00, 0x06, 0x10, 0xaa}, + {0x00, 0x07, 0x10, 0xaa}, + {0x00, 0x08, 0x13, 0xaa}, + {0x00, 0x0a, 0x00, 0xaa}, + {0x00, 0x0b, 0x10, 0xaa}, + {0x00, 0x0c, 0x20, 0xaa}, + {0x00, 0x0d, 0x18, 0xaa}, + {0x00, 0x22, 0x01, 0xaa}, + {0x00, 0x23, 0x60, 0xaa}, + {0x00, 0x25, 0x08, 0xaa}, + {0x00, 0x26, 0x82, 0xaa}, + {0x00, 0x2e, 0x0f, 0xaa}, + {0x00, 0x2f, 0x1e, 0xaa}, + {0x00, 0x30, 0x2d, 0xaa}, + {0x00, 0x31, 0x3c, 0xaa}, + {0x00, 0x32, 0x4b, 0xaa}, + {0x00, 0x33, 0x5a, 0xaa}, + {0x00, 0x34, 0x69, 0xaa}, + {0x00, 0x35, 0x78, 0xaa}, + {0x00, 0x36, 0x87, 0xaa}, + {0x00, 0x37, 0x96, 0xaa}, + {0x00, 0x38, 0xa5, 0xaa}, + {0x00, 0x39, 0xb4, 0xaa}, + {0x00, 0x3a, 0xc3, 0xaa}, + {0x00, 0x3b, 0xd2, 0xaa}, + {0x00, 0x3c, 0xe1, 0xaa}, + {0x00, 0x3e, 0xff, 0xaa}, + {0x00, 0x3f, 0xff, 0xaa}, + {0x00, 0x40, 0xff, 0xaa}, + {0x00, 0x41, 0xff, 0xaa}, + {0x00, 0x42, 0xff, 0xaa}, + {0x00, 0x43, 0xff, 0xaa}, + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x20, 0xc4, 0xaa}, + {0x00, 0x13, 0x03, 0xaa}, + {0x00, 0x3c, 0x50, 0xaa}, + {0x00, 0x61, 0x6a, 0xaa}, + {0x00, 0x51, 0x5b, 0xaa}, + {0x00, 0x52, 0x91, 0xaa}, + {0x00, 0x53, 0x4c, 0xaa}, + {0x00, 0x54, 0x50, 0xaa}, + {0x00, 0x56, 0x02, 0xaa}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x03, 0xcc}, + {0xb6, 0x02, 0x20, 0xcc}, + {0xb6, 0x05, 0x02, 0xcc}, + {0xb6, 0x04, 0x58, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x21, 0xcc}, + {0xb6, 0x18, 0x03, 0xcc}, + {0xb6, 0x17, 0xa9, 0xcc}, + {0xb6, 0x16, 0x80, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, + {0xb8, 0x06, 0x20, 0xcc}, + {0xb8, 0x07, 0x03, 0xcc}, + {0xb8, 0x08, 0x58, 0xcc}, + {0xb8, 0x09, 0x02, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0xd9, 0x0f, 0xaa}, + {0x00, 0xda, 0xaa, 0xaa}, + {0x00, 0xd9, 0x10, 0xaa}, + {0x00, 0xda, 0xaa, 0xaa}, + {0x00, 0xd9, 0x11, 0xaa}, + {0x00, 0xda, 0x00, 0xaa}, + {0x00, 0xd9, 0x12, 0xaa}, + {0x00, 0xda, 0xff, 0xaa}, + {0x00, 0xd9, 0x13, 0xaa}, + {0x00, 0xda, 0xff, 0xaa}, + {0x00, 0xe8, 0x11, 0xaa}, + {0x00, 0xe9, 0x12, 0xaa}, + {0x00, 0xea, 0x5c, 0xaa}, + {0x00, 0xeb, 0xff, 0xaa}, + {0x00, 0xd8, 0x80, 0xaa}, + {0x00, 0xe6, 0x02, 0xaa}, + {0x00, 0xd6, 0x40, 0xaa}, + {0x00, 0xe3, 0x05, 0xaa}, + {0x00, 0xe0, 0x40, 0xaa}, + {0x00, 0xde, 0x03, 0xaa}, + {0x00, 0xdf, 0x03, 0xaa}, + {0x00, 0xdb, 0x02, 0xaa}, + {0x00, 0xdc, 0x00, 0xaa}, + {0x00, 0xdd, 0x03, 0xaa}, + {0x00, 0xe1, 0x08, 0xaa}, + {0x00, 0xe2, 0x01, 0xaa}, + {0x00, 0xd6, 0x40, 0xaa}, + {0x00, 0xe4, 0x40, 0xaa}, + {0x00, 0xa8, 0x9f, 0xaa}, + {0x00, 0xb4, 0x16, 0xaa}, + {0xb0, 0x02, 0x06, 0xcc}, + {0xb0, 0x18, 0x06, 0xcc}, + {0xb0, 0x19, 0x06, 0xcc}, + {0xb3, 0x5d, 0x18, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, + {0xb3, 0x06, 0x00, 0xcc}, + {0x00, 0xb4, 0x0e, 0xaa}, + {0x00, 0xb5, 0x49, 0xaa}, + {0x00, 0xb6, 0x1c, 0xaa}, + {0x00, 0xb7, 0x96, 0xaa}, +/* end of usbvm326.inf - start of ms-win trace */ + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x3d, 0xcc}, +/*read b306*/ + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x1a, 0x09, 0xaa}, + {0x00, 0x1b, 0x8a, 0xaa}, +/*read b827*/ + {0xb8, 0x27, 0x00, 0xcc}, + {0xb8, 0x26, 0x60, 0xcc}, + {0xb8, 0x26, 0x60, 0xcc}, +/*gamma - to do?*/ + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0xae, 0x84, 0xaa}, +/*gamma again*/ + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x96, 0xa0, 0xaa}, +/*matrix*/ + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x91, 0x35, 0xaa}, + {0x00, 0x92, 0x22, 0xaa}, +/*gamma*/ + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x95, 0x85, 0xaa}, +/*matrix*/ + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x61, 0xb8, 0xaa}, + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x4d, 0x20, 0xaa}, + {0xb8, 0x22, 0x40, 0xcc}, + {0xb8, 0x23, 0x40, 0xcc}, + {0xb8, 0x24, 0x40, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0x00, 0x00, 0x64, 0xdd}, + {0x00, 0x03, 0x01, 0xaa}, +/*read 46*/ + {0x00, 0x46, 0x3c, 0xaa}, + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x16, 0x40, 0xaa}, + {0x00, 0x17, 0x40, 0xaa}, + {0x00, 0x18, 0x40, 0xaa}, + {0x00, 0x19, 0x41, 0xaa}, + {0x00, 0x03, 0x01, 0xaa}, + {0x00, 0x46, 0x3c, 0xaa}, + {0x00, 0x00, 0x18, 0xdd}, +/*read bfff*/ + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0x1e, 0x46, 0xaa}, + {0x00, 0xa8, 0x8f, 0xaa}, + {0x00, 0x03, 0x00, 0xaa}, + {0x00, 0xb4, 0x1c, 0xaa}, + {0x00, 0xb5, 0x92, 0xaa}, + {0x00, 0xb6, 0x39, 0xaa}, + {0x00, 0xb7, 0x24, 0xaa}, +/*write 89 0400 1415*/ +}; + struct sensor_info { int sensorId; __u8 I2cAdd; @@ -1486,6 +1782,7 @@ static const struct sensor_info sensor_info_data[] = { {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, /* (tested in vc032x_probe_sensor) */ /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ + {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, }; /* read 'len' bytes in gspca_dev->usb_buf */ @@ -1709,6 +2006,9 @@ static int sd_config(struct gspca_dev *gspca_dev, case SENSOR_OV7670: PDEBUG(D_PROBE, "Find Sensor OV7670"); break; + case SENSOR_PO1200: + PDEBUG(D_PROBE, "Find Sensor PO1200"); + break; case SENSOR_PO3130NC: PDEBUG(D_PROBE, "Find Sensor PO3130NC"); break; @@ -1719,8 +2019,13 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vc0321_mode; cam->nmodes = ARRAY_SIZE(vc0321_mode); } else { - cam->cam_mode = vc0323_mode; - cam->nmodes = ARRAY_SIZE(vc0323_mode); + if (sensor != SENSOR_PO1200) { + cam->cam_mode = vc0323_mode; + cam->nmodes = ARRAY_SIZE(vc0323_mode); + } else { + cam->cam_mode = svga_mode; + cam->nmodes = ARRAY_SIZE(svga_mode); + } } sd->qindex = 7; @@ -1895,6 +2200,11 @@ static int sd_start(struct gspca_dev *gspca_dev) } usb_exchange(gspca_dev, po3130_rundata); break; + case SENSOR_PO1200: + GammaT = po1200_gamma; + MatrixT = po1200_matrix; + usb_exchange(gspca_dev, po1200_initVGA_data); + break; default: PDEBUG(D_PROBE, "Damned !! no sensor found Bye"); return -EMEDIUMTYPE; @@ -1927,11 +2237,15 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev->dev, 0xa0, 0x23, 0xb800); * ISP CTRL_BAS */ /* set the led on 0x0892 0x0896 */ - reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); - msleep(100); - setquality(gspca_dev); - sethvflip(gspca_dev); - setlightfreq(gspca_dev); + if (sd->sensor != SENSOR_PO1200) { + reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); + msleep(100); + setquality(gspca_dev); + sethvflip(gspca_dev); + setlightfreq(gspca_dev); + } else { + reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); + } } return 0; } @@ -2078,6 +2392,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0ac8, 0x0328), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x0ac8, 0xc001), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x0ac8, 0xc002), .driver_info = BRIDGE_VC0321}, + {USB_DEVICE(0x15b8, 0x6002), .driver_info = BRIDGE_VC0323}, {USB_DEVICE(0x17ef, 0x4802), .driver_info = BRIDGE_VC0323}, {} }; -- cgit v1.2.3 From eb8aba0ce02c6d663348dfc8c7caaa38af7a6549 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Dec 2008 09:13:05 +0100 Subject: gspca - vc032x: Bad detection of sensor mi0360. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index b898f6def..15dc660a5 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -1878,7 +1878,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) /* special case for MI0360 */ if (ptsensor_info->sensorId == SENSOR_MI1310_SOC && value == 0x8243) - return ptsensor_info->sensorId; + return SENSOR_MI0360; } return -1; } -- cgit v1.2.3 From 81fedcd49f2a2f04adc9e38e7cf4747218d596b2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Dec 2008 09:45:14 +0100 Subject: gspca - ov534: Improve payload handling. From: Jim Paris Frame data in bulk transfers is separated into 2048-byte payloads. Each payload has its own header. Priority: normal Signed-off-by: Jim Paris Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 28a798279..74bb7962e 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -1,6 +1,7 @@ /* * ov534/ov772x gspca driver * Copyright (C) 2008 Antonio Ospite + * Copyright (C) 2008 Jim Paris * * Based on a prototype written by Mark Ferrell * USB protocol reverse engineered by Jim Paris @@ -193,8 +194,8 @@ static const __u8 ov534_reg_initdata[][2] = { { 0x1c, 0x00 }, { 0x1d, 0x40 }, - { 0x1d, 0x02 }, - { 0x1d, 0x00 }, + { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */ + { 0x1d, 0x00 }, /* payload size */ { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ { 0x1d, 0x58 }, /* frame size */ { 0x1d, 0x00 }, /* frame size */ @@ -325,7 +326,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - cam->bulk_size = 2048; + cam->bulk_size = 16384; cam->bulk_nurbs = 2; return 0; @@ -402,6 +403,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, struct sd *sd = (struct sd *) gspca_dev; __u32 this_pts; int this_fid; + int remaining_len = len; + __u8 *next_data = data; + +scan_next: + if (remaining_len <= 0) + return; + + data = next_data; + len = min(remaining_len, 2048); + remaining_len -= len; + next_data += len; /* Payloads are prefixed with a the UVC-style header. We consider a frame to start when the FID toggles, or the PTS @@ -452,12 +464,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, gspca_frame_add(gspca_dev, LAST_PACKET, frame, NULL, 0); } - /* Done */ - return; + /* Done this payload */ + goto scan_next; discard: /* Discard data until a new frame starts. */ gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); + goto scan_next; } /* sub-driver description */ -- cgit v1.2.3 From 88fe68b0680d49807a552b016bee47a5020b87b3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Dec 2008 09:47:44 +0100 Subject: gspca - ov534: Explicitly initialize frame format. From: Jim Paris Set frame format registers 0x0a and 0x0b to explicit values rather than relying on reset-time defaults. Priority: normal Signed-off-by: Jim Paris Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 74bb7962e..66a7bd2f6 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -200,6 +200,10 @@ static const __u8 ov534_reg_initdata[][2] = { { 0x1d, 0x58 }, /* frame size */ { 0x1d, 0x00 }, /* frame size */ + { 0x1c, 0x0a }, + { 0x1d, 0x08 }, /* turn on UVC header */ + { 0x1d, 0x0e }, /* .. */ + { 0x8d, 0x1c }, { 0x8e, 0x80 }, { 0xe5, 0x04 }, -- cgit v1.2.3 From e826ea04411b7254088a42b69162390d6432f3bc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Dec 2008 09:50:44 +0100 Subject: gspca - main: Fix vidioc_s_jpegcomp locking. From: Jim Paris Priority: high Signed-off-by: Jim Paris Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 4fda0fca6..7066c9daf 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1320,10 +1320,10 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, struct gspca_dev *gspca_dev = priv; int ret; - if (mutex_lock_interruptible(&gspca_dev->usb_lock)) - return -ERESTARTSYS; if (!gspca_dev->sd_desc->set_jcomp) return -EINVAL; + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); mutex_unlock(&gspca_dev->usb_lock); return ret; -- cgit v1.2.3 From 52e7cacf69005e1a115cceac3f79808852bb09dd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Dec 2008 10:02:42 +0100 Subject: gspca - main: Allow subdrivers to handle v4l2_streamparm requests. From: Jim Paris Add get_streamparm and set_streamparm operations so subdrivers can get/set stream parameters such as framerate. Priority: normal Signed-off-by: Jim Paris Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 22 ++++++++++++++++++++++ linux/drivers/media/video/gspca/gspca.h | 4 ++++ 2 files changed, 26 insertions(+) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 7066c9daf..71e7afe1b 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1337,6 +1337,17 @@ static int vidioc_g_parm(struct file *filp, void *priv, memset(parm, 0, sizeof *parm); parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm->parm.capture.readbuffers = gspca_dev->nbufread; + + if (gspca_dev->sd_desc->get_streamparm) { + int ret; + + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); + mutex_unlock(&gspca_dev->usb_lock); + return ret; + } + return 0; } @@ -1351,6 +1362,17 @@ static int vidioc_s_parm(struct file *filp, void *priv, parm->parm.capture.readbuffers = gspca_dev->nbufread; else gspca_dev->nbufread = n; + + if (gspca_dev->sd_desc->set_streamparm) { + int ret; + + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); + mutex_unlock(&gspca_dev->usb_lock); + return ret; + } + return 0; } diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index 15db13296..79cef31a5 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -74,6 +74,8 @@ typedef void (*cam_v_op) (struct gspca_dev *); typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *); typedef int (*cam_jpg_op) (struct gspca_dev *, struct v4l2_jpegcompression *); +typedef int (*cam_streamparm_op) (struct gspca_dev *, + struct v4l2_streamparm *); typedef int (*cam_qmnu_op) (struct gspca_dev *, struct v4l2_querymenu *); typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, @@ -106,6 +108,8 @@ struct sd_desc { cam_jpg_op get_jcomp; cam_jpg_op set_jcomp; cam_qmnu_op querymenu; + cam_streamparm_op get_streamparm; + cam_streamparm_op set_streamparm; }; /* packet types when moving from iso buf to frame buf */ -- cgit v1.2.3 From cd7fe8de6217a244b405e379bb843357c872fc78 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Dec 2008 10:06:20 +0100 Subject: gspca - ov534: Add framerate support. From: Jim Paris Add support for getting and setting framerate via v4l2 controls, rather than setting a fixed value at module insertion. Priority: normal Signed-off-by: Jim Paris Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 115 ++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 37 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 66a7bd2f6..cd5c302d6 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -43,14 +43,12 @@ MODULE_AUTHOR("Antonio Ospite "); MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver"); MODULE_LICENSE("GPL"); -/* global parameters */ -static int frame_rate; - /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ __u32 last_fid; __u32 last_pts; + int frame_rate; }; /* V4L2 controls supported by the driver */ @@ -296,6 +294,40 @@ static const __u8 ov772x_reg_initdata[][2] = { { 0x0c, 0xd0 } }; +/* set framerate */ +static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int fr = sd->frame_rate; + + switch (fr) { + case 50: + sccb_reg_write(gspca_dev->dev, 0x11, 0x01); + sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); + ov534_reg_write(gspca_dev->dev, 0xe5, 0x02); + break; + case 40: + sccb_reg_write(gspca_dev->dev, 0x11, 0x02); + sccb_reg_write(gspca_dev->dev, 0x0d, 0xc1); + ov534_reg_write(gspca_dev->dev, 0xe5, 0x04); + break; +/* case 30: */ + default: + fr = 30; + sccb_reg_write(gspca_dev->dev, 0x11, 0x04); + sccb_reg_write(gspca_dev->dev, 0x0d, 0x81); + ov534_reg_write(gspca_dev->dev, 0xe5, 0x02); + break; + case 15: + sccb_reg_write(gspca_dev->dev, 0x11, 0x03); + sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); + ov534_reg_write(gspca_dev->dev, 0xe5, 0x04); + break; + } + + sd->frame_rate = fr; + PDEBUG(D_PROBE, "frame_rate: %d", fr); +} /* setup method */ static void ov534_setup(struct usb_device *udev) @@ -339,38 +371,8 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - int fr; - ov534_setup(gspca_dev->dev); - - fr = frame_rate; - - switch (fr) { - case 50: - sccb_reg_write(gspca_dev->dev, 0x11, 0x01); - sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); - ov534_reg_write(gspca_dev->dev, 0xe5, 0x02); - break; - case 40: - sccb_reg_write(gspca_dev->dev, 0x11, 0x02); - sccb_reg_write(gspca_dev->dev, 0x0d, 0xc1); - ov534_reg_write(gspca_dev->dev, 0xe5, 0x04); - break; -/* case 30: */ - default: - fr = 30; - sccb_reg_write(gspca_dev->dev, 0x11, 0x04); - sccb_reg_write(gspca_dev->dev, 0x0d, 0x81); - ov534_reg_write(gspca_dev->dev, 0xe5, 0x02); - break; - case 15: - sccb_reg_write(gspca_dev->dev, 0x11, 0x03); - sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); - ov534_reg_write(gspca_dev->dev, 0xe5, 0x04); - break; - } - - PDEBUG(D_PROBE, "frame_rate: %d", fr); + ov534_set_frame_rate(gspca_dev); return 0; } @@ -477,6 +479,46 @@ discard: goto scan_next; } +/* get stream parameters (framerate) */ +int sd_get_streamparm(struct gspca_dev *gspca_dev, + struct v4l2_streamparm *parm) +{ + struct v4l2_captureparm *cp = &parm->parm.capture; + struct v4l2_fract *tpf = &cp->timeperframe; + struct sd *sd = (struct sd *) gspca_dev; + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + cp->capability |= V4L2_CAP_TIMEPERFRAME; + tpf->numerator = 1; + tpf->denominator = sd->frame_rate; + + return 0; +} + +/* set stream parameters (framerate) */ +int sd_set_streamparm(struct gspca_dev *gspca_dev, + struct v4l2_streamparm *parm) +{ + struct v4l2_captureparm *cp = &parm->parm.capture; + struct v4l2_fract *tpf = &cp->timeperframe; + struct sd *sd = (struct sd *) gspca_dev; + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* Set requested framerate */ + sd->frame_rate = tpf->denominator / tpf->numerator; + ov534_set_frame_rate(gspca_dev); + + /* Return the actual framerate */ + tpf->numerator = 1; + tpf->denominator = sd->frame_rate; + + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -487,6 +529,8 @@ static const struct sd_desc sd_desc = { .start = sd_start, .stopN = sd_stopN, .pkt_scan = sd_pkt_scan, + .get_streamparm = sd_get_streamparm, + .set_streamparm = sd_set_streamparm, }; /* -- module initialisation -- */ @@ -534,6 +578,3 @@ static void __exit sd_mod_exit(void) module_init(sd_mod_init); module_exit(sd_mod_exit); - -module_param(frame_rate, int, 0644); -MODULE_PARM_DESC(frame_rate, "Frame rate (15, 30, 40, 50)"); -- cgit v1.2.3 From 12583b9f4af4d04cce76742c9859bff4068e6345 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 10 Dec 2008 22:27:39 +0100 Subject: [PATCH] short help for Technisat cards to select the right configuration From: Patrick Boettcher This patch adds a short help for Technisat cards to help the user selecting the right configuration for his card(s). Priority: normal Signed-off-by: Uwe Bugla Signed-off-by: Patrick Boettcher --- linux/Documentation/dvb/technisat.txt | 69 +++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 linux/Documentation/dvb/technisat.txt diff --git a/linux/Documentation/dvb/technisat.txt b/linux/Documentation/dvb/technisat.txt new file mode 100644 index 000000000..cdf6ee4b2 --- /dev/null +++ b/linux/Documentation/dvb/technisat.txt @@ -0,0 +1,69 @@ +How to set up the Technisat devices +=================================== + +1) Find out what device you have +================================ + +First start your linux box with a shipped kernel: +lspci -vvv for a PCI device (lsusb -vvv for an USB device) will show you for example: +02:0b.0 Network controller: Techsan Electronics Co Ltd B2C2 FlexCopII DVB chip / Technisat SkyStar2 DVB card (rev 02) + +dmesg | grep frontend may show you for example: +DVB: registering frontend 0 (Conexant CX24123/CX24109)... + +2) Kernel compilation: +====================== + +If the Technisat is the only TV device in your box get rid of unnecessary modules and check this one: +"Multimedia devices" => "Customise analog and hybrid tuner modules to build" +In this directory uncheck every driver which is activated there. + +Then please activate: +2a) Main module part: + +a.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" +b.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC PCI" in case of a PCI card OR +c.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC USB" in case of an USB 1.1 adapter +d.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Enable debug for the B2C2 FlexCop drivers" +Notice: d.) is helpful for troubleshooting + +2b) Frontend module part: + +1.) Revision 2.3: +a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build" +b.)"Multimedia devices" => "Customise DVB frontends" => "Zarlink VP310/MT312/ZL10313 based" + +2.) Revision 2.6: +a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build" +b.)"Multimedia devices" => "Customise DVB frontends" => "ST STV0299 based" + +3.) Revision 2.7: +a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build" +b.)"Multimedia devices" => "Customise DVB frontends" => "Samsung S5H1420 based" +c.)"Multimedia devices" => "Customise DVB frontends" => "Integrant ITD1000 Zero IF tuner for DVB-S/DSS" +d.)"Multimedia devices" => "Customise DVB frontends" => "ISL6421 SEC controller" + +4.) Revision 2.8: +a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build" +b.)"Multimedia devices" => "Customise DVB frontends" => "Conexant CX24113/CX24128 tuner for DVB-S/DSS" +c.)"Multimedia devices" => "Customise DVB frontends" => "Conexant CX24123 based" +d.)"Multimedia devices" => "Customise DVB frontends" => "ISL6421 SEC controller" + +5.) DVB-T card: +a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build" +b.)"Multimedia devices" => "Customise DVB frontends" => "Zarlink MT352 based" + +6.) DVB-C card: +a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build" +b.)"Multimedia devices" => "Customise DVB frontends" => "ST STV0297 based" + +7.) ATSC card 1st generation: +a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build" +b.)"Multimedia devices" => "Customise DVB frontends" => "Broadcom BCM3510" + +8.) ATSC card 2nd generation: +a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build" +b.)"Multimedia devices" => "Customise DVB frontends" => "NxtWave Communications NXT2002/NXT2004 based" +c.)"Multimedia devices" => "Customise DVB frontends" => "LG Electronics LGDT3302/LGDT3303 based" + +Author: Uwe Bugla December 2008 -- cgit v1.2.3 From d2c689d834f3c29dd15a07d5d421fe6c3124880e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 11 Dec 2008 09:02:18 +0100 Subject: gspca - vc032x: Fix frame overflow errors with vc0321. From: Hans de Goede The vc0321 sends some additional data after sending the complete frame, we ignore this. Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 15dc660a5..fb05d866f 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -2291,6 +2291,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data, len); return; } + + /* The vc0321 sends some additional data after sending the complete + * frame, we ignore this. */ + if (sd->bridge == BRIDGE_VC0321 + && len > frame->v4l2_buf.length - (frame->data_end - frame->data)) + len = frame->v4l2_buf.length - (frame->data_end - frame->data); gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -- cgit v1.2.3 From 387f75a867f3844275f727de62d0dc8e7f25a64b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 12 Dec 2008 08:48:06 +0100 Subject: gspca - vc032x: Remove the unused quality/qindex. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index fb05d866f..5812af963 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -36,7 +36,6 @@ struct sd { __u8 vflip; __u8 lightfreq; - char qindex; char bridge; #define BRIDGE_VC0321 0 #define BRIDGE_VC0323 1 @@ -2028,7 +2027,6 @@ static int sd_config(struct gspca_dev *gspca_dev, } } - sd->qindex = 7; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; if (sd->sensor == SENSOR_OV7670) { @@ -2064,17 +2062,6 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void setquality(struct gspca_dev *gspca_dev) -{ -#if 0 - struct sd *sd = (struct sd *) gspca_dev; - __u8 quality = 0; - - quality = sd->qindex & 0xff; - reg_w(gspca_dev->dev, 0xa0, quality, 0x0008); -#endif -} - /* for OV7660 and OV7670 only */ static void sethvflip(struct gspca_dev *gspca_dev) { @@ -2240,7 +2227,6 @@ static int sd_start(struct gspca_dev *gspca_dev) if (sd->sensor != SENSOR_PO1200) { reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); msleep(100); - setquality(gspca_dev); sethvflip(gspca_dev); setlightfreq(gspca_dev); } else { -- cgit v1.2.3 From 1433f6ed5f77ef1a1fedc0aa910800f4e6b60c12 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 13 Dec 2008 11:45:34 +0100 Subject: gspca - vc032x: Add V&H flips and sharpness controls for sensor po1200. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 83 ++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 5812af963..4cc1f69f1 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -35,6 +35,7 @@ struct sd { __u8 hflip; __u8 vflip; __u8 lightfreq; + __u8 sharpness; char bridge; #define BRIDGE_VC0321 0 @@ -57,6 +58,8 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { /* next 2 controls work with ov7660 and ov7670 only */ @@ -105,6 +108,22 @@ static struct ctrl sd_ctrls[] = { .set = sd_setfreq, .get = sd_getfreq, }, +/* po1200 only */ +#define SHARPNESS_IDX 3 + { + { + .id = V4L2_CID_SHARPNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Sharpness", + .minimum = 0, + .maximum = 2, + .step = 1, +#define SHARPNESS_DEF 1 + .default_value = SHARPNESS_DEF, + }, + .set = sd_setsharpness, + .get = sd_getsharpness, + }, }; static struct v4l2_pix_format vc0321_mode[] = { @@ -1531,7 +1550,7 @@ static const __u8 po1200_initVGA_data[][4] = { {0x00, 0x03, 0x00, 0xaa}, {0x00, 0x12, 0x05, 0xaa}, {0x00, 0x13, 0x02, 0xaa}, - {0x00, 0x1e, 0xc6, 0xaa}, + {0x00, 0x1e, 0xc6, 0xaa}, /* h/v flip */ {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x25, 0x02, 0xaa}, {0x00, 0x3c, 0x4f, 0xaa}, @@ -1541,7 +1560,7 @@ static const __u8 po1200_initVGA_data[][4] = { {0x00, 0x55, 0xfe, 0xaa}, {0x00, 0x59, 0xd3, 0xaa}, {0x00, 0x5e, 0x04, 0xaa}, - {0x00, 0x61, 0xb8, 0xaa}, + {0x00, 0x61, 0xb8, 0xaa}, /* sharpness */ {0x00, 0x62, 0x02, 0xaa}, {0x00, 0xa7, 0x31, 0xaa}, {0x00, 0xa9, 0x66, 0xaa}, @@ -1637,7 +1656,7 @@ static const __u8 po1200_initVGA_data[][4] = { {0x00, 0x20, 0xc4, 0xaa}, {0x00, 0x13, 0x03, 0xaa}, {0x00, 0x3c, 0x50, 0xaa}, - {0x00, 0x61, 0x6a, 0xaa}, + {0x00, 0x61, 0x6a, 0xaa}, /* sharpness? */ {0x00, 0x51, 0x5b, 0xaa}, {0x00, 0x52, 0x91, 0xaa}, {0x00, 0x53, 0x4c, 0xaa}, @@ -1692,7 +1711,12 @@ static const __u8 po1200_initVGA_data[][4] = { {0x00, 0xe2, 0x01, 0xaa}, {0x00, 0xd6, 0x40, 0xaa}, {0x00, 0xe4, 0x40, 0xaa}, +#if 1 + {0x00, 0xa8, 0x8f, 0xaa}, +#else +/*modified later*/ {0x00, 0xa8, 0x9f, 0xaa}, +#endif {0x00, 0xb4, 0x16, 0xaa}, {0xb0, 0x02, 0x06, 0xcc}, {0xb0, 0x18, 0x06, 0xcc}, @@ -1729,8 +1753,10 @@ static const __u8 po1200_initVGA_data[][4] = { {0x00, 0x03, 0x00, 0xaa}, {0x00, 0x95, 0x85, 0xaa}, /*matrix*/ +#if 0 {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x61, 0xb8, 0xaa}, + {0x00, 0x61, 0xb8, 0xaa}, /* sharpness */ +#endif {0x00, 0x03, 0x00, 0xaa}, {0x00, 0x4d, 0x20, 0xaa}, {0xb8, 0x22, 0x40, 0xcc}, @@ -1750,9 +1776,11 @@ static const __u8 po1200_initVGA_data[][4] = { {0x00, 0x46, 0x3c, 0xaa}, {0x00, 0x00, 0x18, 0xdd}, /*read bfff*/ +#if 0 {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x1e, 0x46, 0xaa}, + {0x00, 0x1e, 0x46, 0xaa}, /* h/v flip */ {0x00, 0xa8, 0x8f, 0xaa}, +#endif {0x00, 0x03, 0x00, 0xaa}, {0x00, 0xb4, 0x1c, 0xaa}, {0x00, 0xb5, 0x92, 0xaa}, @@ -2039,6 +2067,7 @@ static int sd_config(struct gspca_dev *gspca_dev, switch (sd->sensor) { case SENSOR_OV7660: case SENSOR_OV7670: + case SENSOR_PO1200: break; default: gspca_dev->ctrl_dis = (1 << HFLIP_IDX) @@ -2046,6 +2075,8 @@ static int sd_config(struct gspca_dev *gspca_dev, break; } + sd->sharpness = SHARPNESS_DEF; + if (sd->bridge == BRIDGE_VC0321) { reg_r(gspca_dev, 0x8a, 0, 3); reg_w(dev, 0x87, 0x00, 0x0f0f); @@ -2075,6 +2106,14 @@ static void sethvflip(struct gspca_dev *gspca_dev) case SENSOR_OV7670: data = 7; break; + case SENSOR_PO1200: + data = 0; + i2c_write(gspca_dev, 0x03, &data, 1); + data = 0x80 * sd->hflip + | 0x40 * sd->vflip + | 0x06; + i2c_write(gspca_dev, 0x1e, &data, 1); + return; default: return; } @@ -2094,6 +2133,20 @@ static void setlightfreq(struct gspca_dev *gspca_dev) usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); } +/* po1200 only */ +static void setsharpness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 data; + + if (sd->sensor != SENSOR_PO1200) + return; + data = 0; + i2c_write(gspca_dev, 0x03, &data, 1); + data = 0xb5 + sd->sharpness * 3; + i2c_write(gspca_dev, 0x61, &data, 1); +} + static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -2230,6 +2283,8 @@ static int sd_start(struct gspca_dev *gspca_dev) sethvflip(gspca_dev); setlightfreq(gspca_dev); } else { + setsharpness(gspca_dev); + sethvflip(gspca_dev); reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); } } @@ -2340,6 +2395,24 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->sharpness = val; + if (gspca_dev->streaming) + setsharpness(gspca_dev); + return 0; +} + +static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->sharpness; + return 0; +} + static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu) { -- cgit v1.2.3 From f5fcababcd2cc816a001298326635ea7c52b1cbd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 14 Dec 2008 09:41:56 +0100 Subject: gspca - ov534: Fix typo. From: Antonio Ospite Priority: normal Signed-off-by: Antonio Ospite Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index cd5c302d6..edcd92557 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -421,7 +421,7 @@ scan_next: remaining_len -= len; next_data += len; - /* Payloads are prefixed with a the UVC-style header. We + /* Payloads are prefixed with a UVC-style header. We consider a frame to start when the FID toggles, or the PTS changes. A frame ends when EOF is set, and we've received the correct number of bytes. */ -- cgit v1.2.3 From f74cfcac767db1991854892ac24f5ff39596b851 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 14 Dec 2008 09:48:07 +0100 Subject: gspca - ov534: Show sensor ID. From: Antonio Ospite The original version of sccb_read_reg() is from Jim Paris. NOTE: as it is now reading sensor ID won't work for sensors on different i2c slave address. Priority: normal Signed-off-by: Antonio Ospite Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index edcd92557..ad97b0be5 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -149,6 +149,20 @@ static void sccb_reg_write(struct usb_device *udev, u16 reg, u8 val) PDEBUG(D_ERR, "sccb_reg_write failed"); } +static u8 sccb_reg_read(struct usb_device *udev, u16 reg) +{ + ov534_reg_write(udev, OV534_REG_SUBADDR, reg); + ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_WRITE_2); + if (!sccb_check_status(udev)) + PDEBUG(D_ERR, "sccb_reg_read failed 1"); + + ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_READ_2); + if (!sccb_check_status(udev)) + PDEBUG(D_ERR, "sccb_reg_read failed 2"); + + return ov534_reg_read(udev, OV534_REG_READ); +} + static const __u8 ov534_reg_initdata[][2] = { { 0xe7, 0x3a }, @@ -339,6 +353,9 @@ static void ov534_setup(struct usb_device *udev) ov534_reg_write(udev, ov534_reg_initdata[i][0], ov534_reg_initdata[i][1]); + PDEBUG(D_PROBE, "sensor is ov%02x%02x", + sccb_reg_read(udev, 0x0a), sccb_reg_read(udev, 0x0b)); + ov534_set_led(udev, 1); /* Initialize sensor */ -- cgit v1.2.3 From 9735b6754d8660f40063776b9197b952cb1a4e19 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 14 Dec 2008 09:50:24 +0100 Subject: gspca - ov534: Fix a warning when compilation without GSPCA_DEBUG. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index ad97b0be5..7332947cb 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -149,6 +149,7 @@ static void sccb_reg_write(struct usb_device *udev, u16 reg, u8 val) PDEBUG(D_ERR, "sccb_reg_write failed"); } +#ifdef GSPCA_DEBUG static u8 sccb_reg_read(struct usb_device *udev, u16 reg) { ov534_reg_write(udev, OV534_REG_SUBADDR, reg); @@ -162,6 +163,7 @@ static u8 sccb_reg_read(struct usb_device *udev, u16 reg) return ov534_reg_read(udev, OV534_REG_READ); } +#endif static const __u8 ov534_reg_initdata[][2] = { { 0xe7, 0x3a }, -- cgit v1.2.3 From 66c33fb391b11fa484e3a4f6ba4275be3cd2f4dd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 14 Dec 2008 09:28:07 -0200 Subject: changeset: 9885:77f72ebfa794 tag: tip user: Mauro Carvalho Chehab date: Sun Dec 14 09:16:55 2008 -0200 files: linux/drivers/media/dvb/b2c2/Kconfig linux/drivers/media/dvb/bt8xx/Kconfig linux/drivers/media/dvb/dvb-usb/Kconfig linux/drivers/media/dvb/ttpci/Kconfig linux/drivers/media/video/cx18/Kconfig linux/drivers/media/video/cx23885/Kconfig linux/drivers/media/video/cx88/Kconfig linux/drivers/media/video/pvrusb2/Kconfig linux/drivers/media/video/saa7134/Kconfig description: media Kconfigs: fix bugzilla #12204 From: Mauro Carvalho Chehab When the tuner modules were moved to common/tuners, a separate customize option were added for tuners. However, the automatic selection of the tuners were still using the older option. This causes that the automatic selection to fail, if DVB_FE_CUSTOMISE is selected. Also, since those tuners are now under MEDIA_TUNER_CUSTOMIZE menu, if you unset MEDIA_TUNER_CUSTOMIZE, you can't manually select the tuners. This patch fixes this error by replacing DVB_FE_CUSTOMISE by MEDIA_TUNER_CUSTOMIZE on all places were a tuner is selected. The patch were generated by this small script: for i in `find drivers/media -name Kconfig`; do cat $i|perl -ne 's/(MEDIA_TUNER.*)DVB_FE_CUSTOMISE/\1MEDIA_TUNER_CUSTOMIZE/; print $_' >a mv a $i done A manual reordering were done to have the media selects just after the dvb ones. Priority: high Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/b2c2/Kconfig | 2 +- linux/drivers/media/dvb/bt8xx/Kconfig | 2 +- linux/drivers/media/dvb/dvb-usb/Kconfig | 46 +++++++++++++++---------------- linux/drivers/media/dvb/ttpci/Kconfig | 2 +- linux/drivers/media/video/cx18/Kconfig | 2 +- linux/drivers/media/video/cx23885/Kconfig | 4 +-- linux/drivers/media/video/cx88/Kconfig | 2 +- linux/drivers/media/video/pvrusb2/Kconfig | 2 +- linux/drivers/media/video/saa7134/Kconfig | 4 +-- 9 files changed, 33 insertions(+), 33 deletions(-) diff --git a/linux/drivers/media/dvb/b2c2/Kconfig b/linux/drivers/media/dvb/b2c2/Kconfig index e5c27e355..bd21c3bf2 100644 --- a/linux/drivers/media/dvb/b2c2/Kconfig +++ b/linux/drivers/media/dvb/b2c2/Kconfig @@ -9,12 +9,12 @@ config DVB_B2C2_FLEXCOP select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_BCM3510 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select DVB_S5H1420 if !DVB_FE_CUSTOMISE select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/linux/drivers/media/dvb/bt8xx/Kconfig b/linux/drivers/media/dvb/bt8xx/Kconfig index 7e9c090fc..27edb0ece 100644 --- a/linux/drivers/media/dvb/bt8xx/Kconfig +++ b/linux/drivers/media/dvb/bt8xx/Kconfig @@ -8,7 +8,7 @@ config DVB_BT8XX select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE help Support for PCI cards based on the Bt8xx PCI bridge. Examples are the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 62b68c291..49f7b20c2 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -24,8 +24,8 @@ config DVB_USB_A800 tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. @@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MB - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-B demodulator. @@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Support for USB2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-C/P demodulator. @@ -73,11 +73,11 @@ config DVB_USB_DIB0700 select DVB_DIB7000M select DVB_DIB3000MC select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE select DVB_TUNER_DIB0070 + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB @@ -95,7 +95,7 @@ config DVB_USB_UMT_010 depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. @@ -107,11 +107,11 @@ config DVB_USB_CXUSB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE select DVB_DIB7000P if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode @@ -124,9 +124,9 @@ config DVB_USB_M920X tristate "Uli m920x DVB-T USB2.0 support" depends on DVB_USB select DVB_MT352 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Currently, only devices with a product id of @@ -137,7 +137,7 @@ config DVB_USB_GL861 tristate "Genesys Logic GL861 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 receiver with USB ID 0db0:5581. @@ -146,7 +146,7 @@ config DVB_USB_AU6610 tristate "Alcor Micro AU6610 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. @@ -198,8 +198,8 @@ config DVB_USB_NOVA_T_USB2 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. @@ -235,8 +235,8 @@ config DVB_USB_OPERA1 config DVB_USB_AF9005 tristate "Afatech AF9005 DVB-T USB1.1 support" depends on DVB_USB && EXPERIMENTAL - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver and the TerraTec Cinergy T USB XE (Rev.1) @@ -284,7 +284,7 @@ config DVB_USB_DTV5100 tristate "AME DTV-5100 USB2.0 DVB-T support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. @@ -293,9 +293,9 @@ config DVB_USB_AF9015 depends on DVB_USB && EXPERIMENTAL select DVB_AF9013 select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index 9e2ece9e4..ab0bcd208 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -108,7 +108,7 @@ config DVB_BUDGET_CI select DVB_STB6100 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE select VIDEO_IR help Support for simple SAA7146 based DVB cards diff --git a/linux/drivers/media/video/cx18/Kconfig b/linux/drivers/media/video/cx18/Kconfig index ef48565de..8940b5387 100644 --- a/linux/drivers/media/video/cx18/Kconfig +++ b/linux/drivers/media/video/cx18/Kconfig @@ -9,7 +9,7 @@ config VIDEO_CX18 select VIDEO_CX2341X select VIDEO_CS5345 select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE ---help--- This is a video4linux driver for Conexant cx23418 based PCI combo video recorder devices. diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 8c1b7fa47..00f1e2e88 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -11,16 +11,16 @@ config VIDEO_CX23885 select VIDEO_CX25840 select VIDEO_CX2341X select DVB_DIB7000P if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE + select DVB_TDA10048 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE - select DVB_TDA10048 if !DVB_FE_CUSTOMIZE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index 0b9e5fac6..b0f837588 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -56,12 +56,12 @@ config VIDEO_CX88_DVB select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0288 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 19eb274c9..854c2a885 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -42,7 +42,7 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE ---help--- diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index 7021bbf58..fc2164e28 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -34,9 +34,9 @@ config VIDEO_SAA7134_DVB select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. -- cgit v1.2.3 From c8e6336414973fe34750afe8327988ddab7d1a58 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 14 Dec 2008 12:59:55 +0100 Subject: Minor fixes for cx24113-driver (codingstyle) From: Patrick Boettcher Fixed some minor coding style issues and some driver information printed when using the driver on a board. Priority: normal Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/frontends/cx24113.c | 70 ++++++++++++++++------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index e2e5df9de..8850f2303 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -50,46 +50,46 @@ struct cx24113_state { u8 rev; u8 ver; - u8 icp_mode:1; + u8 icp_mode:1; #define ICP_LEVEL1 0 #define ICP_LEVEL2 1 #define ICP_LEVEL3 2 #define ICP_LEVEL4 3 - u8 icp_man:2; - u8 icp_auto_low:2; - u8 icp_auto_mlow:2; - u8 icp_auto_mhi:2; - u8 icp_auto_hi:2; - u8 icp_dig; + u8 icp_man:2; + u8 icp_auto_low:2; + u8 icp_auto_mlow:2; + u8 icp_auto_mhi:2; + u8 icp_auto_hi:2; + u8 icp_dig; #define LNA_MIN_GAIN 0 #define LNA_MID_GAIN 1 #define LNA_MAX_GAIN 2 - u8 lna_gain:2; + u8 lna_gain:2; - u8 acp_on:1; + u8 acp_on:1; - u8 vco_mode:2; - u8 vco_shift:1; + u8 vco_mode:2; + u8 vco_shift:1; #define VCOBANDSEL_6 0x80 #define VCOBANDSEL_5 0x01 #define VCOBANDSEL_4 0x02 #define VCOBANDSEL_3 0x04 #define VCOBANDSEL_2 0x08 #define VCOBANDSEL_1 0x10 - u8 vco_band; + u8 vco_band; #define VCODIV4 4 #define VCODIV2 2 u8 vcodiv; - u8 bs_delay:4; - u16 bs_freqcnt:13; - u16 bs_rdiv; - u8 prescaler_mode:1; + u8 bs_delay:4; + u16 bs_freqcnt:13; + u16 bs_rdiv; + u8 prescaler_mode:1; - u8 rfvga_bias_ctrl; + u8 rfvga_bias_ctrl; s16 tuner_gain_thres; u8 gain_level; @@ -345,12 +345,12 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) } F = freq_hz; F *= (u64) (R * vcodiv * 262144); - dprintk("1 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("1 N: %d, F: %lld, R: %d\n", N, F, R); do_div(F, state->config->xtal_khz*1000 * factor * 2); - dprintk("2 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("2 N: %d, F: %lld, R: %d\n", N, F, R); F -= (N + 32) * 262144; - dprintk("3 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("3 N: %d, F: %lld, R: %d\n", N, F, R); if (state->Fwindow_enabled) { if (F > (262144 / 2 - 1638)) @@ -392,21 +392,21 @@ static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency) u16 n = 6; s32 f = 0; - r = cx24113_readreg(state, 0x14); + r = cx24113_readreg(state, 0x14); cx24113_writereg(state, 0x14, r & 0x3f); - r = cx24113_readreg(state, 0x10); - cx24113_writereg(state, 0x10, r & 0xbf); + r = cx24113_readreg(state, 0x10); + cx24113_writereg(state, 0x10, r & 0xbf); state->frequency = frequency; dprintk("tuning to frequency: %d\n", frequency); - cx24113_calc_pll_nf(state, &n, &f); - cx24113_set_nfr(state, n, f, state->refdiv); + cx24113_calc_pll_nf(state, &n, &f); + cx24113_set_nfr(state, n, f, state->refdiv); r = cx24113_readreg(state, 0x18) & 0xbf; - if (state->vcodiv != VCODIV2) + if (state->vcodiv != VCODIV2) r |= 1 << 6; cx24113_writereg(state, 0x18, r); @@ -527,7 +527,7 @@ static int cx24113_release(struct dvb_frontend *fe) { struct cx24113_state *state = fe->tuner_priv; dprintk("\n"); - fe->tuner_priv = NULL; + fe->tuner_priv = NULL; kfree(state); return 0; } @@ -557,6 +557,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, /* allocate memory for the internal state */ struct cx24113_state *state = kzalloc(sizeof(struct cx24113_state), GFP_KERNEL); + int rc; if (state == NULL) { err("Unable to kmalloc\n"); goto error; @@ -572,15 +573,22 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, * after power on */ cx24113_readreg(state, 0x00); - switch (state->rev = cx24113_readreg(state, 0x00)) { + rc = cx24113_readreg(state, 0x00); + if (rc < 0) { + info("cx24113 not found.\n"); + goto error; + } + state->rev = rc; + + switch (rc) { case 0x43: - info("unknown device\n"); + info("detected Cx24113 variant\n"); break; case REV_CX24113: - info("CX24113\n"); + info("sucessfully detected\n"); break; default: - err("unsupported revision: %x\n", state->rev); + err("unsupported device id: %x\n", state->rev); goto error; } state->ver = cx24113_readreg(state, 0x01); -- cgit v1.2.3 From 89634f12bf2fabd82e3043863cc01da40ec3bfc4 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 14 Dec 2008 13:11:53 +0100 Subject: Patch: fix a typo in cx24113.c From: Uwe Bugla This patch fixes a typo in cx24113.c. Priority: normal Signed-off-by: Uwe Bugla Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/frontends/cx24113.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index 8850f2303..e130b228e 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -1,5 +1,5 @@ /* - * Driver for Conexant CX24113/CX24128 Tuner (Satelite) + * Driver for Conexant CX24113/CX24128 Tuner (Satellite) * * Copyright (C) 2007-8 Patrick Boettcher * -- cgit v1.2.3 From 40f4f221fb5a7e2f157453743e545ddeff42bd55 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 14 Dec 2008 13:37:02 +0100 Subject: gspca - pac207: Update my email address. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/pac207.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c index 39473e6b9..84bcaaf4d 100644 --- a/linux/drivers/media/video/gspca/pac207.c +++ b/linux/drivers/media/video/gspca/pac207.c @@ -1,7 +1,7 @@ /* * Pixart PAC207BCA library * - * Copyright (C) 2008 Hans de Goede + * Copyright (C) 2008 Hans de Goede * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr * @@ -27,7 +27,7 @@ #include "gspca.h" -MODULE_AUTHOR("Hans de Goede "); +MODULE_AUTHOR("Hans de Goede "); MODULE_DESCRIPTION("Pixart PAC207"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 3bef875602189a42ca85a89ace6fc225d739512c Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 14 Dec 2008 15:56:28 +0100 Subject: CX24113: Fixed more typos From: Patrick Boettcher Uwe Bugla pointed out that there are some more typos in some print-statements. Fixed. Priority: normal Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/frontends/cx24113.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index e130b228e..93f35941a 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -575,14 +575,14 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, rc = cx24113_readreg(state, 0x00); if (rc < 0) { - info("cx24113 not found.\n"); + info("CX24113 not found.\n"); goto error; } state->rev = rc; switch (rc) { case 0x43: - info("detected Cx24113 variant\n"); + info("detected CX24113 variant\n"); break; case REV_CX24113: info("sucessfully detected\n"); -- cgit v1.2.3 From 99627092016191ade350fe68ac3c2d17e3cd6a11 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 14 Dec 2008 20:21:16 +0100 Subject: v4l2: Add camera zoom controls From: Laurent Pinchart The zoom controls move the zoom lens group to a an absolute position, as a relative displacement or at a given speed until reaching physical device limits. Positive values move the zoom lens group towards the telephoto direction, negative values towards the wide-angle direction. Priority: normal Signed-off-by: Laurent Pinchart --- linux/include/linux/videodev2.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 00e539e8f..2d7f01059 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1118,6 +1118,10 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) #define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) +#define V4L2_CID_ZOOM_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+13) +#define V4L2_CID_ZOOM_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+14) +#define V4L2_CID_ZOOM_CONTINUOUS (V4L2_CID_CAMERA_CLASS_BASE+15) + /* * T U N I N G */ -- cgit v1.2.3 From a535d91c3ff903c13b31791f5053373a8ec94bc9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 14 Dec 2008 20:22:05 +0100 Subject: v4l2: Add privacy control From: Laurent Pinchart The privacy control prevents video from being acquired by the camera. A true value indicates that no image can be captured. Devices that implement the privacy control must support read access and may support write access. Priority: normal Signed-off-by: Laurent Pinchart --- linux/include/linux/videodev2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 2d7f01059..6ee771108 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1122,6 +1122,8 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_ZOOM_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+14) #define V4L2_CID_ZOOM_CONTINUOUS (V4L2_CID_CAMERA_CLASS_BASE+15) +#define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) + /* * T U N I N G */ -- cgit v1.2.3 From 771b1cc58b98391259bcdb5e4c3d62eb7d4a43d6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 14 Dec 2008 20:24:04 +0100 Subject: v4l2: Add missing control names From: Laurent Pinchart Update v4l2_ctrl_get_name() and v4l2_ctrl_get_menu() with missing control names and menu values. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/v4l2-common.c | 88 ++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 6d5e41ecc..02eb97fa4 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -322,6 +322,19 @@ const char **v4l2_ctrl_get_menu(u32 id) "Private packet, IVTV format", NULL }; + static const char *camera_power_line_frequency[] = { + "Disabled", + "50 Hz", + "60 Hz", + NULL + }; + static const char *camera_exposure_auto[] = { + "Auto Mode", + "Manual Mode", + "Shutter Priority Mode", + "Aperture Priority Mode", + NULL + }; switch (id) { case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: @@ -354,6 +367,10 @@ const char **v4l2_ctrl_get_menu(u32 id) return mpeg_stream_type; case V4L2_CID_MPEG_STREAM_VBI_FMT: return mpeg_stream_vbi_fmt; + case V4L2_CID_POWER_LINE_FREQUENCY: + return camera_power_line_frequency; + case V4L2_CID_EXPOSURE_AUTO: + return camera_exposure_auto; default: return NULL; } @@ -365,17 +382,37 @@ const char *v4l2_ctrl_get_name(u32 id) { switch (id) { /* USER controls */ - case V4L2_CID_USER_CLASS: return "User Controls"; - case V4L2_CID_AUDIO_VOLUME: return "Volume"; - case V4L2_CID_AUDIO_MUTE: return "Mute"; - case V4L2_CID_AUDIO_BALANCE: return "Balance"; - case V4L2_CID_AUDIO_BASS: return "Bass"; - case V4L2_CID_AUDIO_TREBLE: return "Treble"; - case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; - case V4L2_CID_BRIGHTNESS: return "Brightness"; - case V4L2_CID_CONTRAST: return "Contrast"; - case V4L2_CID_SATURATION: return "Saturation"; - case V4L2_CID_HUE: return "Hue"; + case V4L2_CID_USER_CLASS: return "User Controls"; + case V4L2_CID_AUDIO_VOLUME: return "Volume"; + case V4L2_CID_AUDIO_MUTE: return "Mute"; + case V4L2_CID_AUDIO_BALANCE: return "Balance"; + case V4L2_CID_AUDIO_BASS: return "Bass"; + case V4L2_CID_AUDIO_TREBLE: return "Treble"; + case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; + case V4L2_CID_BRIGHTNESS: return "Brightness"; + case V4L2_CID_CONTRAST: return "Contrast"; + case V4L2_CID_SATURATION: return "Saturation"; + case V4L2_CID_HUE: return "Hue"; + case V4L2_CID_BLACK_LEVEL: return "Black Level"; + case V4L2_CID_AUTO_WHITE_BALANCE: return "White Balance, Automatic"; + case V4L2_CID_DO_WHITE_BALANCE: return "Do White Balance"; + case V4L2_CID_RED_BALANCE: return "Red Balance"; + case V4L2_CID_BLUE_BALANCE: return "Blue Balance"; + case V4L2_CID_GAMMA: return "Gamma"; + case V4L2_CID_EXPOSURE: return "Exposure"; + case V4L2_CID_AUTOGAIN: return "Gain, Automatic"; + case V4L2_CID_GAIN: return "Gain"; + case V4L2_CID_HFLIP: return "Horizontal Flip"; + case V4L2_CID_VFLIP: return "Vertical Flip"; + case V4L2_CID_HCENTER: return "Horizontal Center"; + case V4L2_CID_VCENTER: return "Vertical Center"; + case V4L2_CID_POWER_LINE_FREQUENCY: return "Power Line Frequency"; + case V4L2_CID_HUE_AUTO: return "Hue, Automatic"; + case V4L2_CID_WHITE_BALANCE_TEMPERATURE: return "White Balance Temperature"; + case V4L2_CID_SHARPNESS: return "Sharpness"; + case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation"; + case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; + case V4L2_CID_COLOR_KILLER: return "Color Killer"; /* MPEG controls */ case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; @@ -412,6 +449,25 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID"; case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format"; + /* CAMERA controls */ + case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; + case V4L2_CID_EXPOSURE_AUTO: return "Auto Exposure"; + case V4L2_CID_EXPOSURE_ABSOLUTE: return "Exposure Time, Absolute"; + case V4L2_CID_EXPOSURE_AUTO_PRIORITY: return "Exposure, Dynamic Framerate"; + case V4L2_CID_PAN_RELATIVE: return "Pan, Relative"; + case V4L2_CID_TILT_RELATIVE: return "Tilt, Relative"; + case V4L2_CID_PAN_RESET: return "Pan, Reset"; + case V4L2_CID_TILT_RESET: return "Tilt, Reset"; + case V4L2_CID_PAN_ABSOLUTE: return "Pan, Absolute"; + case V4L2_CID_TILT_ABSOLUTE: return "Tilt, Absolute"; + case V4L2_CID_FOCUS_ABSOLUTE: return "Focus, Absolute"; + case V4L2_CID_FOCUS_RELATIVE: return "Focus, Relative"; + case V4L2_CID_FOCUS_AUTO: return "Focus, Automatic"; + case V4L2_CID_ZOOM_ABSOLUTE: return "Zoom, Absolute"; + case V4L2_CID_ZOOM_RELATIVE: return "Zoom, Relative"; + case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous"; + case V4L2_CID_PRIVACY: return "Privacy"; + default: return NULL; } @@ -430,14 +486,22 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste switch (qctrl->id) { case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_LOUDNESS: + case V4L2_CID_AUTO_WHITE_BALANCE: + case V4L2_CID_AUTOGAIN: + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + case V4L2_CID_HUE_AUTO: case V4L2_CID_MPEG_AUDIO_MUTE: case V4L2_CID_MPEG_VIDEO_MUTE: case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: case V4L2_CID_MPEG_VIDEO_PULLDOWN: + case V4L2_CID_EXPOSURE_AUTO_PRIORITY: + case V4L2_CID_PRIVACY: qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; min = 0; max = step = 1; break; + case V4L2_CID_POWER_LINE_FREQUENCY: case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: case V4L2_CID_MPEG_AUDIO_ENCODING: case V4L2_CID_MPEG_AUDIO_L1_BITRATE: @@ -453,10 +517,12 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: case V4L2_CID_MPEG_STREAM_TYPE: case V4L2_CID_MPEG_STREAM_VBI_FMT: + case V4L2_CID_EXPOSURE_AUTO: qctrl->type = V4L2_CTRL_TYPE_MENU; step = 1; break; case V4L2_CID_USER_CLASS: + case V4L2_CID_CAMERA_CLASS: case V4L2_CID_MPEG_CLASS: qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS; qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; -- cgit v1.2.3 From 3eb3874db1537d1723f3d5d8dfc6db8210666408 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 14 Dec 2008 20:39:03 -0200 Subject: drivers/media Kconfig's: fix bugzilla #12204 From: Mauro Carvalho Chehab When the tuner modules were moved to common/tuners, a separate customize option were added for tuners. However, the automatic selection of the tuners were still using the older option. This causes that the automatic selection to fail, if DVB_FE_CUSTOMISE is selected. Also, since those tuners are now under MEDIA_TUNER_CUSTOMIZE menu, if you unset MEDIA_TUNER_CUSTOMIZE, you can't manually select the tuners. This patch fixes this error by replacing DVB_FE_CUSTOMISE by MEDIA_TUNER_CUSTOMIZE on all places were a tuner is selected. The patch were generated by this small script: for i in `find drivers/media -name Kconfig`; do cat $i|perl -ne 's/(MEDIA_TUNER.*)DVB_FE_CUSTOMISE/\1MEDIA_TUNER_CUSTOMIZE/; print $_' >a mv a $i done Also, manually reordered the tuner entries. Priority: high Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/b2c2/Kconfig | 2 +- linux/drivers/media/dvb/bt8xx/Kconfig | 2 +- linux/drivers/media/dvb/dvb-usb/Kconfig | 46 +++++++++++++++---------------- linux/drivers/media/dvb/ttpci/Kconfig | 2 +- linux/drivers/media/video/cx18/Kconfig | 2 +- linux/drivers/media/video/cx23885/Kconfig | 4 +-- linux/drivers/media/video/cx88/Kconfig | 2 +- linux/drivers/media/video/pvrusb2/Kconfig | 2 +- linux/drivers/media/video/saa7134/Kconfig | 4 +-- 9 files changed, 33 insertions(+), 33 deletions(-) diff --git a/linux/drivers/media/dvb/b2c2/Kconfig b/linux/drivers/media/dvb/b2c2/Kconfig index bd21c3bf2..e5c27e355 100644 --- a/linux/drivers/media/dvb/b2c2/Kconfig +++ b/linux/drivers/media/dvb/b2c2/Kconfig @@ -9,12 +9,12 @@ config DVB_B2C2_FLEXCOP select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_BCM3510 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select DVB_S5H1420 if !DVB_FE_CUSTOMISE select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/linux/drivers/media/dvb/bt8xx/Kconfig b/linux/drivers/media/dvb/bt8xx/Kconfig index 27edb0ece..7e9c090fc 100644 --- a/linux/drivers/media/dvb/bt8xx/Kconfig +++ b/linux/drivers/media/dvb/bt8xx/Kconfig @@ -8,7 +8,7 @@ config DVB_BT8XX select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE help Support for PCI cards based on the Bt8xx PCI bridge. Examples are the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 49f7b20c2..62b68c291 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -24,8 +24,8 @@ config DVB_USB_A800 tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" depends on DVB_USB select DVB_DIB3000MC + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. @@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MB - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-B demodulator. @@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Support for USB2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-C/P demodulator. @@ -73,11 +73,11 @@ config DVB_USB_DIB0700 select DVB_DIB7000M select DVB_DIB3000MC select DVB_S5H1411 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE select DVB_TUNER_DIB0070 - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB @@ -95,7 +95,7 @@ config DVB_USB_UMT_010 depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. @@ -107,11 +107,11 @@ config DVB_USB_CXUSB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE select DVB_DIB7000P if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode @@ -124,9 +124,9 @@ config DVB_USB_M920X tristate "Uli m920x DVB-T USB2.0 support" depends on DVB_USB select DVB_MT352 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Currently, only devices with a product id of @@ -137,7 +137,7 @@ config DVB_USB_GL861 tristate "Genesys Logic GL861 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE help Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 receiver with USB ID 0db0:5581. @@ -146,7 +146,7 @@ config DVB_USB_AU6610 tristate "Alcor Micro AU6610 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE help Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. @@ -198,8 +198,8 @@ config DVB_USB_NOVA_T_USB2 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. @@ -235,8 +235,8 @@ config DVB_USB_OPERA1 config DVB_USB_AF9005 tristate "Afatech AF9005 DVB-T USB1.1 support" depends on DVB_USB && EXPERIMENTAL - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE help Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver and the TerraTec Cinergy T USB XE (Rev.1) @@ -284,7 +284,7 @@ config DVB_USB_DTV5100 tristate "AME DTV-5100 USB2.0 DVB-T support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE help Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. @@ -293,9 +293,9 @@ config DVB_USB_AF9015 depends on DVB_USB && EXPERIMENTAL select DVB_AF9013 select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE help Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index ab0bcd208..9e2ece9e4 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -108,7 +108,7 @@ config DVB_BUDGET_CI select DVB_STB6100 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE select VIDEO_IR help Support for simple SAA7146 based DVB cards diff --git a/linux/drivers/media/video/cx18/Kconfig b/linux/drivers/media/video/cx18/Kconfig index 8940b5387..ef48565de 100644 --- a/linux/drivers/media/video/cx18/Kconfig +++ b/linux/drivers/media/video/cx18/Kconfig @@ -9,7 +9,7 @@ config VIDEO_CX18 select VIDEO_CX2341X select VIDEO_CS5345 select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE ---help--- This is a video4linux driver for Conexant cx23418 based PCI combo video recorder devices. diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 00f1e2e88..8c1b7fa47 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -11,16 +11,16 @@ config VIDEO_CX23885 select VIDEO_CX25840 select VIDEO_CX2341X select DVB_DIB7000P if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE + select DVB_TDA10048 if !DVB_FE_CUSTOMIZE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index b0f837588..0b9e5fac6 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -56,12 +56,12 @@ config VIDEO_CX88_DVB select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0288 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 854c2a885..19eb274c9 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -42,7 +42,7 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE ---help--- diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index fc2164e28..7021bbf58 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -34,9 +34,9 @@ config VIDEO_SAA7134_DVB select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. -- cgit v1.2.3 From 75cb6237407f2d533da57987203cfc43c221e380 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 14 Dec 2008 19:26:25 -0500 Subject: cx18: Refine the firmware load and firmware startup process From: Andy Walls Refine the firmware load and firmware startup process. Significant changes are to ensure the SCB and IPC area are correct before starting up the firmware, and letting the CPU firmware start up the APU firmware for us. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 1 + linux/drivers/media/video/cx18/cx18-firmware.c | 101 +++++++++++++------------ linux/drivers/media/video/cx18/cx18-mailbox.c | 3 +- linux/drivers/media/video/cx18/cx18-scb.c | 1 - linux/drivers/media/video/cx18/cx23418.h | 6 ++ 5 files changed, 60 insertions(+), 52 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index f2a5b2c4d..e447b4ce7 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -883,6 +883,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, goto free_i2c; } cx18_init_memory(cx); + cx18_init_scb(cx); /* Register IRQ */ retval = request_irq(cx->dev->irq, cx18_irq_handler, diff --git a/linux/drivers/media/video/cx18/cx18-firmware.c b/linux/drivers/media/video/cx18/cx18-firmware.c index 8eac84314..e74f76d47 100644 --- a/linux/drivers/media/video/cx18/cx18-firmware.c +++ b/linux/drivers/media/video/cx18/cx18-firmware.c @@ -332,6 +332,10 @@ void cx18_init_memory(struct cx18 *cx) int cx18_firmware_init(struct cx18 *cx) { + u32 fw_entry_addr; + int sz, retries; + u32 api_args[MAX_MB_ARGUMENTS]; + /* Allow chip to control CLKRUN */ cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK); @@ -341,65 +345,62 @@ int cx18_firmware_init(struct cx18 *cx) cx18_msleep_timeout(1, 0); + /* If the CPU is still running */ + if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) { + CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__); + return -EIO; + } + cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); - /* Only if the processor is not running */ - if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) { - u32 fw_entry_addr = 0; - int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", - cx->enc_mem, cx, &fw_entry_addr); - - if (sz <= 0) - return sz; - - /* Clear bit0 for APU to start from 0 */ - cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030); - - cx18_write_enc(cx, 0xE51FF004, 0); /* ldr pc, [pc, #-4] */ - cx18_write_enc(cx, fw_entry_addr, 4); - - /* Start APU */ - cx18_write_reg_expect(cx, 0x00010000, CX18_PROC_SOFT_RESET, - 0x00000000, 0x00010001); - cx18_msleep_timeout(500, 0); - - sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", - cx->enc_mem, cx); - - if (sz > 0) { - int retries = 0; - - /* start the CPU */ - cx18_write_reg_expect(cx, - 0x00080000, CX18_PROC_SOFT_RESET, - 0x00000000, 0x00080008); - while (retries++ < 50) { /* Loop for max 500mS */ - if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) - & 1) == 0) - break; - cx18_msleep_timeout(10, 0); - } - cx18_msleep_timeout(200, 0); - if (retries == 51) { - CX18_ERR("Could not start the CPU\n"); - return -EIO; - } - } - if (sz <= 0) - return -EIO; + sz = load_cpu_fw_direct("v4l-cx23418-cpu.fw", cx->enc_mem, cx); + if (sz <= 0) + return sz; + + /* The SCB & IPC area *must* be correct before starting the firmwares */ + cx18_init_scb(cx); + + fw_entry_addr = 0; + sz = load_apu_fw_direct("v4l-cx23418-apu.fw", cx->enc_mem, cx, + &fw_entry_addr); + if (sz <= 0) + return sz; + + /* Start the CPU. The CPU will take care of the APU for us. */ + cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET, + 0x00000000, 0x00080008); + + /* Wait up to 500 ms for the APU to come out of reset */ + for (retries = 0; + retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1; + retries++) + cx18_msleep_timeout(10, 0); + + cx18_msleep_timeout(200, 0); + + if (retries == 50 && + (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) { + CX18_ERR("Could not start the CPU\n"); + return -EIO; } /* - * The CPU firmware apparently sets up to receive an interrupt for it's - * outgoing IRQ_CPU_TO_EPU_ACK to us (*boggle*). We get an interrupt - * when it sends us an ack, but by the time we process it, that flag in - * the SW2 status register has been cleared by the CPU firmware. - * We'll prevent that not so useful behavior by clearing the CPU's - * interrupt enables for Ack IRQ's we want to process. + * The CPU had once before set up to receive an interrupt for it's + * outgoing IRQ_CPU_TO_EPU_ACK to us. If it ever does this, we get an + * interrupt when it sends us an ack, but by the time we process it, + * that flag in the SW2 status register has been cleared by the CPU + * firmware. We'll prevent that not so useful condition from happening + * by clearing the CPU's interrupt enables for Ack IRQ's we want to + * process. */ cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); + /* Try a benign command to see if the CPU is alive and well */ + sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0); + if (sz < 0) + return sz; + /* initialize GPIO */ cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400); return 0; diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index f20fbf091..89a45f51f 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -82,8 +82,9 @@ static const struct cx18_api_info api_info[] = { API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0), API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), - API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), + API_ENTRY(APU, CX18_APU_RESETAI, 0), + API_ENTRY(CPU, CX18_CPU_DEBUG_PEEK32, 0), API_ENTRY(0, 0, 0), }; diff --git a/linux/drivers/media/video/cx18/cx18-scb.c b/linux/drivers/media/video/cx18/cx18-scb.c index ac18bd932..34b4d03c5 100644 --- a/linux/drivers/media/video/cx18/cx18-scb.c +++ b/linux/drivers/media/video/cx18/cx18-scb.c @@ -118,6 +118,5 @@ void cx18_init_scb(struct cx18 *cx) cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), &cx->scb->ipc_offset); - cx18_writel(cx, 1, &cx->scb->hpu_state); cx18_writel(cx, 1, &cx->scb->epu_state); } diff --git a/linux/drivers/media/video/cx18/cx23418.h b/linux/drivers/media/video/cx18/cx23418.h index 668f968d7..601f3a2ab 100644 --- a/linux/drivers/media/video/cx18/cx23418.h +++ b/linux/drivers/media/video/cx18/cx23418.h @@ -44,6 +44,7 @@ /* All commands for CPU have the following mask set */ #define CPU_CMD_MASK 0x20000000 +#define CPU_CMD_MASK_DEBUG (CPU_CMD_MASK | 0x00000000) #define CPU_CMD_MASK_ACK (CPU_CMD_MASK | 0x80000000) #define CPU_CMD_MASK_CAPTURE (CPU_CMD_MASK | 0x00020000) #define CPU_CMD_MASK_TS (CPU_CMD_MASK | 0x00040000) @@ -71,6 +72,11 @@ 0/zero/NULL means "I have nothing to say" */ #define CX18_EPU_DEBUG (EPU_CMD_MASK_DEBUG | 0x0003) +/* Reads memory/registers (32-bit) + IN[0] - Address + OUT[1] - Value */ +#define CX18_CPU_DEBUG_PEEK32 (CPU_CMD_MASK_DEBUG | 0x0003) + /* Description: This command starts streaming with the set channel type IN[0] - Task handle. Handle of the task to start ReturnCode - One of the ERR_CAPTURE_... */ -- cgit v1.2.3 From c5e070eecd80d55b36be4bd4ad717e1c53387c78 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 15 Dec 2008 08:12:57 +0100 Subject: gspca - pac7311: Webcam 093a:262c added. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/pac7311.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index 81d7d891c..a55459456 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -221,6 +221,7 @@ pac7311 093a:2622 Genius Eye 312 pac7311 093a:2624 PAC7302 pac7311 093a:2626 Labtec 2200 pac7311 093a:262a Webcam 300k +pac7311 093a:262c Philips SPC 230 NC zc3xx 0ac8:0302 Z-star Vimicro zc0302 vc032x 0ac8:0321 Vimicro generic vc0321 vc032x 0ac8:0323 Vimicro Vc0323 diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index b0a9d0687..51c8203e3 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -1083,6 +1083,7 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302}, + {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302}, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From 0bb40d367f4b5d1a17b71c1fa354799cb5abf1e0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 15 Dec 2008 11:15:32 +0100 Subject: v4l: fix compile warning. From: Hans Verkuil Fix (bogus) compile warning about uninitialized variable. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index e2e816213..bd2a1754b 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -448,7 +448,7 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { - const struct soc_camera_data_format *cam_fmt; + const struct soc_camera_data_format *cam_fmt = NULL; int ret; /* -- cgit v1.2.3 From f5435c98aa929cc30a19191341329ca7a6a91008 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 15 Dec 2008 11:19:20 +0100 Subject: v4l2-compat32: add missing newline after kernel message From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-compat-ioctl32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index 09d5c5693..e2e7a2061 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -977,6 +977,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) #endif default: v4l_print_ioctl("compat_ioctl32", cmd); + printk(KERN_CONT "\n"); + break; } return ret; } -- cgit v1.2.3 From 4c8a6b3ba0d22598879b1546c088cb8a3eb895a0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Dec 2008 07:36:07 -0200 Subject: Fix compilation for kernels older than 2.6.26 From: Mauro Carvalho Chehab tvp514x were written using newer i2c improvements committed on kernel 2.6.26. So, we need to not compile it with older kernels. As pointed by Devin Heitmueller : Reported by a user on the #linuxtv chatroom and confirmed by mkrufky: make -C /home/wil/v4l-dvb/v4l make[1]: Entering directory `/home/wil/v4l-dvb/v4l' creating symbolic links... Kernel build directory is /lib/modules/2.6.24-20-generic/build make -C /lib/modules/2.6.24-20-generic/build SUBDIRS=/home/wil/v4l-dvb/v4l modules make[2]: Entering directory `/usr/src/linux-headers-2.6.24-20-generic' CC [M] /home/wil/v4l-dvb/v4l/tvp514x.o /home/wil/v4l-dvb/v4l/tvp514x.c: In function 'ioctl_s_power': /home/wil/v4l-dvb/v4l/tvp514x.c:1238: error: dereferencing pointer to incomplete type /home/wil/v4l-dvb/v4l/tvp514x.c: At top level: /home/wil/v4l-dvb/v4l/tvp514x.c:1524: error: array type has incomplete element type /home/wil/v4l-dvb/v4l/tvp514x.c:1539: warning: initialization from incompatible pointer type /home/wil/v4l-dvb/v4l/tvp514x.c:1541: error: unknown field 'id_table' specified in initializer make[3]: *** [/home/wil/v4l-dvb/v4l/tvp514x.o] Error 1 make[2]: *** [_module_/home/wil/v4l-dvb/v4l] Error 2 make[2]: Leaving directory `/usr/src/linux-headers-2.6.24-20-generic' make[1]: *** [default] Error 2 make[1]: Leaving directory `/home/wil/v4l-dvb/v4l' make: *** [all] Error 2 Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l/versions.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l/versions.txt b/v4l/versions.txt index 3ef9af5d8..0393e79b0 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -4,6 +4,8 @@ [2.6.26] # Needs camera.h VIDEO_PXA27x +# Requires struct i2c_device_id +VIDEO_TVP514X [2.6.25] # Requires gpiolib -- cgit v1.2.3 From 7981a739191a95dbcf8fd3aedc2c6a897f1cd3a1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 16 Dec 2008 10:44:11 +0100 Subject: uvcvideo: V4L2 privacy control support From: Laurent Pinchart Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_ctrl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 01c72935d..92b16c3d5 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -534,6 +534,16 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, + { + .id = V4L2_CID_PRIVACY, + .name = "Privacy", + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PRIVACY_CONTROL, + .size = 1, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, + .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, + }, }; /* ------------------------------------------------------------------------ -- cgit v1.2.3 From 7dee6796e962e12a9ee483b99bd808b2a3218c13 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 16 Dec 2008 10:46:32 +0100 Subject: uvcvideo: V4L2 zoom controls support From: Laurent Pinchart Add support for absolute and continuous zoom controls (mapped to absolute and relative UVC zoom controls). Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_ctrl.c | 76 +++++++++++++++++++++++++++----- linux/drivers/media/video/uvc/uvc_v4l2.c | 4 +- linux/drivers/media/video/uvc/uvcvideo.h | 5 +++ 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 92b16c3d5..e9a75b064 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -329,6 +329,31 @@ static struct uvc_menu_info exposure_auto_controls[] = { { 8, "Aperture Priority Mode" }, }; +static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, + __u8 query, const __u8 *data) +{ + __s8 zoom = (__s8)data[0]; + + switch (query) { + case GET_CUR: + return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]); + + case GET_MIN: + case GET_MAX: + case GET_RES: + case GET_DEF: + default: + return data[2]; + } +} + +static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping, + __s32 value, __u8 *data) +{ + data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff; + data[2] = min(abs(value), 0xff); +} + static struct uvc_control_mapping uvc_ctrl_mappings[] = { { .id = V4L2_CID_BRIGHTNESS, @@ -534,6 +559,28 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, + { + .id = V4L2_CID_ZOOM_ABSOLUTE, + .name = "Zoom, Absolute", + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ZOOM_ABSOLUTE_CONTROL, + .size = 16, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_ZOOM_CONTINUOUS, + .name = "Zoom, Continuous", + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ZOOM_RELATIVE_CONTROL, + .size = 0, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + .get = uvc_ctrl_get_zoom, + .set = uvc_ctrl_set_zoom, + }, { .id = V4L2_CID_PRIVACY, .name = "Privacy", @@ -570,8 +617,8 @@ static inline void uvc_clear_bit(__u8 *data, int bit) * a signed 32bit integer. Sign extension will be performed if the mapping * references a signed data type. */ -static __s32 uvc_get_le_value(const __u8 *data, - struct uvc_control_mapping *mapping) +static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping, + __u8 query, const __u8 *data) { int bits = mapping->size; int offset = mapping->offset; @@ -600,8 +647,8 @@ static __s32 uvc_get_le_value(const __u8 *data, /* Set the bit string specified by mapping->offset and mapping->size * in the little-endian data stored at 'data' to the value 'value'. */ -static void uvc_set_le_value(__s32 value, __u8 *data, - struct uvc_control_mapping *mapping) +static void uvc_set_le_value(struct uvc_control_mapping *mapping, + __s32 value, __u8 *data) { int bits = mapping->size; int offset = mapping->offset; @@ -753,7 +800,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, video->dev->intfnum, ctrl->info->selector, data, ctrl->info->size)) < 0) goto out; - v4l2_ctrl->default_value = uvc_get_le_value(data, mapping); + v4l2_ctrl->default_value = mapping->get(mapping, GET_DEF, data); } switch (mapping->v4l2_type) { @@ -789,21 +836,21 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, video->dev->intfnum, ctrl->info->selector, data, ctrl->info->size)) < 0) goto out; - v4l2_ctrl->minimum = uvc_get_le_value(data, mapping); + v4l2_ctrl->minimum = mapping->get(mapping, GET_MIN, data); } if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id, video->dev->intfnum, ctrl->info->selector, data, ctrl->info->size)) < 0) goto out; - v4l2_ctrl->maximum = uvc_get_le_value(data, mapping); + v4l2_ctrl->maximum = mapping->get(mapping, GET_MAX, data); } if (ctrl->info->flags & UVC_CONTROL_GET_RES) { if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id, video->dev->intfnum, ctrl->info->selector, data, ctrl->info->size)) < 0) goto out; - v4l2_ctrl->step = uvc_get_le_value(data, mapping); + v4l2_ctrl->step = mapping->get(mapping, GET_RES, data); } ret = 0; @@ -940,8 +987,8 @@ int uvc_ctrl_get(struct uvc_video_device *video, ctrl->loaded = 1; } - xctrl->value = uvc_get_le_value( - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping); + xctrl->value = mapping->get(mapping, GET_CUR, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { menu = mapping->menu_info; @@ -997,8 +1044,8 @@ int uvc_ctrl_set(struct uvc_video_device *video, ctrl->info->size); } - uvc_set_le_value(value, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping); + mapping->set(mapping, value, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); ctrl->dirty = 1; ctrl->modified = 1; @@ -1274,6 +1321,11 @@ int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping) struct uvc_control_mapping *map; int ret = -EINVAL; + if (mapping->get == NULL) + mapping->get = uvc_get_le_value; + if (mapping->set == NULL) + mapping->set = uvc_set_le_value; + if (mapping->id & ~V4L2_CTRL_ID_MASK) { uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with " "invalid control id 0x%08x\n", mapping->name, diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 95eb6f3ad..b6ee9aac6 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -920,7 +920,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - info = kmalloc(sizeof *info, GFP_KERNEL); + info = kzalloc(sizeof *info, GFP_KERNEL); if (info == NULL) return -ENOMEM; @@ -947,7 +947,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - map = kmalloc(sizeof *map, GFP_KERNEL); + map = kzalloc(sizeof *map, GFP_KERNEL); if (map == NULL) return -ENOMEM; diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index a699c0bb1..549d09fd3 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -384,6 +384,11 @@ struct uvc_control_mapping { struct uvc_menu_info *menu_info; __u32 menu_count; + + __s32 (*get) (struct uvc_control_mapping *mapping, __u8 query, + const __u8 *data); + void (*set) (struct uvc_control_mapping *mapping, __s32 value, + __u8 *data); }; struct uvc_control { -- cgit v1.2.3 From bd1a1f2bd484ed3eaa12def931e17c4444535ef8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 16 Dec 2008 12:32:37 +0100 Subject: v4l2-compat: test for unlocked_ioctl as well. From: Hans Verkuil The v4l_compat_ioctl32() function only tested for the presence of the ioctl op, not for unlocked_ioctl. So it would always return an error when used with drivers that use unlocked_ioctl instead of ioctl. Priority: high Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-compat-ioctl32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index e2e7a2061..171f1ccd1 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -887,7 +887,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) { int ret = -ENOIOCTLCMD; - if (!file->f_op->ioctl) + if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl) return ret; switch (cmd) { -- cgit v1.2.3 From d3b9334a55811e523ddf592d3a00a08b9a30dc6a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 16 Dec 2008 14:41:57 +0100 Subject: uvcvideo: Fix bulk URB processing when the header is erroneous From: Laurent Pinchart When the first bulk URB of a video payload contains an erroneous header, or when no V4L2 buffer is available, the whole payload must be dropped. Change the skip logic to drop all bulk URBs until the end of the payload instead of the first one only. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_video.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index b19e91dd5..3cb91444e 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -368,7 +368,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video, /* Synchronize to the input stream by waiting for the FID bit to be * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. - * queue->last_fid is initialized to -1, so the first isochronous + * video->last_fid is initialized to -1, so the first isochronous * frame will always be in sync. * * If the device doesn't toggle the FID bit, invert video->last_fid @@ -395,7 +395,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video, * last payload can be lost anyway). We thus must check if the FID has * been toggled. * - * queue->last_fid is initialized to -1, so the first isochronous + * video->last_fid is initialized to -1, so the first isochronous * frame will never trigger an end of frame detection. * * Empty buffers (bytesused == 0) don't trigger end of frame detection @@ -512,7 +512,7 @@ static void uvc_video_decode_bulk(struct urb *urb, /* If the URB is the first of its payload, decode and save the * header. */ - if (video->bulk.header_size == 0) { + if (video->bulk.header_size == 0 && !video->bulk.skip_payload) { do { ret = uvc_video_decode_start(video, buf, mem, len); if (ret == -EAGAIN) @@ -522,14 +522,13 @@ static void uvc_video_decode_bulk(struct urb *urb, /* If an error occured skip the rest of the payload. */ if (ret < 0 || buf == NULL) { video->bulk.skip_payload = 1; - return; - } + } else { + memcpy(video->bulk.header, mem, ret); + video->bulk.header_size = ret; - video->bulk.header_size = ret; - memcpy(video->bulk.header, mem, video->bulk.header_size); - - mem += ret; - len -= ret; + mem += ret; + len -= ret; + } } /* The buffer queue might have been cancelled while a bulk transfer -- cgit v1.2.3 From 1e115775994e75b023a2b0a53fecb75bb949cc95 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Dec 2008 16:25:46 -0200 Subject: Revert changeset 9886 From: Mauro Carvalho Chehab Changeset 9886 were applied by mistake, reverting changeset 9885, that got a wrong comment. Let's revert it. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/b2c2/Kconfig | 2 +- linux/drivers/media/dvb/bt8xx/Kconfig | 2 +- linux/drivers/media/dvb/dvb-usb/Kconfig | 46 +++++++++++++++---------------- linux/drivers/media/dvb/ttpci/Kconfig | 2 +- linux/drivers/media/video/cx18/Kconfig | 2 +- linux/drivers/media/video/cx23885/Kconfig | 4 +-- linux/drivers/media/video/cx88/Kconfig | 2 +- linux/drivers/media/video/pvrusb2/Kconfig | 2 +- linux/drivers/media/video/saa7134/Kconfig | 4 +-- 9 files changed, 33 insertions(+), 33 deletions(-) diff --git a/linux/drivers/media/dvb/b2c2/Kconfig b/linux/drivers/media/dvb/b2c2/Kconfig index e5c27e355..bd21c3bf2 100644 --- a/linux/drivers/media/dvb/b2c2/Kconfig +++ b/linux/drivers/media/dvb/b2c2/Kconfig @@ -9,12 +9,12 @@ config DVB_B2C2_FLEXCOP select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_BCM3510 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select DVB_S5H1420 if !DVB_FE_CUSTOMISE select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/linux/drivers/media/dvb/bt8xx/Kconfig b/linux/drivers/media/dvb/bt8xx/Kconfig index 7e9c090fc..27edb0ece 100644 --- a/linux/drivers/media/dvb/bt8xx/Kconfig +++ b/linux/drivers/media/dvb/bt8xx/Kconfig @@ -8,7 +8,7 @@ config DVB_BT8XX select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE help Support for PCI cards based on the Bt8xx PCI bridge. Examples are the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 62b68c291..49f7b20c2 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -24,8 +24,8 @@ config DVB_USB_A800 tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. @@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MB - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-B demodulator. @@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Support for USB2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-C/P demodulator. @@ -73,11 +73,11 @@ config DVB_USB_DIB0700 select DVB_DIB7000M select DVB_DIB3000MC select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE select DVB_TUNER_DIB0070 + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB @@ -95,7 +95,7 @@ config DVB_USB_UMT_010 depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. @@ -107,11 +107,11 @@ config DVB_USB_CXUSB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE select DVB_DIB7000P if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode @@ -124,9 +124,9 @@ config DVB_USB_M920X tristate "Uli m920x DVB-T USB2.0 support" depends on DVB_USB select DVB_MT352 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Currently, only devices with a product id of @@ -137,7 +137,7 @@ config DVB_USB_GL861 tristate "Genesys Logic GL861 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 receiver with USB ID 0db0:5581. @@ -146,7 +146,7 @@ config DVB_USB_AU6610 tristate "Alcor Micro AU6610 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. @@ -198,8 +198,8 @@ config DVB_USB_NOVA_T_USB2 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. @@ -235,8 +235,8 @@ config DVB_USB_OPERA1 config DVB_USB_AF9005 tristate "Afatech AF9005 DVB-T USB1.1 support" depends on DVB_USB && EXPERIMENTAL - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver and the TerraTec Cinergy T USB XE (Rev.1) @@ -284,7 +284,7 @@ config DVB_USB_DTV5100 tristate "AME DTV-5100 USB2.0 DVB-T support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. @@ -293,9 +293,9 @@ config DVB_USB_AF9015 depends on DVB_USB && EXPERIMENTAL select DVB_AF9013 select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index 9e2ece9e4..ab0bcd208 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -108,7 +108,7 @@ config DVB_BUDGET_CI select DVB_STB6100 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE select VIDEO_IR help Support for simple SAA7146 based DVB cards diff --git a/linux/drivers/media/video/cx18/Kconfig b/linux/drivers/media/video/cx18/Kconfig index ef48565de..8940b5387 100644 --- a/linux/drivers/media/video/cx18/Kconfig +++ b/linux/drivers/media/video/cx18/Kconfig @@ -9,7 +9,7 @@ config VIDEO_CX18 select VIDEO_CX2341X select VIDEO_CS5345 select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE ---help--- This is a video4linux driver for Conexant cx23418 based PCI combo video recorder devices. diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 8c1b7fa47..00f1e2e88 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -11,16 +11,16 @@ config VIDEO_CX23885 select VIDEO_CX25840 select VIDEO_CX2341X select DVB_DIB7000P if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE + select DVB_TDA10048 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE - select DVB_TDA10048 if !DVB_FE_CUSTOMIZE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index 0b9e5fac6..b0f837588 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -56,12 +56,12 @@ config VIDEO_CX88_DVB select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0288 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 19eb274c9..854c2a885 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -42,7 +42,7 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE ---help--- diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index 7021bbf58..fc2164e28 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -34,9 +34,9 @@ config VIDEO_SAA7134_DVB select DVB_NXT200X if !DVB_FE_CUSTOMISE select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. -- cgit v1.2.3 From a0eaf112882fd10323cb5a701bffffb4e5dfcb7b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Dec 2008 21:00:49 -0200 Subject: em28xx: move dev->lock from res_free to the caller routines From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index ff960f90c..9ac643abb 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -622,10 +622,8 @@ static void res_free(struct em28xx_fh *fh) { struct em28xx *dev = fh->dev; - mutex_lock(&dev->lock); fh->stream_on = 0; dev->stream_on = 0; - mutex_unlock(&dev->lock); } /* @@ -1293,7 +1291,9 @@ static int vidioc_streamoff(struct file *file, void *priv, return -EINVAL; videobuf_streamoff(&fh->vb_vidq); + mutex_lock(&dev->lock); res_free(fh); + mutex_unlock(&dev->lock); return 0; } @@ -1740,11 +1740,10 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) em28xx_videodbg("users=%d\n", dev->users); + mutex_lock(&dev->lock); if (res_check(fh)) res_free(fh); - mutex_lock(&dev->lock); - if (dev->users == 1) { videobuf_stop(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq); -- cgit v1.2.3 From a382f22c815364a55ab62b31eb5f3b6157dc250c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Dec 2008 21:19:24 -0200 Subject: em28xx: move res_get locks to the caller routines From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 36 +++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 9ac643abb..d486bc204 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -604,12 +604,10 @@ static int res_get(struct em28xx_fh *fh) return rc; if (dev->stream_on) - return -EINVAL; + return -EBUSY; - mutex_lock(&dev->lock); dev->stream_on = 1; fh->stream_on = 1; - mutex_unlock(&dev->lock); return rc; } @@ -1268,8 +1266,12 @@ static int vidioc_streamon(struct file *file, void *priv, return rc; - if (unlikely(res_get(fh) < 0)) - return -EBUSY; + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; return (videobuf_streamon(&fh->vb_vidq)); } @@ -1801,8 +1803,12 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, */ if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (unlikely(res_get(fh))) - return -EBUSY; + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); @@ -1824,7 +1830,11 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) if (rc < 0) return rc; - if (unlikely(res_get(fh) < 0)) + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) return POLLERR; if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) @@ -1842,13 +1852,17 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) struct em28xx *dev = fh->dev; int rc; - if (unlikely(res_get(fh) < 0)) - return -EBUSY; - rc = check_dev(dev); if (rc < 0) return rc; + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; + rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", -- cgit v1.2.3 From e19130557b656d2b6aeaf8da6a9a58e428ef1b00 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Dec 2008 21:36:13 -0200 Subject: em28xx: vidioc_try_fmt_vid_cap() doesn't need any lock From: Mauro Carvalho Chehab vidioc_try_fmt_vid_cap() just checks if a given resolution is supported. It doesn't touch on struct em28xx device descriptor. so, there's no need to lock. While there, use unlikely() for those values that aren't likely to occur. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index d486bc204..415ac9861 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -735,19 +735,17 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, /* width must even because of the YUYV format height must be even because of interlacing */ height &= 0xfffe; - width &= 0xfffe; + width &= 0xfffe; - if (height < 32) + if (unlikely(height < 32)) height = 32; - if (height > maxh) + if (unlikely(height > maxh)) height = maxh; - if (width < 48) + if (unlikely(width < 48)) width = 48; - if (width > maxw) + if (unlikely(width > maxw)) width = maxw; - mutex_lock(&dev->lock); - if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ if (height % (maxh / 2)) @@ -777,7 +775,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.field = V4L2_FIELD_INTERLACED; - mutex_unlock(&dev->lock); return 0; } -- cgit v1.2.3 From 9052d2a1095d9cf39e4f9d3fa8989beefbd2933e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Dec 2008 23:04:56 -0200 Subject: em28xx: fix/improve em28xx locking schema From: Mauro Carvalho Chehab Changes/fixes on em28xx dev->lock: - em28xx_init_dev() were unlocking without a previous lock; - some read ioctls need to lock after the removal of KBL, since a write may be happening at the same time an ioctl is reading; - keep the device locked during all device initialization; - lock/unlock while reading/writing registers. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 55 +++++++++++++++++++------ 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 415ac9861..acf6141aa 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -789,10 +789,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (rc < 0) return rc; - vidioc_try_fmt_vid_cap(file, priv, f); - mutex_lock(&dev->lock); + vidioc_try_fmt_vid_cap(file, priv, f); + if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); rc = -EBUSY; @@ -833,15 +833,12 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) mutex_lock(&dev->lock); dev->norm = *norm; - mutex_unlock(&dev->lock); /* Adjusts width/height, if needed */ f.fmt.pix.width = dev->width; f.fmt.pix.height = dev->height; vidioc_try_fmt_vid_cap(file, priv, &f); - mutex_lock(&dev->lock); - /* set new image size */ dev->width = f.fmt.pix.width; dev->height = f.fmt.pix.height; @@ -976,11 +973,15 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) if (a->index != dev->ctl_ainput) return -EINVAL; #else + mutex_lock(&dev->lock); + dev->ctl_ainput = INPUT(a->index)->amux; dev->ctl_aoutput = INPUT(a->index)->aout; if (!dev->ctl_aoutput) dev->ctl_aoutput = EM28XX_AOUT_MASTER; + + mutex_unlock(&dev->lock); #endif return 0; } @@ -1030,6 +1031,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, rc = check_dev(dev); if (rc < 0) return rc; + mutex_lock(&dev->lock); if (!dev->board.has_msp34xx) @@ -1140,8 +1142,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; + mutex_lock(&dev->lock); f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->ctl_freq; + mutex_unlock(&dev->lock); return 0; } @@ -1171,6 +1175,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); mutex_unlock(&dev->lock); + return 0; } @@ -1198,15 +1203,20 @@ static int vidioc_g_register(struct file *file, void *priv, return -EINVAL; if (em28xx_reg_len(reg->reg) == 1) { + mutex_lock(&dev->lock); ret = em28xx_read_reg(dev, reg->reg); + mutex_unlock(&dev->lock); + if (ret < 0) return ret; reg->val = ret; } else { __le64 val = 0; + mutex_lock(&dev->lock); ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, reg->reg, (char *)&val, 2); + mutex_unlock(&dev->lock); if (ret < 0) return ret; @@ -1222,11 +1232,16 @@ static int vidioc_s_register(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; __le64 buf; + int rc; buf = cpu_to_le64(reg->val); - return em28xx_write_regs(dev, reg->reg, (char *)&buf, - em28xx_reg_len(reg->reg)); + mutex_lock(&dev->lock); + rc = em28xx_write_regs(dev, reg->reg, (char *)&buf, + em28xx_reg_len(reg->reg)); + mutex_unlock(&dev->lock); + + return rc; } #endif @@ -1265,12 +1280,15 @@ static int vidioc_streamon(struct file *file, void *priv, mutex_lock(&dev->lock); rc = res_get(fh); - mutex_unlock(&dev->lock); if (unlikely(rc < 0)) return rc; - return (videobuf_streamon(&fh->vb_vidq)); + rc = videobuf_streamon(&fh->vb_vidq); + + mutex_unlock(&dev->lock); + + return rc; } static int vidioc_streamoff(struct file *file, void *priv, @@ -1289,9 +1307,11 @@ static int vidioc_streamoff(struct file *file, void *priv, if (type != fh->type) return -EINVAL; - videobuf_streamoff(&fh->vb_vidq); mutex_lock(&dev->lock); + + videobuf_streamoff(&fh->vb_vidq); res_free(fh); + mutex_unlock(&dev->lock); return 0; @@ -1513,7 +1533,10 @@ static int radio_g_tuner(struct file *file, void *priv, strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; + mutex_lock(&dev->lock); em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); + mutex_unlock(&dev->lock); + return 0; } @@ -1545,7 +1568,9 @@ static int radio_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; + mutex_lock(&dev->lock); em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); + mutex_unlock(&dev->lock); return 0; } @@ -1609,6 +1634,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) } } mutex_unlock(&em28xx_devlist_mutex); + if (NULL == dev) return -ENODEV; @@ -2104,7 +2130,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, unsigned int maxh, maxw; dev->udev = udev; - mutex_init(&dev->lock); mutex_init(&dev->ctrl_urb_lock); spin_lock_init(&dev->slock); init_waitqueue_head(&dev->open); @@ -2222,7 +2247,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return 0; fail_reg_devices: - mutex_unlock(&dev->lock); return retval; } @@ -2425,6 +2449,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, dev->model = card[nr]; /* allocate device struct */ + mutex_init(&dev->lock); + mutex_lock(&dev->lock); retval = em28xx_init_dev(&dev, udev, nr); if (retval) { em28xx_devused &= ~(1<devno); @@ -2438,6 +2464,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, request_modules(dev); + /* Should be the last thing to do, to avoid newer udev's to + open the device before fully initializing it + */ + mutex_unlock(&dev->lock); + return 0; } -- cgit v1.2.3 From 0d788195b491c7c18524b30618f44059eb35bc06 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 16 Dec 2008 21:09:35 -0500 Subject: em28xx: fix NULL pointer dereference in call to VIDIOC_INT_RESET command From: Devin Heitmueller Fix a NULL pointer dereference that would occur if the video decoder tied to the em28xx supports the VIDIOC_INT_RESET call (for example: the cx25840 driver) Priority: high Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index ff960f90c..f3c9e2331 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -555,10 +555,11 @@ static int em28xx_config(struct em28xx *dev) static void em28xx_config_i2c(struct em28xx *dev) { struct v4l2_routing route; + int zero = 0; route.input = INPUT(dev->ctl_input)->vmux; route.output = 0; - em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); + em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero); em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); } -- cgit v1.2.3 From 92b4058a43959c8e3cba8044d4bd3adba9cabdd5 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 16 Dec 2008 21:15:33 -0500 Subject: em28xx: add chip id for em2874 From: Devin Heitmueller Add the em2870 to the list of known em28xx chip ids. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 ++++ linux/drivers/media/video/em28xx/em28xx-reg.h | 1 + 2 files changed, 5 insertions(+) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 2ecc98af7..3eb4408b4 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1480,6 +1480,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) case CHIP_ID_EM2860: em28xx_info("chip ID is em2860\n"); break; + case CHIP_ID_EM2870: + em28xx_info("chip ID is em2870\n"); + dev->wait_after_write = 0; + break; case CHIP_ID_EM2874: em28xx_info("chip ID is em2874\n"); dev->reg_gpio_num = EM2874_R80_GPIO; diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 45d588c3a..a459b7c6a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -151,6 +151,7 @@ enum em28xx_chip_id { CHIP_ID_EM2840 = 20, CHIP_ID_EM2750 = 33, CHIP_ID_EM2860 = 34, + CHIP_ID_EM2870 = 35, CHIP_ID_EM2883 = 36, CHIP_ID_EM2874 = 65, }; -- cgit v1.2.3 From 1a40501f3c36a45f405ee3bc6c76bb87df9c358d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 16 Dec 2008 21:35:23 -0500 Subject: em28xx: don't assume every eb1a:2820 reference design is a Prolink PlayTV USB2 From: Devin Heitmueller Don't operate under the assumption that every device that uses the em2820 default USB ID is a Prolink PlayTV USB. We have an eeprom hash, so use that, since otherwise we cannot support other devices with the 2820 default USB ID (such as the ADS Tech Instant TV USB USBAV-704) Priority: normal Signed-off-by: Devin Heitmueller --- linux/Documentation/video4linux/CARDLIST.em28xx | 4 ++-- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index a6734eb7b..0c4c721da 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -1,5 +1,5 @@ 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] - 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2820,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] + 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] @@ -12,7 +12,7 @@ 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] - 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) [eb1a:2821] + 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) 15 -> V-Gear PocketTV (em2800) 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b] 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227] diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 3eb4408b4..7a2553c4d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1313,7 +1313,7 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2821), - .driver_info = EM2820_BOARD_PROLINK_PLAYTV_USB2 }, + .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2860), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2861), -- cgit v1.2.3 From 0a596528dd15515efbbf6ce078155e61610b57e9 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 17 Dec 2008 00:25:00 -0500 Subject: xc5000: remove init_fw option From: Devin Heitmueller The init_fw option was broken for the HVR-950q because we would call the reset callback inside of dvb_attach() and the callback had not been setup yet. Michael Krufky (who added the init_fw feature) says it's no longer required, so just remove the option completely. Thanks to user Zzeiss from #linuxtv chat for reporting the issue and Michael Krufky for proposing the fix. Priority: normal Signed-off-by: Devin Heitmueller Acked-by: Michael Krufky --- linux/drivers/media/common/tuners/xc5000.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 8cfac7002..36c81febb 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -36,10 +36,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); -static int xc5000_load_fw_on_attach; -module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644); -MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); - static DEFINE_MUTEX(xc5000_list_mutex); static LIST_HEAD(hybrid_tuner_instance_list); @@ -1036,9 +1032,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, sizeof(struct dvb_tuner_ops)); - if (xc5000_load_fw_on_attach) - xc5000_init(fe); - return fe; fail: mutex_unlock(&xc5000_list_mutex); -- cgit v1.2.3 From 33a9296bbce53f4adc778193439835dd44892f72 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 17 Dec 2008 18:01:07 +0100 Subject: mt9m111: mt9m111_get_global_gain() - unsigned >= 0 is always true From: roel kluin unsigned >= 0 is always true and fix formula Signed-off-by: Roel Kluin Acked-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m111.c | 13 +++++-------- 1 files changed, 5 insertions(+), 8 deletions(-) --- linux/drivers/media/video/mt9m111.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 1fde94514..336bb8d8b 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -634,18 +634,15 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) static int mt9m111_get_global_gain(struct soc_camera_device *icd) { - unsigned int data, gain; + int data; data = reg_read(GLOBAL_GAIN); if (data >= 0) - gain = ((data & (1 << 10)) * 2) - | ((data & (1 << 9)) * 2) - | (data & 0x2f); - else - gain = data; - - return gain; + return (data & 0x2f) * (1 << ((data >> 10) & 1)) * + (1 << ((data >> 9) & 1)); + return data; } + static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) { u16 val; -- cgit v1.2.3 From 79cf0e3dfb501a547e6a7b9145a6fddd6ac05f18 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 17 Dec 2008 18:05:31 +0100 Subject: mt9m111: add all yuv format combinations. From: Robert Jarzmik The Micron mt9m111 offers 4 byte orders for YCbCr output. This patchs adds all possible outputs capabilities to the mt9m111 driver. Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m111.c | 24 +++++++++++++++++++++++- 1 files changed, 23 insertions(+), 1 deletions(-) --- linux/drivers/media/video/mt9m111.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 336bb8d8b..dc3a913da 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -128,9 +128,14 @@ .colorspace = _colorspace } #define RGB_FMT(_name, _depth, _fourcc) \ COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB) +#define JPG_FMT(_name, _depth, _fourcc) \ + COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG) static const struct soc_camera_data_format mt9m111_colour_formats[] = { - COL_FMT("YCrYCb 8 bit", 8, V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_JPEG), + JPG_FMT("CbYCrY 16 bit", 16, V4L2_PIX_FMT_UYVY), + JPG_FMT("CrYCbY 16 bit", 16, V4L2_PIX_FMT_VYUY), + JPG_FMT("YCbYCr 16 bit", 16, V4L2_PIX_FMT_YUYV), + JPG_FMT("YCrYCb 16 bit", 16, V4L2_PIX_FMT_YVYU), RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565), RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555), RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16), @@ -438,7 +443,24 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) case V4L2_PIX_FMT_RGB565: ret = mt9m111_setfmt_rgb565(icd); break; + case V4L2_PIX_FMT_UYVY: + mt9m111->swap_yuv_y_chromas = 0; + mt9m111->swap_yuv_cb_cr = 0; + ret = mt9m111_setfmt_yuv(icd); + break; + case V4L2_PIX_FMT_VYUY: + mt9m111->swap_yuv_y_chromas = 0; + mt9m111->swap_yuv_cb_cr = 1; + ret = mt9m111_setfmt_yuv(icd); + break; case V4L2_PIX_FMT_YUYV: + mt9m111->swap_yuv_y_chromas = 1; + mt9m111->swap_yuv_cb_cr = 0; + ret = mt9m111_setfmt_yuv(icd); + break; + case V4L2_PIX_FMT_YVYU: + mt9m111->swap_yuv_y_chromas = 1; + mt9m111->swap_yuv_cb_cr = 1; ret = mt9m111_setfmt_yuv(icd); break; default: -- cgit v1.2.3 From cd63b99e5c28670053a6a7ce199d683073417d68 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 17 Dec 2008 18:05:38 +0100 Subject: mt9m001 mt9v022: fix bus-width switch GPIO availability test From: Guennadi Liakhovetski Testing for non-NULL platform-data is not enough, we have to check if the GPIO in the platform data is valid or not. Also see my earlier patch: [ARM] pxa/pcm990: use negative number for an invalid GPIO in camera data Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m001.c | 5 +++-- drivers/media/video/mt9v022.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) --- linux/drivers/media/video/mt9m001.c | 5 +++-- linux/drivers/media/video/mt9v022.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index edacba723..a489f239f 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -578,6 +578,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9m001_video_probe(struct soc_camera_device *icd) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; s32 data; int ret; @@ -600,7 +601,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) case 0x8421: mt9m001->model = V4L2_IDENT_MT9M001C12ST; icd->formats = mt9m001_colour_formats; - if (mt9m001->client->dev.platform_data) + if (gpio_is_valid(icl->gpio)) icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats); else icd->num_formats = 1; @@ -608,7 +609,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) case 0x8431: mt9m001->model = V4L2_IDENT_MT9M001C12STM; icd->formats = mt9m001_monochrome_formats; - if (mt9m001->client->dev.platform_data) + if (gpio_is_valid(icl->gpio)) icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); else icd->num_formats = 1; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 1ca28c087..88380e05f 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -690,6 +690,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, static int mt9v022_video_probe(struct soc_camera_device *icd) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; s32 data; int ret; @@ -725,7 +726,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; icd->formats = mt9v022_colour_formats; - if (mt9v022->client->dev.platform_data) + if (gpio_is_valid(icl->gpio)) icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats); else icd->num_formats = 1; @@ -733,7 +734,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; icd->formats = mt9v022_monochrome_formats; - if (mt9v022->client->dev.platform_data) + if (gpio_is_valid(icl->gpio)) icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); else icd->num_formats = 1; -- cgit v1.2.3 From b47a355e559b5ff0a294071f14caccb77b56db0d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 17 Dec 2008 18:05:45 +0100 Subject: Remove ov772x_default_regs from ov772x driver From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 21 +++------------------ 1 files changed, 3 insertions(+), 18 deletions(-) --- linux/drivers/media/video/ov772x.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index c023bbc84..582e72d2f 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -378,30 +378,17 @@ struct ov772x_priv { #define ENDMARKER { 0xff, 0xff } -static const struct regval_list ov772x_default_regs[] = -{ - { COM3, 0x00 }, - { COM4, PLL_4x | 0x01 }, - { 0x16, 0x00 }, /* Mystery */ - { COM11, 0x10 }, /* Mystery */ - { 0x28, 0x00 }, /* Mystery */ - { HREF, 0x00 }, - { COM13, 0xe2 }, /* Mystery */ - { AREF0, 0xef }, - { AREF2, 0x60 }, - { AREF6, 0x7a }, - ENDMARKER, -}; - /* * register setting for color format */ static const struct regval_list ov772x_RGB555_regs[] = { + { COM3, 0x00 }, { COM7, FMT_RGB555 | OFMT_RGB }, ENDMARKER, }; static const struct regval_list ov772x_RGB565_regs[] = { + { COM3, 0x00 }, { COM7, FMT_RGB565 | OFMT_RGB }, ENDMARKER, }; @@ -413,6 +400,7 @@ static const struct regval_list ov772x_YYUV_regs[] = { }; static const struct regval_list ov772x_UVYY_regs[] = { + { COM3, 0x00 }, { COM7, OFMT_YUV }, ENDMARKER, }; @@ -634,9 +622,6 @@ static int ov772x_start_capture(struct soc_camera_device *icd) * reset hardware */ ov772x_reset(priv->client); - ret = ov772x_write_array(priv->client, ov772x_default_regs); - if (ret < 0) - goto start_end; /* * set color format -- cgit v1.2.3 From 7e4100d01b2feacf1b8b3836bc93d5f60b965ce3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 17 Dec 2008 18:34:53 +0100 Subject: gspca - spca561: Cleanup source. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca561.c | 260 ++++++++++++++---------------- 1 file changed, 117 insertions(+), 143 deletions(-) diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c index 4c0046cc7..3a27faf60 100644 --- a/linux/drivers/media/video/gspca/spca561.c +++ b/linux/drivers/media/video/gspca/spca561.c @@ -146,98 +146,7 @@ static struct v4l2_pix_format sif_072a_mode[] = { #define SPCA561_SNAPBIT 0x20 #define SPCA561_SNAPCTRL 0x40 -static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value) -{ - int ret; - - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); - if (ret < 0) - PDEBUG(D_ERR, "reg write: error %d", ret); -} - -static void write_vector(struct gspca_dev *gspca_dev, - const __u16 data[][2]) -{ - struct usb_device *dev = gspca_dev->dev; - int i; - - i = 0; - while (data[i][1] != 0) { - reg_w_val(dev, data[i][1], data[i][0]); - i++; - } -} - -/* read 'len' bytes to gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - __u16 index, __u16 length) -{ - usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, length, 500); -} - -static void reg_w_buf(struct gspca_dev *gspca_dev, - __u16 index, const __u8 *buffer, __u16 len) -{ - memcpy(gspca_dev->usb_buf, buffer, len); - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, len, 500); -} - -static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg) -{ - int retry = 60; - __u8 DataLow; - __u8 DataHight; - - DataLow = valeur; - DataHight = valeur >> 8; - reg_w_val(gspca_dev->dev, 0x8801, reg); - reg_w_val(gspca_dev->dev, 0x8805, DataLow); - reg_w_val(gspca_dev->dev, 0x8800, DataHight); - while (retry--) { - reg_r(gspca_dev, 0x8803, 1); - if (!gspca_dev->usb_buf[0]) - break; - } -} - -static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode) -{ - int retry = 60; - __u8 value; - __u8 vallsb; - - reg_w_val(gspca_dev->dev, 0x8804, 0x92); - reg_w_val(gspca_dev->dev, 0x8801, reg); - reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01)); - do { - reg_r(gspca_dev, 0x8803, 1); - if (!gspca_dev->usb_buf[0]) - break; - } while (--retry); - if (retry == 0) - return -1; - reg_r(gspca_dev, 0x8800, 1); - value = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8805, 1); - vallsb = gspca_dev->usb_buf[0]; - return ((int) value << 8) | vallsb; -} - -static const __u16 spca561_init_data[][2] = { +static const __u16 rev72a_init_data[][2] = { {0x0000, 0x8114}, /* Software GPIO output data */ {0x0001, 0x8114}, /* Software GPIO output data */ {0x0000, 0x8112}, /* Some kind of reset */ @@ -324,7 +233,7 @@ static const __u16 spca561_init_data[][2] = { {0x0002, 0x865b}, /* Horizontal offset for valid pixels */ {0x0003, 0x865c}, /* Vertical offset for valid lines */ - /***************//* sensor active */ + /***************/ /* sensor active */ {0x0003, 0x8801}, /* 0x03 <- 0x01 0x21 //289 */ {0x0021, 0x8805}, {0x0001, 0x8800}, @@ -434,21 +343,6 @@ static const __u16 spca561_init_data[][2] = { {} }; -#if 0 -static void sensor_reset(struct gspca_dev *gspca_dev) -{ - reg_w_val(gspca_dev->dev, 0x8631, 0xc8); - reg_w_val(gspca_dev->dev, 0x8634, 0xc8); - reg_w_val(gspca_dev->dev, 0x8112, 0x00); - reg_w_val(gspca_dev->dev, 0x8114, 0x00); - reg_w_val(gspca_dev->dev, 0x8118, 0x21); - reg_w_val(gspca_dev->dev, 0x8804, 0x92); /* i2c init */ - reg_w_val(gspca_dev->dev, 0x8802, 0x14); - i2c_write(gspca_dev, 0x0001, 0x0d); - i2c_write(gspca_dev, 0x0000, 0x0d); -} -#endif - /******************** QC Express etch2 stuff ********************/ static const __u16 Pb100_1map8300[][2] = { /* reg, value */ @@ -529,22 +423,103 @@ static const __u16 spca561_161rev12A_data2[][2] = { {} }; -static void sensor_mapwrite(struct gspca_dev *gspca_dev, - const __u16 sensormap[][2]) +static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value) { - int i = 0; - __u8 usbval[2]; + int ret; + + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, NULL, 0, 500); + PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); + if (ret < 0) + PDEBUG(D_ERR, "reg write: error %d", ret); +} + +static void write_vector(struct gspca_dev *gspca_dev, + const __u16 data[][2]) +{ + struct usb_device *dev = gspca_dev->dev; + int i; - while (sensormap[i][0]) { - usbval[0] = sensormap[i][1]; - usbval[1] = sensormap[i][1] >> 8; - reg_w_buf(gspca_dev, sensormap[i][0], usbval, 2); + i = 0; + while (data[i][1] != 0) { + reg_w_val(dev, data[i][1], data[i][0]); i++; } } + +/* read 'len' bytes to gspca_dev->usb_buf */ +static void reg_r(struct gspca_dev *gspca_dev, + __u16 index, __u16 length) +{ + usb_control_msg(gspca_dev->dev, + usb_rcvctrlpipe(gspca_dev->dev, 0), + 0, /* request */ + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, /* value */ + index, gspca_dev->usb_buf, length, 500); +} + +/* write 'len' bytes from gspca_dev->usb_buf */ +static void reg_w_buf(struct gspca_dev *gspca_dev, + __u16 index, __u16 len) +{ + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, /* value */ + index, gspca_dev->usb_buf, len, 500); +} + +static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg) +{ + int retry = 60; + + reg_w_val(gspca_dev->dev, 0x8801, reg); + reg_w_val(gspca_dev->dev, 0x8805, value); + reg_w_val(gspca_dev->dev, 0x8800, value >> 8); + do { + reg_r(gspca_dev, 0x8803, 1); + if (!gspca_dev->usb_buf[0]) + return; + } while (--retry); +} + +static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode) +{ + int retry = 60; + __u8 value; + + reg_w_val(gspca_dev->dev, 0x8804, 0x92); + reg_w_val(gspca_dev->dev, 0x8801, reg); + reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01); + do { + reg_r(gspca_dev, 0x8803, 1); + if (!gspca_dev->usb_buf[0]) { + reg_r(gspca_dev, 0x8800, 1); + value = gspca_dev->usb_buf[0]; + reg_r(gspca_dev, 0x8805, 1); + return ((int) value << 8) | gspca_dev->usb_buf[0]; + } + } while (--retry); + return -1; +} + +static void sensor_mapwrite(struct gspca_dev *gspca_dev, + const __u16 (*sensormap)[2]) +{ + while ((*sensormap)[0]) { + gspca_dev->usb_buf[0] = (*sensormap)[1]; + gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8; + reg_w_buf(gspca_dev, (*sensormap)[0], 2); + sensormap++; + } +} + static void init_161rev12A(struct gspca_dev *gspca_dev) { -/* sensor_reset(gspca_dev); (not in win) */ write_vector(gspca_dev, spca561_161rev12A_data1); sensor_mapwrite(gspca_dev, Pb100_1map8300); /*fixme: should be in sd_start*/ @@ -612,7 +587,7 @@ static int sd_init_12a(struct gspca_dev *gspca_dev) static int sd_init_72a(struct gspca_dev *gspca_dev) { PDEBUG(D_STREAM, "Chip revision: 072a"); - write_vector(gspca_dev, spca561_init_data); + write_vector(gspca_dev, rev72a_init_data); return 0; } @@ -635,8 +610,9 @@ static void setcontrast(struct gspca_dev *gspca_dev) static const __u8 Reg8391[] = { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 }; - reg_w_buf(gspca_dev, 0x8391, Reg8391, 8); - reg_w_buf(gspca_dev, 0x8390, Reg8391, 8); + memcpy(gspca_dev->usb_buf, Reg8391, 8); + reg_w_buf(gspca_dev, 0x8391, 8); + reg_w_buf(gspca_dev, 0x8390, 8); break; } } @@ -663,7 +639,6 @@ static void setexposure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int expo; int clock_divider; - __u8 data[2]; /* Register 0x8309 controls exposure for the spca561, the basic exposure setting goes from 1-2047, where 1 is completely @@ -687,20 +662,19 @@ static void setexposure(struct gspca_dev *gspca_dev) clock_divider = 3; } expo |= clock_divider << 11; - data[0] = expo; - data[1] = expo >> 8; - reg_w_buf(gspca_dev, 0x8309, data, 2); + gspca_dev->usb_buf[0] = expo; + gspca_dev->usb_buf[1] = expo >> 8; + reg_w_buf(gspca_dev, 0x8309, 2); } /* rev 12a only */ static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 data[2]; - data[0] = sd->gain; - data[1] = 0; - reg_w_buf(gspca_dev, 0x8335, data, 2); + gspca_dev->usb_buf[0] = sd->gain; + gspca_dev->usb_buf[1] = 0; + reg_w_buf(gspca_dev, 0x8335, 2); } static void setautogain(struct gspca_dev *gspca_dev) @@ -730,7 +704,9 @@ static int sd_start_12a(struct gspca_dev *gspca_dev) * is sufficient to push raw frames at ~20fps */ reg_w_val(dev, 0x8500, mode); } /* -- qq@kuku.eu.org */ - reg_w_buf(gspca_dev, 0x8307, Reg8307, 2); + + memcpy(gspca_dev->usb_buf, Reg8307, sizeof Reg8307); + reg_w_buf(gspca_dev, 0x8307, sizeof Reg8307); reg_w_val(gspca_dev->dev, 0x8700, Clck); /* 0x8f 0x85 0x27 clock */ reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); @@ -805,7 +781,6 @@ static void do_autogain(struct gspca_dev *gspca_dev) __u8 luma_mean = 110; __u8 luma_delta = 20; __u8 spring = 4; - __u8 reg8339[2]; if (sd->ag_cnt < 0) return; @@ -848,13 +823,13 @@ static void do_autogain(struct gspca_dev *gspca_dev) if (gainG > 0x3f) gainG = 0x3f; - else if (gainG < 4) + else if (gainG < 3) gainG = 3; i2c_write(gspca_dev, gainG, 0x35); - if (expotimes >= 0x0256) + if (expotimes > 0x0256) expotimes = 0x0256; - else if (expotimes < 4) + else if (expotimes < 3) expotimes = 3; i2c_write(gspca_dev, expotimes | pixelclk, 0x09); } @@ -862,13 +837,13 @@ static void do_autogain(struct gspca_dev *gspca_dev) case Rev012A: reg_r(gspca_dev, 0x8330, 2); if (gspca_dev->usb_buf[1] > 0x08) { - reg8339[0] = ++sd->expo12a; - reg8339[1] = 0; - reg_w_buf(gspca_dev, 0x8339, reg8339, 2); + gspca_dev->usb_buf[0] = ++sd->expo12a; + gspca_dev->usb_buf[1] = 0; + reg_w_buf(gspca_dev, 0x8339, 2); } else if (gspca_dev->usb_buf[1] < 0x02) { - reg8339[0] = --sd->expo12a; - reg8339[1] = 0; - reg_w_buf(gspca_dev, 0x8339, reg8339, 2); + gspca_dev->usb_buf[0] = --sd->expo12a; + gspca_dev->usb_buf[1] = 0; + reg_w_buf(gspca_dev, 0x8339, 2); } break; } @@ -881,8 +856,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; - switch (data[0]) { - case 0: /* start of frame */ + switch (data[0]) { /* sequence number */ + case 0: /* start of frame */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); data += SPCA561_OFFSET_DATA; @@ -904,8 +879,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame, data, len); } return; - case 0xff: /* drop */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ + case 0xff: /* drop (empty mpackets) */ return; } data++; -- cgit v1.2.3 From 6a40b4fae51fd46e2d381f81d77b12696762302e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 17 Dec 2008 18:43:05 +0100 Subject: gspca - spca561: Don't get the control values from the webcam. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca561.c | 38 ------------------------------- 1 file changed, 38 deletions(-) diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c index 3a27faf60..ee24629f0 100644 --- a/linux/drivers/media/video/gspca/spca561.c +++ b/linux/drivers/media/video/gspca/spca561.c @@ -900,42 +900,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev->dev, 0x8614, value); } -static void getbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u16 tot; - - tot = 0; - reg_r(gspca_dev, 0x8611, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8612, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8613, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8614, 1); - tot += gspca_dev->usb_buf[0]; - sd->brightness = tot >> 2; -} - -/* rev72a only */ -static void getcontrast(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u16 tot; - - tot = 0; - reg_r(gspca_dev, 0x8651, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8652, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8653, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8654, 1); - tot += gspca_dev->usb_buf[0]; - sd->contrast = tot << 6; - PDEBUG(D_CONF, "get contrast %d", sd->contrast); -} - /* rev 72a only */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { @@ -951,7 +915,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -971,7 +934,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcontrast(gspca_dev); *val = sd->contrast; return 0; } -- cgit v1.2.3 From 8a118c204b8f52bd5b51f99be1d641360696bb21 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Dec 2008 07:00:25 -0200 Subject: tuner-xc2028: allow printing stack trace as debug on sleep code From: Mauro Carvalho Chehab tuner-xc3028 can be put to sleep to save power. However, if not properly recovered from sleep, the device won't work. It is noticed that some devices doesn't recover properly, so let's add a dump_stack() as a debug option, to allow us to track when this happens. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c index 9536e3d3b..bd010379b 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -1111,6 +1111,10 @@ static int xc2028_sleep(struct dvb_frontend *fe) return 0; tuner_dbg("Putting xc2028/3028 into poweroff mode.\n"); + if (debug > 1) { + tuner_dbg("Printing sleep stack trace:\n"); + dump_stack(); + } mutex_lock(&priv->lock); -- cgit v1.2.3 From 6b758467e8ad1f6f860d74878d4aa59d85c558b8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Dec 2008 07:21:51 -0200 Subject: cx24116: bugfix: add missing delsys in FEC lookup From: Darron Broad Delsys was missing when searching for FEC in table. This fixes FEC lookup for DVB-S2 QPSK modulation. Priority: normal CC: Steven Toth Signed-off-by: Darron Broad Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/cx24116.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c index 497ea635e..46341cfba 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.c +++ b/linux/drivers/media/dvb/frontends/cx24116.c @@ -160,6 +160,7 @@ struct cx24116_tuning { fe_spectral_inversion_t inversion; fe_code_rate_t fec; + fe_delivery_system_t delsys; fe_modulation_t modulation; fe_pilot_t pilot; fe_rolloff_t rolloff; @@ -411,14 +412,15 @@ struct cx24116_modfec { }; static int cx24116_lookup_fecmod(struct cx24116_state *state, - fe_modulation_t m, fe_code_rate_t f) + fe_delivery_system_t d, fe_modulation_t m, fe_code_rate_t f) { int i, ret = -EOPNOTSUPP; dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f); for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) { - if ((m == CX24116_MODFEC_MODES[i].modulation) && + if ((d == CX24116_MODFEC_MODES[i].delivery_system) && + (m == CX24116_MODFEC_MODES[i].modulation) && (f == CX24116_MODFEC_MODES[i].fec)) { ret = i; break; @@ -429,13 +431,13 @@ static int cx24116_lookup_fecmod(struct cx24116_state *state, } static int cx24116_set_fec(struct cx24116_state *state, - fe_modulation_t mod, fe_code_rate_t fec) + fe_delivery_system_t delsys, fe_modulation_t mod, fe_code_rate_t fec) { int ret = 0; dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec); - ret = cx24116_lookup_fecmod(state, mod, fec); + ret = cx24116_lookup_fecmod(state, delsys, mod, fec); if (ret < 0) return ret; @@ -1304,6 +1306,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe, __func__, c->delivery_system); return -EOPNOTSUPP; } + state->dnxt.delsys = c->delivery_system; state->dnxt.modulation = c->modulation; state->dnxt.frequency = c->frequency; state->dnxt.pilot = c->pilot; @@ -1314,7 +1317,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe, return ret; /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */ - ret = cx24116_set_fec(state, c->modulation, c->fec_inner); + ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner); if (ret != 0) return ret; @@ -1325,6 +1328,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe, /* discard the 'current' tuning parameters and prepare to tune */ cx24116_clone_params(fe); + dprintk("%s: delsys = %d\n", __func__, state->dcur.delsys); dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation); dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency); dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__, -- cgit v1.2.3 From afa40a80ec7ad439b805d50be5c10a90b776b6fe Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Dec 2008 07:27:23 -0200 Subject: cx24116: fix retune regression introduced in 70ee86a7c630 From: Darron Broad Thanks to AKPM for spotting this. Priority: normal CC: Steven Toth Signed-off-by: Darron Broad Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/cx24116.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c index 46341cfba..44818232d 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.c +++ b/linux/drivers/media/dvb/frontends/cx24116.c @@ -1224,7 +1224,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24116_cmd cmd; fe_status_t tunerstat; - int i, status, ret, retune; + int i, status, ret, retune = 1; dprintk("%s()\n", __func__); @@ -1241,7 +1241,6 @@ static int cx24116_set_frontend(struct dvb_frontend *fe, /* Pilot doesn't exist in DVB-S, turn bit off */ state->dnxt.pilot_val = CX24116_PILOT_OFF; - retune = 1; /* DVB-S only supports 0.35 */ if (c->rolloff != ROLLOFF_35) { @@ -1269,7 +1268,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe, case PILOT_AUTO: /* Not supported but emulated */ state->dnxt.pilot_val = (c->modulation == QPSK) ? CX24116_PILOT_OFF : CX24116_PILOT_ON; - retune = 2; + retune++; break; case PILOT_OFF: state->dnxt.pilot_val = CX24116_PILOT_OFF; -- cgit v1.2.3 From bf795fdb460dc7a6726f60f46d3f934ac83e9ad3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Dec 2008 07:27:50 -0200 Subject: dvb-core: don't add an event when in ONE SHOT mode for algo type HW From: Darron Broad It has been noticed that in HW tuning mode in cx24123.c that a check is made to not alter the status var when in one shot mode, a simpler solution is to not update here for all cards. Priority: normal Signed-off-by: Darron Broad CC: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index e7adf9f47..d1a9e587c 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -591,7 +591,7 @@ restart: if (fe->ops.tune) fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); - if (s != fepriv->status) { + if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { dprintk("%s: state changed, adding current state\n", __func__); dvb_frontend_add_event(fe, s); fepriv->status = s; -- cgit v1.2.3 From 5f031edf628f28dd28156ee7df488107f5dc3725 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Dec 2008 07:28:18 -0200 Subject: cx24116: change to ALGO_HW From: Darron Broad Slow tuning, EG: > szap-s2 -r -c 39.FTATV "1=Pgm1;Net1" reading channels from file '39.FTATV' zapping to 3 '1=Pgm1;Net1': delivery DVB-S, modulation QPSK sat 0, frequency 11140 MHz V, symbolrate 1425000, coderate 5/6, rolloff 0.35 vpid 0x0200, apid 0x0300, sid 0x0001 using '/dev/dvb/adapter0/frontend0' and '/dev/dvb/adapter0/demux0' status 00 | signal c2c0 | snr 0000 | ber 00012d4a | unc 00000000 | status 03 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 03 | signal c040 | snr 0000 | ber 00000000 | unc 00000000 | status 03 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 03 | signal c040 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal c040 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 01 | signal c040 | snr 0000 | ber 00000000 | unc 00000000 | status 03 | signal c040 | snr 0000 | ber 00000000 | unc 00000000 | status 1f | signal c040 | snr bb33 | ber 00000000 | unc 00000000 | FE_HAS_LOCK Appears to be resolved by dropping zig-zag tuning and relying on hardware only: > szap-s2 -r -c 39.FTATV "1=Pgm1;Net1" reading channels from file '39.FTATV' zapping to 3 '1=Pgm1;Net1': delivery DVB-S, modulation QPSK sat 0, frequency 11140 MHz V, symbolrate 1425000, coderate 5/6, rolloff 0.35 vpid 0x0200, apid 0x0300, sid 0x0001 using '/dev/dvb/adapter0/frontend0' and '/dev/dvb/adapter0/demux0' status 01 | signal ff80 | snr 0000 | ber 00000000 | unc 00000000 | status 1f | signal ff80 | snr c199 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal c040 | snr c199 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 1f | signal ff80 | snr c199 | ber 00000000 | unc 00000000 | FE_HAS_LOCK Tuning to a weaker channel shows that the hardware recovers sync: status 1f | signal fe40 | snr 5199 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 03 | signal fd40 | snr 5000 | ber 00000000 | unc 00000000 | status 1f | signal fe40 | snr 5000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 03 | signal fd80 | snr 5000 | ber 00000000 | unc 00000000 | status 01 | signal fd80 | snr 4e66 | ber 00000000 | unc 00000000 | status 1f | signal fe40 | snr 5000 | ber 00000000 | unc 00000000 | FE_HAS_LOCK status 03 | signal fe40 | snr 5000 | ber 00000000 | unc 00000000 | status 01 | signal fd80 | snr 0000 | ber 00000000 | unc 00000000 | status 1f | signal fe40 | snr 5199 | ber 00000000 | unc 00000000 | FE_HAS_LOCK Also, tuning, moving the dish and then restoring the dish also retunes. Priority: normal Signed-off-by: Darron Broad CC: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/cx24116.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c index 44818232d..6413c2c90 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.c +++ b/linux/drivers/media/dvb/frontends/cx24116.c @@ -106,7 +106,7 @@ MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); #define CX24116_HAS_SYNCLOCK (0x08) #define CX24116_HAS_UNKNOWN1 (0x10) #define CX24116_HAS_UNKNOWN2 (0x20) -#define CX24116_STATUS_MASK (0x3f) +#define CX24116_STATUS_MASK (0x0f) #define CX24116_SIGNAL_MASK (0xc0) #define CX24116_DISEQC_TONEOFF (0) /* toneburst never sent */ @@ -681,7 +681,8 @@ static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct cx24116_state *state = fe->demodulator_priv; - int lock = cx24116_readreg(state, CX24116_REG_SSTATUS); + int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) & + CX24116_STATUS_MASK; dprintk("%s: status = 0x%02x\n", __func__, lock); @@ -1447,6 +1448,23 @@ tuned: /* Set/Reset B/W */ return ret; } +static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, + unsigned int mode_flags, unsigned int *delay, fe_status_t *status) +{ + *delay = HZ / 5; + if (params) { + int ret = cx24116_set_frontend(fe, params); + if (ret) + return ret; + } + return cx24116_read_status(fe, status); +} + +static int cx24116_get_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_HW; +} + static struct dvb_frontend_ops cx24116_ops = { .info = { @@ -1478,6 +1496,8 @@ static struct dvb_frontend_ops cx24116_ops = { .set_voltage = cx24116_set_voltage, .diseqc_send_master_cmd = cx24116_send_diseqc_msg, .diseqc_send_burst = cx24116_diseqc_send_burst, + .get_frontend_algo = cx24116_get_algo, + .tune = cx24116_tune, .set_property = cx24116_set_property, .get_property = cx24116_get_property, -- cgit v1.2.3 From f7e86b8ee653d423731cb9a1c8a081a111d3d83b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Dec 2008 07:28:35 -0200 Subject: cx88: advise/acquire clean-up for HVR-1300/3000/4000 From: Darron Broad This cleans-up the advise/acquire methods. This has been tested on the hvr-1300/4000 and assumed to be correct on the hvr-3000. This update also fixes analogue tuning on the hvr-1300 when in blackbird mode. Priority: normal Signed-off-by: Darron Broad CC: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-blackbird.c | 12 +++++-- linux/drivers/media/video/cx88/cx88-dvb.c | 48 +++++++++++++------------ 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index b090c6620..561dc7f0b 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -1263,8 +1263,16 @@ static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv) * We're being given access to re-arrange the GPIOs. * Take the bus off the cx22702 and put the cx23416 on it. */ - cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */ - cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */ + /* Toggle reset on cx22702 leaving i2c active */ + cx_set(MO_GP0_IO, 0x00000080); + udelay(1000); + cx_clear(MO_GP0_IO, 0x00000080); + udelay(50); + cx_set(MO_GP0_IO, 0x00000080); + udelay(1000); + /* tri-state the cx22702 pins */ + cx_set(MO_GP0_IO, 0x00000004); + udelay(1000); break; default: err = -ENODEV; diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 5a9fafd25..fc3a080ac 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -1135,40 +1135,44 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) * on the bus. Take the bus from the cx23416 and enable the * cx22702 demod */ - cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */ + /* Toggle reset on cx22702 leaving i2c active */ + cx_set(MO_GP0_IO, 0x00000080); + udelay(1000); + cx_clear(MO_GP0_IO, 0x00000080); + udelay(50); + cx_set(MO_GP0_IO, 0x00000080); + udelay(1000); + /* enable the cx22702 pins */ cx_clear(MO_GP0_IO, 0x00000004); udelay(1000); break; case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: - if(core->dvbdev->frontends.active_fe_id == 1) { - /* DVB-S/S2 Enabled */ - - /* Toggle reset on cx22702 leaving i2c active */ - cx_write(MO_GP0_IO, (core->board.input[0].gpio0 & 0x0000ff00) | 0x00000080); - udelay(1000); - cx_clear(MO_GP0_IO, 0x00000080); - udelay(50); - cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset */ - cx_set(MO_GP0_IO, 0x00000004); /* tri-state the cx22702 pins */ - udelay(1000); - - cx_write(MO_SRST_IO, 1); /* Take the cx24116/cx24123 out of reset */ + /* Toggle reset on cx22702 leaving i2c active */ + cx_set(MO_GP0_IO, 0x00000080); + udelay(1000); + cx_clear(MO_GP0_IO, 0x00000080); + udelay(50); + cx_set(MO_GP0_IO, 0x00000080); + udelay(1000); + switch (core->dvbdev->frontends.active_fe_id) { + case 1: /* DVB-S/S2 Enabled */ + /* tri-state the cx22702 pins */ + cx_set(MO_GP0_IO, 0x00000004); + /* Take the cx24116/cx24123 out of reset */ + cx_write(MO_SRST_IO, 1); core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */ - } else - if (core->dvbdev->frontends.active_fe_id == 2) { - /* DVB-T Enabled */ - + break; + case 2: /* DVB-T Enabled */ /* Put the cx24116/cx24123 into reset */ cx_write(MO_SRST_IO, 0); - - /* cx22702 out of reset and enable it */ - cx_set(MO_GP0_IO, 0x00000080); + /* enable the cx22702 pins */ cx_clear(MO_GP0_IO, 0x00000004); core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */ - udelay(1000); + break; } + udelay(1000); break; default: -- cgit v1.2.3 From 39cd615e96596e38d89c78b02905a2e3e5cb6acb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:05:49 +0100 Subject: Change device ID selection method on ov772x driver From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- linux/drivers/media/video/ov772x.c | 27 +++++++++++++++++++++------ linux/include/media/v4l2-chip-ident.h | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 582e72d2f..e8a5be921 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -345,6 +345,12 @@ #define OP_UV 0x00000001 #define OP_SWAP_RGB 0x00000002 +/* + * ID + */ +#define OV7720 0x7720 +#define VERSION(pid, ver) ((pid<<8)|(ver&0xFF)) + /* * struct */ @@ -374,6 +380,7 @@ struct ov772x_priv { struct soc_camera_device icd; const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; + int model; }; #define ENDMARKER { 0xff, 0xff } @@ -702,7 +709,9 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) static int ov772x_get_chip_id(struct soc_camera_device *icd, struct v4l2_chip_ident *id) { - id->ident = V4L2_IDENT_OV772X; + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + + id->ident = priv->model; id->revision = 0; return 0; @@ -796,6 +805,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); u8 pid, ver; + const char *devname; /* * We must have a parent by now. And it cannot be a wrong one. @@ -822,15 +832,21 @@ static int ov772x_video_probe(struct soc_camera_device *icd) */ pid = i2c_smbus_read_byte_data(priv->client, PID); ver = i2c_smbus_read_byte_data(priv->client, VER); - if (pid != 0x77 || - ver != 0x21) { + + switch (VERSION(pid, ver)) { + case OV7720: + devname = "ov7720"; + priv->model = V4L2_IDENT_OV7720; + break; + default: dev_err(&icd->dev, "Product ID error %x:%x\n", pid, ver); return -ENODEV; } dev_info(&icd->dev, - "ov772x Product ID %0x:%0x Manufacturer ID %x:%x\n", + "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", + devname, pid, ver, i2c_smbus_read_byte_data(priv->client, MIDH), @@ -926,7 +942,7 @@ static int ov772x_remove(struct i2c_client *client) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id ov772x_id[] = { - {"ov772x", 0}, + { "ov772x", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ov772x_id); @@ -949,7 +965,6 @@ static struct i2c_driver ov772x_i2c_driver = { static int __init ov772x_module_init(void) { - printk(KERN_INFO "ov772x driver\n"); return i2c_add_driver(&ov772x_i2c_driver); } diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index bfe5142e6..456ac0da2 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -60,7 +60,7 @@ enum { /* OmniVision sensors: reserved range 250-299 */ V4L2_IDENT_OV7670 = 250, - V4L2_IDENT_OV772X = 251, + V4L2_IDENT_OV7720 = 251, /* Conexant MPEG encoder/decoders: reserved range 410-420 */ V4L2_IDENT_CX23415 = 415, -- cgit v1.2.3 From 6219eb9131ed5c90f9c4b1b56ef220ad09892126 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:07:11 +0100 Subject: Add ov7725 support to ov772x driver From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 22 ++++++++++++++++++++++ include/media/v4l2-chip-ident.h | 1 + 2 files changed, 23 insertions(+), 0 deletions(-) --- linux/drivers/media/video/ov772x.c | 22 ++++++++++++++++++++++ linux/include/media/v4l2-chip-ident.h | 1 + 2 files changed, 23 insertions(+) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index e8a5be921..89cacadad 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -51,6 +51,7 @@ #define COM8 0x13 /* Common control 8 */ #define COM9 0x14 /* Common control 9 */ #define COM10 0x15 /* Common control 10 */ +#define REG16 0x16 /* Register 16 */ #define HSTART 0x17 /* Horizontal sensor size */ #define HSIZE 0x18 /* Horizontal frame (HREF column) end high 8-bit */ #define VSTART 0x19 /* Vertical frame (row) start high 8-bit */ @@ -65,6 +66,7 @@ #define AEW 0x24 /* AGC/AEC - Stable operating region (upper limit) */ #define AEB 0x25 /* AGC/AEC - Stable operating region (lower limit) */ #define VPT 0x26 /* AGC/AEC Fast mode operating region */ +#define REG28 0x28 /* Register 28 */ #define HOUTSIZE 0x29 /* Horizontal data output size MSBs */ #define EXHCH 0x2A /* Dummy pixel insert MSB */ #define EXHCL 0x2B /* Dummy pixel insert LSB */ @@ -94,6 +96,7 @@ #define TGT_R 0x43 /* BLC red channel target value */ #define TGT_GB 0x44 /* BLC Gb channel target value */ #define TGT_GR 0x45 /* BLC Gr channel target value */ +/* for ov7720 */ #define LCC0 0x46 /* Lens correction control 0 */ #define LCC1 0x47 /* Lens correction option 1 - X coordinate */ #define LCC2 0x48 /* Lens correction option 2 - Y coordinate */ @@ -101,6 +104,15 @@ #define LCC4 0x4A /* Lens correction option 4 - radius of the circular */ #define LCC5 0x4B /* Lens correction option 5 */ #define LCC6 0x4C /* Lens correction option 6 */ +/* for ov7725 */ +#define LC_CTR 0x46 /* Lens correction control */ +#define LC_XC 0x47 /* X coordinate of lens correction center relative */ +#define LC_YC 0x48 /* Y coordinate of lens correction center relative */ +#define LC_COEF 0x49 /* Lens correction coefficient */ +#define LC_RADI 0x4A /* Lens correction radius */ +#define LC_COEFB 0x4B /* Lens B channel compensation coefficient */ +#define LC_COEFR 0x4C /* Lens R channel compensation coefficient */ + #define FIXGAIN 0x4D /* Analog fix gain amplifer */ #define AREF0 0x4E /* Sensor reference control */ #define AREF1 0x4F /* Sensor reference current control */ @@ -182,8 +194,13 @@ #define SDE 0xA6 /* Special digital effect control */ #define USAT 0xA7 /* U component saturation control */ #define VSAT 0xA8 /* V component saturation control */ +/* for ov7720 */ #define HUE0 0xA9 /* Hue control 0 */ #define HUE1 0xAA /* Hue control 1 */ +/* for ov7725 */ +#define HUECOS 0xA9 /* Cosine value */ +#define HUESIN 0xAA /* Sine value */ + #define SIGN 0xAB /* Sign bit for Hue and contrast */ #define DSPAUTO 0xAC /* DSP auto function ON/OFF control */ @@ -349,6 +366,7 @@ * ID */ #define OV7720 0x7720 +#define OV7725 0x7721 #define VERSION(pid, ver) ((pid<<8)|(ver&0xFF)) /* @@ -838,6 +856,10 @@ static int ov772x_video_probe(struct soc_camera_device *icd) devname = "ov7720"; priv->model = V4L2_IDENT_OV7720; break; + case OV7725: + devname = "ov7725"; + priv->model = V4L2_IDENT_OV7725; + break; default: dev_err(&icd->dev, "Product ID error %x:%x\n", pid, ver); diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index 456ac0da2..14a205f44 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -61,6 +61,7 @@ enum { /* OmniVision sensors: reserved range 250-299 */ V4L2_IDENT_OV7670 = 250, V4L2_IDENT_OV7720 = 251, + V4L2_IDENT_OV7725 = 252, /* Conexant MPEG encoder/decoders: reserved range 410-420 */ V4L2_IDENT_CX23415 = 415, -- cgit v1.2.3 From 15db11f0dfbb4a48553462dd7752015725300723 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:13:30 +0100 Subject: [ARM] pxa: move camera (QCI) registers definition out of pxa-regs.h From: Eric Miao Signed-off-by: Eric Miao Acked-by: Guennadi Liakhovetski kernel-sync: --- linux/drivers/media/video/pxa_camera.c | 2 + linux/drivers/media/video/pxa_camera.h | 95 +++++++++++++++++++++++++++++++ linux/include/asm-arm/arch-pxa/pxa-regs.h | 95 ------------------------------- 3 files changed, 97 insertions(+), 95 deletions(-) create mode 100644 linux/drivers/media/video/pxa_camera.h diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 210a99780..5003ada41 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -44,6 +44,8 @@ #include #endif +#include "pxa_camera.h" + #define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) #define PXA_CAM_DRV_NAME "pxa27x-camera" diff --git a/linux/drivers/media/video/pxa_camera.h b/linux/drivers/media/video/pxa_camera.h new file mode 100644 index 000000000..89cbfc9a3 --- /dev/null +++ b/linux/drivers/media/video/pxa_camera.h @@ -0,0 +1,95 @@ +/* Camera Interface */ +#define CICR0 __REG(0x50000000) +#define CICR1 __REG(0x50000004) +#define CICR2 __REG(0x50000008) +#define CICR3 __REG(0x5000000C) +#define CICR4 __REG(0x50000010) +#define CISR __REG(0x50000014) +#define CIFR __REG(0x50000018) +#define CITOR __REG(0x5000001C) +#define CIBR0 __REG(0x50000028) +#define CIBR1 __REG(0x50000030) +#define CIBR2 __REG(0x50000038) + +#define CICR0_DMAEN (1 << 31) /* DMA request enable */ +#define CICR0_PAR_EN (1 << 30) /* Parity enable */ +#define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */ +#define CICR0_ENB (1 << 28) /* Camera interface enable */ +#define CICR0_DIS (1 << 27) /* Camera interface disable */ +#define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ +#define CICR0_TOM (1 << 9) /* Time-out mask */ +#define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ +#define CICR0_FEM (1 << 7) /* FIFO-empty mask */ +#define CICR0_EOLM (1 << 6) /* End-of-line mask */ +#define CICR0_PERRM (1 << 5) /* Parity-error mask */ +#define CICR0_QDM (1 << 4) /* Quick-disable mask */ +#define CICR0_CDM (1 << 3) /* Disable-done mask */ +#define CICR0_SOFM (1 << 2) /* Start-of-frame mask */ +#define CICR0_EOFM (1 << 1) /* End-of-frame mask */ +#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */ + +#define CICR1_TBIT (1 << 31) /* Transparency bit */ +#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */ +#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ +#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ +#define CICR1_RGB_F (1 << 11) /* RGB format */ +#define CICR1_YCBCR_F (1 << 10) /* YCbCr format */ +#define CICR1_RGB_BPP (0x7 << 7) /* RGB bis per pixel mask */ +#define CICR1_RAW_BPP (0x3 << 5) /* Raw bis per pixel mask */ +#define CICR1_COLOR_SP (0x3 << 3) /* Color space mask */ +#define CICR1_DW (0x7 << 0) /* Data width mask */ + +#define CICR2_BLW (0xff << 24) /* Beginning-of-line pixel clock + wait count mask */ +#define CICR2_ELW (0xff << 16) /* End-of-line pixel clock + wait count mask */ +#define CICR2_HSW (0x3f << 10) /* Horizontal sync pulse width mask */ +#define CICR2_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock + wait count mask */ +#define CICR2_FSW (0x7 << 0) /* Frame stabilization + wait count mask */ + +#define CICR3_BFW (0xff << 24) /* Beginning-of-frame line clock + wait count mask */ +#define CICR3_EFW (0xff << 16) /* End-of-frame line clock + wait count mask */ +#define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */ +#define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock + wait count mask */ +#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */ + +#define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */ +#define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */ +#define CICR4_PCP (1 << 22) /* Pixel clock polarity */ +#define CICR4_HSP (1 << 21) /* Horizontal sync polarity */ +#define CICR4_VSP (1 << 20) /* Vertical sync polarity */ +#define CICR4_MCLK_EN (1 << 19) /* MCLK enable */ +#define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ +#define CICR4_DIV (0xff << 0) /* Clock divisor mask */ + +#define CISR_FTO (1 << 15) /* FIFO time-out */ +#define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ +#define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ +#define CISR_RDAV_0 (1 << 12) /* Channel 0 receive data available */ +#define CISR_FEMPTY_2 (1 << 11) /* Channel 2 FIFO empty */ +#define CISR_FEMPTY_1 (1 << 10) /* Channel 1 FIFO empty */ +#define CISR_FEMPTY_0 (1 << 9) /* Channel 0 FIFO empty */ +#define CISR_EOL (1 << 8) /* End of line */ +#define CISR_PAR_ERR (1 << 7) /* Parity error */ +#define CISR_CQD (1 << 6) /* Camera interface quick disable */ +#define CISR_CDD (1 << 5) /* Camera interface disable done */ +#define CISR_SOF (1 << 4) /* Start of frame */ +#define CISR_EOF (1 << 3) /* End of frame */ +#define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */ +#define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */ +#define CISR_IFO_0 (1 << 0) /* FIFO overrun for Channel 0 */ + +#define CIFR_FLVL2 (0x7f << 23) /* FIFO 2 level mask */ +#define CIFR_FLVL1 (0x7f << 16) /* FIFO 1 level mask */ +#define CIFR_FLVL0 (0xff << 8) /* FIFO 0 level mask */ +#define CIFR_THL_0 (0x3 << 4) /* Threshold Level for Channel 0 FIFO */ +#define CIFR_RESET_F (1 << 3) /* Reset input FIFOs */ +#define CIFR_FEN2 (1 << 2) /* FIFO enable for channel 2 */ +#define CIFR_FEN1 (1 << 1) /* FIFO enable for channel 1 */ +#define CIFR_FEN0 (1 << 0) /* FIFO enable for channel 0 */ + diff --git a/linux/include/asm-arm/arch-pxa/pxa-regs.h b/linux/include/asm-arm/arch-pxa/pxa-regs.h index dce930862..676995b90 100644 --- a/linux/include/asm-arm/arch-pxa/pxa-regs.h +++ b/linux/include/asm-arm/arch-pxa/pxa-regs.h @@ -842,101 +842,6 @@ #ifdef CONFIG_PXA27x -/* Camera Interface */ -#define CICR0 __REG(0x50000000) -#define CICR1 __REG(0x50000004) -#define CICR2 __REG(0x50000008) -#define CICR3 __REG(0x5000000C) -#define CICR4 __REG(0x50000010) -#define CISR __REG(0x50000014) -#define CIFR __REG(0x50000018) -#define CITOR __REG(0x5000001C) -#define CIBR0 __REG(0x50000028) -#define CIBR1 __REG(0x50000030) -#define CIBR2 __REG(0x50000038) - -#define CICR0_DMAEN (1 << 31) /* DMA request enable */ -#define CICR0_PAR_EN (1 << 30) /* Parity enable */ -#define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */ -#define CICR0_ENB (1 << 28) /* Camera interface enable */ -#define CICR0_DIS (1 << 27) /* Camera interface disable */ -#define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ -#define CICR0_TOM (1 << 9) /* Time-out mask */ -#define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ -#define CICR0_FEM (1 << 7) /* FIFO-empty mask */ -#define CICR0_EOLM (1 << 6) /* End-of-line mask */ -#define CICR0_PERRM (1 << 5) /* Parity-error mask */ -#define CICR0_QDM (1 << 4) /* Quick-disable mask */ -#define CICR0_CDM (1 << 3) /* Disable-done mask */ -#define CICR0_SOFM (1 << 2) /* Start-of-frame mask */ -#define CICR0_EOFM (1 << 1) /* End-of-frame mask */ -#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */ - -#define CICR1_TBIT (1 << 31) /* Transparency bit */ -#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */ -#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ -#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ -#define CICR1_RGB_F (1 << 11) /* RGB format */ -#define CICR1_YCBCR_F (1 << 10) /* YCbCr format */ -#define CICR1_RGB_BPP (0x7 << 7) /* RGB bis per pixel mask */ -#define CICR1_RAW_BPP (0x3 << 5) /* Raw bis per pixel mask */ -#define CICR1_COLOR_SP (0x3 << 3) /* Color space mask */ -#define CICR1_DW (0x7 << 0) /* Data width mask */ - -#define CICR2_BLW (0xff << 24) /* Beginning-of-line pixel clock - wait count mask */ -#define CICR2_ELW (0xff << 16) /* End-of-line pixel clock - wait count mask */ -#define CICR2_HSW (0x3f << 10) /* Horizontal sync pulse width mask */ -#define CICR2_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock - wait count mask */ -#define CICR2_FSW (0x7 << 0) /* Frame stabilization - wait count mask */ - -#define CICR3_BFW (0xff << 24) /* Beginning-of-frame line clock - wait count mask */ -#define CICR3_EFW (0xff << 16) /* End-of-frame line clock - wait count mask */ -#define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */ -#define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock - wait count mask */ -#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */ - -#define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */ -#define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */ -#define CICR4_PCP (1 << 22) /* Pixel clock polarity */ -#define CICR4_HSP (1 << 21) /* Horizontal sync polarity */ -#define CICR4_VSP (1 << 20) /* Vertical sync polarity */ -#define CICR4_MCLK_EN (1 << 19) /* MCLK enable */ -#define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ -#define CICR4_DIV (0xff << 0) /* Clock divisor mask */ - -#define CISR_FTO (1 << 15) /* FIFO time-out */ -#define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ -#define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ -#define CISR_RDAV_0 (1 << 12) /* Channel 0 receive data available */ -#define CISR_FEMPTY_2 (1 << 11) /* Channel 2 FIFO empty */ -#define CISR_FEMPTY_1 (1 << 10) /* Channel 1 FIFO empty */ -#define CISR_FEMPTY_0 (1 << 9) /* Channel 0 FIFO empty */ -#define CISR_EOL (1 << 8) /* End of line */ -#define CISR_PAR_ERR (1 << 7) /* Parity error */ -#define CISR_CQD (1 << 6) /* Camera interface quick disable */ -#define CISR_CDD (1 << 5) /* Camera interface disable done */ -#define CISR_SOF (1 << 4) /* Start of frame */ -#define CISR_EOF (1 << 3) /* End of frame */ -#define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */ -#define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */ -#define CISR_IFO_0 (1 << 0) /* FIFO overrun for Channel 0 */ - -#define CIFR_FLVL2 (0x7f << 23) /* FIFO 2 level mask */ -#define CIFR_FLVL1 (0x7f << 16) /* FIFO 1 level mask */ -#define CIFR_FLVL0 (0xff << 8) /* FIFO 0 level mask */ -#define CIFR_THL_0 (0x3 << 4) /* Threshold Level for Channel 0 FIFO */ -#define CIFR_RESET_F (1 << 3) /* Reset input FIFOs */ -#define CIFR_FEN2 (1 << 2) /* FIFO enable for channel 2 */ -#define CIFR_FEN1 (1 << 1) /* FIFO enable for channel 1 */ -#define CIFR_FEN0 (1 << 0) /* FIFO enable for channel 0 */ - #define SRAM_SIZE 0x40000 /* 4x64K */ #define SRAM_MEM_PHYS 0x5C000000 -- cgit v1.2.3 From 4d71e0f99bbbad2f387a34daed239ce1c45f5ef6 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:15:50 +0100 Subject: V4L/DVB: pxa-camera: use memory mapped IO access for camera (QCI) registers From: Eric Miao Signed-off-by: Eric Miao Signed-off-by: Guennadi Liakhovetski --- linux/drivers/media/video/pxa_camera.c | 204 ++++++++++++++++++++++++++------- linux/drivers/media/video/pxa_camera.h | 95 --------------- 2 files changed, 162 insertions(+), 137 deletions(-) delete mode 100644 linux/drivers/media/video/pxa_camera.h diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 5003ada41..338a7a6a7 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -44,11 +44,104 @@ #include #endif -#include "pxa_camera.h" - #define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) #define PXA_CAM_DRV_NAME "pxa27x-camera" +/* Camera Interface */ +#define CICR0 0x0000 +#define CICR1 0x0004 +#define CICR2 0x0008 +#define CICR3 0x000C +#define CICR4 0x0010 +#define CISR 0x0014 +#define CIFR 0x0018 +#define CITOR 0x001C +#define CIBR0 0x0028 +#define CIBR1 0x0030 +#define CIBR2 0x0038 + +#define CICR0_DMAEN (1 << 31) /* DMA request enable */ +#define CICR0_PAR_EN (1 << 30) /* Parity enable */ +#define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */ +#define CICR0_ENB (1 << 28) /* Camera interface enable */ +#define CICR0_DIS (1 << 27) /* Camera interface disable */ +#define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ +#define CICR0_TOM (1 << 9) /* Time-out mask */ +#define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ +#define CICR0_FEM (1 << 7) /* FIFO-empty mask */ +#define CICR0_EOLM (1 << 6) /* End-of-line mask */ +#define CICR0_PERRM (1 << 5) /* Parity-error mask */ +#define CICR0_QDM (1 << 4) /* Quick-disable mask */ +#define CICR0_CDM (1 << 3) /* Disable-done mask */ +#define CICR0_SOFM (1 << 2) /* Start-of-frame mask */ +#define CICR0_EOFM (1 << 1) /* End-of-frame mask */ +#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */ + +#define CICR1_TBIT (1 << 31) /* Transparency bit */ +#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */ +#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ +#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ +#define CICR1_RGB_F (1 << 11) /* RGB format */ +#define CICR1_YCBCR_F (1 << 10) /* YCbCr format */ +#define CICR1_RGB_BPP (0x7 << 7) /* RGB bis per pixel mask */ +#define CICR1_RAW_BPP (0x3 << 5) /* Raw bis per pixel mask */ +#define CICR1_COLOR_SP (0x3 << 3) /* Color space mask */ +#define CICR1_DW (0x7 << 0) /* Data width mask */ + +#define CICR2_BLW (0xff << 24) /* Beginning-of-line pixel clock + wait count mask */ +#define CICR2_ELW (0xff << 16) /* End-of-line pixel clock + wait count mask */ +#define CICR2_HSW (0x3f << 10) /* Horizontal sync pulse width mask */ +#define CICR2_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock + wait count mask */ +#define CICR2_FSW (0x7 << 0) /* Frame stabilization + wait count mask */ + +#define CICR3_BFW (0xff << 24) /* Beginning-of-frame line clock + wait count mask */ +#define CICR3_EFW (0xff << 16) /* End-of-frame line clock + wait count mask */ +#define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */ +#define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock + wait count mask */ +#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */ + +#define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */ +#define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */ +#define CICR4_PCP (1 << 22) /* Pixel clock polarity */ +#define CICR4_HSP (1 << 21) /* Horizontal sync polarity */ +#define CICR4_VSP (1 << 20) /* Vertical sync polarity */ +#define CICR4_MCLK_EN (1 << 19) /* MCLK enable */ +#define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ +#define CICR4_DIV (0xff << 0) /* Clock divisor mask */ + +#define CISR_FTO (1 << 15) /* FIFO time-out */ +#define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ +#define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ +#define CISR_RDAV_0 (1 << 12) /* Channel 0 receive data available */ +#define CISR_FEMPTY_2 (1 << 11) /* Channel 2 FIFO empty */ +#define CISR_FEMPTY_1 (1 << 10) /* Channel 1 FIFO empty */ +#define CISR_FEMPTY_0 (1 << 9) /* Channel 0 FIFO empty */ +#define CISR_EOL (1 << 8) /* End of line */ +#define CISR_PAR_ERR (1 << 7) /* Parity error */ +#define CISR_CQD (1 << 6) /* Camera interface quick disable */ +#define CISR_CDD (1 << 5) /* Camera interface disable done */ +#define CISR_SOF (1 << 4) /* Start of frame */ +#define CISR_EOF (1 << 3) /* End of frame */ +#define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */ +#define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */ +#define CISR_IFO_0 (1 << 0) /* FIFO overrun for Channel 0 */ + +#define CIFR_FLVL2 (0x7f << 23) /* FIFO 2 level mask */ +#define CIFR_FLVL1 (0x7f << 16) /* FIFO 1 level mask */ +#define CIFR_FLVL0 (0xff << 8) /* FIFO 0 level mask */ +#define CIFR_THL_0 (0x3 << 4) /* Threshold Level for Channel 0 FIFO */ +#define CIFR_RESET_F (1 << 3) /* Reset input FIFOs */ +#define CIFR_FEN2 (1 << 2) /* FIFO enable for channel 2 */ +#define CIFR_FEN1 (1 << 1) /* FIFO enable for channel 1 */ +#define CIFR_FEN0 (1 << 0) /* FIFO enable for channel 0 */ + #define CICR0_SIM_MP (0 << 24) #define CICR0_SIM_SP (1 << 24) #define CICR0_SIM_MS (2 << 24) @@ -392,7 +485,10 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, active = pcdev->active; if (!active) { - CIFR |= CIFR_RESET_F; + unsigned long cifr, cicr0; + + cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; + __raw_writel(cifr, pcdev->base + CIFR); for (i = 0; i < pcdev->channels; i++) { DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma; @@ -401,7 +497,9 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, } pcdev->active = buf; - CICR0 |= CICR0_ENB; + + cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB; + __raw_writel(cicr0, pcdev->base + CICR0); } else { struct pxa_cam_dma *buf_dma; struct pxa_cam_dma *act_dma; @@ -485,6 +583,8 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, struct videobuf_buffer *vb, struct pxa_buffer *buf) { + unsigned long cicr0; + /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ list_del_init(&vb->queue); vb->state = VIDEOBUF_DONE; @@ -497,7 +597,9 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, DCSR(pcdev->dma_chans[0]) = 0; DCSR(pcdev->dma_chans[1]) = 0; DCSR(pcdev->dma_chans[2]) = 0; - CICR0 &= ~CICR0_ENB; + + cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; + __raw_writel(cicr0, pcdev->base + CICR0); return; } @@ -512,6 +614,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, unsigned long flags; u32 status, camera_status, overrun; struct videobuf_buffer *vb; + unsigned long cifr, cicr0; spin_lock_irqsave(&pcdev->lock, flags); @@ -534,22 +637,26 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, goto out; } - camera_status = CISR; + camera_status = __raw_readl(pcdev->base + CISR); overrun = CISR_IFO_0; if (pcdev->channels == 3) overrun |= CISR_IFO_1 | CISR_IFO_2; if (camera_status & overrun) { dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status); /* Stop the Capture Interface */ - CICR0 &= ~CICR0_ENB; + cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; + __raw_writel(cicr0, pcdev->base + CICR0); + /* Stop DMA */ DCSR(channel) = 0; /* Reset the FIFOs */ - CIFR |= CIFR_RESET_F; + cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; + __raw_writel(cifr, pcdev->base + CIFR); /* Enable End-Of-Frame Interrupt */ - CICR0 &= ~CICR0_EOFM; + cicr0 &= ~CICR0_EOFM; + __raw_writel(cicr0, pcdev->base + CICR0); /* Restart the Capture Interface */ - CICR0 |= CICR0_ENB; + __raw_writel(cicr0 | CICR0_ENB, pcdev->base + CICR0); goto out; } @@ -636,7 +743,8 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) pdata->init(pcdev->dev); } - CICR0 = 0x3FF; /* disable all interrupts */ + /* disable all interrupts */ + __raw_writel(0x3ff, pcdev->base + CICR0); if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) cicr4 |= CICR4_PCLK_EN; @@ -649,7 +757,8 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) if (pcdev->platform_flags & PXA_CAMERA_VSP) cicr4 |= CICR4_VSP; - CICR4 = mclk_get_divisor(pcdev) | cicr4; + cicr4 |= mclk_get_divisor(pcdev); + __raw_writel(cicr4, pcdev->base + CICR4); clk_enable(pcdev->clk); } @@ -662,14 +771,15 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) static irqreturn_t pxa_camera_irq(int irq, void *data) { struct pxa_camera_dev *pcdev = data; - unsigned int status = CISR; + unsigned long status, cicr0; - dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status); + status = __raw_readl(pcdev->base + CISR); + dev_dbg(pcdev->dev, "Camera interrupt status 0x%lx\n", status); if (!status) return IRQ_NONE; - CISR = status; + __raw_writel(status, pcdev->base + CISR); if (status & CISR_EOF) { int i; @@ -678,7 +788,8 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) pcdev->active->dmas[i].sg_dma; DCSR(pcdev->dma_chans[i]) = DCSR_RUN; } - CICR0 |= CICR0_EOFM; + cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM; + __raw_writel(cicr0, pcdev->base + CICR0); } return IRQ_HANDLED; @@ -725,7 +836,7 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) icd->devnum); /* disable capture, disable interrupts */ - CICR0 = 0x3ff; + __raw_writel(0x3ff, pcdev->base + CICR0); /* Stop DMA engine */ DCSR(pcdev->dma_chans[0]) = 0; @@ -786,7 +897,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; unsigned long dw, bpp, bus_flags, camera_flags, common_flags; - u32 cicr0, cicr1, cicr4 = 0; + u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0; int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); if (ret < 0) @@ -859,9 +970,9 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) cicr4 |= CICR4_VSP; - cicr0 = CICR0; + cicr0 = __raw_readl(pcdev->base + CICR0); if (cicr0 & CICR0_ENB) - CICR0 = cicr0 & ~CICR0_ENB; + __raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0); cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw; @@ -891,16 +1002,21 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) break; } - CICR1 = cicr1; - CICR2 = 0; - CICR3 = CICR3_LPF_VAL(icd->height - 1) | + cicr2 = 0; + cicr3 = CICR3_LPF_VAL(icd->height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); - CICR4 = mclk_get_divisor(pcdev) | cicr4; + cicr4 |= mclk_get_divisor(pcdev); + + __raw_writel(cicr1, pcdev->base + CICR1); + __raw_writel(cicr2, pcdev->base + CICR2); + __raw_writel(cicr3, pcdev->base + CICR3); + __raw_writel(cicr4, pcdev->base + CICR4); /* CIF interrupts are not used, only DMA */ - CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ? - CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) | - CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB); + cicr0 = (cicr0 & CICR0_ENB) | (pcdev->platform_flags & PXA_CAMERA_MASTER ? + CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)); + cicr0 |= CICR0_DMAEN | CICR0_IRQ_MASK; + __raw_writel(cicr0, pcdev->base + CICR0); return 0; } @@ -1146,11 +1262,11 @@ static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state) struct pxa_camera_dev *pcdev = ici->priv; int i = 0, ret = 0; - pcdev->save_cicr[i++] = CICR0; - pcdev->save_cicr[i++] = CICR1; - pcdev->save_cicr[i++] = CICR2; - pcdev->save_cicr[i++] = CICR3; - pcdev->save_cicr[i++] = CICR4; + pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR0); + pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR1); + pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR2); + pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR3); + pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR4); if ((pcdev->icd) && (pcdev->icd->ops->suspend)) ret = pcdev->icd->ops->suspend(pcdev->icd, state); @@ -1169,23 +1285,27 @@ static int pxa_camera_resume(struct soc_camera_device *icd) DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD; DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD; - CICR0 = pcdev->save_cicr[i++] & ~CICR0_ENB; - CICR1 = pcdev->save_cicr[i++]; - CICR2 = pcdev->save_cicr[i++]; - CICR3 = pcdev->save_cicr[i++]; - CICR4 = pcdev->save_cicr[i++]; + __raw_writel(pcdev->save_cicr[i++] & ~CICR0_ENB, pcdev->base + CICR0); + __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR1); + __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR2); + __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR3); + __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR4); if ((pcdev->icd) && (pcdev->icd->ops->resume)) ret = pcdev->icd->ops->resume(pcdev->icd); /* Restart frame capture if active buffer exists */ if (!ret && pcdev->active) { + unsigned long cifr, cicr0; + /* Reset the FIFOs */ - CIFR |= CIFR_RESET_F; - /* Enable End-Of-Frame Interrupt */ - CICR0 &= ~CICR0_EOFM; - /* Restart the Capture Interface */ - CICR0 |= CICR0_ENB; + cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; + __raw_writel(cifr, pcdev->base + CIFR); + + cicr0 = __raw_readl(pcdev->base + CICR0); + cicr0 &= ~CICR0_EOFM; /* Enable End-Of-Frame Interrupt */ + cicr0 |= CICR0_ENB; /* Restart the Capture Interface */ + __raw_writel(cicr0, pcdev->base + CICR0); } return ret; diff --git a/linux/drivers/media/video/pxa_camera.h b/linux/drivers/media/video/pxa_camera.h deleted file mode 100644 index 89cbfc9a3..000000000 --- a/linux/drivers/media/video/pxa_camera.h +++ /dev/null @@ -1,95 +0,0 @@ -/* Camera Interface */ -#define CICR0 __REG(0x50000000) -#define CICR1 __REG(0x50000004) -#define CICR2 __REG(0x50000008) -#define CICR3 __REG(0x5000000C) -#define CICR4 __REG(0x50000010) -#define CISR __REG(0x50000014) -#define CIFR __REG(0x50000018) -#define CITOR __REG(0x5000001C) -#define CIBR0 __REG(0x50000028) -#define CIBR1 __REG(0x50000030) -#define CIBR2 __REG(0x50000038) - -#define CICR0_DMAEN (1 << 31) /* DMA request enable */ -#define CICR0_PAR_EN (1 << 30) /* Parity enable */ -#define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */ -#define CICR0_ENB (1 << 28) /* Camera interface enable */ -#define CICR0_DIS (1 << 27) /* Camera interface disable */ -#define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ -#define CICR0_TOM (1 << 9) /* Time-out mask */ -#define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ -#define CICR0_FEM (1 << 7) /* FIFO-empty mask */ -#define CICR0_EOLM (1 << 6) /* End-of-line mask */ -#define CICR0_PERRM (1 << 5) /* Parity-error mask */ -#define CICR0_QDM (1 << 4) /* Quick-disable mask */ -#define CICR0_CDM (1 << 3) /* Disable-done mask */ -#define CICR0_SOFM (1 << 2) /* Start-of-frame mask */ -#define CICR0_EOFM (1 << 1) /* End-of-frame mask */ -#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */ - -#define CICR1_TBIT (1 << 31) /* Transparency bit */ -#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */ -#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ -#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ -#define CICR1_RGB_F (1 << 11) /* RGB format */ -#define CICR1_YCBCR_F (1 << 10) /* YCbCr format */ -#define CICR1_RGB_BPP (0x7 << 7) /* RGB bis per pixel mask */ -#define CICR1_RAW_BPP (0x3 << 5) /* Raw bis per pixel mask */ -#define CICR1_COLOR_SP (0x3 << 3) /* Color space mask */ -#define CICR1_DW (0x7 << 0) /* Data width mask */ - -#define CICR2_BLW (0xff << 24) /* Beginning-of-line pixel clock - wait count mask */ -#define CICR2_ELW (0xff << 16) /* End-of-line pixel clock - wait count mask */ -#define CICR2_HSW (0x3f << 10) /* Horizontal sync pulse width mask */ -#define CICR2_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock - wait count mask */ -#define CICR2_FSW (0x7 << 0) /* Frame stabilization - wait count mask */ - -#define CICR3_BFW (0xff << 24) /* Beginning-of-frame line clock - wait count mask */ -#define CICR3_EFW (0xff << 16) /* End-of-frame line clock - wait count mask */ -#define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */ -#define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock - wait count mask */ -#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */ - -#define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */ -#define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */ -#define CICR4_PCP (1 << 22) /* Pixel clock polarity */ -#define CICR4_HSP (1 << 21) /* Horizontal sync polarity */ -#define CICR4_VSP (1 << 20) /* Vertical sync polarity */ -#define CICR4_MCLK_EN (1 << 19) /* MCLK enable */ -#define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ -#define CICR4_DIV (0xff << 0) /* Clock divisor mask */ - -#define CISR_FTO (1 << 15) /* FIFO time-out */ -#define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ -#define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ -#define CISR_RDAV_0 (1 << 12) /* Channel 0 receive data available */ -#define CISR_FEMPTY_2 (1 << 11) /* Channel 2 FIFO empty */ -#define CISR_FEMPTY_1 (1 << 10) /* Channel 1 FIFO empty */ -#define CISR_FEMPTY_0 (1 << 9) /* Channel 0 FIFO empty */ -#define CISR_EOL (1 << 8) /* End of line */ -#define CISR_PAR_ERR (1 << 7) /* Parity error */ -#define CISR_CQD (1 << 6) /* Camera interface quick disable */ -#define CISR_CDD (1 << 5) /* Camera interface disable done */ -#define CISR_SOF (1 << 4) /* Start of frame */ -#define CISR_EOF (1 << 3) /* End of frame */ -#define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */ -#define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */ -#define CISR_IFO_0 (1 << 0) /* FIFO overrun for Channel 0 */ - -#define CIFR_FLVL2 (0x7f << 23) /* FIFO 2 level mask */ -#define CIFR_FLVL1 (0x7f << 16) /* FIFO 1 level mask */ -#define CIFR_FLVL0 (0xff << 8) /* FIFO 0 level mask */ -#define CIFR_THL_0 (0x3 << 4) /* Threshold Level for Channel 0 FIFO */ -#define CIFR_RESET_F (1 << 3) /* Reset input FIFOs */ -#define CIFR_FEN2 (1 << 2) /* FIFO enable for channel 2 */ -#define CIFR_FEN1 (1 << 1) /* FIFO enable for channel 1 */ -#define CIFR_FEN0 (1 << 0) /* FIFO enable for channel 0 */ - -- cgit v1.2.3 From 9197c4fd6177feb18b8102adb92d8c465687d443 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 15:16:24 +0100 Subject: v4l2-subdev: add g_sliced_vbi_cap and add NULL pointer checks From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-subdev.c | 10 ++++++---- linux/include/media/v4l2-subdev.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/v4l2-subdev.c b/linux/drivers/media/video/v4l2-subdev.c index fe1f01c97..e3612f29d 100644 --- a/linux/drivers/media/video/v4l2-subdev.c +++ b/linux/drivers/media/video/v4l2-subdev.c @@ -40,13 +40,13 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) case VIDIOC_G_CHIP_IDENT: return v4l2_subdev_call(sd, core, g_chip_ident, arg); case VIDIOC_INT_S_STANDBY: - return v4l2_subdev_call(sd, core, s_standby, *(u32 *)arg); + return v4l2_subdev_call(sd, core, s_standby, arg ? (*(u32 *)arg) : 0); case VIDIOC_INT_RESET: - return v4l2_subdev_call(sd, core, reset, *(u32 *)arg); + return v4l2_subdev_call(sd, core, reset, arg ? (*(u32 *)arg) : 0); case VIDIOC_INT_S_GPIO: - return v4l2_subdev_call(sd, core, s_gpio, *(u32 *)arg); + return v4l2_subdev_call(sd, core, s_gpio, arg ? (*(u32 *)arg) : 0); case VIDIOC_INT_INIT: - return v4l2_subdev_call(sd, core, init, *(u32 *)arg); + return v4l2_subdev_call(sd, core, init, arg ? (*(u32 *)arg) : 0); #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: return v4l2_subdev_call(sd, core, g_register, arg); @@ -90,6 +90,8 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, video, s_vbi_data, arg); case VIDIOC_INT_G_VBI_DATA: return v4l2_subdev_call(sd, video, g_vbi_data, arg); + case VIDIOC_G_SLICED_VBI_CAP: + return v4l2_subdev_call(sd, video, g_sliced_vbi_cap, arg); case VIDIOC_S_FMT: return v4l2_subdev_call(sd, video, s_fmt, arg); case VIDIOC_G_FMT: diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h index bc9e0fbf2..bca25e8ea 100644 --- a/linux/include/media/v4l2-subdev.h +++ b/linux/include/media/v4l2-subdev.h @@ -110,6 +110,7 @@ struct v4l2_subdev_video_ops { int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line); int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data); int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data); + int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap); int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std); int (*s_stream)(struct v4l2_subdev *sd, int enable); int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); -- cgit v1.2.3 From 9371b503a9b26eda909aa27f396e0cfce9eea569 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 15:17:25 +0100 Subject: tvp5150: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvp5150.c | 933 +++++++++++++++++------------------- 1 file changed, 436 insertions(+), 497 deletions(-) diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index ac8205d87..37421fb03 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -10,8 +10,9 @@ #include #include #include -#include +#include #include +#include #include "tvp5150_reg.h" @@ -30,21 +31,7 @@ I2C_CLIENT_INSMOD; static int debug; module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0-1)"); - -#define tvp5150_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, c->driver->driver.name, \ - i2c_adapter_id(c->adapter), c->addr , ## arg); } while (0) -#define tvp5150_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, c->driver->driver.name, \ - i2c_adapter_id(c->adapter), c->addr , ## arg); } while (0) -#define tvp5150_dbg(num, fmt, arg...) \ - do { \ - if (debug >= num) \ - printk(KERN_DEBUG "%s debug %d-%04x: " fmt,\ - c->driver->driver.name, \ - i2c_adapter_id(c->adapter), \ - c->addr , ## arg); } while (0) +MODULE_PARM_DESC(debug, "Debug level (0-2)"); /* supported controls */ static struct v4l2_queryctrl tvp5150_qctrl[] = { @@ -88,7 +75,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = { }; struct tvp5150 { - struct i2c_client *client; + struct v4l2_subdev sd; v4l2_std_id norm; /* Current set standard */ struct v4l2_routing route; @@ -99,49 +86,57 @@ struct tvp5150 { int sat; }; -static int tvp5150_read(struct i2c_client *c, unsigned char addr) +static inline struct tvp5150 *to_tvp5150(struct v4l2_subdev *sd) { + return container_of(sd, struct tvp5150, sd); +} + +static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr) +{ + struct i2c_client *c = v4l2_get_subdevdata(sd); unsigned char buffer[1]; int rc; buffer[0] = addr; if (1 != (rc = i2c_master_send(c, buffer, 1))) - tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 1)\n", rc); + v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 1)\n", rc); msleep(10); if (1 != (rc = i2c_master_recv(c, buffer, 1))) - tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 1)\n", rc); + v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 1)\n", rc); - tvp5150_dbg(2, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]); + v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]); return (buffer[0]); } -static inline void tvp5150_write(struct i2c_client *c, unsigned char addr, +static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr, unsigned char value) { + struct i2c_client *c = v4l2_get_subdevdata(sd); unsigned char buffer[2]; int rc; buffer[0] = addr; buffer[1] = value; - tvp5150_dbg(2, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]); + v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]); if (2 != (rc = i2c_master_send(c, buffer, 2))) - tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 2)\n", rc); + v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 2)\n", rc); } -static void dump_reg_range(struct i2c_client *c, char *s, u8 init, const u8 end,int max_line) +static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init, + const u8 end, int max_line) { - int i=0; + int i = 0; - while (init!=(u8)(end+1)) { - if ((i%max_line) == 0) { - if (i>0) + while (init != (u8)(end + 1)) { + if ((i % max_line) == 0) { + if (i > 0) printk("\n"); - printk("tvp5150: %s reg 0x%02x = ",s,init); + printk("tvp5150: %s reg 0x%02x = ", s, init); } - printk("%02x ",tvp5150_read(c, init)); + printk("%02x ", tvp5150_read(sd, init)); init++; i++; @@ -149,151 +144,152 @@ static void dump_reg_range(struct i2c_client *c, char *s, u8 init, const u8 end, printk("\n"); } -static void dump_reg(struct i2c_client *c) +static int tvp5150_log_status(struct v4l2_subdev *sd) { printk("tvp5150: Video input source selection #1 = 0x%02x\n", - tvp5150_read(c, TVP5150_VD_IN_SRC_SEL_1)); + tvp5150_read(sd, TVP5150_VD_IN_SRC_SEL_1)); printk("tvp5150: Analog channel controls = 0x%02x\n", - tvp5150_read(c, TVP5150_ANAL_CHL_CTL)); + tvp5150_read(sd, TVP5150_ANAL_CHL_CTL)); printk("tvp5150: Operation mode controls = 0x%02x\n", - tvp5150_read(c, TVP5150_OP_MODE_CTL)); + tvp5150_read(sd, TVP5150_OP_MODE_CTL)); printk("tvp5150: Miscellaneous controls = 0x%02x\n", - tvp5150_read(c, TVP5150_MISC_CTL)); + tvp5150_read(sd, TVP5150_MISC_CTL)); printk("tvp5150: Autoswitch mask= 0x%02x\n", - tvp5150_read(c, TVP5150_AUTOSW_MSK)); + tvp5150_read(sd, TVP5150_AUTOSW_MSK)); printk("tvp5150: Color killer threshold control = 0x%02x\n", - tvp5150_read(c, TVP5150_COLOR_KIL_THSH_CTL)); + tvp5150_read(sd, TVP5150_COLOR_KIL_THSH_CTL)); printk("tvp5150: Luminance processing controls #1 #2 and #3 = %02x %02x %02x\n", - tvp5150_read(c, TVP5150_LUMA_PROC_CTL_1), - tvp5150_read(c, TVP5150_LUMA_PROC_CTL_2), - tvp5150_read(c, TVP5150_LUMA_PROC_CTL_3)); + tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_1), + tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_2), + tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_3)); printk("tvp5150: Brightness control = 0x%02x\n", - tvp5150_read(c, TVP5150_BRIGHT_CTL)); + tvp5150_read(sd, TVP5150_BRIGHT_CTL)); printk("tvp5150: Color saturation control = 0x%02x\n", - tvp5150_read(c, TVP5150_SATURATION_CTL)); + tvp5150_read(sd, TVP5150_SATURATION_CTL)); printk("tvp5150: Hue control = 0x%02x\n", - tvp5150_read(c, TVP5150_HUE_CTL)); + tvp5150_read(sd, TVP5150_HUE_CTL)); printk("tvp5150: Contrast control = 0x%02x\n", - tvp5150_read(c, TVP5150_CONTRAST_CTL)); + tvp5150_read(sd, TVP5150_CONTRAST_CTL)); printk("tvp5150: Outputs and data rates select = 0x%02x\n", - tvp5150_read(c, TVP5150_DATA_RATE_SEL)); + tvp5150_read(sd, TVP5150_DATA_RATE_SEL)); printk("tvp5150: Configuration shared pins = 0x%02x\n", - tvp5150_read(c, TVP5150_CONF_SHARED_PIN)); + tvp5150_read(sd, TVP5150_CONF_SHARED_PIN)); printk("tvp5150: Active video cropping start = 0x%02x%02x\n", - tvp5150_read(c, TVP5150_ACT_VD_CROP_ST_MSB), - tvp5150_read(c, TVP5150_ACT_VD_CROP_ST_LSB)); + tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_MSB), + tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_LSB)); printk("tvp5150: Active video cropping stop = 0x%02x%02x\n", - tvp5150_read(c, TVP5150_ACT_VD_CROP_STP_MSB), - tvp5150_read(c, TVP5150_ACT_VD_CROP_STP_LSB)); + tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_MSB), + tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_LSB)); printk("tvp5150: Genlock/RTC = 0x%02x\n", - tvp5150_read(c, TVP5150_GENLOCK)); + tvp5150_read(sd, TVP5150_GENLOCK)); printk("tvp5150: Horizontal sync start = 0x%02x\n", - tvp5150_read(c, TVP5150_HORIZ_SYNC_START)); + tvp5150_read(sd, TVP5150_HORIZ_SYNC_START)); printk("tvp5150: Vertical blanking start = 0x%02x\n", - tvp5150_read(c, TVP5150_VERT_BLANKING_START)); + tvp5150_read(sd, TVP5150_VERT_BLANKING_START)); printk("tvp5150: Vertical blanking stop = 0x%02x\n", - tvp5150_read(c, TVP5150_VERT_BLANKING_STOP)); + tvp5150_read(sd, TVP5150_VERT_BLANKING_STOP)); printk("tvp5150: Chrominance processing control #1 and #2 = %02x %02x\n", - tvp5150_read(c, TVP5150_CHROMA_PROC_CTL_1), - tvp5150_read(c, TVP5150_CHROMA_PROC_CTL_2)); + tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_1), + tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_2)); printk("tvp5150: Interrupt reset register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_RESET_REG_B)); + tvp5150_read(sd, TVP5150_INT_RESET_REG_B)); printk("tvp5150: Interrupt enable register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_ENABLE_REG_B)); + tvp5150_read(sd, TVP5150_INT_ENABLE_REG_B)); printk("tvp5150: Interrupt configuration register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INTT_CONFIG_REG_B)); + tvp5150_read(sd, TVP5150_INTT_CONFIG_REG_B)); printk("tvp5150: Video standard = 0x%02x\n", - tvp5150_read(c, TVP5150_VIDEO_STD)); + tvp5150_read(sd, TVP5150_VIDEO_STD)); printk("tvp5150: Chroma gain factor: Cb=0x%02x Cr=0x%02x\n", - tvp5150_read(c, TVP5150_CB_GAIN_FACT), - tvp5150_read(c, TVP5150_CR_GAIN_FACTOR)); + tvp5150_read(sd, TVP5150_CB_GAIN_FACT), + tvp5150_read(sd, TVP5150_CR_GAIN_FACTOR)); printk("tvp5150: Macrovision on counter = 0x%02x\n", - tvp5150_read(c, TVP5150_MACROVISION_ON_CTR)); + tvp5150_read(sd, TVP5150_MACROVISION_ON_CTR)); printk("tvp5150: Macrovision off counter = 0x%02x\n", - tvp5150_read(c, TVP5150_MACROVISION_OFF_CTR)); + tvp5150_read(sd, TVP5150_MACROVISION_OFF_CTR)); printk("tvp5150: ITU-R BT.656.%d timing(TVP5150AM1 only)\n", - (tvp5150_read(c, TVP5150_REV_SELECT)&1)?3:4); + (tvp5150_read(sd, TVP5150_REV_SELECT) & 1) ? 3 : 4); printk("tvp5150: Device ID = %02x%02x\n", - tvp5150_read(c, TVP5150_MSB_DEV_ID), - tvp5150_read(c, TVP5150_LSB_DEV_ID)); + tvp5150_read(sd, TVP5150_MSB_DEV_ID), + tvp5150_read(sd, TVP5150_LSB_DEV_ID)); printk("tvp5150: ROM version = (hex) %02x.%02x\n", - tvp5150_read(c, TVP5150_ROM_MAJOR_VER), - tvp5150_read(c, TVP5150_ROM_MINOR_VER)); + tvp5150_read(sd, TVP5150_ROM_MAJOR_VER), + tvp5150_read(sd, TVP5150_ROM_MINOR_VER)); printk("tvp5150: Vertical line count = 0x%02x%02x\n", - tvp5150_read(c, TVP5150_VERT_LN_COUNT_MSB), - tvp5150_read(c, TVP5150_VERT_LN_COUNT_LSB)); + tvp5150_read(sd, TVP5150_VERT_LN_COUNT_MSB), + tvp5150_read(sd, TVP5150_VERT_LN_COUNT_LSB)); printk("tvp5150: Interrupt status register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_STATUS_REG_B)); + tvp5150_read(sd, TVP5150_INT_STATUS_REG_B)); printk("tvp5150: Interrupt active register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_ACTIVE_REG_B)); + tvp5150_read(sd, TVP5150_INT_ACTIVE_REG_B)); printk("tvp5150: Status regs #1 to #5 = %02x %02x %02x %02x %02x\n", - tvp5150_read(c, TVP5150_STATUS_REG_1), - tvp5150_read(c, TVP5150_STATUS_REG_2), - tvp5150_read(c, TVP5150_STATUS_REG_3), - tvp5150_read(c, TVP5150_STATUS_REG_4), - tvp5150_read(c, TVP5150_STATUS_REG_5)); + tvp5150_read(sd, TVP5150_STATUS_REG_1), + tvp5150_read(sd, TVP5150_STATUS_REG_2), + tvp5150_read(sd, TVP5150_STATUS_REG_3), + tvp5150_read(sd, TVP5150_STATUS_REG_4), + tvp5150_read(sd, TVP5150_STATUS_REG_5)); #if 0 /* This will pop a value from vbi reg */ printk("tvp5150: VBI FIFO read data = 0x%02x\n", - tvp5150_read(c, TVP5150_VBI_FIFO_READ_DATA)); + tvp5150_read(sd, TVP5150_VBI_FIFO_READ_DATA)); #endif - dump_reg_range(c,"Teletext filter 1", TVP5150_TELETEXT_FIL1_INI, - TVP5150_TELETEXT_FIL1_END,8); - dump_reg_range(c,"Teletext filter 2", TVP5150_TELETEXT_FIL2_INI, - TVP5150_TELETEXT_FIL2_END,8); + dump_reg_range(sd, "Teletext filter 1", TVP5150_TELETEXT_FIL1_INI, + TVP5150_TELETEXT_FIL1_END, 8); + dump_reg_range(sd, "Teletext filter 2", TVP5150_TELETEXT_FIL2_INI, + TVP5150_TELETEXT_FIL2_END, 8); printk("tvp5150: Teletext filter enable = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_ENA)); + tvp5150_read(sd, TVP5150_TELETEXT_FIL_ENA)); printk("tvp5150: Interrupt status register A = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_STATUS_REG_A)); + tvp5150_read(sd, TVP5150_INT_STATUS_REG_A)); printk("tvp5150: Interrupt enable register A = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_ENABLE_REG_A)); + tvp5150_read(sd, TVP5150_INT_ENABLE_REG_A)); printk("tvp5150: Interrupt configuration = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_CONF)); + tvp5150_read(sd, TVP5150_INT_CONF)); printk("tvp5150: VDP status register = 0x%02x\n", - tvp5150_read(c, TVP5150_VDP_STATUS_REG)); + tvp5150_read(sd, TVP5150_VDP_STATUS_REG)); printk("tvp5150: FIFO word count = 0x%02x\n", - tvp5150_read(c, TVP5150_FIFO_WORD_COUNT)); + tvp5150_read(sd, TVP5150_FIFO_WORD_COUNT)); printk("tvp5150: FIFO interrupt threshold = 0x%02x\n", - tvp5150_read(c, TVP5150_FIFO_INT_THRESHOLD)); + tvp5150_read(sd, TVP5150_FIFO_INT_THRESHOLD)); printk("tvp5150: FIFO reset = 0x%02x\n", - tvp5150_read(c, TVP5150_FIFO_RESET)); + tvp5150_read(sd, TVP5150_FIFO_RESET)); printk("tvp5150: Line number interrupt = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_NUMBER_INT)); + tvp5150_read(sd, TVP5150_LINE_NUMBER_INT)); printk("tvp5150: Pixel alignment register = 0x%02x%02x\n", - tvp5150_read(c, TVP5150_PIX_ALIGN_REG_HIGH), - tvp5150_read(c, TVP5150_PIX_ALIGN_REG_LOW)); + tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_HIGH), + tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_LOW)); printk("tvp5150: FIFO output control = 0x%02x\n", - tvp5150_read(c, TVP5150_FIFO_OUT_CTRL)); + tvp5150_read(sd, TVP5150_FIFO_OUT_CTRL)); printk("tvp5150: Full field enable = 0x%02x\n", - tvp5150_read(c, TVP5150_FULL_FIELD_ENA)); + tvp5150_read(sd, TVP5150_FULL_FIELD_ENA)); printk("tvp5150: Full field mode register = 0x%02x\n", - tvp5150_read(c, TVP5150_FULL_FIELD_MODE_REG)); + tvp5150_read(sd, TVP5150_FULL_FIELD_MODE_REG)); - dump_reg_range(c,"CC data", TVP5150_CC_DATA_INI, - TVP5150_CC_DATA_END,8); + dump_reg_range(sd, "CC data", TVP5150_CC_DATA_INI, + TVP5150_CC_DATA_END, 8); - dump_reg_range(c,"WSS data", TVP5150_WSS_DATA_INI, - TVP5150_WSS_DATA_END,8); + dump_reg_range(sd, "WSS data", TVP5150_WSS_DATA_INI, + TVP5150_WSS_DATA_END, 8); - dump_reg_range(c,"VPS data", TVP5150_VPS_DATA_INI, - TVP5150_VPS_DATA_END,8); + dump_reg_range(sd, "VPS data", TVP5150_VPS_DATA_INI, + TVP5150_VPS_DATA_END, 8); - dump_reg_range(c,"VITC data", TVP5150_VITC_DATA_INI, - TVP5150_VITC_DATA_END,10); + dump_reg_range(sd, "VITC data", TVP5150_VITC_DATA_INI, + TVP5150_VITC_DATA_END, 10); - dump_reg_range(c,"Line mode", TVP5150_LINE_MODE_INI, - TVP5150_LINE_MODE_END,8); + dump_reg_range(sd, "Line mode", TVP5150_LINE_MODE_INI, + TVP5150_LINE_MODE_END, 8); + return 0; } /**************************************************************************** Basic functions ****************************************************************************/ -static inline void tvp5150_selmux(struct i2c_client *c) +static inline void tvp5150_selmux(struct v4l2_subdev *sd) { int opmode=0; - struct tvp5150 *decoder = i2c_get_clientdata(c); + struct tvp5150 *decoder = to_tvp5150(sd); int input = 0; unsigned char val; @@ -314,23 +310,23 @@ static inline void tvp5150_selmux(struct i2c_client *c) break; } - tvp5150_dbg( 1, "Selecting video route: route input=%i, output=%i " + v4l2_dbg(1, debug, sd, "Selecting video route: route input=%i, output=%i " "=> tvp5150 input=%i, opmode=%i\n", decoder->route.input,decoder->route.output, input, opmode ); - tvp5150_write(c, TVP5150_OP_MODE_CTL, opmode); - tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input); + tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode); + tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input); /* Svideo should enable YCrCb output and disable GPCL output * For Composite and TV, it should be the reverse */ - val = tvp5150_read(c, TVP5150_MISC_CTL); + val = tvp5150_read(sd, TVP5150_MISC_CTL); if (decoder->route.input == TVP5150_SVIDEO) val = (val & ~0x40) | 0x10; else val = (val & ~0x10) | 0x40; - tvp5150_write(c, TVP5150_MISC_CTL, val); + tvp5150_write(sd, TVP5150_MISC_CTL, val); }; struct i2c_reg_value { @@ -605,35 +601,35 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = { (u16)-1 } }; -static int tvp5150_write_inittab(struct i2c_client *c, +static int tvp5150_write_inittab(struct v4l2_subdev *sd, const struct i2c_reg_value *regs) { while (regs->reg != 0xff) { - tvp5150_write(c, regs->reg, regs->value); + tvp5150_write(sd, regs->reg, regs->value); regs++; } return 0; } -static int tvp5150_vdp_init(struct i2c_client *c, +static int tvp5150_vdp_init(struct v4l2_subdev *sd, const struct i2c_vbi_ram_value *regs) { unsigned int i; /* Disable Full Field */ - tvp5150_write(c, TVP5150_FULL_FIELD_ENA, 0); + tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0); /* Before programming, Line mode should be at 0xff */ - for (i=TVP5150_LINE_MODE_INI; i<=TVP5150_LINE_MODE_END; i++) - tvp5150_write(c, i, 0xff); + for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++) + tvp5150_write(sd, i, 0xff); /* Load Ram Table */ - while (regs->reg != (u16)-1 ) { - tvp5150_write(c, TVP5150_CONF_RAM_ADDR_HIGH,regs->reg>>8); - tvp5150_write(c, TVP5150_CONF_RAM_ADDR_LOW,regs->reg); + while (regs->reg != (u16)-1) { + tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8); + tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg); - for (i=0;i<16;i++) - tvp5150_write(c, TVP5150_VDP_CONF_RAM_DATA,regs->values[i]); + for (i = 0; i < 16; i++) + tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]); regs++; } @@ -641,11 +637,13 @@ static int tvp5150_vdp_init(struct i2c_client *c, } /* Fills VBI capabilities based on i2c_vbi_ram_value struct */ -static void tvp5150_vbi_get_cap(const struct i2c_vbi_ram_value *regs, +static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap) { + const struct i2c_vbi_ram_value *regs = vbi_ram_default; int line; + v4l2_dbg(1, debug, sd, "VIDIOC_G_SLICED_VBI_CAP\n"); memset(cap, 0, sizeof *cap); while (regs->reg != (u16)-1 ) { @@ -656,6 +654,7 @@ static void tvp5150_vbi_get_cap(const struct i2c_vbi_ram_value *regs, regs++; } + return 0; } /* Set vbi processing @@ -671,18 +670,18 @@ static void tvp5150_vbi_get_cap(const struct i2c_vbi_ram_value *regs, * LSB = field1 * MSB = field2 */ -static int tvp5150_set_vbi(struct i2c_client *c, +static int tvp5150_set_vbi(struct v4l2_subdev *sd, const struct i2c_vbi_ram_value *regs, unsigned int type,u8 flags, int line, const int fields) { - struct tvp5150 *decoder = i2c_get_clientdata(c); - v4l2_std_id std=decoder->norm; + struct tvp5150 *decoder = to_tvp5150(sd); + v4l2_std_id std = decoder->norm; u8 reg; int pos=0; if (std == V4L2_STD_ALL) { - tvp5150_err("VBI can't be configured without knowing number of lines\n"); + v4l2_err(sd, "VBI can't be configured without knowing number of lines\n"); return 0; } else if (std & V4L2_STD_625_50) { /* Don't follow NTSC Line number convension */ @@ -710,174 +709,186 @@ static int tvp5150_set_vbi(struct i2c_client *c, reg=((line-6)<<1)+TVP5150_LINE_MODE_INI; if (fields&1) { - tvp5150_write(c, reg, type); + tvp5150_write(sd, reg, type); } if (fields&2) { - tvp5150_write(c, reg+1, type); + tvp5150_write(sd, reg+1, type); } return type; } -static int tvp5150_get_vbi(struct i2c_client *c, +static int tvp5150_get_vbi(struct v4l2_subdev *sd, const struct i2c_vbi_ram_value *regs, int line) { - struct tvp5150 *decoder = i2c_get_clientdata(c); - v4l2_std_id std=decoder->norm; + struct tvp5150 *decoder = to_tvp5150(sd); + v4l2_std_id std = decoder->norm; u8 reg; - int pos, type=0; + int pos, type = 0; if (std == V4L2_STD_ALL) { - tvp5150_err("VBI can't be configured without knowing number of lines\n"); + v4l2_err(sd, "VBI can't be configured without knowing number of lines\n"); return 0; } else if (std & V4L2_STD_625_50) { /* Don't follow NTSC Line number convension */ line += 3; } - if (line<6||line>27) + if (line < 6 || line > 27) return 0; - reg=((line-6)<<1)+TVP5150_LINE_MODE_INI; + reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI; - pos=tvp5150_read(c, reg)&0x0f; - if (pos<0x0f) - type=regs[pos].type.vbi_type; + pos = tvp5150_read(sd, reg) & 0x0f; + if (pos < 0x0f) + type = regs[pos].type.vbi_type; - pos=tvp5150_read(c, reg+1)&0x0f; - if (pos<0x0f) - type|=regs[pos].type.vbi_type; + pos = tvp5150_read(sd, reg + 1) & 0x0f; + if (pos < 0x0f) + type |= regs[pos].type.vbi_type; return type; } -#if 0 -static int decode_vbi_data(struct i2c_client *c, vbi) -{ - count=tvp5150_read(c, TVP5150_FIFO_WORD_COUNT); - for (i=0;inorm=std; + decoder->norm = std; /* First tests should be against specific std */ if (std == V4L2_STD_ALL) { - fmt=0; /* Autodetect mode */ + fmt = 0; /* Autodetect mode */ } else if (std & V4L2_STD_NTSC_443) { - fmt=0xa; + fmt = 0xa; } else if (std & V4L2_STD_PAL_M) { - fmt=0x6; - } else if (std & (V4L2_STD_PAL_N| V4L2_STD_PAL_Nc)) { - fmt=0x8; + fmt = 0x6; + } else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { + fmt = 0x8; } else { /* Then, test against generic ones */ - if (std & V4L2_STD_NTSC) { - fmt=0x2; - } else if (std & V4L2_STD_PAL) { - fmt=0x4; - } else if (std & V4L2_STD_SECAM) { - fmt=0xc; - } + if (std & V4L2_STD_NTSC) + fmt = 0x2; + else if (std & V4L2_STD_PAL) + fmt = 0x4; + else if (std & V4L2_STD_SECAM) + fmt = 0xc; } - tvp5150_dbg(1,"Set video std register to %d.\n",fmt); - tvp5150_write(c, TVP5150_VIDEO_STD, fmt); - + v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt); + tvp5150_write(sd, TVP5150_VIDEO_STD, fmt); return 0; } -static inline void tvp5150_reset(struct i2c_client *c) +static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + + if (decoder->norm == std) + return 0; + + return tvp5150_set_std(sd, std); +} + +static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) { + struct tvp5150 *decoder = to_tvp5150(sd); u8 msb_id, lsb_id, msb_rom, lsb_rom; - struct tvp5150 *decoder = i2c_get_clientdata(c); - msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID); - lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID); - msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER); - lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER); + msb_id = tvp5150_read(sd, TVP5150_MSB_DEV_ID); + lsb_id = tvp5150_read(sd, TVP5150_LSB_DEV_ID); + msb_rom = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER); + lsb_rom = tvp5150_read(sd, TVP5150_ROM_MINOR_VER); - if ((msb_rom==4)&&(lsb_rom==0)) { /* Is TVP5150AM1 */ - tvp5150_info("tvp%02x%02xam1 detected.\n",msb_id, lsb_id); + if (msb_rom == 4 && lsb_rom == 0) { /* Is TVP5150AM1 */ + v4l2_info(sd, "tvp%02x%02xam1 detected.\n", msb_id, lsb_id); /* ITU-T BT.656.4 timing */ - tvp5150_write(c,TVP5150_REV_SELECT,0); + tvp5150_write(sd, TVP5150_REV_SELECT, 0); } else { - if ((msb_rom==3)||(lsb_rom==0x21)) { /* Is TVP5150A */ - tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); + if (msb_rom == 3 || lsb_rom == 0x21) { /* Is TVP5150A */ + v4l2_info(sd, "tvp%02x%02xa detected.\n", msb_id, lsb_id); } else { - tvp5150_info("*** unknown tvp%02x%02x chip detected.\n",msb_id,lsb_id); - tvp5150_info("*** Rom ver is %d.%d\n",msb_rom,lsb_rom); + v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n", + msb_id, lsb_id); + v4l2_info(sd, "*** Rom ver is %d.%d\n", msb_rom, lsb_rom); } } /* Initializes TVP5150 to its default values */ - tvp5150_write_inittab(c, tvp5150_init_default); + tvp5150_write_inittab(sd, tvp5150_init_default); /* Initializes VDP registers */ - tvp5150_vdp_init(c, vbi_ram_default); + tvp5150_vdp_init(sd, vbi_ram_default); /* Selects decoder input */ - tvp5150_selmux(c); + tvp5150_selmux(sd); /* Initializes TVP5150 to stream enabled values */ - tvp5150_write_inittab(c, tvp5150_init_enable); + tvp5150_write_inittab(sd, tvp5150_init_enable); /* Initialize image preferences */ - tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright); - tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast); - tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast); - tvp5150_write(c, TVP5150_HUE_CTL, decoder->hue); + tvp5150_write(sd, TVP5150_BRIGHT_CTL, decoder->bright); + tvp5150_write(sd, TVP5150_CONTRAST_CTL, decoder->contrast); + tvp5150_write(sd, TVP5150_SATURATION_CTL, decoder->contrast); + tvp5150_write(sd, TVP5150_HUE_CTL, decoder->hue); - tvp5150_set_std(c, decoder->norm); + tvp5150_set_std(sd, decoder->norm); + return 0; }; -static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) +static int tvp5150_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { -/* struct tvp5150 *decoder = i2c_get_clientdata(c); */ + v4l2_dbg(1, debug, sd, "VIDIOC_G_CTRL called\n"); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - ctrl->value = tvp5150_read(c, TVP5150_BRIGHT_CTL); + ctrl->value = tvp5150_read(sd, TVP5150_BRIGHT_CTL); return 0; case V4L2_CID_CONTRAST: - ctrl->value = tvp5150_read(c, TVP5150_CONTRAST_CTL); + ctrl->value = tvp5150_read(sd, TVP5150_CONTRAST_CTL); return 0; case V4L2_CID_SATURATION: - ctrl->value = tvp5150_read(c, TVP5150_SATURATION_CTL); + ctrl->value = tvp5150_read(sd, TVP5150_SATURATION_CTL); return 0; case V4L2_CID_HUE: - ctrl->value = tvp5150_read(c, TVP5150_HUE_CTL); + ctrl->value = tvp5150_read(sd, TVP5150_HUE_CTL); return 0; } return -EINVAL; } -static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) +static int tvp5150_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { -/* struct tvp5150 *decoder = i2c_get_clientdata(c); */ + u8 i, n; + n = ARRAY_SIZE(tvp5150_qctrl); + + for (i = 0; i < n; i++) { + if (ctrl->id != tvp5150_qctrl[i].id) + continue; + if (ctrl->value < tvp5150_qctrl[i].minimum || + ctrl->value > tvp5150_qctrl[i].maximum) + return -ERANGE; + v4l2_dbg(1, debug, sd, "VIDIOC_S_CTRL: id=%d, value=%d\n", + ctrl->id, ctrl->value); + break; + } switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - tvp5150_write(c, TVP5150_BRIGHT_CTL, ctrl->value); + tvp5150_write(sd, TVP5150_BRIGHT_CTL, ctrl->value); return 0; case V4L2_CID_CONTRAST: - tvp5150_write(c, TVP5150_CONTRAST_CTL, ctrl->value); + tvp5150_write(sd, TVP5150_CONTRAST_CTL, ctrl->value); return 0; case V4L2_CID_SATURATION: - tvp5150_write(c, TVP5150_SATURATION_CTL, ctrl->value); + tvp5150_write(sd, TVP5150_SATURATION_CTL, ctrl->value); return 0; case V4L2_CID_HUE: - tvp5150_write(c, TVP5150_HUE_CTL, ctrl->value); + tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->value); return 0; } return -EINVAL; @@ -886,289 +897,250 @@ static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) /**************************************************************************** I2C Command ****************************************************************************/ -static int tvp5150_command(struct i2c_client *c, - unsigned int cmd, void *arg) -{ - struct tvp5150 *decoder = i2c_get_clientdata(c); - - switch (cmd) { - - case 0: - case VIDIOC_INT_RESET: - tvp5150_reset(c); - break; - case VIDIOC_INT_G_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - *route = decoder->route; - break; - } - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - decoder->route = *route; - tvp5150_selmux(c); - break; - } - case VIDIOC_S_STD: - if (decoder->norm == *(v4l2_std_id *)arg) - break; - return tvp5150_set_std(c, *(v4l2_std_id *)arg); - case VIDIOC_G_STD: - *(v4l2_std_id *)arg = decoder->norm; - break; +static int tvp5150_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct tvp5150 *decoder = to_tvp5150(sd); - case VIDIOC_G_SLICED_VBI_CAP: - { - struct v4l2_sliced_vbi_cap *cap = arg; - tvp5150_dbg(1, "VIDIOC_G_SLICED_VBI_CAP\n"); + decoder->route = *route; + tvp5150_selmux(sd); + return 0; +} - tvp5150_vbi_get_cap(vbi_ram_default, cap); - break; +static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_sliced_vbi_format *svbi; + int i; + + /* raw vbi */ + if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + /* this is for capturing 36 raw vbi lines + if there's a way to cut off the beginning 2 vbi lines + with the tvp5150 then the vbi line count could be lowered + to 17 lines/field again, although I couldn't find a register + which could do that cropping */ + if (fmt->fmt.vbi.sample_format == V4L2_PIX_FMT_GREY) + tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70); + if (fmt->fmt.vbi.count[0] == 18 && fmt->fmt.vbi.count[1] == 18) { + tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00); + tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01); + } + return 0; } - case VIDIOC_S_FMT: - { - struct v4l2_format *fmt; - struct v4l2_sliced_vbi_format *svbi; - int i; - - fmt = arg; - /* raw vbi */ - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* this is for capturing 36 raw vbi lines - if there's a way to cut off the beginning 2 vbi lines - with the tvp5150 then the vbi line count could be lowered - to 17 lines/field again, although I couldn't find a register - which could do that cropping */ - if (fmt->fmt.vbi.sample_format == V4L2_PIX_FMT_GREY) - tvp5150_write(c, TVP5150_LUMA_PROC_CTL_1, 0x70); - if (fmt->fmt.vbi.count[0] == 18 && fmt->fmt.vbi.count[1] == 18) { - tvp5150_write(c, TVP5150_VERT_BLANKING_START, 0x00); - tvp5150_write(c, TVP5150_VERT_BLANKING_STOP, 0x01); - } - break; + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + if (svbi->service_set != 0) { + for (i = 0; i <= 23; i++) { + svbi->service_lines[1][i] = 0; + svbi->service_lines[0][i] = + tvp5150_set_vbi(sd, vbi_ram_default, + svbi->service_lines[0][i], 0xf0, i, 3); } - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - if (svbi->service_set != 0) { - for (i = 0; i <= 23; i++) { - svbi->service_lines[1][i] = 0; - - svbi->service_lines[0][i]=tvp5150_set_vbi(c, - vbi_ram_default, - svbi->service_lines[0][i],0xf0,i,3); - } - /* Enables FIFO */ - tvp5150_write(c, TVP5150_FIFO_OUT_CTRL,1); - } else { - /* Disables FIFO*/ - tvp5150_write(c, TVP5150_FIFO_OUT_CTRL,0); + /* Enables FIFO */ + tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1); + } else { + /* Disables FIFO*/ + tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 0); - /* Disable Full Field */ - tvp5150_write(c, TVP5150_FULL_FIELD_ENA, 0); + /* Disable Full Field */ + tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0); - /* Disable Line modes */ - for (i=TVP5150_LINE_MODE_INI; i<=TVP5150_LINE_MODE_END; i++) - tvp5150_write(c, i, 0xff); - } - break; + /* Disable Line modes */ + for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++) + tvp5150_write(sd, i, 0xff); } - case VIDIOC_G_FMT: - { - struct v4l2_format *fmt; - struct v4l2_sliced_vbi_format *svbi; + return 0; +} - int i, mask=0; +static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_sliced_vbi_format *svbi; + int i, mask = 0; - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - memset(svbi, 0, sizeof(*svbi)); + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + memset(svbi, 0, sizeof(*svbi)); - for (i = 0; i <= 23; i++) { - svbi->service_lines[0][i]=tvp5150_get_vbi(c, - vbi_ram_default,i); - mask|=svbi->service_lines[0][i]; - } - svbi->service_set=mask; - break; + for (i = 0; i <= 23; i++) { + svbi->service_lines[0][i] = + tvp5150_get_vbi(sd, vbi_ram_default, i); + mask |= svbi->service_lines[0][i]; } + svbi->service_set = mask; + return 0; +} + #if 0 - /* This will not work for USB devices */ - case VIDIOC_INT_G_VBI_DATA: - { - struct v4l2_sliced_vbi_data *data = arg; - u8 status; - - status=tvp5150_read(c, TVP5150_VDP_STATUS_REG); - - if (data->id & V4L2_SLICED_CAPTION) { - if (!field && (status&0x10)) { - data->data[0]=tvp5150_read(c, TVP5150_CC_DATA_INI); - data->data[1]=tvp5150_read(c, TVP5150_CC_DATA_INI+1); - } if (field && (status&0x8)) { - data->data[0]=tvp5150_read(c, TVP5150_CC_DATA_INI+2); - data->data[1]=tvp5150_read(c, TVP5150_CC_DATA_INI+3); - } else data->id=0; - return 0; - } else if (data->id & V4L2_SLICED_WSS) { - } else if (data->id & V4L2_SLICED_VPS) { +/* This will not work for USB devices */ +static int tvp5150_g_vbi_data(struct v4l2_subdev *sd, + struct v4l2_sliced_vbi_data *data) +{ + u8 status = tvp5150_read(sd, TVP5150_VDP_STATUS_REG); + + if (data->id & V4L2_SLICED_CAPTION) { + if (!field && (status & 0x10)) { + data->data[0] = tvp5150_read(sd, TVP5150_CC_DATA_INI); + data->data[1] = tvp5150_read(sd, TVP5150_CC_DATA_INI+1); + } if (field && (status & 0x8)) { + data->data[0] = tvp5150_read(sd, TVP5150_CC_DATA_INI+2); + data->data[1] = tvp5150_read(sd, TVP5150_CC_DATA_INI+3); + } else { + data->id = 0; } - break; + return 0; + } else if (data->id & V4L2_SLICED_WSS) { + } else if (data->id & V4L2_SLICED_VPS) { } - case VIDIOC_INT_DECODE_VBI_LINE: - { - struct v4l2_decode_vbi_line *vbi = arg; - u8 status; + return 0; +} - status=tvp5150_read(c, TVP5150_VDP_STATUS_REG); +static int decode_vbi_data(struct v4l2_subdev *sd, vbi) +{ + count = tvp5150_read(sd, TVP5150_FIFO_WORD_COUNT); - if (status&0x80) { - tvp5150_err("Full field error"); - status&=0x7f; - tvp5150_write(c, TVP5150_VDP_STATUS_REG,status); - } + for (i = 0; i < count; i++) { + *p = tvp5150_read(sd, TVP5150_VBI_FIFO_READ_DATA); + p++; + } +} - /* FIFO */ - /* Current V4L2 API allows sliced VBI only with fifo mode, - since line and types are not provided on other means - on tvp5150. - */ - if (!(status&0x40)) /* Has FIFO data */ - decode_vbi_data(c,vbi); +static int tvp5150_decode_vbi_line(struct v4l2_subdev *sd, + struct v4l2_decode_vbi_line *vbi) +{ + u8 status = tvp5150_read(sd, TVP5150_VDP_STATUS_REG); - break; + if (status & 0x80) { + v4l2_err(sd, "Full field error"); + status &= 0x7f; + tvp5150_write(sd, TVP5150_VDP_STATUS_REG, status); } + + /* FIFO */ + /* Current V4L2 API allows sliced VBI only with fifo mode, + since line and types are not provided on other means + on tvp5150. + */ + if (!(status & 0x40)) /* Has FIFO data */ + decode_vbi_data(sd, vbi); + return 0; +} #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - - if (!v4l2_chip_match_i2c_client(c, reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (cmd == VIDIOC_DBG_G_REGISTER) - reg->val = tvp5150_read(c, reg->reg & 0xff); - else - tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff); - break; - } -#endif +static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - case VIDIOC_LOG_STATUS: - dump_reg(c); - break; + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = tvp5150_read(sd, reg->reg & 0xff); + return 0; +} - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *vt = arg; - int status = tvp5150_read(c, 0x88); +static int tvp5150_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - vt->signal = ((status & 0x04) && (status & 0x02)) ? 0xffff : 0x0; - break; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - int i; + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} +#endif - tvp5150_dbg(1, "VIDIOC_QUERYCTRL called\n"); +static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + int status = tvp5150_read(sd, 0x88); + + vt->signal = ((status & 0x04) && (status & 0x02)) ? 0xffff : 0x0; + return 0; +} - for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++) - if (qc->id && qc->id == tvp5150_qctrl[i].id) { - memcpy(qc, &(tvp5150_qctrl[i]), - sizeof(*qc)); - return 0; - } +static int tvp5150_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + int i; - return -EINVAL; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - tvp5150_dbg(1, "VIDIOC_G_CTRL called\n"); + v4l2_dbg(1, debug, sd, "VIDIOC_QUERYCTRL called\n"); - return tvp5150_get_ctrl(c, ctrl); - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - u8 i, n; - n = ARRAY_SIZE(tvp5150_qctrl); - for (i = 0; i < n; i++) - if (ctrl->id == tvp5150_qctrl[i].id) { - if (ctrl->value < - tvp5150_qctrl[i].minimum - || ctrl->value > - tvp5150_qctrl[i].maximum) - return -ERANGE; - tvp5150_dbg(1, - "VIDIOC_S_CTRL: id=%d, value=%d\n", - ctrl->id, ctrl->value); - return tvp5150_set_ctrl(c, ctrl); - } - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++) + if (qc->id && qc->id == tvp5150_qctrl[i].id) { + memcpy(qc, &(tvp5150_qctrl[i]), + sizeof(*qc)); + return 0; } - default: - return -EINVAL; - } + return -EINVAL; +} - return 0; +static int tvp5150_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops tvp5150_core_ops = { + .log_status = tvp5150_log_status, + .g_ctrl = tvp5150_g_ctrl, + .s_ctrl = tvp5150_s_ctrl, + .queryctrl = tvp5150_queryctrl, + .reset = tvp5150_reset, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = tvp5150_g_register, + .s_register = tvp5150_s_register, +#endif +}; + +static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { + .s_std = tvp5150_s_std, + .g_tuner = tvp5150_g_tuner, +}; + +static const struct v4l2_subdev_video_ops tvp5150_video_ops = { + .s_routing = tvp5150_s_routing, + .g_fmt = tvp5150_g_fmt, + .s_fmt = tvp5150_s_fmt, + .g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap, +}; + +static const struct v4l2_subdev_ops tvp5150_ops = { + .core = &tvp5150_core_ops, + .tuner = &tvp5150_tuner_ops, + .video = &tvp5150_video_ops, +}; + + /**************************************************************************** I2C Client & Driver ****************************************************************************/ -static struct i2c_driver driver; - -static struct i2c_client client_template = { - .name = "(unset)", - .driver = &driver, -}; -static int tvp5150_detect_client(struct i2c_adapter *adapter, - int address, int kind) +static int tvp5150_probe(struct i2c_client *c, + const struct i2c_device_id *id) { - struct i2c_client *c; struct tvp5150 *core; - int rv; - - if (debug) - printk( KERN_INFO - "tvp5150.c: detecting tvp5150 client on address 0x%x\n", - address << 1); - - client_template.adapter = adapter; - client_template.addr = address; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality - (adapter, + if (!i2c_check_functionality(c->adapter, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) - return 0; - - c = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!c) - return -ENOMEM; - memcpy(c, &client_template, sizeof(struct i2c_client)); + return -EIO; core = kzalloc(sizeof(struct tvp5150), GFP_KERNEL); if (!core) { - kfree(c); return -ENOMEM; } - i2c_set_clientdata(c, core); - - rv = i2c_attach_client(c); + sd = &core->sd; + v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); + v4l_info(c, "chip found @ 0x%02x (%s)\n", + c->addr << 1, c->adapter->name); core->norm = V4L2_STD_ALL; /* Default is autodetect */ core->route.input = TVP5150_COMPOSITE1; @@ -1178,75 +1150,42 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, core->hue = 0; core->sat = 128; - if (rv) { - kfree(c); - kfree(core); - return rv; - } - if (debug > 1) - dump_reg(c); + tvp5150_log_status(sd); return 0; } -static int tvp5150_attach_adapter(struct i2c_adapter *adapter) +static int tvp5150_remove(struct i2c_client *c) { - if (debug) - printk( KERN_INFO - "tvp5150.c: starting probe for adapter %s (0x%x)\n", - adapter->name, adapter->id); - return i2c_probe(adapter, &addr_data, &tvp5150_detect_client); -} + struct v4l2_subdev *sd = i2c_get_clientdata(c); -static int tvp5150_detach_client(struct i2c_client *c) -{ - struct tvp5150 *decoder = i2c_get_clientdata(c); - int err; - - tvp5150_dbg(1, + v4l2_dbg(1, debug, sd, "tvp5150.c: removing tvp5150 adapter on address 0x%x\n", c->addr << 1); - err = i2c_detach_client(c); - if (err) { - return err; - } - - kfree(decoder); - kfree(c); - + v4l2_device_unregister_subdev(sd); + kfree(to_tvp5150(sd)); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver driver = { - .driver = { - .name = "tvp5150", - }, - .id = I2C_DRIVERID_TVP5150, - - .attach_adapter = tvp5150_attach_adapter, - .detach_client = tvp5150_detach_client, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id tvp5150_id[] = { + { "tvp5150", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tvp5150_id); +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "tvp5150", + .driverid = I2C_DRIVERID_TVP5150, .command = tvp5150_command, -#if 0 - .driver = { - .suspend = tvp5150_suspend, - .resume = tvp5150_resume, - }, + .probe = tvp5150_probe, + .remove = tvp5150_remove, + .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = tvp5150_id, #endif }; - -static int __init tvp5150_init(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit tvp5150_exit(void) -{ - i2c_del_driver(&driver); -} - -module_init(tvp5150_init); -module_exit(tvp5150_exit); -- cgit v1.2.3 From d3918ffc89527a22f0ba31095387201cee5aff10 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 23 Dec 2008 09:54:45 +0100 Subject: soc-camera: Add signal inversion flags to be used by camera drivers From: Guennadi Liakhovetski As reported by Antonio Ospite two platforms with a mt9m111 camera require opposite pixel clock polarity, which means one of them inverts it. This patch adds support for inversion flags and switches all available camera drivers to using them. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m001.c | 15 +++++++-------- drivers/media/video/mt9m111.c | 6 +++++- drivers/media/video/mt9v022.c | 3 +++ drivers/media/video/ov772x.c | 10 +++++----- drivers/media/video/soc_camera.c | 34 ++++++++++++++++++++++++++++++++++ include/media/soc_camera.h | 11 +++++++++++ 6 files changed, 65 insertions(+), 14 deletions(-) --- linux/drivers/media/video/mt9m001.c | 15 +++++++-------- linux/drivers/media/video/mt9m111.c | 6 +++++- linux/drivers/media/video/mt9v022.c | 3 +++ linux/drivers/media/video/ov772x.c | 10 +++++----- linux/drivers/media/video/soc_camera.c | 34 ++++++++++++++++++++++++++++++++++ linux/include/media/soc_camera.h | 11 +++++++++++ 6 files changed, 65 insertions(+), 14 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index a489f239f..ed8a02269 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -272,17 +272,16 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - unsigned int width_flag = SOCAM_DATAWIDTH_10; + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + /* MT9M001 has all capture_format parameters fixed */ + unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING | + SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_MASTER; if (bus_switch_possible(mt9m001)) - width_flag |= SOCAM_DATAWIDTH_8; + flags |= SOCAM_DATAWIDTH_8; - /* MT9M001 has all capture_format parameters fixed */ - return SOCAM_PCLK_SAMPLE_RISING | - SOCAM_HSYNC_ACTIVE_HIGH | - SOCAM_VSYNC_ACTIVE_HIGH | - SOCAM_MASTER | - width_flag; + return soc_camera_apply_sensor_flags(icl, flags); } static int mt9m001_set_fmt(struct soc_camera_device *icd, diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index dc3a913da..2241b916e 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -415,9 +415,13 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd) static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) { - return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; + + return soc_camera_apply_sensor_flags(icl, flags); } static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 88380e05f..419cbe61f 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -273,6 +273,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; u16 pixclk = 0; @@ -296,6 +297,8 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; } + flags = soc_camera_apply_sensor_flags(icl, flags); + if (flags & SOCAM_PCLK_SAMPLE_RISING) pixclk |= 0x10; diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 89cacadad..bed830aed 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -716,12 +716,12 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - - return SOCAM_PCLK_SAMPLE_RISING | - SOCAM_HSYNC_ACTIVE_HIGH | - SOCAM_VSYNC_ACTIVE_HIGH | - SOCAM_MASTER | + struct soc_camera_link *icl = priv->client->dev.platform_data; + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | priv->info->buswidth; + + return soc_camera_apply_sensor_flags(icl, flags); } static int ov772x_get_chip_id(struct soc_camera_device *icd, diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4a9c52c37..d512cede8 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -60,6 +60,40 @@ const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( } EXPORT_SYMBOL(soc_camera_xlate_by_fourcc); +/** + * soc_camera_apply_sensor_flags() - apply platform SOCAM_SENSOR_INVERT_* flags + * @icl: camera platform parameters + * @flags: flags to be inverted according to platform configuration + * @return: resulting flags + */ +unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, + unsigned long flags) +{ + unsigned long f; + + /* If only one of the two polarities is supported, switch to the opposite */ + if (icl->flags & SOCAM_SENSOR_INVERT_HSYNC) { + f = flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW); + if (f == SOCAM_HSYNC_ACTIVE_HIGH || f == SOCAM_HSYNC_ACTIVE_LOW) + flags ^= SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW; + } + + if (icl->flags & SOCAM_SENSOR_INVERT_VSYNC) { + f = flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW); + if (f == SOCAM_VSYNC_ACTIVE_HIGH || f == SOCAM_VSYNC_ACTIVE_LOW) + flags ^= SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW; + } + + if (icl->flags & SOCAM_SENSOR_INVERT_PCLK) { + f = flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING); + if (f == SOCAM_PCLK_SAMPLE_RISING || f == SOCAM_PCLK_SAMPLE_FALLING) + flags ^= SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING; + } + + return flags; +} +EXPORT_SYMBOL(soc_camera_apply_sensor_flags); + static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index da57ffdae..e6ed0d94a 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -81,11 +81,19 @@ struct soc_camera_host_ops { unsigned int (*poll)(struct file *, poll_table *); }; +#define SOCAM_SENSOR_INVERT_PCLK (1 << 0) +#define SOCAM_SENSOR_INVERT_MCLK (1 << 1) +#define SOCAM_SENSOR_INVERT_HSYNC (1 << 2) +#define SOCAM_SENSOR_INVERT_VSYNC (1 << 3) +#define SOCAM_SENSOR_INVERT_DATA (1 << 4) + struct soc_camera_link { /* Camera bus id, used to match a camera and a bus */ int bus_id; /* GPIO number to switch between 8 and 10 bit modes */ unsigned int gpio; + /* Per camera SOCAM_SENSOR_* bus flags */ + unsigned long flags; /* Optional callbacks to power on or off and reset the sensor */ int (*power)(struct device *, int); int (*reset)(struct device *); @@ -206,4 +214,7 @@ static inline unsigned long soc_camera_bus_param_compatible( return (!hsync || !vsync || !pclk) ? 0 : common_flags; } +extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, + unsigned long flags); + #endif -- cgit v1.2.3 From f6f0ba19f43abdbe858fc402613d07a1885a482f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:29:05 +0100 Subject: mt9m111: Add automatic white balance control From: Robert Jarzmik Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m111.c | 28 +++++++++++++++++++++++++++- 1 files changed, 27 insertions(+), 1 deletions(-) --- linux/drivers/media/video/mt9m111.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 2241b916e..bfa00a7ff 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -90,7 +90,7 @@ #define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b #define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14) - +#define MT9M111_OPMODE_AUTOWHITEBAL_EN (1 << 1) #define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14) #define MT9M111_OUTFMT_BYPASS_IFP (1 << 10) @@ -163,6 +163,7 @@ struct mt9m111 { unsigned int swap_rgb_red_blue:1; unsigned int swap_yuv_y_chromas:1; unsigned int swap_yuv_cb_cr:1; + unsigned int autowhitebalance:1; }; static int reg_page_map_set(struct i2c_client *client, const u16 reg) @@ -702,6 +703,23 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) return ret; } + +static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret; + + if (on) + ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN); + else + ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN); + + if (!ret) + mt9m111->autowhitebalance = on; + + return ret; +} + static int mt9m111_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { @@ -738,6 +756,9 @@ static int mt9m111_get_control(struct soc_camera_device *icd, case V4L2_CID_EXPOSURE_AUTO: ctrl->value = mt9m111->autoexposure; break; + case V4L2_CID_AUTO_WHITE_BALANCE: + ctrl->value = mt9m111->autowhitebalance; + break; } return 0; } @@ -771,6 +792,9 @@ static int mt9m111_set_control(struct soc_camera_device *icd, case V4L2_CID_EXPOSURE_AUTO: ret = mt9m111_set_autoexposure(icd, ctrl->value); break; + case V4L2_CID_AUTO_WHITE_BALANCE: + ret = mt9m111_set_autowhitebalance(icd, ctrl->value); + break; default: ret = -EINVAL; } @@ -789,6 +813,7 @@ static int mt9m111_restore_state(struct soc_camera_device *icd) mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); mt9m111_set_global_gain(icd, icd->gain); mt9m111_set_autoexposure(icd, mt9m111->autoexposure); + mt9m111_set_autowhitebalance(icd, mt9m111->autowhitebalance); return 0; } @@ -883,6 +908,7 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) goto eisis; mt9m111->autoexposure = 1; + mt9m111->autowhitebalance = 1; mt9m111->swap_rgb_even_odd = 1; mt9m111->swap_rgb_red_blue = 1; -- cgit v1.2.3 From 0f0829dfa93f384ef8f33ecdcd0bd0d0d3335177 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:34:20 +0100 Subject: soc-camera: add camera sense data From: Guennadi Liakhovetski Add a struct soc_camera_sense, that can be used by camera host drivers to request additional information from a camera driver, for example, when changing data format. This struct can be extended in the future, its first use is to request the camera driver whether the pixel-clock frequency has changed. Signed-off-by: Guennadi Liakhovetski Tested-by: Robert Jarzmik --- include/media/soc_camera.h | 27 +++++++++++++++++++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-) --- linux/include/media/soc_camera.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index e6ed0d94a..38b826c60 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -36,6 +36,7 @@ struct soc_camera_device { unsigned char iface; /* Host number */ unsigned char devnum; /* Device number per host */ unsigned char buswidth; /* See comment in .c */ + struct soc_camera_sense *sense; /* See comment in struct definition */ struct soc_camera_ops *ops; struct video_device *vdev; const struct soc_camera_data_format *current_fmt; @@ -172,6 +173,32 @@ struct soc_camera_ops { int num_controls; }; +#define SOCAM_SENSE_PCLK_CHANGED (1 << 0) + +/** + * This struct can be attached to struct soc_camera_device by the host driver + * to request sense from the camera, for example, when calling .set_fmt(). The + * host then can check which flags are set and verify respective values if any. + * For example, if SOCAM_SENSE_PCLK_CHANGED is set, it means, pixclock has + * changed during this operation. After completion the host should detach sense. + * + * @flags ored SOCAM_SENSE_* flags + * @master_clock if the host wants to be informed about pixel-clock + * change, it better set master_clock. + * @pixel_clock_max maximum pixel clock frequency supported by the host, + * camera is not allowed to exceed this. + * @pixel_clock if the camera driver changed pixel clock during this + * operation, it sets SOCAM_SENSE_PCLK_CHANGED, uses + * master_clock to calculate the new pixel-clock and + * sets this field. + */ +struct soc_camera_sense { + unsigned long flags; + unsigned long master_clock; + unsigned long pixel_clock_max; + unsigned long pixel_clock; +}; + static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( struct soc_camera_ops *ops, int id) { -- cgit v1.2.3 From 52a0d0b3f7626ad29694d3b2a05d4c339b093d5d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:38:03 +0100 Subject: pxa-camera: setup the FIFO inactivity time-out register From: Guennadi Liakhovetski Using PXA270's FIFO inactivity time-out register (CITOR) reduces FIFO overruns. The time-out is calculated in CICLK / LCDCLK ticks and has to be longer than one pixel time. For this we have to know the pixel clock frequency, which usually is provided by the camera. We use the struct soc_camera_sense to request PCLK frequency from the camera driver upon each data format change. Signed-off-by: Guennadi Liakhovetski Tested-by: Robert Jarzmik --- drivers/media/video/pxa_camera.c | 90 +++++++++++++++++++++++++++++--------- 1 files changed, 69 insertions(+), 21 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 90 ++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 21 deletions(-) diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 338a7a6a7..108219e79 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -220,7 +220,9 @@ struct pxa_camera_dev { struct pxacamera_platform_data *pdata; struct resource *res; unsigned long platform_flags; - unsigned long platform_mclk_10khz; + unsigned long ciclk; + unsigned long mclk; + u32 mclk_divisor; struct list_head capture; @@ -712,24 +714,43 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, sizeof(struct pxa_buffer), icd); } -static int mclk_get_divisor(struct pxa_camera_dev *pcdev) +static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) { - unsigned int mclk_10khz = pcdev->platform_mclk_10khz; - unsigned long div; + unsigned long mclk = pcdev->mclk; + u32 div; unsigned long lcdclk; - lcdclk = clk_get_rate(pcdev->clk) / 10000; + lcdclk = clk_get_rate(pcdev->clk); + pcdev->ciclk = lcdclk; - /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here - * they get a nice Oops */ - div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1; + /* mclk <= ciclk / 4 (27.4.2) */ + if (mclk > lcdclk / 4) { + mclk = lcdclk / 4; + dev_warn(pcdev->dev, "Limiting master clock to %lu\n", mclk); + } + + /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ + div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; + + /* If we're not supplying MCLK, leave it at 0 */ + if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) + pcdev->mclk = lcdclk / (2 * (div + 1)); - dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, " - "divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div); + dev_dbg(pcdev->dev, "LCD clock %luHz, target freq %luHz, " + "divisor %u\n", lcdclk, mclk, div); return div; } +static void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev, + unsigned long pclk) +{ + /* We want a timeout > 1 pixel time, not ">=" */ + u32 ciclk_per_pixel = pcdev->ciclk / pclk + 1; + + __raw_writel(ciclk_per_pixel, pcdev->base + CITOR); +} + static void pxa_camera_activate(struct pxa_camera_dev *pcdev) { struct pxacamera_platform_data *pdata = pcdev->pdata; @@ -757,8 +778,14 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) if (pcdev->platform_flags & PXA_CAMERA_VSP) cicr4 |= CICR4_VSP; - cicr4 |= mclk_get_divisor(pcdev); - __raw_writel(cicr4, pcdev->base + CICR4); + __raw_writel(pcdev->mclk_divisor | cicr4, pcdev->base + CICR4); + + if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) + /* Initialise the timeout under the assumption pclk = mclk */ + recalculate_fifo_timeout(pcdev, pcdev->mclk); + else + /* "Safe default" - 13MHz */ + recalculate_fifo_timeout(pcdev, 13000000); clk_enable(pcdev->clk); } @@ -1005,7 +1032,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) cicr2 = 0; cicr3 = CICR3_LPF_VAL(icd->height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); - cicr4 |= mclk_get_divisor(pcdev); + cicr4 |= pcdev->mclk_divisor; __raw_writel(cicr1, pcdev->base + CICR1); __raw_writel(cicr2, pcdev->base + CICR2); @@ -1024,8 +1051,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) static int pxa_camera_try_bus_param(struct soc_camera_device *icd, unsigned char buswidth) { - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; unsigned long bus_flags, camera_flags; int ret = test_platform_param(pcdev, buswidth, &bus_flags); @@ -1141,8 +1167,13 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL; const struct soc_camera_format_xlate *xlate; + struct soc_camera_sense sense = { + .master_clock = pcdev->mclk, + .pixel_clock_max = pcdev->ciclk / 4, + }; int ret, buswidth; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); @@ -1155,6 +1186,10 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, host_fmt = xlate->host_fmt; cam_fmt = xlate->cam_fmt; + /* If PCLK is used to latch data from the sensor, check sense */ + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + icd->sense = &sense; + switch (pixfmt) { case 0: /* Only geometry change */ ret = icd->ops->set_fmt(icd, pixfmt, rect); @@ -1163,9 +1198,20 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect); } - if (ret < 0) + icd->sense = NULL; + + if (ret < 0) { dev_warn(&ici->dev, "Failed to configure for format %x\n", pixfmt); + } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { + if (sense.pixel_clock > sense.pixel_clock_max) { + dev_err(&ici->dev, + "pixel clock %lu set by the camera too high!", + sense.pixel_clock); + return -EIO; + } + recalculate_fifo_timeout(pcdev, sense.pixel_clock); + } if (pixfmt && !ret) { icd->buswidth = buswidth; @@ -1374,14 +1420,17 @@ static int pxa_camera_probe(struct platform_device *pdev) "data widths, using default 10 bit\n"); pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; } - pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz; - if (!pcdev->platform_mclk_10khz) { + pcdev->mclk = pcdev->pdata->mclk_10khz * 10000; + if (!pcdev->mclk) { dev_warn(&pdev->dev, - "mclk_10khz == 0! Please, fix your platform data. " + "mclk == 0! Please, fix your platform data. " "Using default 20MHz\n"); - pcdev->platform_mclk_10khz = 2000; + pcdev->mclk = 20000000; } + pcdev->dev = &pdev->dev; + pcdev->mclk_divisor = mclk_get_divisor(pcdev); + INIT_LIST_HEAD(&pcdev->capture); spin_lock_init(&pcdev->lock); @@ -1401,7 +1450,6 @@ static int pxa_camera_probe(struct platform_device *pdev) } pcdev->irq = irq; pcdev->base = base; - pcdev->dev = &pdev->dev; /* request dma */ err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, -- cgit v1.2.3 From a7acb20d1a9ab6804581faeaa192630443540732 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:42:54 +0100 Subject: v4l: add chip ID for MT9M112 camera sensor from Micron From: Mike Rapoport The chip is largely compatible with MT9M111 and is going to be supported by the same driver. Signed-off-by: Mike Rapoport Signed-off-by: Guennadi Liakhovetski --- include/media/v4l2-chip-ident.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) --- linux/include/media/v4l2-chip-ident.h | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index 14a205f44..52e778ded 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -168,6 +168,7 @@ enum { V4L2_IDENT_MT9M001C12ST = 45000, V4L2_IDENT_MT9M001C12STM = 45005, V4L2_IDENT_MT9M111 = 45007, + V4L2_IDENT_MT9M112 = 45008, V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ }; -- cgit v1.2.3 From 739b7bf4583076c2429200ccc83736bfe05a0ec9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:44:15 +0100 Subject: mt9m111: add support for mt9m112 since sensors seem identical From: Mike Rapoport Signed-off-by: Mike Rapoport Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/Kconfig | 4 ++-- drivers/media/video/mt9m111.c | 28 ++++++++++++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) --- linux/drivers/media/video/Kconfig | 4 ++-- linux/drivers/media/video/mt9m111.c | 28 ++++++++++++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index cc224744b..e6c89cdfe 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -736,10 +736,10 @@ config MT9M001_PCA9536_SWITCH extender to switch between 8 and 10 bit datawidth modes config SOC_CAMERA_MT9M111 - tristate "mt9m111 support" + tristate "mt9m111 and mt9m112 support" depends on SOC_CAMERA && I2C help - This driver supports MT9M111 cameras from Micron + This driver supports MT9M111 and MT9M112 cameras from Micron config SOC_CAMERA_MT9V022 tristate "mt9v022 support" diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index bfa00a7ff..a554e6c55 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -1,5 +1,5 @@ /* - * Driver for MT9M111 CMOS Image Sensor from Micron + * Driver for MT9M111/MT9M112 CMOS Image Sensor from Micron * * Copyright (C) 2008, Robert Jarzmik * @@ -19,7 +19,7 @@ #include /* - * mt9m111 i2c address is 0x5d or 0x48 (depending on SAddr pin) + * mt9m111 and mt9m112 i2c address is 0x5d or 0x48 (depending on SAddr pin) * The platform has to define i2c_board_info and call i2c_register_board_info() */ @@ -150,7 +150,7 @@ enum mt9m111_context { struct mt9m111 { struct i2c_client *client; struct soc_camera_device icd; - int model; /* V4L2_IDENT_MT9M111* codes from v4l2-chip-ident.h */ + int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ enum mt9m111_context context; unsigned int left, top, width, height; u32 pixfmt; @@ -846,7 +846,7 @@ static int mt9m111_init(struct soc_camera_device *icd) if (!ret) ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure); if (ret) - dev_err(&icd->dev, "mt9m111 init failed: %d\n", ret); + dev_err(&icd->dev, "mt9m11x init failed: %d\n", ret); return ret; } @@ -856,7 +856,7 @@ static int mt9m111_release(struct soc_camera_device *icd) ret = mt9m111_disable(icd); if (ret < 0) - dev_err(&icd->dev, "mt9m111 release failed: %d\n", ret); + dev_err(&icd->dev, "mt9m11x release failed: %d\n", ret); return ret; } @@ -889,19 +889,23 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) data = reg_read(CHIP_VERSION); switch (data) { - case 0x143a: + case 0x143a: /* MT9M111 */ mt9m111->model = V4L2_IDENT_MT9M111; - icd->formats = mt9m111_colour_formats; - icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); + break; + case 0x148c: /* MT9M112 */ + mt9m111->model = V4L2_IDENT_MT9M112; break; default: ret = -ENODEV; dev_err(&icd->dev, - "No MT9M111 chip detected, register read %x\n", data); + "No MT9M11x chip detected, register read %x\n", data); goto ei2c; } - dev_info(&icd->dev, "Detected a MT9M111 chip ID 0x143a\n"); + icd->formats = mt9m111_colour_formats; + icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); + + dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data); ret = soc_camera_video_start(icd); if (ret) @@ -942,7 +946,7 @@ static int mt9m111_probe(struct i2c_client *client, int ret; if (!icl) { - dev_err(&client->dev, "MT9M111 driver needs platform data\n"); + dev_err(&client->dev, "MT9M11x driver needs platform data\n"); return -EINVAL; } @@ -1025,6 +1029,6 @@ static void __exit mt9m111_mod_exit(void) module_init(mt9m111_mod_init); module_exit(mt9m111_mod_exit); -MODULE_DESCRIPTION("Micron MT9M111 Camera driver"); +MODULE_DESCRIPTION("Micron MT9M111/MT9M112 Camera driver"); MODULE_AUTHOR("Robert Jarzmik"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b5f1adc8eee3163e1b6742c0e1f0c611a084193e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:45:00 +0100 Subject: video: add NV16 and NV61 pixel formats From: Magnus Damm This patch adds support for NV16 and NV61 pixel formats. These pixel formats use two planes; one for 8-bit Y values and one for interleaved 8-bit U and V values. NV16/NV61 formats are very similar to NV12/NV21 with the exception that NV16/NV61 are using the same number of lines for both planes. The difference between NV16 and NV61 is the U and V byte order. The fourcc values are extrapolated from the NV12/NV21 case. Signed-off-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski --- include/linux/videodev2.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) --- linux/include/linux/videodev2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 018894814..0aae06946 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -305,6 +305,8 @@ struct v4l2_pix_format { /* two planes -- one Y, one Cr + Cb interleaved */ #define V4L2_PIX_FMT_NV12 v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */ #define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */ +#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */ +#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */ /* The following formats are not defined in the V4L2 specification */ #define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y', 'U', 'V', '9') /* 9 YUV 4:1:0 */ -- cgit v1.2.3 From 57f8aa8b893b6b4eaccdb54f8836f8ff241acd37 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:49:06 +0100 Subject: sh_mobile_ceu: use new pixel format translation code From: Magnus Damm This patch converts the sh_mobile_ceu driver to make use of the new pixel format translation code. Only pass-though mode at this point. Signed-off-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 83 +++++++++++++++++++--------- 1 files changed, 57 insertions(+), 26 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 83 ++++++++++++++++-------- 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index bd2a1754b..e7c5cf2a0 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -429,8 +429,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, return 0; } -static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, - __u32 pixfmt) +static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -445,25 +444,60 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, return 0; } +static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, + struct soc_camera_format_xlate *xlate) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int ret; + int formats = 0; + + ret = sh_mobile_ceu_try_bus_param(icd); + if (ret < 0) + return 0; + + switch (icd->formats[idx].fourcc) { + default: + /* Generic pass-through */ + formats++; + if (xlate) { + xlate->host_fmt = icd->formats + idx; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = icd->formats[idx].depth; + xlate++; + dev_dbg(&ici->dev, + "Providing format %s in pass-through mode\n", + icd->formats[idx].name); + } + } + + return formats; +} + static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { - const struct soc_camera_data_format *cam_fmt = NULL; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct soc_camera_format_xlate *xlate; int ret; - /* - * TODO: find a suitable supported by the SoC output format, check - * whether the sensor supports one of acceptable input formats. - */ - if (pixfmt) { - cam_fmt = soc_camera_format_by_fourcc(icd, pixfmt); - if (!cam_fmt) - return -EINVAL; + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; } - ret = icd->ops->set_fmt(icd, pixfmt, rect); - if (pixfmt && !ret) - icd->current_fmt = cam_fmt; + switch (pixfmt) { + case 0: /* Only geometry change */ + ret = icd->ops->set_fmt(icd, pixfmt, rect); + break; + default: + ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); + } + + if (pixfmt && !ret) { + icd->buswidth = xlate->buswidth; + icd->current_fmt = xlate->host_fmt; + } return ret; } @@ -471,19 +505,15 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - const struct soc_camera_data_format *cam_fmt; - int ret = sh_mobile_ceu_try_bus_param(icd, f->fmt.pix.pixelformat); - - if (ret < 0) - return ret; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct soc_camera_format_xlate *xlate; + __u32 pixfmt = f->fmt.pix.pixelformat; - /* - * TODO: find a suitable supported by the SoC output format, check - * whether the sensor supports one of acceptable input formats. - */ - cam_fmt = soc_camera_format_by_fourcc(icd, f->fmt.pix.pixelformat); - if (!cam_fmt) + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; + } /* FIXME: calculate using depth and bus width */ @@ -499,7 +529,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, f->fmt.pix.height &= ~0x03; f->fmt.pix.bytesperline = f->fmt.pix.width * - DIV_ROUND_UP(cam_fmt->depth, 8); + DIV_ROUND_UP(xlate->host_fmt->depth, 8); f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; /* limit to sensor capabilities */ @@ -571,6 +601,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .owner = THIS_MODULE, .add = sh_mobile_ceu_add_device, .remove = sh_mobile_ceu_remove_device, + .get_formats = sh_mobile_ceu_get_formats, .set_fmt = sh_mobile_ceu_set_fmt, .try_fmt = sh_mobile_ceu_try_fmt, .reqbufs = sh_mobile_ceu_reqbufs, -- cgit v1.2.3 From 07f7d043ce9816eb9222877c9bcad522a485b3f3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:51:55 +0100 Subject: soc-camera: readability improvements, more strict operations checks From: Guennadi Liakhovetski Simplify multiple drivers by replacing f->fmt.pix.* with a single pointer dereference, merge some needlessly broken lines, verify host and camera operations pointers on registration. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m001.c | 20 ++++---- drivers/media/video/mt9m111.c | 10 ++-- drivers/media/video/mt9v022.c | 20 ++++---- drivers/media/video/pxa_camera.c | 21 +++----- drivers/media/video/soc_camera.c | 74 +++++++++++++++++------------ drivers/media/video/soc_camera_platform.c | 5 +- 6 files changed, 81 insertions(+), 69 deletions(-) --- linux/drivers/media/video/mt9m001.c | 20 ++++--- linux/drivers/media/video/mt9m111.c | 10 ++-- linux/drivers/media/video/mt9v022.c | 20 ++++--- linux/drivers/media/video/pxa_camera.c | 21 +++---- linux/drivers/media/video/soc_camera.c | 74 ++++++++++++++----------- linux/drivers/media/video/soc_camera_platform.c | 5 +- 6 files changed, 81 insertions(+), 69 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index ed8a02269..2f431a5d6 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -327,15 +327,17 @@ static int mt9m001_set_fmt(struct soc_camera_device *icd, static int mt9m001_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - if (f->fmt.pix.height < 32 + icd->y_skip_top) - f->fmt.pix.height = 32 + icd->y_skip_top; - if (f->fmt.pix.height > 1024 + icd->y_skip_top) - f->fmt.pix.height = 1024 + icd->y_skip_top; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.width > 1280) - f->fmt.pix.width = 1280; - f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */ + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (pix->height < 32 + icd->y_skip_top) + pix->height = 32 + icd->y_skip_top; + if (pix->height > 1024 + icd->y_skip_top) + pix->height = 1024 + icd->y_skip_top; + if (pix->width < 48) + pix->width = 48; + if (pix->width > 1280) + pix->width = 1280; + pix->width &= ~0x01; /* has to be even, unsure why was ~3 */ return 0; } diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index a554e6c55..39f2e83cf 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -503,10 +503,12 @@ static int mt9m111_set_fmt(struct soc_camera_device *icd, static int mt9m111_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - if (f->fmt.pix.height > MT9M111_MAX_HEIGHT) - f->fmt.pix.height = MT9M111_MAX_HEIGHT; - if (f->fmt.pix.width > MT9M111_MAX_WIDTH) - f->fmt.pix.width = MT9M111_MAX_WIDTH; + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (pix->height > MT9M111_MAX_HEIGHT) + pix->height = MT9M111_MAX_HEIGHT; + if (pix->width > MT9M111_MAX_WIDTH) + pix->width = MT9M111_MAX_WIDTH; return 0; } diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 419cbe61f..ff30c99e9 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -406,15 +406,17 @@ static int mt9v022_set_fmt(struct soc_camera_device *icd, static int mt9v022_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - if (f->fmt.pix.height < 32 + icd->y_skip_top) - f->fmt.pix.height = 32 + icd->y_skip_top; - if (f->fmt.pix.height > 480 + icd->y_skip_top) - f->fmt.pix.height = 480 + icd->y_skip_top; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.width > 752) - f->fmt.pix.width = 752; - f->fmt.pix.width &= ~0x03; /* ? */ + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (pix->height < 32 + icd->y_skip_top) + pix->height = 32 + icd->y_skip_top; + if (pix->height > 480 + icd->y_skip_top) + pix->height = 480 + icd->y_skip_top; + if (pix->width < 48) + pix->width = 48; + if (pix->width > 752) + pix->width = 752; + pix->width &= ~0x03; /* ? */ return 0; } diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 108219e79..54801a527 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -245,8 +245,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); @@ -272,8 +271,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); int i; @@ -349,8 +347,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) { struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); int ret; @@ -469,8 +466,7 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); struct pxa_buffer *active; @@ -920,8 +916,7 @@ static int test_platform_param(struct pxa_camera_dev *pcdev, static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) { - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; unsigned long dw, bpp, bus_flags, camera_flags, common_flags; u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0; @@ -1303,8 +1298,7 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state) { - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; int i = 0, ret = 0; @@ -1322,8 +1316,7 @@ static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state) static int pxa_camera_resume(struct soc_camera_device *icd) { - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; int i = 0, ret = 0; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index d512cede8..2e8f11a0d 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -99,8 +99,7 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); enum v4l2_field field; int ret; @@ -164,8 +163,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv, int ret; struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); WARN_ON(priv != file->private_data); @@ -389,8 +387,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); if (list_empty(&icf->vb_vidq.stream)) { dev_err(&icd->dev, "Trying to poll with no queued buffers!\n"); @@ -416,9 +413,9 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); - __u32 pixfmt = f->fmt.pix.pixelformat; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_pix_format *pix = &f->fmt.pix; + __u32 pixfmt = pix->pixelformat; int ret; struct v4l2_rect rect; @@ -430,9 +427,9 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, rect.left = icd->x_current; rect.top = icd->y_current; - rect.width = f->fmt.pix.width; - rect.height = f->fmt.pix.height; - ret = ici->ops->set_fmt(icd, f->fmt.pix.pixelformat, &rect); + rect.width = pix->width; + rect.height = pix->height; + ret = ici->ops->set_fmt(icd, pix->pixelformat, &rect); if (ret < 0) { return ret; } else if (!icd->current_fmt || @@ -444,7 +441,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, icd->width = rect.width; icd->height = rect.height; - icf->vb_vidq.field = f->fmt.pix.field; + icf->vb_vidq.field = pix->field; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", f->type); @@ -480,16 +477,17 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct v4l2_pix_format *pix = &f->fmt.pix; WARN_ON(priv != file->private_data); - f->fmt.pix.width = icd->width; - f->fmt.pix.height = icd->height; - f->fmt.pix.field = icf->vb_vidq.field; - f->fmt.pix.pixelformat = icd->current_fmt->fourcc; - f->fmt.pix.bytesperline = f->fmt.pix.width * + pix->width = icd->width; + pix->height = icd->height; + pix->field = icf->vb_vidq.field; + pix->pixelformat = icd->current_fmt->fourcc; + pix->bytesperline = pix->width * DIV_ROUND_UP(icd->current_fmt->depth, 8); - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + pix->sizeimage = pix->height * pix->bytesperline; dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", icd->current_fmt->fourcc); return 0; @@ -500,8 +498,7 @@ static int soc_camera_querycap(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); WARN_ON(priv != file->private_data); @@ -652,8 +649,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret; if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -777,13 +773,9 @@ static int scan_add_device(struct soc_camera_device *icd) static int soc_camera_probe(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret; - if (!icd->ops->probe) - return -ENODEV; - /* We only call ->add() here to activate and probe the camera. * We shall ->remove() and deactivate it immediately afterwards. */ ret = ici->ops->add(icd); @@ -864,7 +856,16 @@ int soc_camera_host_register(struct soc_camera_host *ici) int ret; struct soc_camera_host *ix; - if (!ici->ops->init_videobuf || !ici->ops->add || !ici->ops->remove) + if (!ici || !ici->ops || + !ici->ops->try_fmt || + !ici->ops->set_fmt || + !ici->ops->set_bus_param || + !ici->ops->querycap || + !ici->ops->init_videobuf || + !ici->ops->reqbufs || + !ici->ops->add || + !ici->ops->remove || + !ici->ops->poll) return -EINVAL; /* Number might be equal to the platform device ID */ @@ -932,7 +933,16 @@ int soc_camera_device_register(struct soc_camera_device *icd) struct soc_camera_device *ix; int num = -1, i; - if (!icd) + if (!icd || !icd->ops || + !icd->ops->probe || + !icd->ops->init || + !icd->ops->release || + !icd->ops->start_capture || + !icd->ops->stop_capture || + !icd->ops->set_fmt || + !icd->ops->try_fmt || + !icd->ops->query_bus_param || + !icd->ops->set_bus_param) return -EINVAL; for (i = 0; i < 256 && num < 0; i++) { @@ -954,7 +964,9 @@ int soc_camera_device_register(struct soc_camera_device *icd) icd->dev.bus = &soc_camera_bus_type; dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum); - icd->dev.release = dummy_release; + icd->dev.release = dummy_release; + icd->use_count = 0; + icd->host_priv = NULL; return scan_add_device(icd); } diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index c23871e4c..013ab06e3 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -89,9 +89,10 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct v4l2_pix_format *pix = &f->fmt.pix; - f->fmt.pix.width = p->format.width; - f->fmt.pix.height = p->format.height; + pix->width = p->format.width; + pix->height = p->format.height; return 0; } -- cgit v1.2.3 From 2d2a08f8d286aa67875536b82adb44119b446960 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 15:53:51 +0100 Subject: pxa-camera: call try_fmt() camera device method with correct pixel format From: Guennadi Liakhovetski With the introduction of the format conversion support in soc-camera, we now also have to take care to pass the correct pixel format to the camera driver when calling its try_fmt() method. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 54801a527..cec1a5a21 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1223,6 +1223,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; + int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { @@ -1245,8 +1246,13 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, DIV_ROUND_UP(xlate->host_fmt->depth, 8); pix->sizeimage = pix->height * pix->bytesperline; + /* camera has to see its format, but the user the original one */ + pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - return icd->ops->try_fmt(icd, f); + ret = icd->ops->try_fmt(icd, f); + pix->pixelformat = xlate->host_fmt->fourcc; + + return ret; } static int pxa_camera_reqbufs(struct soc_camera_file *icf, -- cgit v1.2.3 From 35577a13c8b70866b531522be67f11a4cf56a80e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Dec 2008 13:05:51 -0200 Subject: Fix an error and print a line that can be pasted From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- hgimport | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hgimport b/hgimport index 75cc4ae97..099acbc52 100755 --- a/hgimport +++ b/hgimport @@ -102,8 +102,5 @@ for i in $TMP/*.patch; do fi done - -# To cherry pick all files, you can do something like: -for i in $TMP/newpatches/*; do - hg import $i; -done +echo To cherry pick all files, you can do something like: +echo "for i in $TMP/*.patch; do ./mailimport \$i; done" -- cgit v1.2.3 From 51a0d7da82dc5d293c59c43e1e912f1c673a9849 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 16:11:32 +0100 Subject: tvaudio: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvaudio.c | 715 +++++++++++++++++++----------------- 1 file changed, 387 insertions(+), 328 deletions(-) diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 0a86c80a2..492da4d8e 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -36,8 +36,7 @@ #include "compat.h" #include -#include -#include +#include #include #include @@ -113,7 +112,7 @@ struct CHIPDESC { /* current state of the chip */ struct CHIPSTATE { - struct i2c_client *c; + struct v4l2_subdev sd; /* chip-specific description - should point to an entry at CHIPDESC table */ @@ -135,6 +134,11 @@ struct CHIPSTATE { int audmode; }; +static inline struct CHIPSTATE *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct CHIPSTATE, sd); +} + /* ---------------------------------------------------------------------- */ /* i2c addresses */ @@ -155,34 +159,34 @@ I2C_CLIENT_INSMOD; static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) { + struct v4l2_subdev *sd = &chip->sd; + struct i2c_client *c = v4l2_get_subdevdata(sd); unsigned char buffer[2]; if (subaddr < 0) { - v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", - chip->c->name, val); + v4l2_dbg(1, debug, sd, "chip_write: 0x%x\n", val); chip->shadow.bytes[1] = val; buffer[0] = val; - if (1 != i2c_master_send(chip->c,buffer,1)) { - v4l_warn(chip->c, "%s: I/O error (write 0x%x)\n", - chip->c->name, val); + if (1 != i2c_master_send(c, buffer, 1)) { + v4l2_warn(sd, "I/O error (write 0x%x)\n", val); return -1; } } else { if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { - v4l_info(chip->c, + v4l2_info(sd, "Tried to access a non-existent register: %d\n", subaddr); return -EINVAL; } - v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", - chip->c->name, subaddr, val); + v4l2_dbg(1, debug, sd, "chip_write: reg%d=0x%x\n", + subaddr, val); chip->shadow.bytes[subaddr+1] = val; buffer[0] = subaddr; buffer[1] = val; - if (2 != i2c_master_send(chip->c,buffer,2)) { - v4l_warn(chip->c, "%s: I/O error (write reg%d=0x%x)\n", - chip->c->name, subaddr, val); + if (2 != i2c_master_send(c, buffer, 2)) { + v4l2_warn(sd, "I/O error (write reg%d=0x%x)\n", + subaddr, val); return -1; } } @@ -192,12 +196,14 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask) { + struct v4l2_subdev *sd = &chip->sd; + if (mask != 0) { if (subaddr < 0) { val = (chip->shadow.bytes[1] & ~mask) | (val & mask); } else { if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { - v4l_info(chip->c, + v4l2_info(sd, "Tried to access a non-existent register: %d\n", subaddr); return -EINVAL; @@ -211,45 +217,51 @@ static int chip_write_masked(struct CHIPSTATE *chip, static int chip_read(struct CHIPSTATE *chip) { + struct v4l2_subdev *sd = &chip->sd; + struct i2c_client *c = v4l2_get_subdevdata(sd); unsigned char buffer; - if (1 != i2c_master_recv(chip->c,&buffer,1)) { - v4l_warn(chip->c, "%s: I/O error (read)\n", - chip->c->name); + if (1 != i2c_master_recv(c, &buffer, 1)) { + v4l2_warn(sd, "I/O error (read)\n"); return -1; } - v4l_dbg(1, debug, chip->c, "%s: chip_read: 0x%x\n",chip->c->name, buffer); + v4l2_dbg(1, debug, sd, "chip_read: 0x%x\n", buffer); return buffer; } static int chip_read2(struct CHIPSTATE *chip, int subaddr) { + struct v4l2_subdev *sd = &chip->sd; + struct i2c_client *c = v4l2_get_subdevdata(sd); unsigned char write[1]; unsigned char read[1]; struct i2c_msg msgs[2] = { - { chip->c->addr, 0, 1, write }, - { chip->c->addr, I2C_M_RD, 1, read } + { c->addr, 0, 1, write }, + { c->addr, I2C_M_RD, 1, read } }; + write[0] = subaddr; - if (2 != i2c_transfer(chip->c->adapter,msgs,2)) { - v4l_warn(chip->c, "%s: I/O error (read2)\n", chip->c->name); + if (2 != i2c_transfer(c->adapter, msgs, 2)) { + v4l2_warn(sd, "I/O error (read2)\n"); return -1; } - v4l_dbg(1, debug, chip->c, "%s: chip_read2: reg%d=0x%x\n", - chip->c->name, subaddr,read[0]); + v4l2_dbg(1, debug, sd, "chip_read2: reg%d=0x%x\n", + subaddr, read[0]); return read[0]; } static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) { + struct v4l2_subdev *sd = &chip->sd; + struct i2c_client *c = v4l2_get_subdevdata(sd); int i; if (0 == cmd->count) return 0; if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) { - v4l_info(chip->c, + v4l2_info(sd, "Tried to access a non-existent register range: %d to %d\n", cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1); return -EINVAL; @@ -258,19 +270,19 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) /* FIXME: it seems that the shadow bytes are wrong bellow !*/ /* update our shadow register set; print bytes if (debug > 0) */ - v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", - chip->c->name, name,cmd->bytes[0]); + v4l2_dbg(1, debug, sd, "chip_cmd(%s): reg=%d, data:", + name, cmd->bytes[0]); for (i = 1; i < cmd->count; i++) { if (debug) - printk(" 0x%x",cmd->bytes[i]); + printk(KERN_CONT " 0x%x", cmd->bytes[i]); chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i]; } if (debug) - printk("\n"); + printk(KERN_CONT "\n"); /* send data to the chip */ - if (cmd->count != i2c_master_send(chip->c,cmd->bytes,cmd->count)) { - v4l_warn(chip->c, "%s: I/O error (%s)\n", chip->c->name, name); + if (cmd->count != i2c_master_send(c, cmd->bytes, cmd->count)) { + v4l2_warn(sd, "I/O error (%s)\n", name); return -1; } return 0; @@ -293,9 +305,10 @@ static int chip_thread(void *data) { struct CHIPSTATE *chip = data; struct CHIPDESC *desc = chip->desc; + struct v4l2_subdev *sd = &chip->sd; int mode; - v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); + v4l2_dbg(1, debug, sd, "thread started\n"); set_freezable(); for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -305,7 +318,7 @@ static int chip_thread(void *data) try_to_freeze(); if (kthread_should_stop()) break; - v4l_dbg(1, debug, chip->c, "%s: thread wakeup\n", chip->c->name); + v4l2_dbg(1, debug, sd, "thread wakeup\n"); /* don't do anything for radio or if mode != auto */ if (chip->radio || chip->mode != 0) @@ -317,8 +330,7 @@ static int chip_thread(void *data) continue; /* chip detected a new audio mode - set it */ - v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", - chip->c->name); + v4l2_dbg(1, debug, sd, "thread checkmode\n"); chip->prevmode = mode; @@ -337,7 +349,7 @@ static int chip_thread(void *data) mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); } - v4l_dbg(1, debug, chip->c, "%s: thread exiting\n", chip->c->name); + v4l2_dbg(1, debug, sd, "thread exiting\n"); return 0; } @@ -366,6 +378,7 @@ static int chip_thread(void *data) static int tda9840_getmode(struct CHIPSTATE *chip) { + struct v4l2_subdev *sd = &chip->sd; int val, mode; val = chip_read(chip); @@ -375,7 +388,7 @@ static int tda9840_getmode(struct CHIPSTATE *chip) if (val & TDA9840_ST_STEREO) mode |= V4L2_TUNER_MODE_STEREO; - v4l_dbg(1, debug, chip->c, "tda9840_getmode(): raw chip read: %d, return: %d\n", + v4l2_dbg(1, debug, sd, "tda9840_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; } @@ -671,6 +684,7 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) static int tda9873_getmode(struct CHIPSTATE *chip) { + struct v4l2_subdev *sd = &chip->sd; int val,mode; val = chip_read(chip); @@ -679,23 +693,24 @@ static int tda9873_getmode(struct CHIPSTATE *chip) mode |= V4L2_TUNER_MODE_STEREO; if (val & TDA9873_DUAL) mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; - v4l_dbg(1, debug, chip->c, "tda9873_getmode(): raw chip read: %d, return: %d\n", + v4l2_dbg(1, debug, sd, "tda9873_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; } static void tda9873_setmode(struct CHIPSTATE *chip, int mode) { + struct v4l2_subdev *sd = &chip->sd; int sw_data = chip->shadow.bytes[TDA9873_SW+1] & ~ TDA9873_TR_MASK; /* int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */ if ((sw_data & TDA9873_INP_MASK) != TDA9873_INTERNAL) { - v4l_dbg(1, debug, chip->c, "tda9873_setmode(): external input\n"); + v4l2_dbg(1, debug, sd, "tda9873_setmode(): external input\n"); return; } - v4l_dbg(1, debug, chip->c, "tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]); - v4l_dbg(1, debug, chip->c, "tda9873_setmode(): sw_data = %d\n", sw_data); + v4l2_dbg(1, debug, sd, "tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]); + v4l2_dbg(1, debug, sd, "tda9873_setmode(): sw_data = %d\n", sw_data); switch (mode) { case V4L2_TUNER_MODE_MONO: @@ -716,7 +731,7 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) } chip_write(chip, TDA9873_SW, sw_data); - v4l_dbg(1, debug, chip->c, "tda9873_setmode(): req. mode %d; chip_write: %d\n", + v4l2_dbg(1, debug, sd, "tda9873_setmode(): req. mode %d; chip_write: %d\n", mode, sw_data); } @@ -825,6 +840,8 @@ static struct tda9874a_MODES { static int tda9874a_setup(struct CHIPSTATE *chip) { + struct v4l2_subdev *sd = &chip->sd; + chip_write(chip, TDA9874A_AGCGR, 0x00); /* 0 dB */ chip_write(chip, TDA9874A_GCONR, tda9874a_GCONR); chip_write(chip, TDA9874A_MSR, (tda9874a_mode) ? 0x03:0x02); @@ -855,13 +872,14 @@ static int tda9874a_setup(struct CHIPSTATE *chip) chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80); chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */ } - v4l_dbg(1, debug, chip->c, "tda9874a_setup(): %s [0x%02X].\n", + v4l2_dbg(1, debug, sd, "tda9874a_setup(): %s [0x%02X].\n", tda9874a_modelist[tda9874a_STD].name,tda9874a_STD); return 1; } static int tda9874a_getmode(struct CHIPSTATE *chip) { + struct v4l2_subdev *sd = &chip->sd; int dsr,nsr,mode; int necr; /* just for debugging */ @@ -903,16 +921,18 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) mode |= V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; } - v4l_dbg(1, debug, chip->c, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", + v4l2_dbg(1, debug, sd, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", dsr, nsr, necr, mode); return mode; } static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) { + struct v4l2_subdev *sd = &chip->sd; + /* Disable/enable NICAM auto-muting (based on DSR.RSSF status bit). */ /* If auto-muting is disabled, we can hear a signal of degrading quality. */ - if(tda9874a_mode) { + if (tda9874a_mode) { if(chip->shadow.bytes[MAXREGS-2] & 0x20) /* DSR.RSSF=1 */ tda9874a_NCONR &= 0xfe; /* enable */ else @@ -949,7 +969,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) chip_write(chip, TDA9874A_AOSR, aosr); chip_write(chip, TDA9874A_MDACOSR, mdacosr); - v4l_dbg(1, debug, chip->c, "tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n", + v4l2_dbg(1, debug, sd, "tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n", mode, aosr, mdacosr); } else { /* dic == 0x07 */ @@ -984,13 +1004,14 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) chip_write(chip, TDA9874A_FMMR, fmmr); chip_write(chip, TDA9874A_AOSR, aosr); - v4l_dbg(1, debug, chip->c, "tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n", + v4l2_dbg(1, debug, sd, "tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n", mode, fmmr, aosr); } } static int tda9874a_checkit(struct CHIPSTATE *chip) { + struct v4l2_subdev *sd = &chip->sd; int dic,sic; /* device id. and software id. codes */ if(-1 == (dic = chip_read2(chip,TDA9874A_DIC))) @@ -998,10 +1019,10 @@ static int tda9874a_checkit(struct CHIPSTATE *chip) if(-1 == (sic = chip_read2(chip,TDA9874A_SIC))) return 0; - v4l_dbg(1, debug, chip->c, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic); + v4l2_dbg(1, debug, sd, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic); if((dic == 0x11)||(dic == 0x07)) { - v4l_info(chip->c, "found tda9874%s.\n", (dic == 0x11) ? "a":"h"); + v4l2_info(sd, "found tda9874%s.\n", (dic == 0x11) ? "a" : "h"); tda9874a_dic = dic; /* remember device id. */ return 1; } @@ -1121,12 +1142,12 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; } static int tda8425_initialize(struct CHIPSTATE *chip) { struct CHIPDESC *desc = chip->desc; + struct i2c_client *c = v4l2_get_subdevdata(&chip->sd); int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; - if (chip->c->adapter->id == I2C_HW_B_RIVA) { - memcpy (desc->inputmap, inputmap, sizeof (inputmap)); - } + if (c->adapter->id == I2C_HW_B_RIVA) + memcpy(desc->inputmap, inputmap, sizeof(inputmap)); return 0; } @@ -1223,9 +1244,11 @@ static audiocmd ta8874z_sub = {2, { TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT static void ta8874z_setmode(struct CHIPSTATE *chip, int mode) { + struct v4l2_subdev *sd = &chip->sd; int update = 1; audiocmd *t = NULL; - v4l_dbg(1, debug, chip->c, "ta8874z_setmode(): mode: 0x%02x\n", mode); + + v4l2_dbg(1, debug, sd, "ta8874z_setmode(): mode: 0x%02x\n", mode); switch(mode){ case V4L2_TUNER_MODE_MONO: @@ -1487,146 +1510,11 @@ static struct CHIPDESC chiplist[] = { /* ---------------------------------------------------------------------- */ -/* i2c registration */ -static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct CHIPSTATE *chip; - struct CHIPDESC *desc; - - if (debug) { - printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n"); - printk(KERN_INFO "tvaudio: known chips: "); - for (desc = chiplist; desc->name != NULL; desc++) - printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name); - printk("\n"); - } - - chip = kzalloc(sizeof(*chip),GFP_KERNEL); - if (!chip) - return -ENOMEM; - chip->c = client; - i2c_set_clientdata(client, chip); - - /* find description for the chip */ - v4l_dbg(1, debug, client, "chip found @ 0x%x\n", client->addr<<1); - for (desc = chiplist; desc->name != NULL; desc++) { - if (0 == *(desc->insmodopt)) - continue; - if (client->addr < desc->addr_lo || - client->addr > desc->addr_hi) - continue; - if (desc->checkit && !desc->checkit(chip)) - continue; - break; - } - if (desc->name == NULL) { - v4l_dbg(1, debug, client, "no matching chip description found\n"); - kfree(chip); - return -EIO; - } - v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); - if (desc->flags) { - v4l_dbg(1, debug, client, "matches:%s%s%s.\n", - (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "", - (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "", - (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : ""); - } - - /* fill required data structures */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - strlcpy(client->name, desc->name, I2C_NAME_SIZE); -#else - if (!id) - strlcpy(client->name, desc->name, I2C_NAME_SIZE); -#endif - chip->desc = desc; - chip->shadow.count = desc->registers+1; - chip->prevmode = -1; - chip->audmode = V4L2_TUNER_MODE_LANG1; - - /* initialization */ - if (desc->initialize != NULL) - desc->initialize(chip); - else - chip_cmd(chip,"init",&desc->init); - - if (desc->flags & CHIP_HAS_VOLUME) { - if (!desc->volfunc) { - /* This shouldn't be happen. Warn user, but keep working - without volume controls - */ - v4l_info(chip->c, "volume callback undefined!\n"); - desc->flags &= ~CHIP_HAS_VOLUME; - } else { - chip->left = desc->leftinit ? desc->leftinit : 65535; - chip->right = desc->rightinit ? desc->rightinit : 65535; - chip_write(chip, desc->leftreg, - desc->volfunc(chip->left)); - chip_write(chip, desc->rightreg, - desc->volfunc(chip->right)); - } - } - if (desc->flags & CHIP_HAS_BASSTREBLE) { - if (!desc->bassfunc || !desc->treblefunc) { - /* This shouldn't be happen. Warn user, but keep working - without bass/treble controls - */ - v4l_info(chip->c, "bass/treble callbacks undefined!\n"); - desc->flags &= ~CHIP_HAS_BASSTREBLE; - } else { - chip->treble = desc->trebleinit ? - desc->trebleinit : 32768; - chip->bass = desc->bassinit ? - desc->bassinit : 32768; - chip_write(chip, desc->bassreg, - desc->bassfunc(chip->bass)); - chip_write(chip, desc->treblereg, - desc->treblefunc(chip->treble)); - } - } - - chip->thread = NULL; - if (desc->flags & CHIP_NEED_CHECKMODE) { - if (!desc->getmode || !desc->setmode) { - /* This shouldn't be happen. Warn user, but keep working - without kthread - */ - v4l_info(chip->c, "set/get mode callbacks undefined!\n"); - return 0; - } - /* start async thread */ - init_timer(&chip->wt); - chip->wt.function = chip_thread_wake; - chip->wt.data = (unsigned long)chip; - chip->thread = kthread_run(chip_thread, chip, chip->c->name); - if (IS_ERR(chip->thread)) { - v4l_warn(chip->c, "%s: failed to create kthread\n", - chip->c->name); - chip->thread = NULL; - } - } - return 0; -} - -static int chip_remove(struct i2c_client *client) -{ - struct CHIPSTATE *chip = i2c_get_clientdata(client); - - del_timer_sync(&chip->wt); - if (chip->thread) { - /* shutdown async thread */ - kthread_stop(chip->thread); - chip->thread = NULL; - } - - kfree(chip); - return 0; -} - -static int tvaudio_get_ctrl(struct CHIPSTATE *chip, +static int tvaudio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { + struct CHIPSTATE *chip = to_state(sd); struct CHIPDESC *desc = chip->desc; switch (ctrl->id) { @@ -1664,9 +1552,10 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, return -EINVAL; } -static int tvaudio_set_ctrl(struct CHIPSTATE *chip, +static int tvaudio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { + struct CHIPSTATE *chip = to_state(sd); struct CHIPDESC *desc = chip->desc; switch (ctrl->id) { @@ -1738,161 +1627,331 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip, /* ---------------------------------------------------------------------- */ /* video4linux interface */ -static int chip_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static int tvaudio_s_radio(struct v4l2_subdev *sd) { - struct CHIPSTATE *chip = i2c_get_clientdata(client); - struct CHIPDESC *desc = chip->desc; + struct CHIPSTATE *chip = to_state(sd); - if (debug > 0) { - v4l_i2c_print_ioctl(chip->c, cmd); - printk("\n"); + chip->radio = 1; + chip->watch_stereo = 0; + /* del_timer(&chip->wt); */ + return 0; +} + +static int tvaudio_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + struct CHIPSTATE *chip = to_state(sd); + struct CHIPDESC *desc = chip->desc; + + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + break; + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BALANCE: + if (!(desc->flags & CHIP_HAS_VOLUME)) + return -EINVAL; + break; + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) + return -EINVAL; + break; + default: + return -EINVAL; + } + return v4l2_ctrl_query_fill_std(qc); +} + +static int tvaudio_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *rt) +{ + struct CHIPSTATE *chip = to_state(sd); + struct CHIPDESC *desc = chip->desc; + + if (!(desc->flags & CHIP_HAS_INPUTSEL) || rt->input >= 4) + return -EINVAL; + /* There are four inputs: tuner, radio, extern and intern. */ + chip->input = rt->input; + if (chip->muted) + return 0; + chip_write_masked(chip, desc->inputreg, + desc->inputmap[chip->input], desc->inputmask); + return 0; +} + +static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct CHIPSTATE *chip = to_state(sd); + struct CHIPDESC *desc = chip->desc; + int mode = 0; + + if (chip->radio) + return 0; + switch (vt->audmode) { + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1: + case V4L2_TUNER_MODE_LANG2: + mode = vt->audmode; + break; + case V4L2_TUNER_MODE_LANG1_LANG2: + mode = V4L2_TUNER_MODE_STEREO; + break; + default: + return -EINVAL; } + chip->audmode = vt->audmode; - switch (cmd) { - case AUDC_SET_RADIO: - chip->radio = 1; + if (desc->setmode && mode) { chip->watch_stereo = 0; /* del_timer(&chip->wt); */ - break; - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - - switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: - break; - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BALANCE: - if (!(desc->flags & CHIP_HAS_VOLUME)) - return -EINVAL; - break; - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - if (!(desc->flags & CHIP_HAS_BASSTREBLE)) - return -EINVAL; - break; - default: - return -EINVAL; - } - return v4l2_ctrl_query_fill_std(qc); + chip->mode = mode; + desc->setmode(chip, mode); } - case VIDIOC_S_CTRL: - return tvaudio_set_ctrl(chip, arg); + return 0; +} - case VIDIOC_G_CTRL: - return tvaudio_get_ctrl(chip, arg); - case VIDIOC_INT_G_AUDIO_ROUTING: - { - struct v4l2_routing *rt = arg; +static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct CHIPSTATE *chip = to_state(sd); + struct CHIPDESC *desc = chip->desc; + int mode = V4L2_TUNER_MODE_MONO; - rt->input = chip->input; - rt->output = 0; - break; + if (chip->radio) + return 0; + vt->audmode = chip->audmode; + vt->rxsubchans = 0; + vt->capability = V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; + + if (desc->getmode) + mode = desc->getmode(chip); + + if (mode & V4L2_TUNER_MODE_MONO) + vt->rxsubchans |= V4L2_TUNER_SUB_MONO; + if (mode & V4L2_TUNER_MODE_STEREO) + vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; + /* Note: for SAP it should be mono/lang2 or stereo/lang2. + When this module is converted fully to v4l2, then this + should change for those chips that can detect SAP. */ + if (mode & V4L2_TUNER_MODE_LANG1) + vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | + V4L2_TUNER_SUB_LANG2; + return 0; +} + +static int tvaudio_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct CHIPSTATE *chip = to_state(sd); + + chip->radio = 0; + return 0; +} + +static int tvaudio_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) +{ + struct CHIPSTATE *chip = to_state(sd); + struct CHIPDESC *desc = chip->desc; + + chip->mode = 0; /* automatic */ + + /* For chips that provide getmode and setmode, and doesn't + automatically follows the stereo carrier, a kthread is + created to set the audio standard. In this case, when then + the video channel is changed, tvaudio starts on MONO mode. + After waiting for 2 seconds, the kernel thread is called, + to follow whatever audio standard is pointed by the + audio carrier. + */ + if (chip->thread) { + desc->setmode(chip, V4L2_TUNER_MODE_MONO); + if (chip->prevmode != V4L2_TUNER_MODE_MONO) + chip->prevmode = -1; /* reset previous mode */ + mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); } - case VIDIOC_INT_S_AUDIO_ROUTING: - { - struct v4l2_routing *rt = arg; + return 0; +} - if (!(desc->flags & CHIP_HAS_INPUTSEL) || rt->input >= 4) - return -EINVAL; - /* There are four inputs: tuner, radio, extern and intern. */ - chip->input = rt->input; - if (chip->muted) - break; - chip_write_masked(chip, desc->inputreg, - desc->inputmap[chip->input], desc->inputmask); - break; +static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVAUDIO, 0); +} + +static int tvaudio_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops tvaudio_core_ops = { + .g_chip_ident = tvaudio_g_chip_ident, + .queryctrl = tvaudio_queryctrl, + .g_ctrl = tvaudio_g_ctrl, + .s_ctrl = tvaudio_s_ctrl, +}; + +static const struct v4l2_subdev_tuner_ops tvaudio_tuner_ops = { + .s_radio = tvaudio_s_radio, + .s_frequency = tvaudio_s_frequency, + .s_std = tvaudio_s_std, + .s_tuner = tvaudio_s_tuner, + .s_tuner = tvaudio_g_tuner, +}; + +static const struct v4l2_subdev_audio_ops tvaudio_audio_ops = { + .s_routing = tvaudio_s_routing, +}; + +static const struct v4l2_subdev_ops tvaudio_ops = { + .core = &tvaudio_core_ops, + .tuner = &tvaudio_tuner_ops, + .audio = &tvaudio_audio_ops, +}; + +/* ----------------------------------------------------------------------- */ + + +/* i2c registration */ + +static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct CHIPSTATE *chip; + struct CHIPDESC *desc; + struct v4l2_subdev *sd; + + if (debug) { + printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n"); + printk(KERN_INFO "tvaudio: known chips: "); + for (desc = chiplist; desc->name != NULL; desc++) + printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name); + printk("\n"); } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt = arg; - int mode = 0; - if (chip->radio) - break; - switch (vt->audmode) { - case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_STEREO: - case V4L2_TUNER_MODE_LANG1: - case V4L2_TUNER_MODE_LANG2: - mode = vt->audmode; - break; - case V4L2_TUNER_MODE_LANG1_LANG2: - mode = V4L2_TUNER_MODE_STEREO; - break; - default: - return -EINVAL; - } - chip->audmode = vt->audmode; + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + sd = &chip->sd; + v4l2_i2c_subdev_init(sd, client, &tvaudio_ops); - if (desc->setmode && mode) { - chip->watch_stereo = 0; - /* del_timer(&chip->wt); */ - chip->mode = mode; - desc->setmode(chip, mode); - } + /* find description for the chip */ + v4l2_dbg(1, debug, sd, "chip found @ 0x%x\n", client->addr<<1); + for (desc = chiplist; desc->name != NULL; desc++) { + if (0 == *(desc->insmodopt)) + continue; + if (client->addr < desc->addr_lo || + client->addr > desc->addr_hi) + continue; + if (desc->checkit && !desc->checkit(chip)) + continue; break; } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *vt = arg; - int mode = V4L2_TUNER_MODE_MONO; + if (desc->name == NULL) { + v4l2_dbg(1, debug, sd, "no matching chip description found\n"); + kfree(chip); + return -EIO; + } + v4l2_info(sd, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); + if (desc->flags) { + v4l2_dbg(1, debug, sd, "matches:%s%s%s.\n", + (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "", + (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "", + (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : ""); + } - if (chip->radio) - break; - vt->audmode = chip->audmode; - vt->rxsubchans = 0; - vt->capability = V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; + /* fill required data structures */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + strlcpy(client->name, desc->name, I2C_NAME_SIZE); +#else + if (!id) + strlcpy(client->name, desc->name, I2C_NAME_SIZE); +#endif + chip->desc = desc; + chip->shadow.count = desc->registers+1; + chip->prevmode = -1; + chip->audmode = V4L2_TUNER_MODE_LANG1; - if (desc->getmode) - mode = desc->getmode(chip); + /* initialization */ + if (desc->initialize != NULL) + desc->initialize(chip); + else + chip_cmd(chip, "init", &desc->init); - if (mode & V4L2_TUNER_MODE_MONO) - vt->rxsubchans |= V4L2_TUNER_SUB_MONO; - if (mode & V4L2_TUNER_MODE_STEREO) - vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; - /* Note: for SAP it should be mono/lang2 or stereo/lang2. - When this module is converted fully to v4l2, then this - should change for those chips that can detect SAP. */ - if (mode & V4L2_TUNER_MODE_LANG1) - vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | - V4L2_TUNER_SUB_LANG2; - break; + if (desc->flags & CHIP_HAS_VOLUME) { + if (!desc->volfunc) { + /* This shouldn't be happen. Warn user, but keep working + without volume controls + */ + v4l2_info(sd, "volume callback undefined!\n"); + desc->flags &= ~CHIP_HAS_VOLUME; + } else { + chip->left = desc->leftinit ? desc->leftinit : 65535; + chip->right = desc->rightinit ? desc->rightinit : 65535; + chip_write(chip, desc->leftreg, + desc->volfunc(chip->left)); + chip_write(chip, desc->rightreg, + desc->volfunc(chip->right)); + } } - case VIDIOC_S_STD: - chip->radio = 0; - break; - case VIDIOC_S_FREQUENCY: - chip->mode = 0; /* automatic */ - - /* For chips that provide getmode and setmode, and doesn't - automatically follows the stereo carrier, a kthread is - created to set the audio standard. In this case, when then - the video channel is changed, tvaudio starts on MONO mode. - After waiting for 2 seconds, the kernel thread is called, - to follow whatever audio standard is pointed by the - audio carrier. - */ - if (chip->thread) { - desc->setmode(chip,V4L2_TUNER_MODE_MONO); - if (chip->prevmode != V4L2_TUNER_MODE_MONO) - chip->prevmode = -1; /* reset previous mode */ - mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); + if (desc->flags & CHIP_HAS_BASSTREBLE) { + if (!desc->bassfunc || !desc->treblefunc) { + /* This shouldn't be happen. Warn user, but keep working + without bass/treble controls + */ + v4l2_info(sd, "bass/treble callbacks undefined!\n"); + desc->flags &= ~CHIP_HAS_BASSTREBLE; + } else { + chip->treble = desc->trebleinit ? + desc->trebleinit : 32768; + chip->bass = desc->bassinit ? + desc->bassinit : 32768; + chip_write(chip, desc->bassreg, + desc->bassfunc(chip->bass)); + chip_write(chip, desc->treblereg, + desc->treblefunc(chip->treble)); } - break; + } + + chip->thread = NULL; + if (desc->flags & CHIP_NEED_CHECKMODE) { + if (!desc->getmode || !desc->setmode) { + /* This shouldn't be happen. Warn user, but keep working + without kthread + */ + v4l2_info(sd, "set/get mode callbacks undefined!\n"); + return 0; + } + /* start async thread */ + init_timer(&chip->wt); + chip->wt.function = chip_thread_wake; + chip->wt.data = (unsigned long)chip; + chip->thread = kthread_run(chip_thread, chip, client->name); + if (IS_ERR(chip->thread)) { + v4l2_warn(sd, "failed to create kthread\n"); + chip->thread = NULL; + } + } + return 0; +} + +static int tvaudio_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct CHIPSTATE *chip = to_state(sd); - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_TVAUDIO, 0); + del_timer_sync(&chip->wt); + if (chip->thread) { + /* shutdown async thread */ + kthread_stop(chip->thread); + chip->thread = NULL; } + + v4l2_device_unregister_subdev(sd); + kfree(chip); return 0; } -static int chip_legacy_probe(struct i2c_adapter *adap) +static int tvaudio_legacy_probe(struct i2c_adapter *adap) { /* don't attach on saa7146 based cards, because dedicated drivers are used */ @@ -1907,21 +1966,21 @@ static int chip_legacy_probe(struct i2c_adapter *adap) /* This driver supports many devices and the idea is to let the driver detect which device is present. So rather than listing all supported devices here, we pretend to support a single, fake device type. */ -static const struct i2c_device_id chip_id[] = { +static const struct i2c_device_id tvaudio_id[] = { { "tvaudio", 0 }, { } }; -MODULE_DEVICE_TABLE(i2c, chip_id); +MODULE_DEVICE_TABLE(i2c, tvaudio_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tvaudio", .driverid = I2C_DRIVERID_TVAUDIO, - .command = chip_command, - .probe = chip_probe, - .remove = chip_remove, - .legacy_probe = chip_legacy_probe, + .command = tvaudio_command, + .probe = tvaudio_probe, + .remove = tvaudio_remove, + .legacy_probe = tvaudio_legacy_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - .id_table = chip_id, + .id_table = tvaudio_id, #endif }; -- cgit v1.2.3 From 7d538f92603bb1975760b0b9c0b215b8191e4f82 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:25:31 +0100 Subject: sh: sh_mobile ceu clock framework support From: Magnus Damm Add clock framework support to the sh_mobile ceu and adjust the board specific code accordingly. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt kernel-sync: --- --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index e7c5cf2a0..dfe9dc219 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -90,6 +91,7 @@ struct sh_mobile_ceu_dev { unsigned int irq; void __iomem *base; + struct clk *clk; unsigned long video_limit; /* lock used to protect videobuf */ @@ -310,6 +312,8 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) if (ret) goto err; + clk_enable(pcdev->clk); + ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ while (ceu_read(pcdev, CSTSR) & 1) msleep(1); @@ -343,6 +347,8 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) } spin_unlock_irqrestore(&pcdev->lock, flags); + clk_disable(pcdev->clk); + icd->ops->release(icd); dev_info(&icd->dev, @@ -616,6 +622,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) struct sh_mobile_ceu_dev *pcdev; struct resource *res; void __iomem *base; + char clk_name[8]; unsigned int irq; int err = 0; @@ -681,6 +688,14 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_release_mem; } + snprintf(clk_name, sizeof(clk_name), "ceu%d", pdev->id); + pcdev->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(pcdev->clk)) { + dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); + err = PTR_ERR(pcdev->clk); + goto exit_free_irq; + } + pcdev->ici.priv = pcdev; pcdev->ici.dev.parent = &pdev->dev; pcdev->ici.nr = pdev->id; @@ -689,10 +704,12 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) err = soc_camera_host_register(&pcdev->ici); if (err) - goto exit_free_irq; + goto exit_free_clk; return 0; +exit_free_clk: + clk_put(pcdev->clk); exit_free_irq: free_irq(pcdev->irq, pcdev); exit_release_mem: @@ -711,6 +728,7 @@ static int sh_mobile_ceu_remove(struct platform_device *pdev) struct sh_mobile_ceu_dev *pcdev = platform_get_drvdata(pdev); soc_camera_host_unregister(&pcdev->ici); + clk_put(pcdev->clk); free_irq(pcdev->irq, pcdev); if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) dma_release_declared_memory(&pdev->dev); -- cgit v1.2.3 From 3fa4127b747284ddb0986e285315094ffb1362c5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 16:27:28 +0100 Subject: v4l2-subdev: ioctl ops should use unsigned for cmd arg. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/msp3400-driver.c | 2 +- linux/drivers/media/video/tuner-core.c | 2 +- linux/include/media/v4l2-subdev.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index def15e381..9d2c98b82 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -488,7 +488,7 @@ static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) } #ifdef CONFIG_VIDEO_ALLOW_V4L1 -static int msp_ioctl(struct v4l2_subdev *sd, int cmd, void *arg) +static int msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct msp_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index e649f2eb7..3e674ad0e 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -806,7 +806,7 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) } #ifdef CONFIG_VIDEO_ALLOW_V4L1 -static int tuner_ioctl(struct v4l2_subdev *sd, int cmd, void *arg) +static int tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h index bca25e8ea..ceef016bb 100644 --- a/linux/include/media/v4l2-subdev.h +++ b/linux/include/media/v4l2-subdev.h @@ -79,7 +79,7 @@ struct v4l2_subdev_core_ops { int (*g_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl); int (*s_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl); int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm); - int (*ioctl)(struct v4l2_subdev *sd, int cmd, void *arg); + int (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); #ifdef CONFIG_VIDEO_ADV_DEBUG int (*g_register)(struct v4l2_subdev *sd, struct v4l2_register *reg); int (*s_register)(struct v4l2_subdev *sd, struct v4l2_register *reg); -- cgit v1.2.3 From ffcb9d5faa4646d9cc1eb76d94fb97beb14e67d7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:28:54 +0100 Subject: soc-camera: unify locking, play nicer with videobuf locking From: Guennadi Liakhovetski Move mutex from host drivers to camera device object, take into account videobuf locking. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 15 ++--- drivers/media/video/sh_mobile_ceu_camera.c | 9 +-- drivers/media/video/soc_camera.c | 99 +++++++++++++++++++++++----- include/media/soc_camera.h | 8 ++- 4 files changed, 96 insertions(+), 35 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 15 ++-- linux/drivers/media/video/sh_mobile_ceu_camera.c | 9 +-- linux/drivers/media/video/soc_camera.c | 99 ++++++++++++++++++++---- linux/include/media/soc_camera.h | 8 +- 4 files changed, 96 insertions(+), 35 deletions(-) diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index cec1a5a21..484d474b3 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -169,8 +168,6 @@ CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \ CICR0_EOFM | CICR0_FOM) -static DEFINE_MUTEX(camera_lock); - /* * Structures */ @@ -818,16 +815,17 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) return IRQ_HANDLED; } -/* The following two functions absolutely depend on the fact, that - * there can be only one camera on PXA quick capture interface */ +/* + * The following two functions absolutely depend on the fact, that + * there can be only one camera on PXA quick capture interface + * Called with .video_lock held + */ static int pxa_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; int ret; - mutex_lock(&camera_lock); - if (pcdev->icd) { ret = -EBUSY; goto ebusy; @@ -843,11 +841,10 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) pcdev->icd = icd; ebusy: - mutex_unlock(&camera_lock); - return ret; } +/* Called with .video_lock held */ static void pxa_camera_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index dfe9dc219..590955c67 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -76,8 +75,6 @@ #define CDBYR2 0x98 /* Capture data bottom-field address Y register 2 */ #define CDBCR2 0x9c /* Capture data bottom-field address C register 2 */ -static DEFINE_MUTEX(camera_lock); - /* per video frame buffer */ struct sh_mobile_ceu_buffer { struct videobuf_buffer vb; /* v4l buffer must be first */ @@ -293,14 +290,13 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) return IRQ_HANDLED; } +/* Called with .video_lock held */ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; int ret = -EBUSY; - mutex_lock(&camera_lock); - if (pcdev->icd) goto err; @@ -320,11 +316,10 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) pcdev->icd = icd; err: - mutex_unlock(&camera_lock); - return ret; } +/* Called with .video_lock held */ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 2e8f11a0d..5af588f6b 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -34,7 +34,6 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); -static DEFINE_MUTEX(video_lock); const struct soc_camera_data_format *soc_camera_format_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) @@ -271,8 +270,10 @@ static int soc_camera_open(struct inode *inode, struct file *file) if (!icf) return -ENOMEM; - /* Protect against icd->remove() until we module_get() both drivers. */ - mutex_lock(&video_lock); + /* + * It is safe to dereference these pointers now as long as a user has + * the video device open - we are protected by the held cdev reference. + */ vdev = video_devdata(file); icd = container_of(vdev->parent, struct soc_camera_device, dev); @@ -290,6 +291,9 @@ static int soc_camera_open(struct inode *inode, struct file *file) goto emgi; } + /* Protect against icd->remove() until we module_get() both drivers. */ + mutex_lock(&icd->video_lock); + icf->icd = icd; icd->use_count++; @@ -305,7 +309,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) } } - mutex_unlock(&video_lock); + mutex_unlock(&icd->video_lock); file->private_data = icf; dev_dbg(&icd->dev, "camera device open\n"); @@ -314,16 +318,16 @@ static int soc_camera_open(struct inode *inode, struct file *file) return 0; - /* All errors are entered with the video_lock held */ + /* First two errors are entered with the .video_lock held */ eiciadd: soc_camera_free_user_formats(icd); eiufmt: icd->use_count--; + mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); emgi: module_put(icd->ops->owner); emgd: - mutex_unlock(&video_lock); vfree(icf); return ret; } @@ -335,15 +339,16 @@ static int soc_camera_close(struct inode *inode, struct file *file) struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct video_device *vdev = icd->vdev; - mutex_lock(&video_lock); + mutex_lock(&icd->video_lock); icd->use_count--; if (!icd->use_count) { ici->ops->remove(icd); soc_camera_free_user_formats(icd); } + mutex_unlock(&icd->video_lock); + module_put(icd->ops->owner); module_put(ici->ops->owner); - mutex_unlock(&video_lock); vfree(icf); @@ -425,18 +430,27 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, if (ret < 0) return ret; + mutex_lock(&icf->vb_vidq.vb_lock); + + if (videobuf_queue_is_busy(&icf->vb_vidq)) { + dev_err(&icd->dev, "S_FMT denied: queue busy\n"); + ret = -EBUSY; + goto unlock; + } + rect.left = icd->x_current; rect.top = icd->y_current; rect.width = pix->width; rect.height = pix->height; ret = ici->ops->set_fmt(icd, pix->pixelformat, &rect); if (ret < 0) { - return ret; + goto unlock; } else if (!icd->current_fmt || icd->current_fmt->fourcc != pixfmt) { dev_err(&ici->dev, "Host driver hasn't set up current format correctly!\n"); - return -EINVAL; + ret = -EINVAL; + goto unlock; } icd->width = rect.width; @@ -450,7 +464,12 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, icd->width, icd->height); /* set physical bus parameters */ - return ici->ops->set_bus_param(icd, pixfmt); + ret = ici->ops->set_bus_param(icd, pixfmt); + +unlock: + mutex_unlock(&icf->vb_vidq.vb_lock); + + return ret; } static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, @@ -511,6 +530,7 @@ static int soc_camera_streamon(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + int ret; WARN_ON(priv != file->private_data); @@ -519,10 +539,16 @@ static int soc_camera_streamon(struct file *file, void *priv, if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + mutex_lock(&icd->video_lock); + icd->ops->start_capture(icd); /* This calls buf_queue from host driver's videobuf_queue_ops */ - return videobuf_streamon(&icf->vb_vidq); + ret = videobuf_streamon(&icf->vb_vidq); + + mutex_unlock(&icd->video_lock); + + return ret; } static int soc_camera_streamoff(struct file *file, void *priv, @@ -538,12 +564,16 @@ static int soc_camera_streamoff(struct file *file, void *priv, if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + mutex_lock(&icd->video_lock); + /* This calls buf_release from host driver's videobuf_queue_ops for all * remaining buffers. When the last buffer is freed, stop capture */ videobuf_streamoff(&icf->vb_vidq); icd->ops->stop_capture(icd); + mutex_unlock(&icd->video_lock); + return 0; } @@ -655,6 +685,9 @@ static int soc_camera_s_crop(struct file *file, void *fh, if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + /* Cropping is allowed during a running capture, guard consistency */ + mutex_lock(&icf->vb_vidq.vb_lock); + ret = ici->ops->set_fmt(icd, 0, &a->c); if (!ret) { icd->width = a->c.width; @@ -663,6 +696,8 @@ static int soc_camera_s_crop(struct file *file, void *fh, icd->y_current = a->c.top; } + mutex_unlock(&icf->vb_vidq.vb_lock); + return ret; } @@ -776,11 +811,32 @@ static int soc_camera_probe(struct device *dev) struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret; + /* + * Possible race scenario: + * modprobe triggers __func__ + * at this moment respective gets rmmod'ed + * to protect take module references. + */ + + if (!try_module_get(icd->ops->owner)) { + dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); + ret = -EINVAL; + goto emgd; + } + + if (!try_module_get(ici->ops->owner)) { + dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); + ret = -EINVAL; + goto emgi; + } + + mutex_lock(&icd->video_lock); + /* We only call ->add() here to activate and probe the camera. * We shall ->remove() and deactivate it immediately afterwards. */ ret = ici->ops->add(icd); if (ret < 0) - return ret; + goto eiadd; ret = icd->ops->probe(icd); if (ret >= 0) { @@ -794,6 +850,12 @@ static int soc_camera_probe(struct device *dev) } ici->ops->remove(icd); +eiadd: + mutex_unlock(&icd->video_lock); + module_put(ici->ops->owner); +emgi: + module_put(icd->ops->owner); +emgd: return ret; } @@ -967,6 +1029,7 @@ int soc_camera_device_register(struct soc_camera_device *icd) icd->dev.release = dummy_release; icd->use_count = 0; icd->host_priv = NULL; + mutex_init(&icd->video_lock); return scan_add_device(icd); } @@ -1013,6 +1076,10 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { #endif }; +/* + * Usually called from the struct soc_camera_ops .probe() method, i.e., from + * soc_camera_probe() above with .video_lock held + */ int soc_camera_video_start(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); @@ -1028,7 +1095,7 @@ int soc_camera_video_start(struct soc_camera_device *icd) dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); - /* Maybe better &ici->dev */ + vdev->parent = &icd->dev; vdev->current_norm = V4L2_STD_UNKNOWN; vdev->fops = &soc_camera_fops; @@ -1062,10 +1129,10 @@ void soc_camera_video_stop(struct soc_camera_device *icd) if (!icd->dev.parent || !vdev) return; - mutex_lock(&video_lock); + mutex_lock(&icd->video_lock); video_unregister_device(vdev); icd->vdev = NULL; - mutex_unlock(&video_lock); + mutex_unlock(&icd->video_lock); } EXPORT_SYMBOL(soc_camera_video_stop); diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 38b826c60..8bae9a359 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -12,9 +12,10 @@ #ifndef SOC_CAMERA_H #define SOC_CAMERA_H +#include +#include #include #include -#include struct soc_camera_device { struct list_head list; @@ -45,9 +46,10 @@ struct soc_camera_device { struct soc_camera_format_xlate *user_formats; int num_user_formats; struct module *owner; - void *host_priv; /* per-device host private data */ - /* soc_camera.c private count. Only accessed with video_lock held */ + void *host_priv; /* Per-device host private data */ + /* soc_camera.c private count. Only accessed with .video_lock held */ int use_count; + struct mutex video_lock; /* Protects device data */ }; struct soc_camera_file { -- cgit v1.2.3 From dc5868e91136a22b5899beae9487121c964a3666 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 16:29:07 +0100 Subject: tea6415c: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tea6415c.c | 49 ++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index 073f020fa..21900def4 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include "tea6415c.h" #include "compat.h" @@ -123,31 +123,57 @@ static int switch_matrix(struct i2c_client *client, int i, int o) return ret; } -static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg) +static int tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) { - struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; - int result = 0; + if (cmd == TEA6415C_SWITCH) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; - switch (cmd) { - case TEA6415C_SWITCH: - result = switch_matrix(client, v->in, v->out); - break; - default: - return -ENOIOCTLCMD; + return switch_matrix(client, v->in, v->out); } - return result; + return -ENOIOCTLCMD; } +static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops tea6415c_core_ops = { + .ioctl = tea6415c_ioctl, +}; + +static const struct v4l2_subdev_ops tea6415c_ops = { + .core = &tea6415c_core_ops, +}; + /* this function is called by i2c_probe */ static int tea6415c_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct v4l2_subdev *sd; + /* let's see whether this adapter can support what we need */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) return 0; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); + sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &tea6415c_ops); + return 0; +} + +static int tea6415c_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); return 0; } @@ -171,6 +197,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .driverid = I2C_DRIVERID_TEA6415C, .command = tea6415c_command, .probe = tea6415c_probe, + .remove = tea6415c_remove, .legacy_probe = tea6415c_legacy_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tea6415c_id, -- cgit v1.2.3 From 2a05d665a9177e46028b495558a77321a718a19d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 16:33:45 +0100 Subject: tea6420: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tea6420.c | 49 ++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index 8ded72ade..aee419402 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include "tea6420.h" #include "compat.h" @@ -91,26 +91,37 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) return 0; } -static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg) +static int tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) { - struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; - int result = 0; + if (cmd == TEA6420_SWITCH) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; - switch (cmd) { - case TEA6420_SWITCH: - result = tea6420_switch(client, a->in, a->out, a->gain); - break; - default: - return -ENOIOCTLCMD; + return tea6420_switch(client, a->in, a->out, a->gain); } + return -ENOIOCTLCMD; +} - return result; +static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops tea6420_core_ops = { + .ioctl = tea6420_ioctl, +}; + +static const struct v4l2_subdev_ops tea6420_ops = { + .core = &tea6420_core_ops, +}; + /* this function is called by i2c_probe */ static int tea6420_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct v4l2_subdev *sd; int err, i; /* let's see whether this adapter can support what we need */ @@ -127,9 +138,22 @@ static int tea6420_probe(struct i2c_client *client, } if (err) { v4l_dbg(1, debug, client, "could not initialize tea6420\n"); - kfree(client); return -ENODEV; } + + sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &tea6420_ops); + return 0; +} + +static int tea6420_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); return 0; } @@ -153,6 +177,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .driverid = I2C_DRIVERID_TEA6420, .command = tea6420_command, .probe = tea6420_probe, + .remove = tea6420_remove, .legacy_probe = tea6420_legacy_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tea6420_id, -- cgit v1.2.3 From 7efe1bcfe7af1611109106fb9bbf033eaa56b00b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:38:06 +0100 Subject: sh_mobile_ceu: add NV12 and NV21 support From: Magnus Damm This patch adds NV12/NV21 support to the sh_mobile_ceu driver. Signed-off-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 114 ++++++++++++++++++++++++---- 1 files changed, 99 insertions(+), 15 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 114 ++++++++++++++++++++--- 1 file changed, 99 insertions(+), 15 deletions(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 590955c67..5e7f7c381 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -97,6 +97,8 @@ struct sh_mobile_ceu_dev { struct videobuf_buffer *active; struct sh_mobile_ceu_info *pdata; + + const struct soc_camera_data_format *camera_fmt; }; static void ceu_write(struct sh_mobile_ceu_dev *priv, @@ -156,6 +158,9 @@ static void free_buffer(struct videobuf_queue *vq, static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { + struct soc_camera_device *icd = pcdev->icd; + unsigned long phys_addr; + ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~1); ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & 0x0317f313); ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | 1); @@ -164,11 +169,21 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) ceu_write(pcdev, CETCR, 0x0317f313 ^ 0x10); - if (pcdev->active) { - pcdev->active->state = VIDEOBUF_ACTIVE; - ceu_write(pcdev, CDAYR, videobuf_to_dma_contig(pcdev->active)); - ceu_write(pcdev, CAPSR, 0x1); /* start capture */ + if (!pcdev->active) + return; + + phys_addr = videobuf_to_dma_contig(pcdev->active); + ceu_write(pcdev, CDAYR, phys_addr); + + switch (icd->current_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + phys_addr += (icd->width * icd->height); + ceu_write(pcdev, CDACR, phys_addr); } + + pcdev->active->state = VIDEOBUF_ACTIVE; + ceu_write(pcdev, CAPSR, 0x1); /* start capture */ } static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, @@ -360,6 +375,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; int ret, buswidth, width, cfszr_width, cdwdr_width; unsigned long camera_flags, common_flags, value; + int yuv_mode, yuv_lineskip; camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, @@ -385,7 +401,35 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CRCNTR, 0); ceu_write(pcdev, CRCMPR, 0); - value = 0x00000010; + value = 0x00000010; /* data fetch by default */ + yuv_mode = yuv_lineskip = 0; + + switch (icd->current_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */ + yuv_mode = 1; + switch (pcdev->camera_fmt->fourcc) { + case V4L2_PIX_FMT_UYVY: + value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ + break; + case V4L2_PIX_FMT_VYUY: + value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */ + break; + case V4L2_PIX_FMT_YUYV: + value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */ + break; + case V4L2_PIX_FMT_YVYU: + value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */ + break; + default: + BUG(); + } + } + + if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21) + value ^= 0x00000100; /* swap U, V to change from NV12->NV21 */ + value |= (common_flags & SOCAM_VSYNC_ACTIVE_LOW) ? (1 << 1) : 0; value |= (common_flags & SOCAM_HSYNC_ACTIVE_LOW) ? (1 << 0) : 0; value |= (buswidth == 16) ? (1 << 12) : 0; @@ -396,16 +440,22 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, mdelay(1); - width = icd->width * (icd->current_fmt->depth / 8); - width = (buswidth == 16) ? width / 2 : width; - cfszr_width = (buswidth == 8) ? width / 2 : width; - cdwdr_width = (buswidth == 16) ? width * 2 : width; + if (yuv_mode) { + width = icd->width * 2; + width = (buswidth == 16) ? width / 2 : width; + cfszr_width = cdwdr_width = icd->width; + } else { + width = icd->width * ((icd->current_fmt->depth + 7) >> 3); + width = (buswidth == 16) ? width / 2 : width; + cfszr_width = (buswidth == 8) ? width / 2 : width; + cdwdr_width = (buswidth == 16) ? width * 2 : width; + } ceu_write(pcdev, CAMOR, 0); ceu_write(pcdev, CAPWR, (icd->height << 16) | width); - ceu_write(pcdev, CFLCR, 0); /* data fetch mode - no scaling */ + ceu_write(pcdev, CFLCR, 0); /* no scaling */ ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width); - ceu_write(pcdev, CLFCR, 0); /* data fetch mode - no lowpass filter */ + ceu_write(pcdev, CLFCR, 0); /* no lowpass filter */ /* A few words about byte order (observed in Big Endian mode) * @@ -419,14 +469,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, * using 7 we swap the data bytes to match the incoming order: * D0, D1, D2, D3, D4, D5, D6, D7 */ - ceu_write(pcdev, CDOCR, 0x00000017); + value = 0x00000017; + if (yuv_lineskip) + value &= ~0x00000010; /* convert 4:2:2 -> 4:2:0 */ + + ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CDWDR, cdwdr_width); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */ - /* in data fetch mode: no need for CDACR, CDBYR, CDBCR */ - return 0; } @@ -445,11 +497,26 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) return 0; } +static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { + { + .name = "NV12", + .depth = 12, + .fourcc = V4L2_PIX_FMT_NV12, + .colorspace = V4L2_COLORSPACE_JPEG, + }, + { + .name = "NV21", + .depth = 12, + .fourcc = V4L2_PIX_FMT_NV21, + .colorspace = V4L2_COLORSPACE_JPEG, + }, +}; + static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - int ret; + int ret, k, n; int formats = 0; ret = sh_mobile_ceu_try_bus_param(icd); @@ -457,6 +524,21 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, return 0; switch (icd->formats[idx].fourcc) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + n = ARRAY_SIZE(sh_mobile_ceu_formats); + formats += n; + for (k = 0; xlate && k < n; k++) { + xlate->host_fmt = &sh_mobile_ceu_formats[k]; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = icd->formats[idx].depth; + xlate++; + dev_dbg(&ici->dev, "Providing format %s using %s\n", + sh_mobile_ceu_formats[k].name, + icd->formats[idx].name); + } default: /* Generic pass-through */ formats++; @@ -478,6 +560,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; const struct soc_camera_format_xlate *xlate; int ret; @@ -498,6 +581,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, if (pixfmt && !ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; + pcdev->camera_fmt = xlate->cam_fmt; } return ret; -- cgit v1.2.3 From 4578c8c9e7298823a34019e02afd73d971971a37 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 18 Dec 2008 16:38:15 +0100 Subject: gspca - spca561: Control changes for Rev72a. From: Jean-Francois Moine - move the rev12a sequence from setcontrast to end of start - add the white balance control for rev72a - adjust the contrast formula Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca561.c | 141 ++++++++++++++++++------------ 1 file changed, 85 insertions(+), 56 deletions(-) diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c index ee24629f0..6114ac5f7 100644 --- a/linux/drivers/media/video/gspca/spca561.c +++ b/linux/drivers/media/video/gspca/spca561.c @@ -32,22 +32,22 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u16 contrast; /* rev72a only */ -#define CONTRAST_MIN 0x0000 -#define CONTRAST_DEF 0x2000 -#define CONTRAST_MAX 0x3fff - __u16 exposure; /* rev12a only */ #define EXPOSURE_MIN 1 #define EXPOSURE_DEF 200 #define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ + __u8 contrast; /* rev72a only */ +#define CONTRAST_MIN 0x00 +#define CONTRAST_DEF 0x20 +#define CONTRAST_MAX 0x3f + __u8 brightness; /* rev72a only */ #define BRIGHTNESS_MIN 0 -#define BRIGHTNESS_DEF 32 -#define BRIGHTNESS_MAX 63 +#define BRIGHTNESS_DEF 0x20 +#define BRIGHTNESS_MAX 0x3f - __u8 white; /* rev12a only */ + __u8 white; #define WHITE_MIN 1 #define WHITE_DEF 0x40 #define WHITE_MAX 0x7f @@ -218,10 +218,18 @@ static const __u16 rev72a_init_data[][2] = { {0x0004, 0x8612}, /* Gr offset for white balance */ {0x0007, 0x8613}, /* B offset for white balance */ {0x0000, 0x8614}, /* Gb offset for white balance */ +#if 1 +/* from ms-win */ + {0x0035, 0x8651}, /* R gain for white balance */ + {0x0040, 0x8652}, /* Gr gain for white balance */ + {0x005f, 0x8653}, /* B gain for white balance */ + {0x0040, 0x8654}, /* Gb gain for white balance */ +#else {0x008c, 0x8651}, /* R gain for white balance */ {0x008c, 0x8652}, /* Gr gain for white balance */ {0x00b5, 0x8653}, /* B gain for white balance */ {0x008c, 0x8654}, /* Gb gain for white balance */ +#endif {0x0002, 0x8502}, /* Maximum average bit rate stuff */ {0x0011, 0x8802}, @@ -591,46 +599,60 @@ static int sd_init_72a(struct gspca_dev *gspca_dev) return 0; } -static void setcontrast(struct gspca_dev *gspca_dev) +/* rev 72a only */ +static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; - __u8 lowb; + __u8 value; - switch (sd->chip_revision) { - case Rev072A: - lowb = sd->contrast >> 8; - reg_w_val(dev, 0x8651, lowb); - reg_w_val(dev, 0x8652, lowb); - reg_w_val(dev, 0x8653, lowb); - reg_w_val(dev, 0x8654, lowb); - break; - default: { -/* case Rev012A: { */ - static const __u8 Reg8391[] = - { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 }; - - memcpy(gspca_dev->usb_buf, Reg8391, 8); - reg_w_buf(gspca_dev, 0x8391, 8); - reg_w_buf(gspca_dev, 0x8390, 8); - break; - } - } + value = sd->brightness; + + /* offsets for white balance */ + reg_w_val(dev, 0x8611, value); /* R */ + reg_w_val(dev, 0x8612, value); /* Gr */ + reg_w_val(dev, 0x8613, value); /* B */ + reg_w_val(dev, 0x8614, value); /* Gb */ } -/* rev12a only */ static void setwhite(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u16 white; - __u8 reg8614, reg8616; + __u8 blue, red; + __u16 reg; - white = sd->white; /* try to emulate MS-win as possible */ - reg8616 = 0x90 - white * 5 / 8; - reg_w_val(gspca_dev->dev, 0x8616, reg8616); - reg8614 = 0x20 + white * 3 / 8; - reg_w_val(gspca_dev->dev, 0x8614, reg8614); + white = sd->white; + red = 0x20 + white * 3 / 8; + blue = 0x90 - white * 5 / 8; + if (sd->chip_revision == Rev012A) { + reg = 0x8614; + } else { + reg = 0x8651; + red += sd->contrast - 0x20; + blue += sd->contrast - 0x20; + } + reg_w_val(gspca_dev->dev, reg, red); + reg_w_val(gspca_dev->dev, reg + 2, blue); +} + +static void setcontrast(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + __u8 value; + + if (sd->chip_revision != Rev072A) + return; + value = sd->contrast + 0x20; + + /* gains for white balance */ + setwhite(gspca_dev); +/* reg_w_val(dev, 0x8651, value); * R - done by setwhite */ + reg_w_val(dev, 0x8652, value); /* Gr */ +/* reg_w_val(dev, 0x8653, value); * B - done by setwhite */ + reg_w_val(dev, 0x8654, value); /* Gb */ } /* rev 12a only */ @@ -690,9 +712,9 @@ static void setautogain(struct gspca_dev *gspca_dev) static int sd_start_12a(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; - int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ - __u8 Reg8307[] = { 0xaa, 0x00 }; int mode; + static const __u8 Reg8391[8] = + {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00}; mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; if (mode <= 1) { @@ -705,15 +727,20 @@ static int sd_start_12a(struct gspca_dev *gspca_dev) reg_w_val(dev, 0x8500, mode); } /* -- qq@kuku.eu.org */ - memcpy(gspca_dev->usb_buf, Reg8307, sizeof Reg8307); - reg_w_buf(gspca_dev, 0x8307, sizeof Reg8307); - reg_w_val(gspca_dev->dev, 0x8700, Clck); + gspca_dev->usb_buf[0] = 0xaa; + gspca_dev->usb_buf[1] = 0x00; + reg_w_buf(gspca_dev, 0x8307, 2); + /* clock - lower 0x8X values lead to fps > 30 */ + reg_w_val(gspca_dev->dev, 0x8700, 0x8a); /* 0x8f 0x85 0x27 clock */ reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); reg_w_val(gspca_dev->dev, 0x850b, 0x03); - setcontrast(gspca_dev); + memcpy(gspca_dev->usb_buf, Reg8391, 8); + reg_w_buf(gspca_dev, 0x8391, 8); + reg_w_buf(gspca_dev, 0x8390, 8); setwhite(gspca_dev); setautogain(gspca_dev); +/* setgain(gspca_dev); */ setexposure(gspca_dev); return 0; } @@ -740,6 +767,9 @@ static int sd_start_72a(struct gspca_dev *gspca_dev) reg_w_val(dev, 0x8500, mode); /* mode */ reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ reg_w_val(dev, 0x8112, 0x10 | 0x20); + setcontrast(gspca_dev); +/* setbrightness(gspca_dev); * fixme: bad values */ + setwhite(gspca_dev); setautogain(gspca_dev); return 0; } @@ -887,19 +917,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -/* rev 72a only */ -static void setbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u8 value; - - value = sd->brightness; - reg_w_val(gspca_dev->dev, 0x8611, value); - reg_w_val(gspca_dev->dev, 0x8612, value); - reg_w_val(gspca_dev->dev, 0x8613, value); - reg_w_val(gspca_dev->dev, 0x8614, value); -} - /* rev 72a only */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { @@ -956,7 +973,6 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -/* rev12a only */ static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1070,6 +1086,19 @@ static struct ctrl sd_ctrls_12a[] = { }; static struct ctrl sd_ctrls_72a[] = { + { + { + .id = V4L2_CID_DO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "White Balance", + .minimum = WHITE_MIN, + .maximum = WHITE_MAX, + .step = 1, + .default_value = WHITE_DEF, + }, + .set = sd_setwhite, + .get = sd_getwhite, + }, { { .id = V4L2_CID_BRIGHTNESS, -- cgit v1.2.3 From e8f15f9a8804dc9ff8ae2642c12cd5fbcaba4655 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 16:43:56 +0100 Subject: tlv320aic23b: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tlv320aic23b.c | 141 +++++++++++++++++++------------ 1 file changed, 87 insertions(+), 54 deletions(-) diff --git a/linux/drivers/media/video/tlv320aic23b.c b/linux/drivers/media/video/tlv320aic23b.c index a531a46d1..ecc3a4ef6 100644 --- a/linux/drivers/media/video/tlv320aic23b.c +++ b/linux/drivers/media/video/tlv320aic23b.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include "compat.h" @@ -45,15 +45,22 @@ I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ struct tlv320aic23b_state { + struct v4l2_subdev sd; u8 muted; }; -static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val) +static inline struct tlv320aic23b_state *to_state(struct v4l2_subdev *sd) { + return container_of(sd, struct tlv320aic23b_state, sd); +} + +static int tlv320aic23b_write(struct v4l2_subdev *sd, int reg, u16 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); int i; if ((reg < 0 || reg > 9) && (reg != 15)) { - v4l_err(client, "Invalid register R%d\n", reg); + v4l2_err(sd, "Invalid register R%d\n", reg); return -1; } @@ -61,61 +68,82 @@ static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val) if (i2c_smbus_write_byte_data(client, (reg << 1) | (val >> 8), val & 0xff) == 0) return 0; - v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); + v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg); return -1; } -static int tlv320aic23b_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static int tlv320aic23b_s_clock_freq(struct v4l2_subdev *sd, u32 freq) { - struct tlv320aic23b_state *state = i2c_get_clientdata(client); - struct v4l2_control *ctrl = arg; - u32 *freq = arg; - - switch (cmd) { - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - switch (*freq) { - case 32000: /* set sample rate to 32 kHz */ - tlv320aic23b_write(client, 8, 0x018); - break; - case 44100: /* set sample rate to 44.1 kHz */ - tlv320aic23b_write(client, 8, 0x022); - break; - case 48000: /* set sample rate to 48 kHz */ - tlv320aic23b_write(client, 8, 0x000); - break; - default: - return -EINVAL; - } - break; - - case VIDIOC_G_CTRL: - if (ctrl->id != V4L2_CID_AUDIO_MUTE) - return -EINVAL; - ctrl->value = state->muted; + switch (freq) { + case 32000: /* set sample rate to 32 kHz */ + tlv320aic23b_write(sd, 8, 0x018); break; - - case VIDIOC_S_CTRL: - if (ctrl->id != V4L2_CID_AUDIO_MUTE) - return -EINVAL; - state->muted = ctrl->value; - tlv320aic23b_write(client, 0, 0x180); /* mute both channels */ - /* set gain on both channels to +3.0 dB */ - if (!state->muted) - tlv320aic23b_write(client, 0, 0x119); + case 44100: /* set sample rate to 44.1 kHz */ + tlv320aic23b_write(sd, 8, 0x022); break; - - case VIDIOC_LOG_STATUS: - v4l_info(client, "Input: %s\n", - state->muted ? "muted" : "active"); + case 48000: /* set sample rate to 48 kHz */ + tlv320aic23b_write(sd, 8, 0x000); break; - default: return -EINVAL; } return 0; } +static int tlv320aic23b_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct tlv320aic23b_state *state = to_state(sd); + + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + ctrl->value = state->muted; + return 0; +} + +static int tlv320aic23b_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct tlv320aic23b_state *state = to_state(sd); + + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + state->muted = ctrl->value; + tlv320aic23b_write(sd, 0, 0x180); /* mute both channels */ + /* set gain on both channels to +3.0 dB */ + if (!state->muted) + tlv320aic23b_write(sd, 0, 0x119); + return 0; +} + +static int tlv320aic23b_log_status(struct v4l2_subdev *sd) +{ + struct tlv320aic23b_state *state = to_state(sd); + + v4l2_info(sd, "Input: %s\n", state->muted ? "muted" : "active"); + return 0; +} + +static int tlv320aic23b_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops tlv320aic23b_core_ops = { + .log_status = tlv320aic23b_log_status, + .g_ctrl = tlv320aic23b_g_ctrl, + .s_ctrl = tlv320aic23b_s_ctrl, +}; + +static const struct v4l2_subdev_audio_ops tlv320aic23b_audio_ops = { + .s_clock_freq = tlv320aic23b_s_clock_freq, +}; + +static const struct v4l2_subdev_ops tlv320aic23b_ops = { + .core = &tlv320aic23b_core_ops, + .audio = &tlv320aic23b_audio_ops, +}; + /* ----------------------------------------------------------------------- */ /* i2c implementation */ @@ -129,6 +157,7 @@ static int tlv320aic23b_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tlv320aic23b_state *state; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -137,32 +166,36 @@ static int tlv320aic23b_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &tlv320aic23b_ops); state->muted = 0; - i2c_set_clientdata(client, state); /* Initialize tlv320aic23b */ /* RESET */ - tlv320aic23b_write(client, 15, 0x000); + tlv320aic23b_write(sd, 15, 0x000); /* turn off DAC & mic input */ - tlv320aic23b_write(client, 6, 0x00A); + tlv320aic23b_write(sd, 6, 0x00A); /* left-justified, 24-bit, master mode */ - tlv320aic23b_write(client, 7, 0x049); + tlv320aic23b_write(sd, 7, 0x049); /* set gain on both channels to +3.0 dB */ - tlv320aic23b_write(client, 0, 0x119); + tlv320aic23b_write(sd, 0, 0x119); /* set sample rate to 48 kHz */ - tlv320aic23b_write(client, 8, 0x000); + tlv320aic23b_write(sd, 8, 0x000); /* activate digital interface */ - tlv320aic23b_write(client, 9, 0x001); + tlv320aic23b_write(sd, 9, 0x001); return 0; } static int tlv320aic23b_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From a9e35d7bb7815127898ada251d5f834389d1aec9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:45:33 +0100 Subject: sh_mobile_ceu: add NV16 and NV61 support From: Magnus Damm This patch adds NV16/NV61 support to the sh_mobile_ceu driver. Signed-off-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 22 ++++++++++++++++++++-- 1 files changed, 20 insertions(+), 2 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 5e7f7c381..cbb5df048 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -178,6 +178,8 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: phys_addr += (icd->width * icd->height); ceu_write(pcdev, CDACR, phys_addr); } @@ -408,6 +410,9 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */ + /* fall-through */ + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: yuv_mode = 1; switch (pcdev->camera_fmt->fourcc) { case V4L2_PIX_FMT_UYVY: @@ -427,8 +432,9 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, } } - if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21) - value ^= 0x00000100; /* swap U, V to change from NV12->NV21 */ + if ((icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21) || + (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61)) + value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */ value |= (common_flags & SOCAM_VSYNC_ACTIVE_LOW) ? (1 << 1) : 0; value |= (common_flags & SOCAM_HSYNC_ACTIVE_LOW) ? (1 << 0) : 0; @@ -510,6 +516,18 @@ static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { .fourcc = V4L2_PIX_FMT_NV21, .colorspace = V4L2_COLORSPACE_JPEG, }, + { + .name = "NV16", + .depth = 16, + .fourcc = V4L2_PIX_FMT_NV16, + .colorspace = V4L2_COLORSPACE_JPEG, + }, + { + .name = "NV61", + .depth = 16, + .fourcc = V4L2_PIX_FMT_NV61, + .colorspace = V4L2_COLORSPACE_JPEG, + }, }; static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, -- cgit v1.2.3 From b8f8d07610fc89fb72fcd5aec751febfcefa3dc7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:46:45 +0100 Subject: Add new set_std function on soc_camera From: Kuninori Morimoto This patch presents new method to be able to check v4l2_std_id Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/soc_camera.c | 9 ++++++++- include/media/soc_camera.h | 1 + 2 files changed, 9 insertions(+), 1 deletions(-) --- linux/drivers/media/video/soc_camera.c | 9 ++++++++- linux/include/media/soc_camera.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 5af588f6b..c468027fb 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -153,7 +153,14 @@ static int soc_camera_s_input(struct file *file, void *priv, unsigned int i) static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) { - return 0; + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int ret = 0; + + if (icd->ops->set_std) + ret = icd->ops->set_std(icd, a); + + return ret; } static int soc_camera_reqbufs(struct file *file, void *priv, diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 8bae9a359..26dede820 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -165,6 +165,7 @@ struct soc_camera_ops { int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*get_chip_id)(struct soc_camera_device *, struct v4l2_chip_ident *); + int (*set_std)(struct soc_camera_device *, v4l2_std_id *); #ifdef CONFIG_VIDEO_ADV_DEBUG int (*get_register)(struct soc_camera_device *, struct v4l2_register *); int (*set_register)(struct soc_camera_device *, struct v4l2_register *); -- cgit v1.2.3 From c5a56e9d9ec8b6de8effceefc806eea532a6e82b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:47:46 +0100 Subject: Add new enum_input function on soc_camera From: Kuninori Morimoto This patch presents new method to be able to select V4L2 input type Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/soc_camera.c | 17 +++++++++++++---- include/media/soc_camera.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) --- linux/drivers/media/video/soc_camera.c | 17 +++++++++++++---- linux/include/media/soc_camera.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index c468027fb..61a72f5ef 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -126,14 +126,23 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, static int soc_camera_enum_input(struct file *file, void *priv, struct v4l2_input *inp) { + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int ret = 0; + if (inp->index != 0) return -EINVAL; - inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_UNKNOWN; - strcpy(inp->name, "Camera"); + if (icd->ops->enum_input) + ret = icd->ops->enum_input(icd, inp); + else { + /* default is camera */ + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_UNKNOWN; + strcpy(inp->name, "Camera"); + } - return 0; + return ret; } static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i) diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 26dede820..50f444756 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -166,6 +166,7 @@ struct soc_camera_ops { int (*get_chip_id)(struct soc_camera_device *, struct v4l2_chip_ident *); int (*set_std)(struct soc_camera_device *, v4l2_std_id *); + int (*enum_input)(struct soc_camera_device *, struct v4l2_input *); #ifdef CONFIG_VIDEO_ADV_DEBUG int (*get_register)(struct soc_camera_device *, struct v4l2_register *); int (*set_register)(struct soc_camera_device *, struct v4l2_register *); -- cgit v1.2.3 From 9eeedf09ec91669962347e1f19db58a3f912d1dc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:50:30 +0100 Subject: video: sh_mobile_ceu cleanups and comments From: Magnus Damm This patch cleans up the sh_mobile_ceu driver and adds comments and constants to clarify the magic sequence in sh_mobile_ceu_capture(). Signed-off-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 51 ++++++++++++++++------------ 1 files changed, 29 insertions(+), 22 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 49 ++++++++++++++---------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index cbb5df048..ee606cd6b 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -102,13 +102,12 @@ struct sh_mobile_ceu_dev { }; static void ceu_write(struct sh_mobile_ceu_dev *priv, - unsigned long reg_offs, unsigned long data) + unsigned long reg_offs, u32 data) { iowrite32(data, priv->base + reg_offs); } -static unsigned long ceu_read(struct sh_mobile_ceu_dev *priv, - unsigned long reg_offs) +static u32 ceu_read(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs) { return ioread32(priv->base + reg_offs); } @@ -156,18 +155,26 @@ static void free_buffer(struct videobuf_queue *vq, buf->vb.state = VIDEOBUF_NEEDS_INIT; } +#define CEU_CETCR_MAGIC 0x0317f313 /* acknowledge magical interrupt sources */ +#define CEU_CETCR_IGRW (1 << 4) /* prohibited register access interrupt bit */ +#define CEU_CEIER_CPEIE (1 << 0) /* one-frame capture end interrupt */ +#define CEU_CAPCR_CTNCP (1 << 16) /* continuous capture mode (if set) */ + + static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { struct soc_camera_device *icd = pcdev->icd; - unsigned long phys_addr; - - ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~1); - ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & 0x0317f313); - ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | 1); + dma_addr_t phys_addr; - ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~0x10000); - - ceu_write(pcdev, CETCR, 0x0317f313 ^ 0x10); + /* The hardware is _very_ picky about this sequence. Especially + * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge + * several not-so-well documented interrupt sources in CETCR. + */ + ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_CPEIE); + ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & CEU_CETCR_MAGIC); + ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_CPEIE); + ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); + ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); if (!pcdev->active) return; @@ -180,7 +187,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - phys_addr += (icd->width * icd->height); + phys_addr += icd->width * icd->height; ceu_write(pcdev, CDACR, phys_addr); } @@ -432,13 +439,13 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, } } - if ((icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21) || - (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61)) + if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21 || + icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61) value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */ - value |= (common_flags & SOCAM_VSYNC_ACTIVE_LOW) ? (1 << 1) : 0; - value |= (common_flags & SOCAM_HSYNC_ACTIVE_LOW) ? (1 << 0) : 0; - value |= (buswidth == 16) ? (1 << 12) : 0; + value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; + value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; + value |= buswidth == 16 ? 1 << 12 : 0; ceu_write(pcdev, CAMCR, value); ceu_write(pcdev, CAPCR, 0x00300000); @@ -448,13 +455,13 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, if (yuv_mode) { width = icd->width * 2; - width = (buswidth == 16) ? width / 2 : width; + width = buswidth == 16 ? width / 2 : width; cfszr_width = cdwdr_width = icd->width; } else { width = icd->width * ((icd->current_fmt->depth + 7) >> 3); - width = (buswidth == 16) ? width / 2 : width; - cfszr_width = (buswidth == 8) ? width / 2 : width; - cdwdr_width = (buswidth == 16) ? width * 2 : width; + width = buswidth == 16 ? width / 2 : width; + cfszr_width = buswidth == 8 ? width / 2 : width; + cdwdr_width = buswidth == 16 ? width * 2 : width; } ceu_write(pcdev, CAMOR, 0); -- cgit v1.2.3 From 7c1e3aaa81179bb1423e03962dbdeae2cb9ceef3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:51:21 +0100 Subject: Add interlace support to sh_mobile_ceu_camera.c From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 56 +++++++++++++++++++++++----- 1 files changed, 46 insertions(+), 10 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 56 +++++++++++++++++++----- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index ee606cd6b..c2e8da2b8 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -95,6 +95,7 @@ struct sh_mobile_ceu_dev { spinlock_t lock; struct list_head capture; struct videobuf_buffer *active; + int is_interlace; struct sh_mobile_ceu_info *pdata; @@ -164,7 +165,7 @@ static void free_buffer(struct videobuf_queue *vq, static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { struct soc_camera_device *icd = pcdev->icd; - dma_addr_t phys_addr; + dma_addr_t phys_addr_top, phys_addr_bottom; /* The hardware is _very_ picky about this sequence. Especially * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge @@ -179,16 +180,24 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) if (!pcdev->active) return; - phys_addr = videobuf_to_dma_contig(pcdev->active); - ceu_write(pcdev, CDAYR, phys_addr); + phys_addr_top = videobuf_to_dma_contig(pcdev->active); + ceu_write(pcdev, CDAYR, phys_addr_top); + if (pcdev->is_interlace) { + phys_addr_bottom = phys_addr_top + icd->width; + ceu_write(pcdev, CDBYR, phys_addr_bottom); + } switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - phys_addr += icd->width * icd->height; - ceu_write(pcdev, CDACR, phys_addr); + phys_addr_top += icd->width * icd->height; + ceu_write(pcdev, CDACR, phys_addr_top); + if (pcdev->is_interlace) { + phys_addr_bottom = phys_addr_top + icd->width; + ceu_write(pcdev, CDBCR, phys_addr_bottom); + } } pcdev->active->state = VIDEOBUF_ACTIVE; @@ -382,7 +391,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - int ret, buswidth, width, cfszr_width, cdwdr_width; + int ret, buswidth, width, height, cfszr_width, cdwdr_width; unsigned long camera_flags, common_flags, value; int yuv_mode, yuv_lineskip; @@ -449,7 +458,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CAMCR, value); ceu_write(pcdev, CAPCR, 0x00300000); - ceu_write(pcdev, CAIFR, 0); + ceu_write(pcdev, CAIFR, (pcdev->is_interlace) ? 0x101 : 0); mdelay(1); @@ -464,10 +473,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, cdwdr_width = buswidth == 16 ? width * 2 : width; } + height = icd->height; + if (pcdev->is_interlace) { + height /= 2; + cdwdr_width *= 2; + } + ceu_write(pcdev, CAMOR, 0); - ceu_write(pcdev, CAPWR, (icd->height << 16) | width); + ceu_write(pcdev, CAPWR, (height << 16) | width); ceu_write(pcdev, CFLCR, 0); /* no scaling */ - ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width); + ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); ceu_write(pcdev, CLFCR, 0); /* no lowpass filter */ /* A few words about byte order (observed in Big Endian mode) @@ -616,8 +631,10 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; const struct soc_camera_format_xlate *xlate; __u32 pixfmt = f->fmt.pix.pixelformat; + int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { @@ -643,7 +660,26 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; /* limit to sensor capabilities */ - return icd->ops->try_fmt(icd, f); + ret = icd->ops->try_fmt(icd, f); + if (ret < 0) + return ret; + + switch (f->fmt.pix.field) { + case V4L2_FIELD_INTERLACED: + pcdev->is_interlace = 1; + break; + case V4L2_FIELD_ANY: + f->fmt.pix.field = V4L2_FIELD_NONE; + /* fall-through */ + case V4L2_FIELD_NONE: + pcdev->is_interlace = 0; + break; + default: + ret = -EINVAL; + break; + } + + return ret; } static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf, -- cgit v1.2.3 From 6f64ac25be69891e1d26e499e739acf8bb52a275 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:52:08 +0100 Subject: soc-camera: let drivers decide upon supported field values From: Guennadi Liakhovetski sh_mobile_ceu_camera.c is already prepared to support interlaced format, this patch moves the choice of a field type down to host and / or camera drivers. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 10 ++++++++++ drivers/media/video/soc_camera.c | 19 +------------------ 2 files changed, 11 insertions(+), 18 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 10 ++++++++++ linux/drivers/media/video/soc_camera.c | 19 +------------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 484d474b3..bb151032b 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1220,6 +1220,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; + enum v4l2_field field; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); @@ -1249,6 +1250,15 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, ret = icd->ops->try_fmt(icd, f); pix->pixelformat = xlate->host_fmt->fourcc; + field = pix->field; + + if (field == V4L2_FIELD_ANY) { + pix->field = V4L2_FIELD_NONE; + } else if (field != V4L2_FIELD_NONE) { + dev_err(&icd->dev, "Field type %d unsupported.\n", field); + return -EINVAL; + } + return ret; } diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 61a72f5ef..ba28c844f 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -99,28 +99,11 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - enum v4l2_field field; - int ret; WARN_ON(priv != file->private_data); - /* - * TODO: this might also have to migrate to host-drivers, if anyone - * wishes to support other fields - */ - field = f->fmt.pix.field; - - if (field == V4L2_FIELD_ANY) { - f->fmt.pix.field = V4L2_FIELD_NONE; - } else if (field != V4L2_FIELD_NONE) { - dev_err(&icd->dev, "Field type invalid.\n"); - return -EINVAL; - } - /* limit format to hardware capabilities */ - ret = ici->ops->try_fmt(icd, f); - - return ret; + return ici->ops->try_fmt(icd, f); } static int soc_camera_enum_input(struct file *file, void *priv, -- cgit v1.2.3 From da48be07e35676b79aef3eda20f9f990145bbbd8 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 16:54:33 +0100 Subject: mt9m001 mt9v022: simplify pointer derefernces From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski --- linux/drivers/media/video/mt9m001.c | 6 +++--- linux/drivers/media/video/mt9v022.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 2f431a5d6..dd1435d41 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -590,7 +590,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) return -ENODEV; /* Enable the chip */ - data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1); + data = reg_write(icd, MT9M001_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); /* Read out the chip version register */ @@ -642,8 +642,8 @@ static void mt9m001_video_remove(struct soc_camera_device *icd) struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, - mt9m001->icd.dev.parent, mt9m001->icd.vdev); - soc_camera_video_stop(&mt9m001->icd); + icd->dev.parent, icd->vdev); + soc_camera_video_stop(icd); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index ff30c99e9..e2579559d 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -766,8 +766,8 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, - mt9v022->icd.dev.parent, mt9v022->icd.vdev); - soc_camera_video_stop(&mt9v022->icd); + icd->dev.parent, icd->vdev); + soc_camera_video_stop(icd); } static int mt9v022_probe(struct i2c_client *client, -- cgit v1.2.3 From 22fd18c49b72180be0a26826a73d0db1c0b3e272 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 17:04:05 +0100 Subject: tda7432: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tda7432.c | 267 +++++++++++++++--------------------- 1 file changed, 114 insertions(+), 153 deletions(-) diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 375b8d6d2..64a90a71b 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -47,9 +47,10 @@ #include #include -#include +#include #include #include +#include #include "compat.h" #ifndef VIDEO_AUDIO_BALANCE @@ -80,6 +81,7 @@ I2C_CLIENT_INSMOD; /* Structure of address and subaddresses for the tda7432 */ struct tda7432 { + struct v4l2_subdev sd; int addr; int input; int volume; @@ -87,10 +89,12 @@ struct tda7432 { int bass, treble; int lf, lr, rf, rr; int loud; - struct i2c_client c; }; -static struct i2c_driver driver; -static struct i2c_client client_template; + +static inline struct tda7432 *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct tda7432, sd); +} /* The TDA7432 is made by STS-Thompson * http://www.st.com @@ -225,45 +229,33 @@ static struct i2c_client client_template; /* Begin code */ -static int tda7432_write(struct i2c_client *client, int subaddr, int val) +static int tda7432_write(struct v4l2_subdev *sd, int subaddr, int val) { + struct i2c_client *client = v4l2_get_subdevdata(sd); unsigned char buffer[2]; - v4l_dbg(2, debug,client,"In tda7432_write\n"); - v4l_dbg(1, debug,client,"Writing %d 0x%x\n", subaddr, val); + + v4l2_dbg(2, debug, sd, "In tda7432_write\n"); + v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n", subaddr, val); buffer[0] = subaddr; buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - v4l_err(client,"I/O error, trying (write %d 0x%x)\n", + if (2 != i2c_master_send(client, buffer, 2)) { + v4l2_err(sd, "I/O error, trying (write %d 0x%x)\n", subaddr, val); return -1; } return 0; } -/* I don't think we ever actually _read_ the chip... */ -#if 0 -static int tda7432_read(struct i2c_client *client) -{ - unsigned char buffer; - v4l_dbg(2, debug,client,"In tda7432_read\n"); - if (1 != i2c_master_recv(client,&buffer,1)) { - v4l_err(client,"I/O error, trying (read)\n"); - return -1; - } - v4l_dbg(1, debug,client,"Read 0x%02x\n", buffer); - return buffer; -} -#endif - -static int tda7432_set(struct i2c_client *client) +static int tda7432_set(struct v4l2_subdev *sd) { - struct tda7432 *t = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct tda7432 *t = to_state(sd); unsigned char buf[16]; - v4l_dbg(2, debug,client,"In tda7432_set\n"); - v4l_dbg(1, debug,client, + v4l2_dbg(1, debug, sd, "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", - t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud); + t->input, t->volume, t->bass, t->treble, t->lf, t->lr, + t->rf, t->rr, t->loud); buf[0] = TDA7432_IN; buf[1] = t->input; buf[2] = t->volume; @@ -274,18 +266,19 @@ static int tda7432_set(struct i2c_client *client) buf[7] = t->rf; buf[8] = t->rr; buf[9] = t->loud; - if (10 != i2c_master_send(client,buf,10)) { - v4l_err(client,"I/O error, trying tda7432_set\n"); + if (10 != i2c_master_send(client, buf, 10)) { + v4l2_err(sd, "I/O error, trying tda7432_set\n"); return -1; } return 0; } -static void do_tda7432_init(struct i2c_client *client) +static void do_tda7432_init(struct v4l2_subdev *sd) { - struct tda7432 *t = i2c_get_clientdata(client); - v4l_dbg(2, debug,client,"In tda7432_init\n"); + struct tda7432 *t = to_state(sd); + + v4l2_dbg(2, debug, sd, "In tda7432_init\n"); t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ TDA7432_BASS_SYM | /* Symmetric bass cut */ @@ -302,57 +295,12 @@ static void do_tda7432_init(struct i2c_client *client) t->rr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ t->loud = loudness; /* insmod parameter */ - tda7432_set(client); -} - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind) -{ - struct tda7432 *t; - struct i2c_client *client; - - t = kzalloc(sizeof *t,GFP_KERNEL); - if (!t) - return -ENOMEM; - - client = &t->c; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - i2c_set_clientdata(client, t); - - do_tda7432_init(client); - i2c_attach_client(client); - - v4l_info(client, "chip found @ 0x%x (%s)\n", addr << 1, adap->name); - return 0; -} - -static int tda7432_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, tda7432_attach); - return 0; -} - -static int tda7432_detach(struct i2c_client *client) -{ - struct tda7432 *t = i2c_get_clientdata(client); - - do_tda7432_init(client); - i2c_detach_client(client); - - kfree(t); - return 0; + tda7432_set(sd); } -static int tda7432_get_ctrl(struct i2c_client *client, - struct v4l2_control *ctrl) +static int tda7432_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct tda7432 *t = i2c_get_clientdata(client); + struct tda7432 *t = to_state(sd); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -396,10 +344,9 @@ static int tda7432_get_ctrl(struct i2c_client *client, return -EINVAL; } -static int tda7432_set_ctrl(struct i2c_client *client, - struct v4l2_control *ctrl) +static int tda7432_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct tda7432 *t = i2c_get_clientdata(client); + struct tda7432 *t = to_state(sd); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -414,7 +361,7 @@ static int tda7432_set_ctrl(struct i2c_client *client, if (loudness) /* Turn on the loudness bit */ t->volume |= TDA7432_LD_ON; - tda7432_write(client,TDA7432_VL, t->volume); + tda7432_write(sd, TDA7432_VL, t->volume); return 0; case V4L2_CID_AUDIO_BALANCE: if (ctrl->value < 32768) { @@ -442,14 +389,14 @@ static int tda7432_set_ctrl(struct i2c_client *client, if(t->bass>= 0x8) t->bass = (~t->bass & 0xf) + 0x8 ; - tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble ); + tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble); return 0; case V4L2_CID_AUDIO_TREBLE: t->treble= ctrl->value >> 12; if(t->treble>= 0x8) t->treble = (~t->treble & 0xf) + 0x8 ; - tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble ); + tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble); return 0; default: return -EINVAL; @@ -459,92 +406,106 @@ static int tda7432_set_ctrl(struct i2c_client *client, if (t->muted) { /* Mute & update balance*/ - tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE); - tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE); - tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE); - tda7432_write(client,TDA7432_RR, t->rr | TDA7432_MUTE); + tda7432_write(sd, TDA7432_LF, t->lf | TDA7432_MUTE); + tda7432_write(sd, TDA7432_LR, t->lr | TDA7432_MUTE); + tda7432_write(sd, TDA7432_RF, t->rf | TDA7432_MUTE); + tda7432_write(sd, TDA7432_RR, t->rr | TDA7432_MUTE); } else { - tda7432_write(client,TDA7432_LF, t->lf); - tda7432_write(client,TDA7432_LR, t->lr); - tda7432_write(client,TDA7432_RF, t->rf); - tda7432_write(client,TDA7432_RR, t->rr); + tda7432_write(sd, TDA7432_LF, t->lf); + tda7432_write(sd, TDA7432_LR, t->lr); + tda7432_write(sd, TDA7432_RF, t->rf); + tda7432_write(sd, TDA7432_RR, t->rr); } return 0; } -static int tda7432_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { - v4l_dbg(2, debug,client,"In tda7432_command\n"); - if (debug>1) - v4l_i2c_print_ioctl(client,cmd); - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - - switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - default: - return -EINVAL; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: return v4l2_ctrl_query_fill_std(qc); } - case VIDIOC_S_CTRL: - return tda7432_set_ctrl(client, arg); - - case VIDIOC_G_CTRL: - return tda7432_get_ctrl(client, arg); - - } /* end of (cmd) switch */ + return -EINVAL; +} - return 0; +static int tda7432_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } -static struct i2c_driver driver = { - .driver = { - .name = "tda7432", - }, - .id = I2C_DRIVERID_TDA7432, - .attach_adapter = tda7432_probe, - .detach_client = tda7432_detach, - .command = tda7432_command, +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops tda7432_core_ops = { + .queryctrl = tda7432_queryctrl, + .g_ctrl = tda7432_g_ctrl, + .s_ctrl = tda7432_s_ctrl, }; -static struct i2c_client client_template = -{ - .name = "tda7432", - .driver = &driver, +static const struct v4l2_subdev_ops tda7432_ops = { + .core = &tda7432_core_ops, }; -static int __init tda7432_init(void) +/* ----------------------------------------------------------------------- */ + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tda7432_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - if ( (loudness < 0) || (loudness > 15) ) { - printk(KERN_ERR "loudness parameter must be between 0 and 15\n"); - return -EINVAL; + struct tda7432 *t; + struct v4l2_subdev *sd; + + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (!t) + return -ENOMEM; + sd = &t->sd; + v4l2_i2c_subdev_init(sd, client, &tda7432_ops); + if (loudness < 0 || loudness > 15) { + v4l2_warn(sd, "loudness parameter must be between 0 and 15\n"); + if (loudness < 0) + loudness = 0; + if (loudness > 15) + loudness = 15; } - return i2c_add_driver(&driver); + do_tda7432_init(sd); + return 0; } -static void __exit tda7432_fini(void) +static int tda7432_remove(struct i2c_client *client) { - i2c_del_driver(&driver); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + do_tda7432_init(sd); + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); + return 0; } -module_init(tda7432_init); -module_exit(tda7432_fini); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id tda7432_id[] = { + { "tda7432", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tda7432_id); -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "tda7432", + .driverid = I2C_DRIVERID_TDA7432, + .command = tda7432_command, + .probe = tda7432_probe, + .remove = tda7432_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = tda7432_id, +#endif +}; -- cgit v1.2.3 From 104b4b757e631192d8c88e2682c0f23444522085 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 17:21:57 +0100 Subject: tda9840: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tda9840.c | 188 ++++++++++++++++++++++-------------- 1 file changed, 116 insertions(+), 72 deletions(-) diff --git a/linux/drivers/media/video/tda9840.c b/linux/drivers/media/video/tda9840.c index 31dde7516..7b749e4bb 100644 --- a/linux/drivers/media/video/tda9840.c +++ b/linux/drivers/media/video/tda9840.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include "tda9840.h" #include "compat.h" @@ -63,85 +63,89 @@ static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; -static void tda9840_write(struct i2c_client *client, u8 reg, u8 val) +static void tda9840_write(struct v4l2_subdev *sd, u8 reg, u8 val) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + if (i2c_smbus_write_byte_data(client, reg, val)) - v4l_dbg(1, debug, client, "error writing %02x to %02x\n", + v4l2_dbg(1, debug, sd, "error writing %02x to %02x\n", val, reg); } -static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) +static int tda9840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) { - int byte = *(int *)arg; - - switch (cmd) { - case VIDIOC_S_TUNER: { - struct v4l2_tuner *t = arg; - int byte; + int byte; - if (t->index) - return -EINVAL; + if (t->index) + return -EINVAL; - switch (t->audmode) { - case V4L2_TUNER_MODE_STEREO: - byte = TDA9840_SET_STEREO; - break; - case V4L2_TUNER_MODE_LANG1_LANG2: - byte = TDA9840_SET_BOTH; - break; - case V4L2_TUNER_MODE_LANG1: - byte = TDA9840_SET_LANG1; - break; - case V4L2_TUNER_MODE_LANG2: - byte = TDA9840_SET_LANG2; - break; - default: - byte = TDA9840_SET_MONO; - break; - } - v4l_dbg(1, debug, client, "TDA9840_SWITCH: 0x%02x\n", byte); - tda9840_write(client, SWITCH, byte); + switch (t->audmode) { + case V4L2_TUNER_MODE_STEREO: + byte = TDA9840_SET_STEREO; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + byte = TDA9840_SET_BOTH; + break; + case V4L2_TUNER_MODE_LANG1: + byte = TDA9840_SET_LANG1; + break; + case V4L2_TUNER_MODE_LANG2: + byte = TDA9840_SET_LANG2; + break; + default: + byte = TDA9840_SET_MONO; + break; + } + v4l2_dbg(1, debug, sd, "TDA9840_SWITCH: 0x%02x\n", byte); + tda9840_write(sd, SWITCH, byte); + return 0; +} + +static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + u8 byte; + + t->rxsubchans = V4L2_TUNER_SUB_MONO; + if (1 != i2c_master_recv(client, &byte, 1)) { + v4l2_dbg(1, debug, sd, + "i2c_master_recv() failed\n"); + return -EIO; + } + + if (byte & 0x80) { + v4l2_dbg(1, debug, sd, + "TDA9840_DETECT: register contents invalid\n"); + return -EINVAL; } - case VIDIOC_G_TUNER: { - struct v4l2_tuner *t = arg; - u8 byte; + v4l2_dbg(1, debug, sd, "TDA9840_DETECT: byte: 0x%02x\n", byte); + switch (byte & 0x60) { + case 0x00: t->rxsubchans = V4L2_TUNER_SUB_MONO; - if (1 != i2c_master_recv(client, &byte, 1)) { - v4l_dbg(1, debug, client, - "i2c_master_recv() failed\n"); - return -EIO; - } - - if (byte & 0x80) { - v4l_dbg(1, debug, client, - "TDA9840_DETECT: register contents invalid\n"); - return -EINVAL; - } - - v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte); - - switch (byte & 0x60) { - case 0x00: - t->rxsubchans = V4L2_TUNER_SUB_MONO; - break; - case 0x20: - t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - break; - case 0x40: - t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; - break; - default: /* Incorrect detect */ - t->rxsubchans = V4L2_TUNER_MODE_MONO; - break; - } + break; + case 0x20: + t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + break; + case 0x40: + t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; + break; + default: /* Incorrect detect */ + t->rxsubchans = V4L2_TUNER_MODE_MONO; break; } + return 0; +} +static int tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +{ + int byte; + + switch (cmd) { case TDA9840_LEVEL_ADJUST: - v4l_dbg(1, debug, client, "TDA9840_LEVEL_ADJUST: %d\n", byte); + byte = *(int *)arg; + v4l2_dbg(1, debug, sd, "TDA9840_LEVEL_ADJUST: %d\n", byte); /* check for correct range */ if (byte > 25 || byte < -20) @@ -153,11 +157,12 @@ static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) byte += 0x8; else byte = -byte; - tda9840_write(client, LEVEL_ADJUST, byte); + tda9840_write(sd, LEVEL_ADJUST, byte); break; case TDA9840_STEREO_ADJUST: - v4l_dbg(1, debug, client, "TDA9840_STEREO_ADJUST: %d\n", byte); + byte = *(int *)arg; + v4l2_dbg(1, debug, sd, "TDA9840_STEREO_ADJUST: %d\n", byte); /* check for correct range */ if (byte > 25 || byte < -24) @@ -170,18 +175,41 @@ static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) else byte = -byte; - tda9840_write(client, STEREO_ADJUST, byte); + tda9840_write(sd, STEREO_ADJUST, byte); break; default: return -ENOIOCTLCMD; } - return 0; } +static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops tda9840_core_ops = { + .ioctl = tda9840_ioctl, +}; + +static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = { + .s_tuner = tda9840_s_tuner, + .g_tuner = tda9840_g_tuner, +}; + +static const struct v4l2_subdev_ops tda9840_ops = { + .core = &tda9840_core_ops, + .tuner = &tda9840_tuner_ops, +}; + +/* ----------------------------------------------------------------------- */ + static int tda9840_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct v4l2_subdev *sd; int result; int byte; @@ -189,23 +217,38 @@ static int tda9840_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) - return 0; + return -EIO; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); + sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &tda9840_ops); + /* set initial values for level & stereo - adjustment, mode */ byte = 0; - result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte); - result += tda9840_command(client, TDA9840_STEREO_ADJUST, &byte); - tda9840_write(client, SWITCH, TDA9840_SET_STEREO); + result = tda9840_ioctl(sd, TDA9840_LEVEL_ADJUST, &byte); + result |= tda9840_ioctl(sd, TDA9840_STEREO_ADJUST, &byte); + tda9840_write(sd, SWITCH, TDA9840_SET_STEREO); if (result) { - v4l_dbg(1, debug, client, "could not initialize tda9840\n"); + v4l2_dbg(1, debug, sd, "could not initialize tda9840\n"); + kfree(sd); return -ENODEV; } return 0; } +static int tda9840_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); + return 0; +} + static int tda9840_legacy_probe(struct i2c_adapter *adapter) { /* Let's see whether this is a known adapter we can attach to. @@ -225,6 +268,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .driverid = I2C_DRIVERID_TDA9840, .command = tda9840_command, .probe = tda9840_probe, + .remove = tda9840_remove, .legacy_probe = tda9840_legacy_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tda9840_id, -- cgit v1.2.3 From e3ee9e96571066103d1768d9ab377dbd9c103f89 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 18 Dec 2008 17:43:45 +0100 Subject: tda9875: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tda9875.c | 354 ++++++++++++++++-------------------- 1 file changed, 156 insertions(+), 198 deletions(-) diff --git a/linux/drivers/media/video/tda9875.c b/linux/drivers/media/video/tda9875.c index 20e738264..2e72c36a9 100644 --- a/linux/drivers/media/video/tda9875.c +++ b/linux/drivers/media/video/tda9875.c @@ -25,13 +25,12 @@ #include #include #include -#include -#include #include -#include -#include "compat.h" - +#include +#include +#include #include +#include "compat.h" static int debug; /* insmod parameter */ module_param(debug, int, S_IRUGO | S_IWUSR); @@ -47,13 +46,15 @@ I2C_CLIENT_INSMOD; /* This is a superset of the TDA9875 */ struct tda9875 { + struct v4l2_subdev sd; int rvol, lvol; int bass, treble; - struct i2c_client c; }; -static struct i2c_driver driver; -static struct i2c_client client_template; +static inline struct tda9875 *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct tda9875, sd); +} #define dprintk if (debug) printk @@ -106,15 +107,16 @@ static struct i2c_client client_template; /* Begin code */ -static int tda9875_write(struct i2c_client *client, int subaddr, unsigned char val) +static int tda9875_write(struct v4l2_subdev *sd, int subaddr, unsigned char val) { + struct i2c_client *client = v4l2_get_subdevdata(sd); unsigned char buffer[2]; - dprintk("In tda9875_write\n"); - dprintk("Writing %d 0x%x\n", subaddr, val); + + v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n", subaddr, val); buffer[0] = subaddr; buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tda9875: I/O error, trying (write %d 0x%x)\n", + if (2 != i2c_master_send(client, buffer, 2)) { + v4l2_warn(sd, "I/O error, trying (write %d 0x%x)\n", subaddr, val); return -1; } @@ -135,7 +137,7 @@ static int tda9875_read(struct i2c_client *client) } #endif -static int i2c_read_register(struct i2c_adapter *adap, int addr, int reg) +static int i2c_read_register(struct i2c_client *client, int addr, int reg) { unsigned char write[1]; unsigned char read[1]; @@ -143,150 +145,83 @@ static int i2c_read_register(struct i2c_adapter *adap, int addr, int reg) { addr, 0, 1, write }, { addr, I2C_M_RD, 1, read } }; + write[0] = reg; - if (2 != i2c_transfer(adap,msgs,2)) { - printk(KERN_WARNING "tda9875: I/O error (read2)\n"); + if (2 != i2c_transfer(client->adapter, msgs, 2)) { + v4l_warn(client, "I/O error (read2)\n"); return -1; } - dprintk("tda9875: chip_read2: reg%d=0x%x\n",reg,read[0]); + v4l_dbg(1, debug, client, "chip_read2: reg%d=0x%x\n", reg, read[0]); return read[0]; } -static void tda9875_set(struct i2c_client *client) +static void tda9875_set(struct v4l2_subdev *sd) { - struct tda9875 *tda = i2c_get_clientdata(client); + struct tda9875 *tda = to_state(sd); unsigned char a; - dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n", - tda->lvol,tda->rvol,tda->bass,tda->treble); - + v4l2_dbg(1, debug, sd, "tda9875_set(%04x,%04x,%04x,%04x)\n", + tda->lvol, tda->rvol, tda->bass, tda->treble); a = tda->lvol & 0xff; - tda9875_write(client, TDA9875_MVL, a); + tda9875_write(sd, TDA9875_MVL, a); a =tda->rvol & 0xff; - tda9875_write(client, TDA9875_MVR, a); + tda9875_write(sd, TDA9875_MVR, a); a =tda->bass & 0xff; - tda9875_write(client, TDA9875_MBA, a); + tda9875_write(sd, TDA9875_MBA, a); a =tda->treble & 0xff; - tda9875_write(client, TDA9875_MTR, a); + tda9875_write(sd, TDA9875_MTR, a); } -static void do_tda9875_init(struct i2c_client *client) +static void do_tda9875_init(struct v4l2_subdev *sd) { - struct tda9875 *t = i2c_get_clientdata(client); - dprintk("In tda9875_init\n"); - tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ - tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ - tda9875_write(client, TDA9875_C1MSB, 0x00 ); /*Car1(FM) MSB XMHz*/ - tda9875_write(client, TDA9875_C1MIB, 0x00 ); /*Car1(FM) MIB XMHz*/ - tda9875_write(client, TDA9875_C1LSB, 0x00 ); /*Car1(FM) LSB XMHz*/ - tda9875_write(client, TDA9875_C2MSB, 0x00 ); /*Car2(NICAM) MSB XMHz*/ - tda9875_write(client, TDA9875_C2MIB, 0x00 ); /*Car2(NICAM) MIB XMHz*/ - tda9875_write(client, TDA9875_C2LSB, 0x00 ); /*Car2(NICAM) LSB XMHz*/ - tda9875_write(client, TDA9875_DCR, 0x00 ); /*Demod config 0x00*/ - tda9875_write(client, TDA9875_DEEM, 0x44 ); /*DE-Emph 0b0100 0100*/ - tda9875_write(client, TDA9875_FMAT, 0x00 ); /*FM Matrix reg 0x00*/ - tda9875_write(client, TDA9875_SC1, 0x00 ); /* SCART 1 (SC1)*/ - tda9875_write(client, TDA9875_SC2, 0x01 ); /* SCART 2 (sc2)*/ - - tda9875_write(client, TDA9875_CH1V, 0x10 ); /* Channel volume 1 mute*/ - tda9875_write(client, TDA9875_CH2V, 0x10 ); /* Channel volume 2 mute */ - tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/ - tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/ - tda9875_write(client, TDA9875_LOSR, 0x00 ); /* line out (in:mono)*/ - tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ - tda9875_write(client, TDA9875_MCS, 0x44 ); /* Main ch select (DAC) */ - tda9875_write(client, TDA9875_MVL, 0x03 ); /* Vol Main left 10dB */ - tda9875_write(client, TDA9875_MVR, 0x03 ); /* Vol Main right 10dB*/ - tda9875_write(client, TDA9875_MBA, 0x00 ); /* Main Bass Main 0dB*/ - tda9875_write(client, TDA9875_MTR, 0x00 ); /* Main Treble Main 0dB*/ - tda9875_write(client, TDA9875_ACS, 0x44 ); /* Aux chan select (dac)*/ - tda9875_write(client, TDA9875_AVL, 0x00 ); /* Vol Aux left 0dB*/ - tda9875_write(client, TDA9875_AVR, 0x00 ); /* Vol Aux right 0dB*/ - tda9875_write(client, TDA9875_ABA, 0x00 ); /* Aux Bass Main 0dB*/ - tda9875_write(client, TDA9875_ATR, 0x00 ); /* Aux Aigus Main 0dB*/ - - tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */ - - t->lvol=t->rvol =0; /* 0dB */ - t->bass=0; /* 0dB */ - t->treble=0; /* 0dB */ - tda9875_set(client); - -} - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda9875_checkit(struct i2c_adapter *adap, int addr) -{ - int dic,rev; - - dic=i2c_read_register(adap,addr,254); - rev=i2c_read_register(adap,addr,255); - - if(dic==0 || dic==2) { // tda9875 and tda9875A - printk("tda9875: TDA9875%s Rev.%d detected at 0x%x\n", - dic==0?"":"A", rev,addr<<1); - return 1; - } - printk("tda9875: no such chip at 0x%x (dic=0x%x rev=0x%x)\n",addr<<1,dic,rev); - return(0); + struct tda9875 *t = to_state(sd); + + v4l2_dbg(1, debug, sd, "In tda9875_init\n"); + tda9875_write(sd, TDA9875_CFG, 0xd0); /*reg de config 0 (reset)*/ + tda9875_write(sd, TDA9875_MSR, 0x03); /* Monitor 0b00000XXX*/ + tda9875_write(sd, TDA9875_C1MSB, 0x00); /*Car1(FM) MSB XMHz*/ + tda9875_write(sd, TDA9875_C1MIB, 0x00); /*Car1(FM) MIB XMHz*/ + tda9875_write(sd, TDA9875_C1LSB, 0x00); /*Car1(FM) LSB XMHz*/ + tda9875_write(sd, TDA9875_C2MSB, 0x00); /*Car2(NICAM) MSB XMHz*/ + tda9875_write(sd, TDA9875_C2MIB, 0x00); /*Car2(NICAM) MIB XMHz*/ + tda9875_write(sd, TDA9875_C2LSB, 0x00); /*Car2(NICAM) LSB XMHz*/ + tda9875_write(sd, TDA9875_DCR, 0x00); /*Demod config 0x00*/ + tda9875_write(sd, TDA9875_DEEM, 0x44); /*DE-Emph 0b0100 0100*/ + tda9875_write(sd, TDA9875_FMAT, 0x00); /*FM Matrix reg 0x00*/ + tda9875_write(sd, TDA9875_SC1, 0x00); /* SCART 1 (SC1)*/ + tda9875_write(sd, TDA9875_SC2, 0x01); /* SCART 2 (sc2)*/ + + tda9875_write(sd, TDA9875_CH1V, 0x10); /* Channel volume 1 mute*/ + tda9875_write(sd, TDA9875_CH2V, 0x10); /* Channel volume 2 mute */ + tda9875_write(sd, TDA9875_DACOS, 0x02); /* sig DAC i/o(in:nicam)*/ + tda9875_write(sd, TDA9875_ADCIS, 0x6f); /* sig ADC input(in:mono)*/ + tda9875_write(sd, TDA9875_LOSR, 0x00); /* line out (in:mono)*/ + tda9875_write(sd, TDA9875_AER, 0x00); /*06 Effect (AVL+PSEUDO) */ + tda9875_write(sd, TDA9875_MCS, 0x44); /* Main ch select (DAC) */ + tda9875_write(sd, TDA9875_MVL, 0x03); /* Vol Main left 10dB */ + tda9875_write(sd, TDA9875_MVR, 0x03); /* Vol Main right 10dB*/ + tda9875_write(sd, TDA9875_MBA, 0x00); /* Main Bass Main 0dB*/ + tda9875_write(sd, TDA9875_MTR, 0x00); /* Main Treble Main 0dB*/ + tda9875_write(sd, TDA9875_ACS, 0x44); /* Aux chan select (dac)*/ + tda9875_write(sd, TDA9875_AVL, 0x00); /* Vol Aux left 0dB*/ + tda9875_write(sd, TDA9875_AVR, 0x00); /* Vol Aux right 0dB*/ + tda9875_write(sd, TDA9875_ABA, 0x00); /* Aux Bass Main 0dB*/ + tda9875_write(sd, TDA9875_ATR, 0x00); /* Aux Aigus Main 0dB*/ + + tda9875_write(sd, TDA9875_MUT, 0xcc); /* General mute */ + + t->lvol = t->rvol = 0; /* 0dB */ + t->bass = 0; /* 0dB */ + t->treble = 0; /* 0dB */ + tda9875_set(sd); } -static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind) -{ - struct tda9875 *t; - struct i2c_client *client; - dprintk("In tda9875_attach\n"); - - t = kzalloc(sizeof *t,GFP_KERNEL); - if (!t) - return -ENOMEM; - - client = &t->c; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - i2c_set_clientdata(client, t); - - if(!tda9875_checkit(adap,addr)) { - kfree(t); - return 1; - } - - do_tda9875_init(client); - printk(KERN_INFO "tda9875: init\n"); - - i2c_attach_client(client); - return 0; -} - -static int tda9875_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, tda9875_attach); - return 0; -} - -static int tda9875_detach(struct i2c_client *client) -{ - struct tda9875 *t = i2c_get_clientdata(client); - - do_tda9875_init(client); - i2c_detach_client(client); - - kfree(t); - return 0; -} -static int tda9875_get_ctrl(struct i2c_client *client, - struct v4l2_control *ctrl) +static int tda9875_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct tda9875 *t = i2c_get_clientdata(client); + struct tda9875 *t = to_state(sd); switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -318,10 +253,9 @@ static int tda9875_get_ctrl(struct i2c_client *client, return -EINVAL; } -static int tda9875_set_ctrl(struct i2c_client *client, - struct v4l2_control *ctrl) +static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct tda9875 *t = i2c_get_clientdata(client); + struct tda9875 *t = to_state(sd); int chvol=0, volume, balance, left, right; switch (ctrl->id) { @@ -385,85 +319,109 @@ static int tda9875_set_ctrl(struct i2c_client *client, t->rvol = -84 & 0xff; } -//printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); - - tda9875_set(client); - + tda9875_set(sd); return 0; } - -static int tda9875_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static int tda9875_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { - dprintk("In tda9875_command...\n"); - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - - switch (qc->id) { - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - default: - return -EINVAL; - } + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: return v4l2_ctrl_query_fill_std(qc); } - case VIDIOC_S_CTRL: - return tda9875_set_ctrl(client, arg); + return -EINVAL; +} - case VIDIOC_G_CTRL: - return tda9875_get_ctrl(client, arg); +static int tda9875_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} - default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ +/* ----------------------------------------------------------------------- */ - /* nothing */ - dprintk("Default\n"); +static const struct v4l2_subdev_core_ops tda9875_core_ops = { + .queryctrl = tda9875_queryctrl, + .g_ctrl = tda9875_g_ctrl, + .s_ctrl = tda9875_s_ctrl, +}; - } /* end of (cmd) switch */ +static const struct v4l2_subdev_ops tda9875_ops = { + .core = &tda9875_core_ops, +}; - return 0; -} +/* ----------------------------------------------------------------------- */ -static struct i2c_driver driver = { - .driver = { - .name = "tda9875", - }, - .id = I2C_DRIVERID_TDA9875, - .attach_adapter = tda9875_probe, - .detach_client = tda9875_detach, - .command = tda9875_command, -}; +/* *********************** * + * i2c interface functions * + * *********************** */ -static struct i2c_client client_template = +static int tda9875_checkit(struct i2c_client *client, int addr) { - .name = "tda9875", - .driver = &driver, -}; + int dic, rev; -static int __init tda9875_init(void) -{ - return i2c_add_driver(&driver); + dic = i2c_read_register(client, addr, 254); + rev = i2c_read_register(client, addr, 255); + + if (dic == 0 || dic == 2) { /* tda9875 and tda9875A */ + v4l_info(client, "tda9875%s rev. %d detected at 0x%02x\n", + dic == 0 ? "" : "A", rev, addr << 1); + return 1; + } + v4l_info(client, "no such chip at 0x%02x (dic=0x%x rev=0x%x)\n", + addr << 1, dic, rev); + return 0; } -static void __exit tda9875_fini(void) +static int tda9875_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - i2c_del_driver(&driver); + struct tda9875 *t; + struct v4l2_subdev *sd; + + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + + if (!tda9875_checkit(client, client->addr)) + return -ENODEV; + + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (!t) + return -ENOMEM; + sd = &t->sd; + v4l2_i2c_subdev_init(sd, client, &tda9875_ops); + + do_tda9875_init(sd); + return 0; } -module_init(tda9875_init); -module_exit(tda9875_fini); +static int tda9875_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ + do_tda9875_init(sd); + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); + return 0; +} +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id tda9875_id[] = { + { "tda9875", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tda9875_id); + +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "tda9875", + .driverid = I2C_DRIVERID_TDA9875, + .command = tda9875_command, + .probe = tda9875_probe, + .remove = tda9875_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = tda9875_id, +#endif +}; -- cgit v1.2.3 From 20108169e5e7867849b55fe31f273430cf57d3f7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Dec 2008 17:50:40 +0100 Subject: Change V4L2 field to ANY from NONE on sh_mobile_ceu_camera.c From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index c2e8da2b8..ae98eaf5f 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -738,7 +738,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, &sh_mobile_ceu_videobuf_ops, &ici->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_NONE, + V4L2_FIELD_ANY, sizeof(struct sh_mobile_ceu_buffer), icd); } -- cgit v1.2.3 From 0dcfe92792332632804c76a55c66d2555e1fc728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Fri, 19 Dec 2008 07:29:31 +0100 Subject: Add vflip quirk for Alienware m9700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 6531f46e8..115529f41 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -60,6 +60,13 @@ static DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt") } }, + { + .ident = "Alienware Aurora m9700", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700") + } + }, { } }; -- cgit v1.2.3 From 5001dbc132aae3d583ec070cfd2f8382f383cec5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Dec 2008 11:07:56 +0100 Subject: tuner: fix tuner_ioctl compile error if V4L1 ioctls are disabled. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tuner-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index e649f2eb7..74a7402f2 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -1118,7 +1118,9 @@ static int tuner_resume(struct i2c_client *c) static const struct v4l2_subdev_core_ops tuner_core_ops = { .log_status = tuner_log_status, .s_standby = tuner_s_standby, +#ifdef CONFIG_VIDEO_ALLOW_V4L1 .ioctl = tuner_ioctl, +#endif }; static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { -- cgit v1.2.3 From cdd1295a9bfd3f1f39ba27702a1428a2a4691b19 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Dec 2008 11:18:38 +0100 Subject: bt832: remove this driver From: Hans Verkuil The bt832 i2c driver was never used or even compiled and is no longer maintained. It is now removed completely. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/bt832.c | 287 ------------------------- linux/drivers/media/video/bt8xx/bt832.h | 305 --------------------------- linux/drivers/media/video/bt8xx/bttv-cards.c | 45 ---- linux/include/media/i2c-addr.h | 2 - v4l/scripts/release.sh | 2 +- 5 files changed, 1 insertion(+), 640 deletions(-) delete mode 100644 linux/drivers/media/video/bt8xx/bt832.c delete mode 100644 linux/drivers/media/video/bt8xx/bt832.h diff --git a/linux/drivers/media/video/bt8xx/bt832.c b/linux/drivers/media/video/bt8xx/bt832.c deleted file mode 100644 index b677916bf..000000000 --- a/linux/drivers/media/video/bt8xx/bt832.c +++ /dev/null @@ -1,287 +0,0 @@ -/* Driver for Bt832 CMOS Camera Video Processor - i2c-addresses: 0x88 or 0x8a - - The BT832 interfaces to a Quartzsight Digital Camera (352x288, 25 or 30 fps) - via a 9 pin connector ( 4-wire SDATA, 2-wire i2c, SCLK, VCC, GND). - It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly - connected to bt848/bt878 GPIO pins on this purpose. - (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets) - - Supported Cards: - - Pixelview Rev.4E: 0x8a - GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 ! - - (c) Gunther Mayer, 2002 - - STATUS: - - detect chip and hexdump - - reset chip and leave low power mode - - detect camera present - - TODO: - - make it work (find correct setup for Bt832 and Bt878) -*/ - -#include -#include -#include -#include -#include "compat.h" -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "bt832.h" - -MODULE_LICENSE("GPL"); - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_ADDR_BT832_ALT1>>1, I2C_ADDR_BT832_ALT2>>1, - I2C_CLIENT_END }; -I2C_CLIENT_INSMOD; - -int debug; /* debug output */ -module_param(debug, int, 0644); - -/* ---------------------------------------------------------------------- */ - -static int bt832_detach(struct i2c_client *client); - - -static struct i2c_driver driver; -static struct i2c_client client_template; - -struct bt832 { - struct i2c_client client; -}; - -int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf) -{ - int i,rc; - buf[0]=0x80; // start at register 0 with auto-increment - if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) - v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 1)\n",rc); - - for(i=0;i<65;i++) - buf[i]=0; - if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) - v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 65)\n",rc); - - // Note: On READ the first byte is the current index - // (e.g. 0x80, what we just wrote) - - if(debug>1) { - int i; - v4l_dbg(2, debug,i2c_client_s,"hexdump:"); - for(i=1;i<65;i++) { - if(i!=1) { - if(((i-1)%8)==0) printk(" "); - if(((i-1)%16)==0) { - printk("\n"); - v4l_dbg(2, debug,i2c_client_s,"hexdump:"); - } - } - printk(" %02x",buf[i]); - } - printk("\n"); - } - return 0; -} - -// Return: 1 (is a bt832), 0 (No bt832 here) -int bt832_init(struct i2c_client *i2c_client_s) -{ - unsigned char *buf; - int rc; - - buf=kmalloc(65,GFP_KERNEL); - if (!buf) { - v4l_err(&t->client, - "Unable to allocate memory. Detaching.\n"); - return 0; - } - bt832_hexdump(i2c_client_s,buf); - - if(buf[0x40] != 0x31) { - v4l_err(i2c_client_s,"This i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); - kfree(buf); - return 0; - } - - v4l_err(i2c_client_s,"Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); - - - // Leave low power mode: - v4l_err(i2c_client_s,"leave low power mode.\n"); - buf[0]=BT832_CAM_SETUP0; //0x39 57 - buf[1]=0x08; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error LLPM: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); - - v4l_info(i2c_client_s,"Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); - - - // Enable Output - v4l_info(i2c_client_s,"Enable Output\n"); - buf[0]=BT832_VP_CONTROL1; // Reg.40 - buf[1]= 0x27 & (~0x01); // Default | !skip - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error EO: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); - -#if 0 - // Full 30/25 Frame rate - v4l_err(i2c_client_s,"Full 30/25 Frame rate\n"); - buf[0]=BT832_VP_CONTROL0; // Reg.39 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error FFR: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); -#endif - -#if 1 - // for testing (even works when no camera attached) - v4l_info(i2c_client_s,"*** Generate NTSC M Bars *****\n"); - buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42 - buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_info(i2c_client_s,"i2c i/o error MBAR: rc == %d (should be 2)\n",rc); -#endif - - v4l_info(i2c_client_s,"Camera Present: %s\n", - (buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no"); - - bt832_hexdump(i2c_client_s,buf); - kfree(buf); - return 1; -} - - - -static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) -{ - struct bt832 *t; - - client_template.adapter = adap; - client_template.addr = addr; - - if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; - t->client = client_template; - i2c_set_clientdata(&t->client, t); - i2c_attach_client(&t->client); - - v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1); - - if(! bt832_init(&t->client)) { - bt832_detach(&t->client); - return -1; - } - - return 0; -} - -static int bt832_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, bt832_attach); - return 0; -} - -static int bt832_detach(struct i2c_client *client) -{ - struct bt832 *t = i2c_get_clientdata(client); - - v4l_info(&t->client,"dettach\n"); - i2c_detach_client(client); - kfree(t); - return 0; -} - -static int -bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct bt832 *t = i2c_get_clientdata(client); - - if (debug>1) - v4l_i2c_print_ioctl(&t->client,cmd); - - switch (cmd) { - case BT832_HEXDUMP: { - unsigned char *buf; - buf = kmalloc(65, GFP_KERNEL); - if (!buf) { - v4l_err(&t->client, - "Unable to allocate memory\n"); - break; - } - bt832_hexdump(&t->client,buf); - kfree(buf); - } - break; - case BT832_REATTACH: - v4l_info(&t->client,"re-attach\n"); - i2c_del_driver(&driver); - i2c_add_driver(&driver); - break; - } - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static struct i2c_driver driver = { - .driver = { - .name = "bt832", - }, - .id = 0, /* FIXME */ - .attach_adapter = bt832_probe, - .detach_client = bt832_detach, - .command = bt832_command, -}; -static struct i2c_client client_template = -{ - .name = "bt832", - .driver = &driver, -}; - - -static int __init bt832_init_module(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit bt832_cleanup_module(void) -{ - i2c_del_driver(&driver); -} - -module_init(bt832_init_module); -module_exit(bt832_cleanup_module); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/linux/drivers/media/video/bt8xx/bt832.h b/linux/drivers/media/video/bt8xx/bt832.h deleted file mode 100644 index 1ce8fa71f..000000000 --- a/linux/drivers/media/video/bt8xx/bt832.h +++ /dev/null @@ -1,305 +0,0 @@ -/* Bt832 CMOS Camera Video Processor (VP) - - The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS - color digital camera directly to video capture devices via an 8-bit, - 4:2:2 YUV or YCrCb video interface. - - i2c addresses: 0x88 or 0x8a - */ - -/* The 64 registers: */ - -// Input Processor -#define BT832_OFFSET 0 -#define BT832_RCOMP 1 -#define BT832_G1COMP 2 -#define BT832_G2COMP 3 -#define BT832_BCOMP 4 -// Exposures: -#define BT832_FINEH 5 -#define BT832_FINEL 6 -#define BT832_COARSEH 7 -#define BT832_COARSEL 8 -#define BT832_CAMGAIN 9 -// Main Processor: -#define BT832_M00 10 -#define BT832_M01 11 -#define BT832_M02 12 -#define BT832_M10 13 -#define BT832_M11 14 -#define BT832_M12 15 -#define BT832_M20 16 -#define BT832_M21 17 -#define BT832_M22 18 -#define BT832_APCOR 19 -#define BT832_GAMCOR 20 -// Level Accumulator Inputs -#define BT832_VPCONTROL2 21 -#define BT832_ZONECODE0 22 -#define BT832_ZONECODE1 23 -#define BT832_ZONECODE2 24 -#define BT832_ZONECODE3 25 -// Level Accumulator Outputs: -#define BT832_RACC 26 -#define BT832_GACC 27 -#define BT832_BACC 28 -#define BT832_BLACKACC 29 -#define BT832_EXP_AGC 30 -#define BT832_LACC0 31 -#define BT832_LACC1 32 -#define BT832_LACC2 33 -#define BT832_LACC3 34 -#define BT832_LACC4 35 -#define BT832_LACC5 36 -#define BT832_LACC6 37 -#define BT832_LACC7 38 -// System: -#define BT832_VP_CONTROL0 39 -#define BT832_VP_CONTROL1 40 -#define BT832_THRESH 41 -#define BT832_VP_TESTCONTROL0 42 -#define BT832_VP_DMCODE 43 -#define BT832_ACB_CONFIG 44 -#define BT832_ACB_GNBASE 45 -#define BT832_ACB_MU 46 -#define BT832_CAM_TEST0 47 -#define BT832_AEC_CONFIG 48 -#define BT832_AEC_TL 49 -#define BT832_AEC_TC 50 -#define BT832_AEC_TH 51 -// Status: -#define BT832_VP_STATUS 52 -#define BT832_VP_LINECOUNT 53 -#define BT832_CAM_DEVICEL 54 // e.g. 0x19 -#define BT832_CAM_DEVICEH 55 // e.g. 0x40 == 0x194 Mask0, 0x194 = 404 decimal (VVL-404 camera) -#define BT832_CAM_STATUS 56 - #define BT832_56_CAMERA_PRESENT 0x20 -//Camera Setups: -#define BT832_CAM_SETUP0 57 -#define BT832_CAM_SETUP1 58 -#define BT832_CAM_SETUP2 59 -#define BT832_CAM_SETUP3 60 -// System: -#define BT832_DEFCOR 61 -#define BT832_VP_TESTCONTROL1 62 -#define BT832_DEVICE_ID 63 -# define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31 - -/* STMicroelectronivcs VV5404 camera module - i2c: 0x20: sensor address - i2c: 0xa0: eeprom for ccd defect map - */ -#define VV5404_device_h 0x00 // 0x19 -#define VV5404_device_l 0x01 // 0x40 -#define VV5404_status0 0x02 -#define VV5404_linecountc 0x03 // current line counter -#define VV5404_linecountl 0x04 -#define VV5404_setup0 0x10 -#define VV5404_setup1 0x11 -#define VV5404_setup2 0x12 -#define VV5404_setup4 0x14 -#define VV5404_setup5 0x15 -#define VV5404_fine_h 0x20 // fine exposure -#define VV5404_fine_l 0x21 -#define VV5404_coarse_h 0x22 //coarse exposure -#define VV5404_coarse_l 0x23 -#define VV5404_gain 0x24 // ADC pre-amp gain setting -#define VV5404_clk_div 0x25 -#define VV5404_cr 0x76 // control register -#define VV5404_as0 0x77 // ADC setup register - - -// IOCTL -#define BT832_HEXDUMP _IOR('b',1,int) -#define BT832_REATTACH _IOR('b',2,int) - -/* from BT8x8VXD/capdrv/dialogs.cpp */ - -/* -typedef enum { SVI, Logitech, Rockwell } CAMERA; - -static COMBOBOX_ENTRY gwCameraOptions[] = -{ - { SVI, "Silicon Vision 512N" }, - { Logitech, "Logitech VideoMan 1.3" }, - { Rockwell, "Rockwell QuartzSight PCI 1.0" } -}; - -// SRAM table values -//=========================================================================== -typedef enum { TGB_NTSC624, TGB_NTSC780, TGB_NTSC858, TGB_NTSC392 } TimeGenByte; - -BYTE SRAMTable[][ 60 ] = -{ - // TGB_NTSC624 - { - 0x33, // size of table = 51 - 0x0E, 0xC0, 0x00, 0x00, 0x90, 0x02, 0x03, 0x10, 0x03, 0x06, - 0x10, 0x04, 0x12, 0x12, 0x05, 0x02, 0x13, 0x04, 0x19, 0x00, - 0x04, 0x39, 0x00, 0x06, 0x59, 0x08, 0x03, 0x85, 0x08, 0x07, - 0x03, 0x50, 0x00, 0x91, 0x40, 0x00, 0x11, 0x01, 0x01, 0x4D, - 0x0D, 0x02, 0x03, 0x11, 0x01, 0x05, 0x37, 0x00, 0x37, 0x21, 0x00 - }, - // TGB_NTSC780 - { - 0x33, // size of table = 51 - 0x0e, 0xc0, 0x00, 0x00, 0x90, 0xe2, 0x03, 0x10, 0x03, 0x06, - 0x10, 0x34, 0x12, 0x12, 0x65, 0x02, 0x13, 0x24, 0x19, 0x00, - 0x24, 0x39, 0x00, 0x96, 0x59, 0x08, 0x93, 0x85, 0x08, 0x97, - 0x03, 0x50, 0x50, 0xaf, 0x40, 0x30, 0x5f, 0x01, 0xf1, 0x7f, - 0x0d, 0xf2, 0x03, 0x11, 0xf1, 0x05, 0x37, 0x30, 0x85, 0x21, 0x50 - }, - // TGB_NTSC858 - { - 0x33, // size of table = 51 - 0x0c, 0xc0, 0x00, 0x00, 0x90, 0xc2, 0x03, 0x10, 0x03, 0x06, - 0x10, 0x34, 0x12, 0x12, 0x65, 0x02, 0x13, 0x24, 0x19, 0x00, - 0x24, 0x39, 0x00, 0x96, 0x59, 0x08, 0x93, 0x83, 0x08, 0x97, - 0x03, 0x50, 0x30, 0xc0, 0x40, 0x30, 0x86, 0x01, 0x01, 0xa6, - 0x0d, 0x62, 0x03, 0x11, 0x61, 0x05, 0x37, 0x30, 0xac, 0x21, 0x50 - }, - // TGB_NTSC392 - // This table has been modified to be used for Fusion Rev D - { - 0x2A, // size of table = 42 - 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24, - 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10, - 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00, - 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3, - 0x20, 0x00 - } -}; - -//=========================================================================== -// This is the structure of the camera specifications -//=========================================================================== -typedef struct tag_cameraSpec -{ - SignalFormat signal; // which digital signal format the camera has - VideoFormat vidFormat; // video standard - SyncVideoRef syncRef; // which sync video reference is used - State syncOutput; // enable sync output for sync video input? - DecInputClk iClk; // which input clock is used - TimeGenByte tgb; // which timing generator byte does the camera use - int HReset; // select 64, 48, 32, or 16 CLKx1 for HReset - PLLFreq pllFreq; // what synthesized frequency to set PLL to - VSIZEPARMS vSize; // video size the camera produces - int lineCount; // expected total number of half-line per frame - 1 - BOOL interlace; // interlace signal? -} CameraSpec; - -//=========================================================================== -// -// Camera specifications database. Update this table whenever camera spec -// has been changed or added/deleted supported camera models -//=========================================================================== -static CameraSpec dbCameraSpec[ N_CAMERAOPTIONS ] = -{ // Silicon Vision 512N - { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC624, 64, KHz19636, - // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace - { 512, 0x64, 480, 0x13, 240 }, 0, TRUE - }, - // Logitech VideoMan 1.3 - { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC780, 64, KHz24545, - // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace - { 640, 0x80, 480, 0x1A, 240 }, 0, TRUE - }, - // Rockwell QuartzSight - // Note: Fusion Rev D (rev ID 0x02) and later supports 16 pixels for HReset which is preferable. - // Use 32 for earlier version of hardware. Clkx1_HDELAY also changed from 0x27 to 0x20. - { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC392, 16, KHz28636, - // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace - { 352, 0x20, 576, 0x08, 288 }, 607, FALSE - } -}; -*/ - -/* -The corresponding APIs required to be invoked are: -SetConnector( ConCamera, TRUE/FALSE ); -SetSignalFormat( spec.signal ); -SetVideoFormat( spec.vidFormat ); -SetSyncVideoRef( spec.syncRef ); -SetEnableSyncOutput( spec.syncOutput ); -SetTimGenByte( SRAMTable[ spec.tgb ], SRAMTableSize[ spec.tgb ] ); -SetHReset( spec.HReset ); -SetPLL( spec.pllFreq ); -SetDecInputClock( spec.iClk ); -SetVideoInfo( spec.vSize ); -SetTotalLineCount( spec.lineCount ); -SetInterlaceMode( spec.interlace ); -*/ - -/* from web: - Video Sampling -Digital video is a sampled form of analog video. The most common sampling schemes in use today are: - Pixel Clock Horiz Horiz Vert - Rate Total Active -NTSC square pixel 12.27 MHz 780 640 525 -NTSC CCIR-601 13.5 MHz 858 720 525 -NTSC 4FSc 14.32 MHz 910 768 525 -PAL square pixel 14.75 MHz 944 768 625 -PAL CCIR-601 13.5 MHz 864 720 625 -PAL 4FSc 17.72 MHz 1135 948 625 - -For the CCIR-601 standards, the sampling is based on a static orthogonal sampling grid. The luminance component (Y) is sampled at 13.5 MHz, while the two color difference signals, Cr and Cb are sampled at half that, or 6.75 MHz. The Cr and Cb samples are colocated with alternate Y samples, and they are taken at the same position on each line, such that one sample is coincident with the 50% point of the falling edge of analog sync. The samples are coded to either 8 or 10 bits per component. -*/ - -/* from DScaler:*/ -/* -//=========================================================================== -// CCIR656 Digital Input Support: The tables were taken from DScaler proyect -// -// 13 Dec 2000 - Michael Eskin, Conexant Systems - Initial version -// - -//=========================================================================== -// Timing generator SRAM table values for CCIR601 720x480 NTSC -//=========================================================================== -// For NTSC CCIR656 -BYTE BtCard::SRAMTable_NTSC[] = -{ - // SRAM Timing Table for NTSC - 0x0c, 0xc0, 0x00, - 0x00, 0x90, 0xc2, - 0x03, 0x10, 0x03, - 0x06, 0x10, 0x34, - 0x12, 0x12, 0x65, - 0x02, 0x13, 0x24, - 0x19, 0x00, 0x24, - 0x39, 0x00, 0x96, - 0x59, 0x08, 0x93, - 0x83, 0x08, 0x97, - 0x03, 0x50, 0x30, - 0xc0, 0x40, 0x30, - 0x86, 0x01, 0x01, - 0xa6, 0x0d, 0x62, - 0x03, 0x11, 0x61, - 0x05, 0x37, 0x30, - 0xac, 0x21, 0x50 -}; - -//=========================================================================== -// Timing generator SRAM table values for CCIR601 720x576 NTSC -//=========================================================================== -// For PAL CCIR656 -BYTE BtCard::SRAMTable_PAL[] = -{ - // SRAM Timing Table for PAL - 0x36, 0x11, 0x01, - 0x00, 0x90, 0x02, - 0x05, 0x10, 0x04, - 0x16, 0x14, 0x05, - 0x11, 0x00, 0x04, - 0x12, 0xc0, 0x00, - 0x31, 0x00, 0x06, - 0x51, 0x08, 0x03, - 0x89, 0x08, 0x07, - 0xc0, 0x44, 0x00, - 0x81, 0x01, 0x01, - 0xa9, 0x0d, 0x02, - 0x02, 0x50, 0x03, - 0x37, 0x3d, 0x00, - 0xaf, 0x21, 0x00, -}; -*/ diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index a00228893..aea093419 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -41,14 +41,10 @@ #include "bttvp.h" #include #include -#if 0 /* not working yet */ -#include "bt832.h" -#endif #include "bttv-audio-hook.h" /* fwd decl */ static void boot_msp34xx(struct bttv *btv, int pin); -static void boot_bt832(struct bttv *btv); static void hauppauge_eeprom(struct bttv *btv); static void avermedia_eeprom(struct bttv *btv); static void osprey_eeprom(struct bttv *btv, const u8 ee[256]); @@ -3762,13 +3758,6 @@ void __devinit bttv_init_card2(struct bttv *btv) if (bttv_tvcards[btv->c.type].audio_mode_gpio) btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio; - if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) { - /* detect Bt832 chip for quartzsight digital camera */ - if ((bttv_I2CRead(btv, I2C_ADDR_BT832_ALT1, "Bt832") >=0) || - (bttv_I2CRead(btv, I2C_ADDR_BT832_ALT2, "Bt832") >=0)) - boot_bt832(btv); - } - if (!autoload) return; @@ -4172,40 +4161,6 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin) "init [%d]\n", btv->c.nr, pin); } -static void __devinit boot_bt832(struct bttv *btv) -{ -#if 0 /* not working yet */ - int resetbit=0; - - switch (btv->c.type) { - case BTTV_BOARD_PXELVWPLTVPAK: - resetbit = 0x400000; - break; - case BTTV_BOARD_MODTEC_205: - resetbit = 1<<9; - break; - default: - BUG(); - } - - request_module("bt832"); - bttv_call_i2c_clients(btv, BT832_HEXDUMP, NULL); - - printk("bttv%d: Reset Bt832 [line=0x%x]\n",btv->c.nr,resetbit); - gpio_write(0); - gpio_inout(resetbit, resetbit); - udelay(5); - gpio_bits(resetbit, resetbit); - udelay(5); - gpio_bits(resetbit, 0); - udelay(5); - - /* bt832 on pixelview changes from i2c 0x8a to 0x88 after - * being reset as above. So we must follow by this: */ - bttv_call_i2c_clients(btv, BT832_REATTACH, NULL); -#endif -} - /* ----------------------------------------------------------------------- */ /* Imagenation L-Model PXC200 Framegrabber */ /* This is basically the same procedure as diff --git a/linux/include/media/i2c-addr.h b/linux/include/media/i2c-addr.h index e7ff44a35..5d0f56054 100644 --- a/linux/include/media/i2c-addr.h +++ b/linux/include/media/i2c-addr.h @@ -12,8 +12,6 @@ /* bttv address list */ #define I2C_ADDR_TSA5522 0xc2 #define I2C_ADDR_TDA7432 0x8a -#define I2C_ADDR_BT832_ALT1 0x88 -#define I2C_ADDR_BT832_ALT2 0x8a // alternate setting #define I2C_ADDR_TDA8425 0x82 #define I2C_ADDR_TDA9840 0x84 #define I2C_ADDR_TDA9850 0xb6 /* also used by 9855,9873 */ diff --git a/v4l/scripts/release.sh b/v4l/scripts/release.sh index 4e9c810bc..5055675d6 100755 --- a/v4l/scripts/release.sh +++ b/v4l/scripts/release.sh @@ -16,7 +16,7 @@ files_common="$files_v4l $files_tuner $files_i2c doc" files_ir="ir-common.[ch]" files_audio="msp3400.[ch] tvaudio.[ch] tvmixer.[ch]" -files_bttv="bt848.h btcx*.[ch] bttv*.[ch] bt832.[ch] ir-kbd*.c" +files_bttv="bt848.h btcx*.[ch] bttv*.[ch] ir-kbd*.c" files_saa="saa7134*.[ch] saa6752hs.[ch] ir-kbd-i2c.c" files_cx="btcx*.[ch] cx*.[ch]" -- cgit v1.2.3 From eebdebc91edbad9e91a7ac0b8762b12fd4160b0b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 19 Dec 2008 11:21:26 +0100 Subject: gspca - spca561: Separate the bridge and sensor tables of Rev72a. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca561.c | 110 +++++++++++++----------------- 1 file changed, 49 insertions(+), 61 deletions(-) diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c index 6114ac5f7..f518bb02f 100644 --- a/linux/drivers/media/video/gspca/spca561.c +++ b/linux/drivers/media/video/gspca/spca561.c @@ -146,7 +146,7 @@ static struct v4l2_pix_format sif_072a_mode[] = { #define SPCA561_SNAPBIT 0x20 #define SPCA561_SNAPCTRL 0x40 -static const __u16 rev72a_init_data[][2] = { +static const __u16 rev72a_init_data1[][2] = { {0x0000, 0x8114}, /* Software GPIO output data */ {0x0001, 0x8114}, /* Software GPIO output data */ {0x0000, 0x8112}, /* Some kind of reset */ @@ -156,44 +156,26 @@ static const __u16 rev72a_init_data[][2] = { {0x0001, 0x8118}, /* Conf sensor */ {0x0092, 0x8804}, /* I know nothing about these */ {0x0010, 0x8802}, /* 0x88xx registers, so I won't */ - /***************/ {0x000d, 0x8805}, /* sensor default setting */ - {0x0001, 0x8801}, /* 1 <- 0x0d */ - {0x0000, 0x8800}, - {0x0018, 0x8805}, - {0x0002, 0x8801}, /* 2 <- 0x18 */ - {0x0000, 0x8800}, - {0x0065, 0x8805}, - {0x0004, 0x8801}, /* 4 <- 0x01 0x65 */ - {0x0001, 0x8800}, - {0x0021, 0x8805}, - {0x0005, 0x8801}, /* 5 <- 0x21 */ - {0x0000, 0x8800}, - {0x00aa, 0x8805}, - {0x0007, 0x8801}, /* 7 <- 0xaa */ - {0x0000, 0x8800}, - {0x0004, 0x8805}, - {0x0020, 0x8801}, /* 0x20 <- 0x15 0x04 */ - {0x0015, 0x8800}, - {0x0002, 0x8805}, - {0x0039, 0x8801}, /* 0x39 <- 0x02 */ - {0x0000, 0x8800}, - {0x0010, 0x8805}, - {0x0035, 0x8801}, /* 0x35 <- 0x10 */ - {0x0000, 0x8800}, - {0x0049, 0x8805}, - {0x0009, 0x8801}, /* 0x09 <- 0x10 0x49 */ - {0x0010, 0x8800}, - {0x000b, 0x8805}, - {0x0028, 0x8801}, /* 0x28 <- 0x0b */ - {0x0000, 0x8800}, - {0x000f, 0x8805}, - {0x003b, 0x8801}, /* 0x3b <- 0x0f */ - {0x0000, 0x8800}, - {0x0000, 0x8805}, - {0x003c, 0x8801}, /* 0x3c <- 0x00 */ - {0x0000, 0x8800}, - /***************/ + {} +}; +static const __u16 rev72a_init_sensor1[][2] = { + /* ms-win values */ + {0x0001, 0x0018}, /* 0x01 <- 0x0d */ + {0x0002, 0x0065}, /* 0x02 <- 0x18 */ + {0x0004, 0x0121}, /* 0x04 <- 0x0165 */ + {0x0005, 0x00aa}, /* 0x05 <- 0x21 */ + {0x0007, 0x0004}, /* 0x07 <- 0xaa */ + {0x0020, 0x1502}, /* 0x20 <- 0x1504 */ + {0x0039, 0x0010}, /* 0x39 <- 0x02 */ + {0x0035, 0x0049}, /* 0x35 <- 0x10 */ + {0x0009, 0x100b}, /* 0x09 <- 0x1049 */ + {0x0028, 0x000f}, /* 0x28 <- 0x0b */ + {0x003b, 0x003c}, /* 0x3b <- 0x0f */ + {0x003c, 0x0000}, /* 0x3c <- 0x00 */ + {} +}; +static const __u16 rev72a_init_data2[][2] = { {0x0018, 0x8601}, /* Pixel/line selection for color separation */ {0x0000, 0x8602}, /* Optical black level for user setting */ {0x0060, 0x8604}, /* Optical black horizontal offset */ @@ -241,29 +223,22 @@ static const __u16 rev72a_init_data[][2] = { {0x0002, 0x865b}, /* Horizontal offset for valid pixels */ {0x0003, 0x865c}, /* Vertical offset for valid lines */ - /***************/ /* sensor active */ - {0x0003, 0x8801}, /* 0x03 <- 0x01 0x21 //289 */ - {0x0021, 0x8805}, - {0x0001, 0x8800}, - {0x0004, 0x8801}, /* 0x04 <- 0x01 0x65 //357 */ - {0x0065, 0x8805}, - {0x0001, 0x8800}, - {0x0005, 0x8801}, /* 0x05 <- 0x2f */ - {0x002f, 0x8805}, - {0x0000, 0x8800}, - {0x0006, 0x8801}, /* 0x06 <- 0 */ - {0x0000, 0x8805}, - {0x0000, 0x8800}, - {0x000a, 0x8801}, /* 0x0a <- 2 */ - {0x0002, 0x8805}, - {0x0000, 0x8800}, - {0x0009, 0x8801}, /* 0x09 <- 0x1061 */ - {0x0061, 0x8805}, - {0x0010, 0x8800}, - {0x0035, 0x8801}, /* 0x35 <-0x14 */ - {0x0014, 0x8805}, - {0x0000, 0x8800}, + {} +}; +static const __u16 rev72a_init_sensor2[][2] = { + /* ms-win values */ + {0x0003, 0x0121}, /* 0x03 <- 0x01 0x21 //289 */ + {0x0004, 0x0165}, /* 0x04 <- 0x01 0x65 //357 */ + {0x0005, 0x002f}, /* 0x05 <- 0x2f */ + {0x0006, 0x0000}, /* 0x06 <- 0 */ + {0x000a, 0x0002}, /* 0x0a <- 2 */ + {0x0009, 0x1061}, /* 0x09 <- 0x1061 */ + {0x0035, 0x0014}, /* 0x35 <- 0x14 */ + {} +}; +static const __u16 rev72a_init_data3[][2] = { {0x0030, 0x8112}, /* ISO and drop packet enable */ +/*fixme: should stop here*/ {0x0000, 0x8112}, /* Some kind of reset ???? */ {0x0009, 0x8118}, /* Enable sensor and set standby */ {0x0000, 0x8114}, /* Software GPIO output data */ @@ -526,6 +501,15 @@ static void sensor_mapwrite(struct gspca_dev *gspca_dev, } } +static void write_sensor_72a(struct gspca_dev *gspca_dev, + const __u16 (*sensor)[2]) +{ + while ((*sensor)[0]) { + i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]); + sensor++; + } +} + static void init_161rev12A(struct gspca_dev *gspca_dev) { write_vector(gspca_dev, spca561_161rev12A_data1); @@ -595,7 +579,11 @@ static int sd_init_12a(struct gspca_dev *gspca_dev) static int sd_init_72a(struct gspca_dev *gspca_dev) { PDEBUG(D_STREAM, "Chip revision: 072a"); - write_vector(gspca_dev, rev72a_init_data); + write_vector(gspca_dev, rev72a_init_data1); + write_sensor_72a(gspca_dev, rev72a_init_sensor1); + write_vector(gspca_dev, rev72a_init_data2); + write_sensor_72a(gspca_dev, rev72a_init_sensor2); + write_vector(gspca_dev, rev72a_init_data3); return 0; } -- cgit v1.2.3 From 4a1ce8a5db70639704279510654844e70138807e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Dec 2008 11:36:46 +0100 Subject: cx24113: fix compile warnings From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/frontends/cx24113.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index 93f35941a..f6e7b0380 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -345,12 +345,12 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) } F = freq_hz; F *= (u64) (R * vcodiv * 262144); - dprintk("1 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("1 N: %d, F: %lld, R: %d\n", N, (long long)F, R); do_div(F, state->config->xtal_khz*1000 * factor * 2); - dprintk("2 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("2 N: %d, F: %lld, R: %d\n", N, (long long)F, R); F -= (N + 32) * 262144; - dprintk("3 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("3 N: %d, F: %lld, R: %d\n", N, (long long)F, R); if (state->Fwindow_enabled) { if (F > (262144 / 2 - 1638)) @@ -363,7 +363,7 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) cx24113_writereg(state, 0x10, r | (1 << 6)); } } - dprintk("4 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("4 N: %d, F: %lld, R: %d\n", N, (long long)F, R); *n = (u16) N; *f = (s32) F; -- cgit v1.2.3 From 2db770287e0d030f614cc7c312c7e5e96041b672 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Dec 2008 13:10:56 +0100 Subject: v4l2-dev: check for parent device in get_index. From: Hans Verkuil get_index requires a valid parent device in order to discover which indices are in use. Some drivers (e.g. pvrusb2) do not set the parent device. In that case just return 0. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-dev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 3b8f33c8d..91849084f 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -194,6 +194,10 @@ static int get_index(struct video_device *vdev, int num) return -EINVAL; } + /* Some drivers do not set the parent. In that case always return 0. */ + if (vdev->parent == NULL) + return 0; + for (i = 0; i < VIDEO_NUM_DEVICES; i++) { if (video_device[i] != NULL && video_device[i] != vdev && -- cgit v1.2.3 From 17cd7738553914ce1e1299fbe8e3ce375ed7f02b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 19 Dec 2008 14:07:49 +0100 Subject: soc-camera: add new bus width and signal polarity flags From: Guennadi Liakhovetski In preparation for i.MX31 camera host driver add flags for 4 and 15 bit bus widths and for data lines polarity inversion. Signed-off-by: Guennadi Liakhovetski --- include/media/soc_camera.h | 23 ++++++++++++++--------- 1 files changed, 14 insertions(+), 9 deletions(-) --- linux/include/media/soc_camera.h | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 50f444756..425b6a98c 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -221,15 +221,20 @@ static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( #define SOCAM_HSYNC_ACTIVE_LOW (1 << 3) #define SOCAM_VSYNC_ACTIVE_HIGH (1 << 4) #define SOCAM_VSYNC_ACTIVE_LOW (1 << 5) -#define SOCAM_DATAWIDTH_8 (1 << 6) -#define SOCAM_DATAWIDTH_9 (1 << 7) -#define SOCAM_DATAWIDTH_10 (1 << 8) -#define SOCAM_DATAWIDTH_16 (1 << 9) -#define SOCAM_PCLK_SAMPLE_RISING (1 << 10) -#define SOCAM_PCLK_SAMPLE_FALLING (1 << 11) - -#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \ - SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_16) +#define SOCAM_DATAWIDTH_4 (1 << 6) +#define SOCAM_DATAWIDTH_8 (1 << 7) +#define SOCAM_DATAWIDTH_9 (1 << 8) +#define SOCAM_DATAWIDTH_10 (1 << 9) +#define SOCAM_DATAWIDTH_15 (1 << 10) +#define SOCAM_DATAWIDTH_16 (1 << 11) +#define SOCAM_PCLK_SAMPLE_RISING (1 << 12) +#define SOCAM_PCLK_SAMPLE_FALLING (1 << 13) +#define SOCAM_DATA_ACTIVE_HIGH (1 << 14) +#define SOCAM_DATA_ACTIVE_LOW (1 << 15) + +#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_4 | SOCAM_DATAWIDTH_8 | \ + SOCAM_DATAWIDTH_9 | SOCAM_DATAWIDTH_10 | \ + SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_16) static inline unsigned long soc_camera_bus_param_compatible( unsigned long camera_flags, unsigned long bus_flags) -- cgit v1.2.3 From 1260044709b00c199d5cc6d8afce99b6aeea019b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Dec 2008 14:20:22 +0100 Subject: v4l2: document video_device. From: Hans Verkuil Add the missing video_device documentation to v4l2-framework.txt. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 160 ++++++++++++++++++++- 1 file changed, 159 insertions(+), 1 deletion(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index 60eaf54e7..eeae76c22 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -86,6 +86,9 @@ to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from dev (driver name followed by the bus_id, to be precise). You may change the name after registration if you want. +The first 'dev' argument is normally the struct device pointer of a pci_dev, +usb_device or platform_device. + You unregister with: v4l2_device_unregister(struct v4l2_device *v4l2_dev); @@ -359,4 +362,159 @@ Both functions return NULL if something went wrong. struct video_device ------------------- -Not yet documented. +The actual device nodes in the /dev directory are created using the +video_device struct (v4l2-dev.h). This struct can either be allocated +dynamically or embedded in a larger struct. + +To allocate it dynamically use: + + struct video_device *vdev = video_device_alloc(); + + if (vdev == NULL) + return -ENOMEM; + + vdev->release = video_device_release; + +If you embed it in a larger struct, then you must set the release() +callback to your own function: + + struct video_device *vdev = &my_vdev->vdev; + + vdev->release = my_vdev_release; + +The release callback must be set and it is called when the last user +of the video device exits. + +The default video_device_release() callback just calls kfree to free the +allocated memory. + +You should also set these fields: + +- parent: set to the parent device (same device as was used to register + v4l2_device). +- name: set to something descriptive and unique. +- fops: set to the file_operations struct. +- ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance + (highly recommended to use this and it might become compulsory in the + future!), then set this to your v4l2_ioctl_ops struct. + +If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to +__video_ioctl2 or .ioctl to video_ioctl2 in your file_operations struct. + + +video_device registration +------------------------- + +Next you register the video device: this will create the character device +for you. + + err = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (err) { + video_device_release(vdev); // or kfree(my_vdev); + return err; + } + +Which device is registered depends on the type argument. The following +types exist: + +VFL_TYPE_GRABBER: videoX for video input/output devices +VFL_TYPE_VBI: vbiX for vertical blank data (i.e. closed captions, teletext) +VFL_TYPE_RADIO: radioX for radio tuners +VFL_TYPE_VTX: vtxX for teletext devices (deprecated, don't use) + +The last argument gives you a certain amount of control over the device +kernel number used (i.e. the X in videoX). Normally you will pass -1 to +let the v4l2 framework pick the first free number. But if a driver creates +many devices, then it can be useful to have different video devices in +separate ranges. For example, video capture devices start at 0, video +output devices start at 16. + +So you can use the last argument to specify a minimum kernel number and +the v4l2 framework will try to pick the first free number that is equal +or higher to what you passed. If that fails, then it will just pick the +first free number. + +Whenever a device node is created some attributes are also created for you. +If you look in /sys/class/video4linux you see the devices. Go into e.g. +video0 and you will see 'name' and 'index' attributes. The 'name' attribute +is the 'name' field of the video_device struct. The 'index' attribute is +a device node index that can be assigned by the driver, or that is calculated +for you. + +If you call video_register_device(), then the index is just increased by +1 for each device node you register. The first video device node you register +always starts off with 0. + +Alternatively you can call video_register_device_index() which is identical +to video_register_device(), but with an extra index argument. Here you can +pass a specific index value (between 0 and 31) that should be used. + +Users can setup udev rules that utilize the index attribute to make fancy +device names (e.g. 'mpegX' for MPEG video capture device nodes). + +After the device was successfully registered, then you can use these fields: + +- vfl_type: the device type passed to video_register_device. +- minor: the assigned device minor number. +- num: the device kernel number (i.e. the X in videoX). +- index: the device index number (calculated or set explicitly using + video_register_device_index). + +If the registration failed, then you need to call video_device_release() +to free the allocated video_device struct, or free your own struct if the +video_device was embedded in it. The vdev->release() callback will never +be called if the registration failed, nor should you ever attempt to +unregister the device if the registration failed. + + +video_device cleanup +-------------------- + +When the video device nodes have to be removed, either during the unload +of the driver or because the USB device was disconnected, then you should +unregister them: + + video_unregister_device(vdev); + +This will remove the device nodes from sysfs (causing udev to remove them +from /dev). + +After video_unregister_device() returns no new opens can be done. + +However, in the case of USB devices some application might still have one +of these device nodes open. You should block all new accesses to read, +write, poll, etc. except possibly for certain ioctl operations like +queueing buffers. + +When the last user of the video device node exits, then the vdev->release() +callback is called and you can do the final cleanup there. + + +video_device helper functions +----------------------------- + +There are a few useful helper functions: + +You can set/get driver private data in the video_device struct using: + +void *video_get_drvdata(struct video_device *dev); +void video_set_drvdata(struct video_device *dev, void *data); + +Note that you can safely call video_set_drvdata() before calling +video_register_device(). + +And this function: + +struct video_device *video_devdata(struct file *file); + +returns the video_device belonging to the file struct. + +The final helper function combines video_get_drvdata with +video_devdata: + +void *video_drvdata(struct file *file); + +You can go from a video_device struct to the v4l2_device struct using: + +struct v4l2_device *v4l2_dev = dev_get_drvdata(vdev->parent); + -- cgit v1.2.3 From ff63d4ba6fa540c90a770d99026921965ab56c80 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Dec 2008 14:34:22 +0100 Subject: cs5345: convert to v4l2_subdev and fix broken s_ctrl. From: Hans Verkuil Converted to v4l2_subdev. While doing that I also discovered a stray 'break' that broke the S_CTRL handling. Fixed that as well. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cs5345.c | 227 ++++++++++++++++++++++--------------- 1 file changed, 138 insertions(+), 89 deletions(-) diff --git a/linux/drivers/media/video/cs5345.c b/linux/drivers/media/video/cs5345.c index decbc5f1f..1af0f53dd 100644 --- a/linux/drivers/media/video/cs5345.c +++ b/linux/drivers/media/video/cs5345.c @@ -23,9 +23,9 @@ #include #include #include -#include -#include +#include #include +#include #include "compat.h" MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC"); @@ -46,111 +46,143 @@ I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ -static inline int cs5345_write(struct i2c_client *client, u8 reg, u8 value) +static inline int cs5345_write(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_write_byte_data(client, reg, value); } -static inline int cs5345_read(struct i2c_client *client, u8 reg) +static inline int cs5345_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } -static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg) +static int cs5345_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct v4l2_routing *route = arg; - struct v4l2_control *ctrl = arg; - - switch (cmd) { - case VIDIOC_INT_G_AUDIO_ROUTING: - route->input = cs5345_read(client, 0x09) & 7; - route->input |= cs5345_read(client, 0x05) & 0x70; - route->output = 0; - break; - - case VIDIOC_INT_S_AUDIO_ROUTING: - if ((route->input & 0xf) > 6) { - v4l_err(client, "Invalid input %d.\n", route->input); - return -EINVAL; - } - cs5345_write(client, 0x09, route->input & 0xf); - cs5345_write(client, 0x05, route->input & 0xf0); - break; - - case VIDIOC_G_CTRL: - if (ctrl->id == V4L2_CID_AUDIO_MUTE) { - ctrl->value = (cs5345_read(client, 0x04) & 0x08) != 0; - break; - } - if (ctrl->id != V4L2_CID_AUDIO_VOLUME) - return -EINVAL; - ctrl->value = cs5345_read(client, 0x07) & 0x3f; - if (ctrl->value >= 32) - ctrl->value = ctrl->value - 64; - break; - - case VIDIOC_S_CTRL: - break; - if (ctrl->id == V4L2_CID_AUDIO_MUTE) { - cs5345_write(client, 0x04, ctrl->value ? 0x80 : 0); - break; - } - if (ctrl->id != V4L2_CID_AUDIO_VOLUME) - return -EINVAL; - if (ctrl->value > 24 || ctrl->value < -24) - return -EINVAL; - cs5345_write(client, 0x07, ((u8)ctrl->value) & 0x3f); - cs5345_write(client, 0x08, ((u8)ctrl->value) & 0x3f); - break; - -#ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (cmd == VIDIOC_DBG_G_REGISTER) - reg->val = cs5345_read(client, reg->reg & 0x1f); - else - cs5345_write(client, reg->reg & 0x1f, reg->val & 0xff); - break; + if ((route->input & 0xf) > 6) { + v4l2_err(sd, "Invalid input %d.\n", route->input); + return -EINVAL; } -#endif + cs5345_write(sd, 0x09, route->input & 0xf); + cs5345_write(sd, 0x05, route->input & 0xf0); + return 0; +} - case VIDIOC_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, - arg, V4L2_IDENT_CS5345, 0); - - case VIDIOC_LOG_STATUS: - { - u8 v = cs5345_read(client, 0x09) & 7; - u8 m = cs5345_read(client, 0x04); - int vol = cs5345_read(client, 0x08) & 0x3f; - - v4l_info(client, "Input: %d%s\n", v, - (m & 0x80) ? " (muted)" : ""); - if (vol >= 32) - vol = vol - 64; - v4l_info(client, "Volume: %d dB\n", vol); - break; - } - - default: +static int cs5345_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + if (ctrl->id == V4L2_CID_AUDIO_MUTE) { + ctrl->value = (cs5345_read(sd, 0x04) & 0x08) != 0; + return 0; + } + if (ctrl->id != V4L2_CID_AUDIO_VOLUME) return -EINVAL; + ctrl->value = cs5345_read(sd, 0x07) & 0x3f; + if (ctrl->value >= 32) + ctrl->value = ctrl->value - 64; + return 0; +} + +static int cs5345_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + if (ctrl->id == V4L2_CID_AUDIO_MUTE) { + cs5345_write(sd, 0x04, ctrl->value ? 0x80 : 0); + return 0; } + if (ctrl->id != V4L2_CID_AUDIO_VOLUME) + return -EINVAL; + if (ctrl->value > 24 || ctrl->value < -24) + return -EINVAL; + cs5345_write(sd, 0x07, ((u8)ctrl->value) & 0x3f); + cs5345_write(sd, 0x08, ((u8)ctrl->value) & 0x3f); + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = cs5345_read(sd, reg->reg & 0x1f); + return 0; +} + +static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, + reg->match_type, reg->match_chip)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + cs5345_write(sd, reg->reg & 0x1f, reg->val & 0xff); return 0; } +#endif + +static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_CS5345, 0); +} + +static int cs5345_log_status(struct v4l2_subdev *sd) +{ + u8 v = cs5345_read(sd, 0x09) & 7; + u8 m = cs5345_read(sd, 0x04); + int vol = cs5345_read(sd, 0x08) & 0x3f; + + v4l2_info(sd, "Input: %d%s\n", v, + (m & 0x80) ? " (muted)" : ""); + if (vol >= 32) + vol = vol - 64; + v4l2_info(sd, "Volume: %d dB\n", vol); + return 0; +} + +static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops cs5345_core_ops = { + .log_status = cs5345_log_status, + .g_chip_ident = cs5345_g_chip_ident, + .g_ctrl = cs5345_g_ctrl, + .s_ctrl = cs5345_s_ctrl, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = cs5345_g_register, + .s_register = cs5345_s_register, +#endif +}; + +static const struct v4l2_subdev_audio_ops cs5345_audio_ops = { + .s_routing = cs5345_s_routing, +}; + +static const struct v4l2_subdev_ops cs5345_ops = { + .core = &cs5345_core_ops, + .audio = &cs5345_audio_ops, +}; /* ----------------------------------------------------------------------- */ static int cs5345_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct v4l2_subdev *sd; + /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; @@ -158,9 +190,25 @@ static int cs5345_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - cs5345_write(client, 0x02, 0x00); - cs5345_write(client, 0x04, 0x01); - cs5345_write(client, 0x09, 0x01); + sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &cs5345_ops); + + cs5345_write(sd, 0x02, 0x00); + cs5345_write(sd, 0x04, 0x01); + cs5345_write(sd, 0x09, 0x01); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static int cs5345_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); return 0; } @@ -179,6 +227,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .driverid = I2C_DRIVERID_CS5345, .command = cs5345_command, .probe = cs5345_probe, + .remove = cs5345_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = cs5345_id, #endif -- cgit v1.2.3 From 1d6cf736e1fc3df22e0f38fa20894cb96e1d32fc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Dec 2008 15:17:56 +0100 Subject: videodev2.h: fix typo. From: Hans Verkuil The comment said CX2584X instead of CX2341X. Priority: normal Signed-off-by: Hans Verkuil --- linux/include/linux/videodev2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 6ee771108..96624e29f 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1051,7 +1051,7 @@ enum v4l2_mpeg_video_bitrate_mode { #define V4L2_CID_MPEG_VIDEO_MUTE (V4L2_CID_MPEG_BASE+210) #define V4L2_CID_MPEG_VIDEO_MUTE_YUV (V4L2_CID_MPEG_BASE+211) -/* MPEG-class control IDs specific to the CX2584x driver as defined by V4L2 */ +/* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */ #define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) enum v4l2_mpeg_cx2341x_video_spatial_filter_mode { -- cgit v1.2.3 From c4c07b3733735bdf3397af8d15d77405cff5f1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Fri, 19 Dec 2008 17:12:04 +0100 Subject: Add some comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 2 +- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index c5f75aa59..e795ab7a3 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -993,7 +993,7 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, /* 639*/ {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 3435a05ab..b1aec70db 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -344,7 +344,7 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_COM24, 0x00}, /* Enable HREF and some out of spec things */ {SENSOR, OV9650_COM12, 0x73}, - /* Set all DBLC offset signs to positive and + /* Set all DBLC offset signs to positive and do some out of spec stuff */ {SENSOR, OV9650_DBLC1, 0xdf}, {SENSOR, OV9650_COM21, 0x06}, @@ -356,7 +356,7 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_RSVD96, 0x04}, /* Enable full range output */ {SENSOR, OV9650_COM15, 0x0}, - /* Enable HREF at optical black, enable ADBLC bias, + /* Enable HREF at optical black, enable ADBLC bias, enable ADBLC, reset timings at format change */ {SENSOR, OV9650_COM6, 0x4b}, /* Subtract 32 from the B channel bias */ @@ -377,7 +377,7 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_AEB, 0x5c}, /* Set the high and low limit nibbles to 3 */ {SENSOR, OV9650_VPT, 0xc3}, - /* Set the Automatic Gain Ceiling (AGC) to 128x, + /* Set the Automatic Gain Ceiling (AGC) to 128x, drop VSYNC at frame drop, limit exposure timing, drop frame when the AEC step is larger than the exposure gap */ @@ -386,9 +386,9 @@ static const unsigned char init_ov9650[][3] = and set PWDN to SLVS (slave mode vertical sync) */ {SENSOR, OV9650_COM10, 0x42}, /* Set horizontal column start high to default value */ - {SENSOR, OV9650_HSTART, 0x1a}, + {SENSOR, OV9650_HSTART, 0x1a}, /* 210 */ /* Set horizontal column end */ - {SENSOR, OV9650_HSTOP, 0xbf}, + {SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */ /* Complementing register to the two writes above */ {SENSOR, OV9650_HREF, 0xb2}, /* Set vertical row start high bits */ @@ -428,11 +428,12 @@ static const unsigned char init_ov9650[][3] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e}, /* 94 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 734 */ {BRIDGE, M5602_XB_HSYNC_PARA, 0xde} }; -- cgit v1.2.3 From 9e743cb43e389adc6843b552f22de1d3f171bb22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Fri, 19 Dec 2008 17:29:21 +0100 Subject: Fixup offset in order to align image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index b1aec70db..9360b8bd9 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -432,9 +432,9 @@ static const unsigned char init_ov9650[][3] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e}, /* 94 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 734 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0xde} + {BRIDGE, M5602_XB_HSYNC_PARA, 0x64}, /* 100 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 100 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0xe4} }; static const unsigned char power_down_ov9650[][3] = -- cgit v1.2.3 From 6880329c518c82eee1f0cbae9d1710285b8a1b3e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 19 Dec 2008 19:08:51 +0100 Subject: gspca - main: Remove useless tests of the buffer type. From: Jean-Francois Moine The buffer type is already checked in v4l2-ioctl. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 71e7afe1b..920e01c0d 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -785,8 +785,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct gspca_dev *gspca_dev = priv; int mode; - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; mode = gspca_dev->curr_mode; memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode], sizeof fmt->fmt.pix); @@ -798,8 +796,6 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev, { int w, h, mode, mode2; - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; w = fmt->fmt.pix.width; h = fmt->fmt.pix.height; @@ -1153,8 +1149,6 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct gspca_dev *gspca_dev = priv; int i, ret = 0; - if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; switch (rb->memory) { case GSPCA_MEMORY_READ: /* (internal call) */ case V4L2_MEMORY_MMAP: @@ -1219,8 +1213,7 @@ static int vidioc_querybuf(struct file *file, void *priv, struct gspca_dev *gspca_dev = priv; struct gspca_frame *frame; - if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE - || v4l2_buf->index < 0 + if (v4l2_buf->index < 0 || v4l2_buf->index >= gspca_dev->nframes) return -EINVAL; @@ -1561,8 +1554,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, int i, ret; PDEBUG(D_FRAM, "dqbuf"); - if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (v4l2_buf->memory != gspca_dev->memory) return -EINVAL; @@ -1617,8 +1608,6 @@ static int vidioc_qbuf(struct file *file, void *priv, int i, index, ret; PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index); - if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; -- cgit v1.2.3 From 21d405e38a20de8a1d21656ffb140a84ffad72be Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 19 Dec 2008 19:17:25 +0100 Subject: gspca - main: Check if a buffer has been queued on streamon. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 920e01c0d..5d2f0ab93 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1236,7 +1236,8 @@ static int vidioc_streamon(struct file *file, void *priv, ret = -ENODEV; goto out; } - if (gspca_dev->nframes == 0) { + if (gspca_dev->nframes == 0 + || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { ret = -EINVAL; goto out; } -- cgit v1.2.3 From a012e750305d20ec8b2f79b6a32c5e7920096fd3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Dec 2008 01:28:27 +0100 Subject: v4l2-dev: use the release callback from device instead of cdev From: Hans Verkuil Instead of relying on the cdev release callback we should rely on the release callback from the device struct. This requires that we use get_device/put_device to do proper refcounting. In order to do this safely v4l2-dev.c now sets up its own file_operations that call out to the driver's ops. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-dev.c | 417 +++++++++++++++++++++++++---------- linux/include/media/v4l2-dev.h | 51 +++-- v4l/compat.h | 1 + 3 files changed, 333 insertions(+), 136 deletions(-) diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 91849084f..f877d3f86 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -43,17 +43,17 @@ static ssize_t show_index(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vfd = container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); - return sprintf(buf, "%i\n", vfd->index); + return sprintf(buf, "%i\n", vdev->index); } static ssize_t show_name(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vfd = container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); - return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); + return sprintf(buf, "%.*s\n", (int)sizeof(vdev->name), vdev->name); } static struct device_attribute video_device_attrs[] = { @@ -64,16 +64,16 @@ static struct device_attribute video_device_attrs[] = { #else static ssize_t show_index(struct class_device *cd, char *buf) { - struct video_device *vfd = container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); - return sprintf(buf, "%i\n", vfd->index); + return sprintf(buf, "%i\n", vdev->index); } static ssize_t show_name(struct class_device *cd, char *buf) { - struct video_device *vfd = container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); - return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); + return sprintf(buf, "%.*s\n", (int)sizeof(vdev->name), vdev->name); } static CLASS_DEVICE_ATTR(index, S_IRUGO, show_index, NULL); @@ -93,71 +93,77 @@ struct video_device *video_device_alloc(void) } EXPORT_SYMBOL(video_device_alloc); -void video_device_release(struct video_device *vfd) +void video_device_release(struct video_device *vdev) { - kfree(vfd); + kfree(vdev); } EXPORT_SYMBOL(video_device_release); -void video_device_release_empty(struct video_device *vfd) +void video_device_release_empty(struct video_device *vdev) { /* Do nothing */ /* Only valid when the video_device struct is a static. */ } EXPORT_SYMBOL(video_device_release_empty); -/* Called when the last user of the character device is gone. */ -static void v4l2_chardev_release(struct kobject *kobj) +static inline void video_get(struct video_device *vdev) { - struct video_device *vfd = container_of(kobj, struct video_device, cdev.kobj); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) + class_device_get(&vdev->dev); +#else + get_device(&vdev->dev); +#endif +} + +static inline void video_put(struct video_device *vdev) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) + class_device_put(&vdev->dev); +#else + put_device(&vdev->dev); +#endif +} + +/* Called when the last user of the video device exits. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void v4l2_device_release(struct class_device *cd) +#else +static void v4l2_device_release(struct device *cd) +#endif +{ + struct video_device *vdev = to_video_device(cd); mutex_lock(&videodev_lock); - if (video_device[vfd->minor] != vfd) { + if (video_device[vdev->minor] != vdev) { mutex_unlock(&videodev_lock); - BUG(); + /* should not happen */ + WARN_ON(1); return; } /* Free up this device for reuse */ - video_device[vfd->minor] = NULL; - clear_bit(vfd->num, video_nums[vfd->vfl_type]); - mutex_unlock(&videodev_lock); + video_device[vdev->minor] = NULL; - /* Release the character device */ - vfd->cdev_release(kobj); - /* Release video_device and perform other - cleanups as needed. */ - if (vfd->release) - vfd->release(vfd); -} + /* Delete the cdev on this minor as well */ + cdev_del(vdev->cdev); + /* Just in case some driver tries to access this from + the release() callback. */ + vdev->cdev = NULL; -/* The new kobj_type for the character device */ -static struct kobj_type v4l2_ktype_cdev_default = { - .release = v4l2_chardev_release, -}; + /* Mark minor as free */ + clear_bit(vdev->num, video_nums[vdev->vfl_type]); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void video_release(struct class_device *cd) -#else -static void video_release(struct device *cd) -#endif -{ - struct video_device *vfd = container_of(cd, struct video_device, dev); + mutex_unlock(&videodev_lock); - /* It's now safe to delete the char device. - This will either trigger the v4l2_chardev_release immediately (if - the refcount goes to 0) or later when the last user of the - character device closes it. */ - cdev_del(&vfd->cdev); + /* Release video_device and perform other + cleanups as needed. */ + vdev->release(vdev); } static struct class video_class = { .name = VIDEO_NAME, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - .release = video_release, -#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) .dev_attrs = video_device_attrs, - .dev_release = video_release, #endif }; @@ -171,13 +177,163 @@ struct video_device *video_devdata(struct file *file) } EXPORT_SYMBOL(video_devdata); +static ssize_t v4l2_read(struct file *filp, char __user *buf, + size_t sz, loff_t *off) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->read) + return -EINVAL; + if (video_is_unregistered(vdev)) + return -EIO; + return vdev->fops->read(filp, buf, sz, off); +} + +static ssize_t v4l2_write(struct file *filp, const char __user *buf, + size_t sz, loff_t *off) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->write) + return -EINVAL; + if (video_is_unregistered(vdev)) + return -EIO; + return vdev->fops->write(filp, buf, sz, off); +} + +static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->poll || video_is_unregistered(vdev)) + return DEFAULT_POLLMASK; + return vdev->fops->poll(filp, poll); +} + +static int v4l2_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->ioctl) + return -ENOTTY; + /* Allow ioctl to continue even if the device was unregistered. + Things like dequeueing buffers might still be useful. */ + return vdev->fops->ioctl(inode, filp, cmd, arg); +} + +static long v4l2_unlocked_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->unlocked_ioctl) + return -ENOTTY; + /* Allow ioctl to continue even if the device was unregistered. + Things like dequeueing buffers might still be useful. */ + return vdev->fops->unlocked_ioctl(filp, cmd, arg); +} + +#ifdef CONFIG_COMPAT +static long v4l2_compat_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->compat_ioctl) + return -ENOIOCTLCMD; + /* Allow ioctl to continue even if the device was unregistered. + Things like dequeueing buffers might still be useful. */ + return vdev->fops->compat_ioctl(filp, cmd, arg); +} +#endif + +static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->mmap || + video_is_unregistered(vdev)) + return -ENODEV; + return vdev->fops->mmap(filp, vm); +} + +/* Override for the open function */ +static int v4l2_open(struct inode *inode, struct file *filp) +{ + struct video_device *vdev; + int ret; + + /* Check if the video device is available */ + mutex_lock(&videodev_lock); + vdev = video_devdata(filp); + /* return ENODEV if the video device has been removed + already or if it is not registered anymore. */ + if (vdev == NULL || video_is_unregistered(vdev)) { + mutex_unlock(&videodev_lock); + return -ENODEV; + } + /* and increase the device refcount */ + video_get(vdev); + mutex_unlock(&videodev_lock); + ret = vdev->fops->open(inode, filp); + /* decrease the refcount in case of an error */ + if (ret) + video_put(vdev); + return ret; +} + +/* Override for the release function */ +static int v4l2_release(struct inode *inode, struct file *filp) +{ + struct video_device *vdev = video_devdata(filp); + int ret = vdev->fops->release(inode, filp); + + /* decrease the refcount unconditionally since the release() + return value is ignored. */ + video_put(vdev); + return ret; +} + +static const struct file_operations v4l2_unlocked_fops = { + .owner = THIS_MODULE, + .read = v4l2_read, + .write = v4l2_write, + .open = v4l2_open, + .mmap = v4l2_mmap, + .unlocked_ioctl = v4l2_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = v4l2_compat_ioctl, +#endif + .release = v4l2_release, + .poll = v4l2_poll, + .llseek = no_llseek, +}; + +static const struct file_operations v4l2_fops = { + .owner = THIS_MODULE, + .read = v4l2_read, + .write = v4l2_write, + .open = v4l2_open, + .mmap = v4l2_mmap, + .ioctl = v4l2_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = v4l2_compat_ioctl, +#endif + .release = v4l2_release, + .poll = v4l2_poll, + .llseek = no_llseek, +}; + /** * get_index - assign stream number based on parent device - * @vdev: video_device to assign index number to, vdev->dev should be assigned - * @num: -1 if auto assign, requested number otherwise + * @vdev: video_device to assign index number to, vdev->parent should be assigned + * @num: -1 if auto assign, requested number otherwise * + * Note that when this is called the new device has not yet been registered + * in the video_device array. * - * returns -ENFILE if num is already in use, a free index number if + * Returns -ENFILE if num is already in use, a free index number if * successful. */ static int get_index(struct video_device *vdev, int num) @@ -200,7 +356,6 @@ static int get_index(struct video_device *vdev, int num) for (i = 0; i < VIDEO_NUM_DEVICES; i++) { if (video_device[i] != NULL && - video_device[i] != vdev && video_device[i]->parent == vdev->parent) { used |= 1 << video_device[i]->index; } @@ -216,17 +371,15 @@ static int get_index(struct video_device *vdev, int num) return i > max_index ? -ENFILE : i; } -static const struct file_operations video_fops; - -int video_register_device(struct video_device *vfd, int type, int nr) +int video_register_device(struct video_device *vdev, int type, int nr) { - return video_register_device_index(vfd, type, nr, -1); + return video_register_device_index(vdev, type, nr, -1); } EXPORT_SYMBOL(video_register_device); /** * video_register_device_index - register video4linux devices - * @vfd: video device structure we want to register + * @vdev: video device structure we want to register * @type: type of device to register * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ... * -1 == first free) @@ -250,8 +403,7 @@ EXPORT_SYMBOL(video_register_device); * * %VFL_TYPE_RADIO - A radio card */ - -int video_register_device_index(struct video_device *vfd, int type, int nr, +int video_register_device_index(struct video_device *vdev, int type, int nr, int index) { int i = 0; @@ -259,14 +411,19 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, int minor_offset = 0; int minor_cnt = VIDEO_NUM_DEVICES; const char *name_base; - void *priv = video_get_drvdata(vfd); + void *priv = video_get_drvdata(vdev); - /* the release callback MUST be present */ - BUG_ON(!vfd->release); + /* A minor value of -1 marks this video device as never + having been registered */ + if (vdev) + vdev->minor = -1; - if (vfd == NULL) + /* the release callback MUST be present */ + WARN_ON(!vdev || !vdev->release); + if (!vdev || !vdev->release) return -EINVAL; + /* Part 1: check device type */ switch (type) { case VFL_TYPE_GRABBER: name_base = "video"; @@ -286,8 +443,10 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, return -EINVAL; } - vfd->vfl_type = type; + vdev->vfl_type = type; + vdev->cdev = NULL; + /* Part 2: find a free minor, kernel number and device index. */ #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES /* Keep the ranges for the first four types for historical * reasons. @@ -318,14 +477,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, } #endif - /* Initialize the character device */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17) - cdev_init(&vfd->cdev, vfd->fops); -#else - cdev_init(&vfd->cdev, (struct file_operations *)vfd->fops); -#endif - vfd->cdev.owner = vfd->fops->owner; - /* pick a minor number */ + /* Pick a minor number */ mutex_lock(&videodev_lock); nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr); if (nr == minor_cnt) @@ -349,98 +501,125 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, return -ENFILE; } #endif - vfd->minor = i + minor_offset; - vfd->num = nr; + vdev->minor = i + minor_offset; + vdev->num = nr; set_bit(nr, video_nums[type]); - BUG_ON(video_device[vfd->minor]); - video_device[vfd->minor] = vfd; - - ret = get_index(vfd, index); - vfd->index = ret; - + /* Should not happen since we thought this minor was free */ + WARN_ON(video_device[vdev->minor] != NULL); + ret = vdev->index = get_index(vdev, index); mutex_unlock(&videodev_lock); if (ret < 0) { printk(KERN_ERR "%s: get_index failed\n", __func__); - goto fail_minor; + goto cleanup; } - ret = cdev_add(&vfd->cdev, MKDEV(VIDEO_MAJOR, vfd->minor), 1); + /* Part 3: Initialize the character device */ + vdev->cdev = cdev_alloc(); + if (vdev->cdev == NULL) { + ret = -ENOMEM; + goto cleanup; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17) + if (vdev->fops->unlocked_ioctl) + vdev->cdev->ops = &v4l2_unlocked_fops; + else + vdev->cdev->ops = &v4l2_fops; +#else + if (vdev->fops->unlocked_ioctl) + vdev->cdev->ops = (struct file_operations *)&v4l2_unlocked_fops; + else + vdev->cdev->ops = (struct file_operations *)&v4l2_fops; +#endif + vdev->cdev->owner = vdev->fops->owner; + ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); if (ret < 0) { printk(KERN_ERR "%s: cdev_add failed\n", __func__); - goto fail_minor; + kfree(vdev->cdev); + vdev->cdev = NULL; + goto cleanup; } - /* sysfs class */ - memset(&vfd->dev, 0, sizeof(vfd->dev)); + + /* Part 4: register the device with sysfs */ + memset(&vdev->dev, 0, sizeof(vdev->dev)); /* The memset above cleared the device's drvdata, so put back the copy we made earlier. */ - video_set_drvdata(vfd, priv); - vfd->dev.class = &video_class; - vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); + video_set_drvdata(vdev, priv); + vdev->dev.class = &video_class; + vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - if (vfd->parent) - vfd->dev.dev = vfd->parent; - sprintf(vfd->dev.class_id, "%s%d", name_base, nr); - ret = class_device_register(&vfd->dev); + if (vdev->parent) + vdev->dev.dev = vdev->parent; + sprintf(vdev->dev.class_id, "%s%d", name_base, nr); + ret = class_device_register(&vdev->dev); #else - if (vfd->parent) - vfd->dev.parent = vfd->parent; - dev_set_name(&vfd->dev, "%s%d", name_base, nr); - ret = device_register(&vfd->dev); + if (vdev->parent) + vdev->dev.parent = vdev->parent; + dev_set_name(&vdev->dev, "%s%d", name_base, nr); + ret = device_register(&vdev->dev); #endif if (ret < 0) { printk(KERN_ERR "%s: device_register failed\n", __func__); - goto del_cdev; + goto cleanup; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - ret = class_device_create_file(&vfd->dev, &class_device_attr_name); + ret = class_device_create_file(&vdev->dev, &class_device_attr_name); if (ret < 0) { printk(KERN_ERR "%s: class_device_create_file 'name' failed\n", __func__); - class_device_unregister(&vfd->dev); - goto del_cdev; + class_device_unregister(&vdev->dev); + goto cleanup; } - ret = class_device_create_file(&vfd->dev, &class_device_attr_index); + ret = class_device_create_file(&vdev->dev, &class_device_attr_index); if (ret < 0) { printk(KERN_ERR "%s: class_device_create_file 'index' failed\n", __func__); - class_device_unregister(&vfd->dev); - goto del_cdev; + class_device_unregister(&vdev->dev); + goto cleanup; } #endif - /* Remember the cdev's release function */ - vfd->cdev_release = vfd->cdev.kobj.ktype->release; - /* Install our own */ - vfd->cdev.kobj.ktype = &v4l2_ktype_cdev_default; - return 0; + /* Register the release callback that will be called when the last + reference to the device goes away. */ + vdev->dev.release = v4l2_device_release; -del_cdev: - cdev_del(&vfd->cdev); + /* Part 5: Activate this minor. The char device can now be used. */ + mutex_lock(&videodev_lock); + video_device[vdev->minor] = vdev; + mutex_unlock(&videodev_lock); + return 0; -fail_minor: +cleanup: mutex_lock(&videodev_lock); - video_device[vfd->minor] = NULL; - clear_bit(vfd->num, video_nums[type]); + if (vdev->cdev) + cdev_del(vdev->cdev); + clear_bit(vdev->num, video_nums[type]); mutex_unlock(&videodev_lock); - vfd->minor = -1; + /* Mark this video device as never having been registered. */ + vdev->minor = -1; return ret; } EXPORT_SYMBOL(video_register_device_index); /** * video_unregister_device - unregister a video4linux device - * @vfd: the device to unregister + * @vdev: the device to unregister * - * This unregisters the passed device and deassigns the minor - * number. Future open calls will be met with errors. + * This unregisters the passed device. Future open calls will + * be met with errors. */ - -void video_unregister_device(struct video_device *vfd) +void video_unregister_device(struct video_device *vdev) { + /* Check if vdev was ever registered at all */ + if (!vdev || vdev->minor < 0) + return; + + mutex_lock(&videodev_lock); + set_bit(V4L2_FL_UNREGISTERED, &vdev->flags); + mutex_unlock(&videodev_lock); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - class_device_unregister(&vfd->dev); + class_device_unregister(&vdev->dev); #else - device_unregister(&vfd->dev); + device_unregister(&vdev->dev); #endif } EXPORT_SYMBOL(video_unregister_device); diff --git a/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h index bd59577d7..6d76f0bce 100644 --- a/linux/include/media/v4l2-dev.h +++ b/linux/include/media/v4l2-dev.h @@ -26,6 +26,11 @@ struct v4l2_ioctl_callbacks; +/* Flag to mark the video_device struct as unregistered. + Drivers can set this flag if they want to block all future + device access. It is set by video_unregister_device. */ +#define V4L2_FL_UNREGISTERED (0) + /* * Newer version of video_device, handled by videodev2.c * This version moves redundant code from video device code to @@ -43,15 +48,17 @@ struct video_device #else struct class_device dev; #endif - struct cdev cdev; /* character device */ - void (*cdev_release)(struct kobject *kobj); + struct cdev *cdev; /* character device */ struct device *parent; /* device parent */ /* device info */ char name[32]; int vfl_type; + /* 'minor' is set to -1 if the registration failed */ int minor; u16 num; + /* use bitops to set/clear/test flags */ + unsigned long flags; /* attribute to differentiate multiple indices on one physical device */ int index; @@ -62,7 +69,7 @@ struct video_device v4l2_std_id current_norm; /* Current tvnorm */ /* callbacks */ - void (*release)(struct video_device *vfd); + void (*release)(struct video_device *vdev); /* ioctl callbacks */ const struct v4l2_ioctl_ops *ioctl_ops; @@ -71,43 +78,48 @@ struct video_device /* dev to video-device */ #define to_video_device(cd) container_of(cd, struct video_device, dev) -/* Register and unregister devices. Note that if video_register_device fails, +/* Register video devices. Note that if video_register_device fails, the release() callback of the video_device structure is *not* called, so the caller is responsible for freeing any data. Usually that means that - you call video_device_release() on failure. */ -int __must_check video_register_device(struct video_device *vfd, int type, int nr); -int __must_check video_register_device_index(struct video_device *vfd, + you call video_device_release() on failure. + + Also note that vdev->minor is set to -1 if the registration failed. */ +int __must_check video_register_device(struct video_device *vdev, int type, int nr); +int __must_check video_register_device_index(struct video_device *vdev, int type, int nr, int index); -void video_unregister_device(struct video_device *vfd); + +/* Unregister video devices. Will do nothing if vdev == NULL or + vdev->minor < 0. */ +void video_unregister_device(struct video_device *vdev); /* helper functions to alloc/release struct video_device, the latter can also be used for video_device->release(). */ struct video_device * __must_check video_device_alloc(void); -/* this release function frees the vfd pointer */ -void video_device_release(struct video_device *vfd); +/* this release function frees the vdev pointer */ +void video_device_release(struct video_device *vdev); /* this release function does nothing, use when the video_device is a static global struct. Note that having a static video_device is a dubious construction at best. */ -void video_device_release_empty(struct video_device *vfd); +void video_device_release_empty(struct video_device *vdev); /* helper functions to access driver private data. */ -static inline void *video_get_drvdata(struct video_device *dev) +static inline void *video_get_drvdata(struct video_device *vdev) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - return class_get_devdata(&dev->dev); + return class_get_devdata(&vdev->dev); #else - return dev_get_drvdata(&dev->dev); + return dev_get_drvdata(&vdev->dev); #endif } -static inline void video_set_drvdata(struct video_device *dev, void *data) +static inline void video_set_drvdata(struct video_device *vdev, void *data) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - class_set_devdata(&dev->dev, data); + class_set_devdata(&vdev->dev, data); #else - dev_set_drvdata(&dev->dev, data); + dev_set_drvdata(&vdev->dev, data); #endif } @@ -120,4 +132,9 @@ static inline void *video_drvdata(struct file *file) return video_get_drvdata(video_devdata(file)); } +static inline int video_is_unregistered(struct video_device *vdev) +{ + return test_bit(V4L2_FL_UNREGISTERED, &vdev->flags); +} + #endif /* _V4L2_DEV_H */ diff --git a/v4l/compat.h b/v4l/compat.h index ad2d9df22..49c89ea2d 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -34,6 +34,7 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) #define set_freezable() #define cancel_delayed_work_sync cancel_rearming_delayed_work +#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) #endif #ifndef __pure -- cgit v1.2.3 From 1e0f865674f729f9f5e346a2f0f77bc3b297c51b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Dec 2008 08:17:10 -0200 Subject: tuner-core: add debug msg's when asking tuner to sleep From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index e649f2eb7..47b58fe98 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -737,6 +737,8 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, t->mode = mode; if (check_mode(t, cmd) == -EINVAL) { + tuner_dbg("Tuner doesn't support this mode. " + "Putting tuner to sleep\n"); t->mode = T_STANDBY; if (analog_ops->standby) analog_ops->standby(&t->fe); @@ -797,6 +799,8 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) struct tuner *t = to_tuner(sd); struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; + tuner_dbg("Putting tuner to sleep\n"); + if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL) return 0; t->mode = T_STANDBY; -- cgit v1.2.3 From 86e292e82d505fb16fd1e283905a65c5c603ec16 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Dec 2008 08:43:34 -0200 Subject: em28xx: Fix a bug that were putting xc2028/3028 tuner to sleep From: Mauro Carvalho Chehab The changeset 78aa52a159cf introduced a bug on em28xx: buffer setup should be awaking xc3028. Instead, since we didn't specify the tuner mode, the device were going to sleep, due to the lack of tuner mode when asking tuner to handle VIDIOC_S_FREQUENCY: xc2028 0-0061: Device is Xceive 3028 version 1.0, firmware version 2.7 xc2028 0-0061: divisor= 00 00 14 d0 (freq=83.250) xc2028 0-0061: Putting xc2028/3028 into poweroff mode. xc2028 0-0061: Printing sleep stack trace: Pid: 10936, comm: mplayer Tainted: P M 2.6.27.8 #1 Call Trace: [] xc2028_sleep+0x89/0x1ab [tuner_xc2028] [] tuner_s_frequency+0xf5/0x165 [tuner] Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 78eb335a5..6e4ee2d96 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -397,9 +397,10 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) if (*count < EM28XX_MIN_BUF) *count = EM28XX_MIN_BUF; - /* Ask tuner to go to analog mode */ + /* Ask tuner to go to analog or radio mode */ memset(&f, 0, sizeof(f)); f.frequency = dev->ctl_freq; + f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); -- cgit v1.2.3 From 1990a8c65fe2820d7426c83c1b0fe0cf13a1c4ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Dec 2008 10:06:37 -0200 Subject: em28xx: use a more standard way to specify video formats From: Mauro Carvalho Chehab This patch uses the same code for enumberating video formats that are present on cx88, bttv and saa7134 drivers. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-core.c | 17 +++++-- linux/drivers/media/video/em28xx/em28xx-video.c | 66 +++++++++++++++++++------ linux/drivers/media/video/em28xx/em28xx.h | 7 ++- 3 files changed, 69 insertions(+), 21 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index f62b05eae..2c975ffa4 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -621,10 +621,19 @@ int em28xx_capture_start(struct em28xx *dev, int start) return rc; } -int em28xx_outfmt_set_yuv422(struct em28xx *dev) +int em28xx_set_outfmt(struct em28xx *dev) { - em28xx_write_reg(dev, EM28XX_R27_OUTFMT, 0x34); - em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); + int ret; + + ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, + dev->format->reg | 0x20, 0x3f); + if (ret < 0) + return ret; + + ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); + if (ret < 0) + return ret; + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); } @@ -686,7 +695,7 @@ int em28xx_resolution_set(struct em28xx *dev) width = norm_maxw(dev); height = norm_maxh(dev) >> 1; - em28xx_outfmt_set_yuv422(dev); + em28xx_set_outfmt(dev); em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); return em28xx_scaler_set(dev, dev->hscale, dev->vscale); diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 6e4ee2d96..9fb9363dc 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -96,6 +96,16 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ static unsigned long em28xx_devused; +/* supported video standards */ +static struct em28xx_fmt format[] = { + { + .name = "16bpp YUY2, 4:2:2, packed", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .reg = 0x14, + }, +}; + /* supported controls */ /* Common to all boards */ static struct v4l2_queryctrl em28xx_qctrl[] = { @@ -390,7 +400,8 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) struct em28xx *dev = fh->dev; struct v4l2_frequency f; - *size = 16 * fh->dev->width * fh->dev->height >> 3; + *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; + if (0 == *count) *count = EM28XX_DEF_BUF; @@ -443,9 +454,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, struct em28xx *dev = fh->dev; int rc = 0, urb_init = 0; - /* FIXME: It assumes depth = 16 */ - /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = 16 * dev->width * dev->height >> 3; + buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; @@ -542,7 +551,7 @@ static int em28xx_config(struct em28xx *dev) dev->mute = 1; /* maybe not the right place... */ dev->volume = 0x1f; - em28xx_outfmt_set_yuv422(dev); + em28xx_set_outfmt(dev); em28xx_colorlevels_set_default(dev); em28xx_compression_disable(dev); @@ -710,8 +719,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - f->fmt.pix.bytesperline = dev->width * 2; + f->fmt.pix.pixelformat = dev->format->fourcc; + f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; @@ -723,6 +732,17 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, return 0; } +static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(format); i++) + if (format[i].fourcc == fourcc) + return &format[i]; + + return NULL; +} + static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { @@ -733,6 +753,14 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, unsigned int maxw = norm_maxw(dev); unsigned int maxh = norm_maxh(dev); unsigned int hscale, vscale; + struct em28xx_fmt *fmt; + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (!fmt) { + em28xx_videodbg("Fourcc format (%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } /* width must even because of the YUYV format height must be even because of interlacing */ @@ -771,9 +799,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width = width; f->fmt.pix.height = height; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - f->fmt.pix.bytesperline = width * 2; - f->fmt.pix.sizeimage = width * 2 * height; + f->fmt.pix.pixelformat = fmt->fourcc; + f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.field = V4L2_FIELD_INTERLACED; @@ -786,6 +814,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int rc; + struct em28xx_fmt *fmt; rc = check_dev(dev); if (rc < 0) @@ -795,6 +824,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, vidioc_try_fmt_vid_cap(file, priv, f); + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (!fmt) + return -EINVAL; + if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); rc = -EBUSY; @@ -810,6 +843,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, /* set new image size */ dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; + dev->format = fmt; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); em28xx_set_alternate(dev); @@ -1347,15 +1381,13 @@ static int vidioc_querycap(struct file *file, void *priv, } static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *fmtd) + struct v4l2_fmtdesc *f) { - if (fmtd->index != 0) + if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmtd->description, "Packed YUY2"); - fmtd->pixelformat = V4L2_PIX_FMT_YUYV; - memset(fmtd->reserved, 0, sizeof(fmtd->reserved)); + strlcpy(f->description, format[f->index].name, sizeof(f->description)); + f->pixelformat = format[f->index].fourcc; return 0; } @@ -2144,6 +2176,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->em28xx_write_regs_req = em28xx_write_regs_req; dev->em28xx_read_reg_req = em28xx_read_reg_req; dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; + dev->format = &format[0]; em28xx_pre_card_setup(dev); @@ -2565,3 +2598,4 @@ static void __exit em28xx_module_exit(void) module_init(em28xx_module_init); module_exit(em28xx_module_exit); + diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 4de9a8190..ae511ed7e 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -210,9 +210,12 @@ struct em28xx_usb_isoc_ctl { }; +/* Struct to enumberate video formats */ struct em28xx_fmt { char *name; u32 fourcc; /* v4l2 format id */ + int depth; + int reg; }; /* buffer for one video frame */ @@ -439,6 +442,8 @@ struct em28xx { unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; + struct em28xx_fmt *format; + struct em28xx_IR *ir; /* Some older em28xx chips needs a waiting time after writing */ @@ -577,7 +582,7 @@ int em28xx_audio_setup(struct em28xx *dev); int em28xx_colorlevels_set_default(struct em28xx *dev); int em28xx_capture_start(struct em28xx *dev, int start); -int em28xx_outfmt_set_yuv422(struct em28xx *dev); +int em28xx_set_outfmt(struct em28xx *dev); int em28xx_resolution_set(struct em28xx *dev); int em28xx_set_alternate(struct em28xx *dev); int em28xx_init_isoc(struct em28xx *dev, int max_packets, -- cgit v1.2.3 From 162b73a47b547cad436989665074bcb093d71c57 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Dec 2008 07:03:06 -0800 Subject: Convert GP8PSK module to use S2API From: Alan Nisota This patch converts the gp8psk module to use the S2API. It pretends to be DVB-S2 capable in order to allow the various supported modulations (8PSK, QPSK-Turbo, etc), and keep software compatibility with the S2API patches for Mythtv and VDR. Signed-off by: Alan Nisota Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c | 140 ++++++++++++++++++++++------ linux/drivers/media/dvb/dvb-usb/gp8psk.c | 2 - linux/drivers/media/dvb/dvb-usb/gp8psk.h | 1 + 3 files changed, 115 insertions(+), 28 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c index 262a858c3..20eadf931 100644 --- a/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c @@ -25,6 +25,20 @@ struct gp8psk_fe_state { unsigned long status_check_interval; }; +static int gp8psk_tuned_to_DCII(struct dvb_frontend *fe) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + u8 status; + gp8psk_usb_in_op(st->d, GET_8PSK_CONFIG, 0, 0, &status, 1); + return status & bmDCtuned; +} + +static int gp8psk_set_tuner_mode(struct dvb_frontend *fe, int mode) +{ + struct gp8psk_fe_state *state = fe->demodulator_priv; + return gp8psk_usb_out_op(state->d, SET_8PSK_CONFIG, mode, 0, NULL, 0); +} + static int gp8psk_fe_update_status(struct gp8psk_fe_state *st) { u8 buf[6]; @@ -99,39 +113,114 @@ static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front return 0; } +static int gp8psk_fe_set_property(struct dvb_frontend *fe, + struct dtv_property *tvp) +{ + deb_fe("%s(..)\n", __func__); + return 0; +} + +static int gp8psk_fe_get_property(struct dvb_frontend *fe, + struct dtv_property *tvp) +{ + deb_fe("%s(..)\n", __func__); + return 0; +} + + static int gp8psk_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) { struct gp8psk_fe_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; u8 cmd[10]; u32 freq = fep->frequency * 1000; + int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct); + + deb_fe("%s()\n", __func__); cmd[4] = freq & 0xff; cmd[5] = (freq >> 8) & 0xff; cmd[6] = (freq >> 16) & 0xff; cmd[7] = (freq >> 24) & 0xff; - switch(fe->ops.info.type) { - case FE_QPSK: - cmd[0] = fep->u.qpsk.symbol_rate & 0xff; - cmd[1] = (fep->u.qpsk.symbol_rate >> 8) & 0xff; - cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff; - cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff; - cmd[8] = ADV_MOD_DVB_QPSK; - cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/ + switch (c->delivery_system) { + case SYS_DVBS: + /* Only QPSK is supported for DVB-S */ + if (c->modulation != QPSK) { + deb_fe("%s: unsupported modulation selected (%d)\n", + __func__, c->modulation); + return -EOPNOTSUPP; + } + c->fec_inner = FEC_AUTO; break; + case SYS_DVBS2: + deb_fe("%s: DVB-S2 delivery system selected\n", __func__); + break; + default: - // other modes are unsuported right now - cmd[0] = 0; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[8] = 0; + deb_fe("%s: unsupported delivery system selected (%d)\n", + __func__, c->delivery_system); + return -EOPNOTSUPP; + } + + cmd[0] = c->symbol_rate & 0xff; + cmd[1] = (c->symbol_rate >> 8) & 0xff; + cmd[2] = (c->symbol_rate >> 16) & 0xff; + cmd[3] = (c->symbol_rate >> 24) & 0xff; + switch (c->modulation) { + case QPSK: + if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) + if (gp8psk_tuned_to_DCII(fe)) + gp8psk_bcm4500_reload(state->d); + switch (c->fec_inner) { + case FEC_1_2: + cmd[9] = 0; break; + case FEC_2_3: + cmd[9] = 1; break; + case FEC_3_4: + cmd[9] = 2; break; + case FEC_5_6: + cmd[9] = 3; break; + case FEC_7_8: + cmd[9] = 4; break; + case FEC_AUTO: + cmd[9] = 5; break; + default: + cmd[9] = 5; break; + } + cmd[8] = ADV_MOD_DVB_QPSK; + break; + case PSK_8: /* PSK_8 is for compatibility with DN */ + cmd[8] = ADV_MOD_TURBO_8PSK; + switch (c->fec_inner) { + case FEC_2_3: + cmd[9] = 0; break; + case FEC_3_4: + cmd[9] = 1; break; + case FEC_3_5: + cmd[9] = 2; break; + case FEC_5_6: + cmd[9] = 3; break; + case FEC_8_9: + cmd[9] = 4; break; + default: + cmd[9] = 0; break; + } + break; + case QAM_16: /* QAM_16 is for compatibility with DN */ + cmd[8] = ADV_MOD_TURBO_16QAM; cmd[9] = 0; break; + default: /* Unknown modulation */ + deb_fe("%s: unsupported modulation selected (%d)\n", + __func__, c->modulation); + return -EOPNOTSUPP; } - gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10); + if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) + gp8psk_set_tuner_mode(fe, 0); + gp8psk_usb_out_op(state->d, TUNE_8PSK, 0, 0, cmd, 10); state->lock = 0; state->next_status_check = jiffies; @@ -140,13 +229,6 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe, return 0; } -static int gp8psk_fe_get_frontend(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) -{ - return 0; -} - - static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *m) { @@ -261,9 +343,13 @@ static struct dvb_frontend_ops gp8psk_fe_ops = { .symbol_rate_max = 45000000, .symbol_rate_tolerance = 500, /* ppm */ .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + /* + * FE_CAN_QAM_16 is for compatibility + * (Myth incorrectly detects Turbo-QPSK as plain QAM-16) + */ + FE_CAN_QPSK | FE_CAN_QAM_16 }, .release = gp8psk_fe_release, @@ -271,8 +357,10 @@ static struct dvb_frontend_ops gp8psk_fe_ops = { .init = NULL, .sleep = NULL, + .set_property = gp8psk_fe_set_property, + .get_property = gp8psk_fe_get_property, .set_frontend = gp8psk_fe_set_frontend, - .get_frontend = gp8psk_fe_get_frontend, + .get_tune_settings = gp8psk_fe_get_tune_settings, .read_status = gp8psk_fe_read_status, diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk.c b/linux/drivers/media/dvb/dvb-usb/gp8psk.c index 1b002909b..c1da962cc 100644 --- a/linux/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.c @@ -174,7 +174,6 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) return 0; } -#if 0 int gp8psk_bcm4500_reload(struct dvb_usb_device *d) { u8 buf; @@ -191,7 +190,6 @@ int gp8psk_bcm4500_reload(struct dvb_usb_device *d) return EINVAL; return 0; } -#endif /* 0 */ static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk.h b/linux/drivers/media/dvb/dvb-usb/gp8psk.h index e5cd8149c..e83a57506 100644 --- a/linux/drivers/media/dvb/dvb-usb/gp8psk.h +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.h @@ -92,5 +92,6 @@ extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d); extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); +extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d); #endif -- cgit v1.2.3 From 45232ac0864b8ed7b275e20303a8175d18b1f3d4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 19 Dec 2008 16:36:48 -0800 Subject: tuner: fix tuner_ioctl build error From: Randy Dunlap Fix drivers/media/video/tuner-core.c so that it will build when CONFIG_VIDEO_ALLOW_V4L1=n: drivers/media/video/tuner-core.c:1111: error: 'tuner_ioctl' undeclared here (not in a function) Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 47b58fe98..fd62aa6bd 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -933,6 +933,11 @@ static int tuner_ioctl(struct v4l2_subdev *sd, int cmd, void *arg) } return -ENOIOCTLCMD; } +#else +static int tuner_ioctl(struct v4l2_subdev *sd, int cmd, void *arg) +{ + return -ENOIOCTLCMD; +} #endif static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg) -- cgit v1.2.3 From 02070de48e42d30eeb6dfa4ea2d3aeff1a0a980f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Dec 2008 13:14:03 +0100 Subject: v4l2-dbg: get-chip-ident has no arguments From: Hans Verkuil get-chip-ident expected an argument when none was needed. Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/util/v4l2-dbg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index e0d6153fe..31206a562 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -136,7 +136,7 @@ static struct option long_options[] = { {"set-register", required_argument, 0, OptSetRegister}, {"chip", required_argument, 0, OptChip}, {"scan-chip-idents", no_argument, 0, OptScanChipIdents}, - {"get-chip-ident", required_argument, 0, OptGetChipIdent}, + {"get-chip-ident", no_argument, 0, OptGetChipIdent}, {"info", no_argument, 0, OptGetDriverInfo}, {"verbose", no_argument, 0, OptVerbose}, {"log-status", no_argument, 0, OptLogStatus}, -- cgit v1.2.3 From f8c54503d6d27d303f307f24a889b96bc1ed6236 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 20 Dec 2008 18:30:58 +0100 Subject: gspca - pac207: Webcam 093a:2461 added. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 3 ++- linux/drivers/media/video/gspca/pac207.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index a55459456..ec00740e6 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -202,7 +202,8 @@ sunplus 08ca:2050 Medion MD 41437 sunplus 08ca:2060 Aiptek PocketDV5300 tv8532 0923:010f ICM532 cams mars 093a:050f Mars-Semi Pc-Camera -pac207 093a:2460 PAC207 Qtec Webcam 100 +pac207 093a:2460 Qtec Webcam 100 +pac207 093a:2461 HP Webcam pac207 093a:2463 Philips SPC 220 NC pac207 093a:2464 Labtec Webcam 1200 pac207 093a:2468 PAC207 diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c index 84bcaaf4d..e46b8e8f0 100644 --- a/linux/drivers/media/video/gspca/pac207.c +++ b/linux/drivers/media/video/gspca/pac207.c @@ -529,6 +529,7 @@ static const struct sd_desc sd_desc = { static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4028)}, {USB_DEVICE(0x093a, 0x2460)}, + {USB_DEVICE(0x093a, 0x2461)}, {USB_DEVICE(0x093a, 0x2463)}, {USB_DEVICE(0x093a, 0x2464)}, {USB_DEVICE(0x093a, 0x2468)}, -- cgit v1.2.3 From 51b7994a471b5bdb5d68cfd1af7743c3faa91268 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 20 Dec 2008 21:26:38 -0500 Subject: cx18: Disable locking of Video and Audio PLL for analog captures From: Andy Walls Disable AV_LOCK, locking of audio PLL to video PLL in the cx18-av-core for analog captures. It seems to have adverse effects on captures from SVideo and CVBS sources with current clock & crystal settings in the driver. Many thanks to Jeff Campbell and Mike Bradley for reporting this problem, and suggesting the solution and performing extensive testing to support their suggestion. Reported-by: Jeff Campbell Reported-by: Mike Bradley Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-audio.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-av-audio.c b/linux/drivers/media/video/cx18/cx18-av-audio.c index fd85b9b2d..148f71097 100644 --- a/linux/drivers/media/video/cx18/cx18-av-audio.c +++ b/linux/drivers/media/video/cx18/cx18-av-audio.c @@ -57,11 +57,11 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x12c, 0x11202fff); /* - * EN_AV_LOCK = 1 + * EN_AV_LOCK = 0 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 = * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8 */ - cx18_av_write4(cx, 0x128, 0xa10d2ef8); + cx18_av_write4(cx, 0x128, 0xa00d2ef8); break; case 44100: @@ -82,11 +82,11 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x12c, 0x112092ff); /* - * EN_AV_LOCK = 1 + * EN_AV_LOCK = 0 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 = * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8 */ - cx18_av_write4(cx, 0x128, 0xa11d4bf8); + cx18_av_write4(cx, 0x128, 0xa01d4bf8); break; case 48000: @@ -107,11 +107,11 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x12c, 0x11205fff); /* - * EN_AV_LOCK = 1 + * EN_AV_LOCK = 0 * VID_COUNT = 0x1193f8 = 143999.000 * 8 = * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8 */ - cx18_av_write4(cx, 0x128, 0xa11193f8); + cx18_av_write4(cx, 0x128, 0xa01193f8); break; } } else { @@ -141,11 +141,11 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x12c, 0x11201fff); /* - * EN_AV_LOCK = 1 + * EN_AV_LOCK = 0 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 = * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8 */ - cx18_av_write4(cx, 0x128, 0xa10d2ef8); + cx18_av_write4(cx, 0x128, 0xa00d2ef8); break; case 44100: @@ -170,11 +170,11 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x12c, 0x112061ff); /* - * EN_AV_LOCK = 1 + * EN_AV_LOCK = 0 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 = * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8 */ - cx18_av_write4(cx, 0x128, 0xa11d4bf8); + cx18_av_write4(cx, 0x128, 0xa01d4bf8); break; case 48000: @@ -199,11 +199,11 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x12c, 0x11203fff); /* - * EN_AV_LOCK = 1 + * EN_AV_LOCK = 0 * VID_COUNT = 0x1193f8 = 143999.000 * 8 = * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8 */ - cx18_av_write4(cx, 0x128, 0xa11193f8); + cx18_av_write4(cx, 0x128, 0xa01193f8); break; } } -- cgit v1.2.3 From bce583f51a7c7b70a1d1f922d5bf816df4f5766b Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 20 Dec 2008 21:48:57 -0500 Subject: cx18: Use a consistent crystal value for computing all PLL parameters From: Andy Walls Use a consistent crystal value of 28.636360 MHz for computing all PLL parameters so clocks don't have relative error due to assumed crystal value mismatches. Also aimed to have all PLLs run their VOCs at close to 400 MHz to minimze the error of these PLLs as frequency synthesizers. Also set the VDCLK and AIMCLK PLLs to sane values before the APU and CPU firmware are loaded. Also fixed I2S Master clock dividers. Many thanks to Mike Bradley and Jeff Campbell for reporting this problem and suggesting the solution, researching and experimenting, and performing extensive testing to support their suggested solution. Reported-by: Jeff Campbell Reported-by: Mike Bradley Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-audio.c | 165 +++++++++++++++++++------ linux/drivers/media/video/cx18/cx18-av-core.c | 2 +- linux/drivers/media/video/cx18/cx18-firmware.c | 69 ++++++++++- 3 files changed, 191 insertions(+), 45 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-av-audio.c b/linux/drivers/media/video/cx18/cx18-av-audio.c index 148f71097..a2f0ad570 100644 --- a/linux/drivers/media/video/cx18/cx18-av-audio.c +++ b/linux/drivers/media/video/cx18/cx18-av-audio.c @@ -31,27 +31,67 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) if (freq != 32000 && freq != 44100 && freq != 48000) return -EINVAL; - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ - cx18_av_write(cx, 0x127, 0x50); + /* + * The PLL parameters are based on the external crystal frequency that + * would ideally be: + * + * NTSC Color subcarrier freq * 8 = + * 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz + * + * The accidents of history and rationale that explain from where this + * combination of magic numbers originate can be found in: + * + * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in + * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80 + * + * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the + * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83 + * + * As Mike Bradley has rightly pointed out, it's not the exact crystal + * frequency that matters, only that all parts of the driver and + * firmware are using the same value (close to the ideal value). + * + * Since I have a strong suspicion that, if the firmware ever assumes a + * crystal value at all, it will assume 28.636360 MHz, the crystal + * freq used in calculations in this driver will be: + * + * xtal_freq = 28.636360 MHz + * + * an error of less than 0.13 ppm which is way, way better than any off + * the shelf crystal will have for accuracy anyway. + * + * Below I aim to run the PLLs' VCOs near 400 MHz to minimze error. + * + * Many thanks to Jeff Campbell and Mike Bradley for their extensive + * investigation, experimentation, testing, and suggested solutions of + * of audio/video sync problems with SVideo and CVBS captures. + */ if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { switch (freq) { case 32000: - /* VID_PLL and AUX_PLL */ - cx18_av_write4(cx, 0x108, 0x1408040f); + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20 + */ + cx18_av_write4(cx, 0x108, 0x200d040f); + + /* VID_PLL Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/ + cx18_av_write4(cx, 0x10c, 0x002be2fe); - /* AUX_PLL_FRAC */ - /* 0x8.9504318a * 28,636,363.636 / 0x14 = 32000 * 384 */ - cx18_av_write4(cx, 0x110, 0x012a0863); + /* AUX_PLL Fraction = 0x176740c */ + /* xtal * 0xd.bb3a060/0x20 = 32000 * 384: 393 MHz p-pd*/ + cx18_av_write4(cx, 0x110, 0x0176740c); /* src3/4/6_ctl */ - /* 0x1.f77f = (4 * 15734.26) / 32000 */ + /* 0x1.f77f = (4 * xtal/8*2/455) / 32000 */ cx18_av_write4(cx, 0x900, 0x0801f77f); cx18_av_write4(cx, 0x904, 0x0801f77f); cx18_av_write4(cx, 0x90c, 0x0801f77f); - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ - cx18_av_write(cx, 0x127, 0x54); + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */ + cx18_av_write(cx, 0x127, 0x60); /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */ cx18_av_write4(cx, 0x12c, 0x11202fff); @@ -65,19 +105,29 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) break; case 44100: - /* VID_PLL and AUX_PLL */ - cx18_av_write4(cx, 0x108, 0x1009040f); + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x18 + */ + cx18_av_write4(cx, 0x108, 0x180e040f); + + /* VID_PLL Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/ + cx18_av_write4(cx, 0x10c, 0x002be2fe); - /* AUX_PLL_FRAC */ - /* 0x9.7635e7 * 28,636,363.63 / 0x10 = 44100 * 384 */ - cx18_av_write4(cx, 0x110, 0x00ec6bce); + /* AUX_PLL Fraction = 0x062a1f2 */ + /* xtal * 0xe.3150f90/0x18 = 44100 * 384: 406 MHz p-pd*/ + cx18_av_write4(cx, 0x110, 0x0062a1f2); /* src3/4/6_ctl */ - /* 0x1.6d59 = (4 * 15734.26) / 44100 */ + /* 0x1.6d59 = (4 * xtal/8*2/455) / 44100 */ cx18_av_write4(cx, 0x900, 0x08016d59); cx18_av_write4(cx, 0x904, 0x08016d59); cx18_av_write4(cx, 0x90c, 0x08016d59); + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x18 */ + cx18_av_write(cx, 0x127, 0x58); + /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */ cx18_av_write4(cx, 0x12c, 0x112092ff); @@ -90,19 +140,29 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) break; case 48000: - /* VID_PLL and AUX_PLL */ - cx18_av_write4(cx, 0x108, 0x100a040f); + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x16 + */ + cx18_av_write4(cx, 0x108, 0x160e040f); - /* AUX_PLL_FRAC */ - /* 0xa.4c6b6ea * 28,636,363.63 / 0x10 = 48000 * 384 */ - cx18_av_write4(cx, 0x110, 0x0098d6dd); + /* VID_PLL Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/ + cx18_av_write4(cx, 0x10c, 0x002be2fe); + + /* AUX_PLL Fraction = 0x05227ad */ + /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz p-pd*/ + cx18_av_write4(cx, 0x110, 0x005227ad); /* src3/4/6_ctl */ - /* 0x1.4faa = (4 * 15734.26) / 48000 */ + /* 0x1.4faa = (4 * xtal/8*2/455) / 48000 */ cx18_av_write4(cx, 0x900, 0x08014faa); cx18_av_write4(cx, 0x904, 0x08014faa); cx18_av_write4(cx, 0x90c, 0x08014faa); + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ + cx18_av_write(cx, 0x127, 0x56); + /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */ cx18_av_write4(cx, 0x12c, 0x11205fff); @@ -117,12 +177,19 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) } else { switch (freq) { case 32000: - /* VID_PLL and AUX_PLL */ - cx18_av_write4(cx, 0x108, 0x1e08040f); + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x30 + */ + cx18_av_write4(cx, 0x108, 0x300d040f); + + /* VID_PLL Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/ + cx18_av_write4(cx, 0x10c, 0x002be2fe); - /* AUX_PLL_FRAC */ - /* 0x8.9504318 * 28,636,363.63 / 0x1e = 32000 * 256 */ - cx18_av_write4(cx, 0x110, 0x012a0863); + /* AUX_PLL Fraction = 0x176740c */ + /* xtal * 0xd.bb3a060/0x30 = 32000 * 256: 393 MHz p-pd*/ + cx18_av_write4(cx, 0x110, 0x0176740c); /* src1_ctl */ /* 0x1.0000 = 32000/32000 */ @@ -134,8 +201,8 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x904, 0x08020000); cx18_av_write4(cx, 0x90c, 0x08020000); - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ - cx18_av_write(cx, 0x127, 0x54); + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x30 */ + cx18_av_write(cx, 0x127, 0x70); /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */ cx18_av_write4(cx, 0x12c, 0x11201fff); @@ -149,12 +216,19 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) break; case 44100: - /* VID_PLL and AUX_PLL */ - cx18_av_write4(cx, 0x108, 0x1809040f); + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x24 + */ + cx18_av_write4(cx, 0x108, 0x240e040f); + + /* VID_PLL Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/ + cx18_av_write4(cx, 0x10c, 0x002be2fe); - /* AUX_PLL_FRAC */ - /* 0x9.7635e74 * 28,636,363.63 / 0x18 = 44100 * 256 */ - cx18_av_write4(cx, 0x110, 0x00ec6bce); + /* AUX_PLL Fraction = 0x062a1f2 */ + /* xtal * 0xe.3150f90/0x24 = 44100 * 256: 406 MHz p-pd*/ + cx18_av_write4(cx, 0x110, 0x0062a1f2); /* src1_ctl */ /* 0x1.60cd = 44100/32000 */ @@ -166,6 +240,9 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x904, 0x08017385); cx18_av_write4(cx, 0x90c, 0x08017385); + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x24 */ + cx18_av_write(cx, 0x127, 0x64); + /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */ cx18_av_write4(cx, 0x12c, 0x112061ff); @@ -178,12 +255,19 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) break; case 48000: - /* VID_PLL and AUX_PLL */ - cx18_av_write4(cx, 0x108, 0x180a040f); + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20 + */ + cx18_av_write4(cx, 0x108, 0x200d040f); - /* AUX_PLL_FRAC */ - /* 0xa.4c6b6ea * 28,636,363.63 / 0x18 = 48000 * 256 */ - cx18_av_write4(cx, 0x110, 0x0098d6dd); + /* VID_PLL Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/ + cx18_av_write4(cx, 0x10c, 0x002be2fe); + + /* AUX_PLL Fraction = 0x176740c */ + /* xtal * 0xd.bb3a060/0x20 = 48000 * 256: 393 MHz p-pd*/ + cx18_av_write4(cx, 0x110, 0x0176740c); /* src1_ctl */ /* 0x1.8000 = 48000/32000 */ @@ -195,6 +279,9 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq) cx18_av_write4(cx, 0x904, 0x08015555); cx18_av_write4(cx, 0x90c, 0x08015555); + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */ + cx18_av_write(cx, 0x127, 0x60); + /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */ cx18_av_write4(cx, 0x12c, 0x11203fff); diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 40ea6fde6..0b1c84b4d 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -271,7 +271,7 @@ void cx18_av_std_setup(struct cx18 *cx) if (pll_post) { int fin, fsc, pll; - pll = (28636364L * ((((u64)pll_int) << 25) + pll_frac)) >> 25; + pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25; pll /= pll_post; CX18_DEBUG_INFO("PLL = %d.%06d MHz\n", pll / 1000000, pll % 1000000); diff --git a/linux/drivers/media/video/cx18/cx18-firmware.c b/linux/drivers/media/video/cx18/cx18-firmware.c index e74f76d47..1fa95da15 100644 --- a/linux/drivers/media/video/cx18/cx18-firmware.c +++ b/linux/drivers/media/video/cx18/cx18-firmware.c @@ -26,6 +26,7 @@ #include "cx18-irq.h" #include "cx18-firmware.h" #include "cx18-cards.h" +#include "cx18-av-core.h" #include #define CX18_PROC_SOFT_RESET 0xc70010 @@ -224,7 +225,45 @@ void cx18_init_power(struct cx18 *cx, int lowpwr) cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL, 0x00000000, 0x00020002); - /* The fast clock is at 200/245 MHz */ + /* + * The PLL parameters are based on the external crystal frequency that + * would ideally be: + * + * NTSC Color subcarrier freq * 8 = + * 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz + * + * The accidents of history and rationale that explain from where this + * combination of magic numbers originate can be found in: + * + * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in + * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80 + * + * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the + * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83 + * + * As Mike Bradley has rightly pointed out, it's not the exact crystal + * frequency that matters, only that all parts of the driver and + * firmware are using the same value (close to the ideal value). + * + * Since I have a strong suspicion that, if the firmware ever assumes a + * crystal value at all, it will assume 28.636360 MHz, the crystal + * freq used in calculations in this driver will be: + * + * xtal_freq = 28.636360 MHz + * + * an error of less than 0.13 ppm which is way, way better than any off + * the shelf crystal will have for accuracy anyway. + * + * Below I aim to run the PLLs' VCOs near 400 MHz to minimze errors. + * + * Many thanks to Jeff Campbell and Mike Bradley for their extensive + * investigation, experimentation, testing, and suggested solutions of + * of audio/video sync problems with SVideo and CVBS captures. + */ + + /* the fast clock is at 200/245 MHz */ + /* 1 * xtal_freq * 0x0d.f7df9b8 / 2 = 200 MHz: 400 MHz pre post-divide*/ + /* 1 * xtal_freq * 0x11.1c71eb8 / 2 = 245 MHz: 490 MHz pre post-divide*/ cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC); @@ -234,16 +273,36 @@ void cx18_init_power(struct cx18 *cx, int lowpwr) cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); /* set slow clock to 125/120 MHz */ - cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); - cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8, + /* xtal_freq * 0x0d.1861a20 / 3 = 125 MHz: 375 MHz before post-divide */ + /* xtal_freq * 0x0c.92493f8 / 3 = 120 MHz: 360 MHz before post-divide */ + cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT); + cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F, CX18_SLOW_CLOCK_PLL_FRAC); - cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST); + cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST); /* mpeg clock pll 54MHz */ + /* xtal_freq * 0xf.15f17f0 / 8 = 54 MHz: 432 MHz before post-divide */ cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT); - cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); + cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC); cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST); + /* + * VDCLK Integer = 0x0f, Post Divider = 0x04 + * AIMCLK Integer = 0x0e, Post Divider = 0x16 + */ + cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); + + /* VDCLK Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ + cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); + + /* AIMCLK Fraction = 0x05227ad */ + /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz before post-divide */ + cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); + + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ + cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); + /* Defaults */ /* APU = SC or SC/2 = 125/62.5 */ /* EPU = SC = 125 */ -- cgit v1.2.3 From 50fbd8c40d2ae7f63c97281f404b9d3870af89a0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 21 Dec 2008 14:35:25 +0100 Subject: v4l2-compat32: fix 32-64 compatibility module From: Hans Verkuil Added all missing v4l1/2 ioctls and fix several broken conversions. Partially based on work done by Cody Pisto . Priority: normal Signed-off-by: Hans Verkuil Tested-by: Brandon Jenkins --- linux/drivers/media/video/v4l2-compat-ioctl32.c | 848 +++++++++++++----------- linux/include/linux/videodev2.h | 2 + 2 files changed, 471 insertions(+), 379 deletions(-) diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index 171f1ccd1..7a0c6b6a4 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -7,12 +7,14 @@ * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be) + * Copyright (C) 2008 Hans Verkuil * * These routines maintain argument size conversion between 32bit and 64bit * ioctls. */ #include +#define __OLD_VIDIOC_ /* To allow fixing old calls*/ #include #include #include @@ -59,55 +61,6 @@ static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user return 0; } -#if 0 /*FIXME */ -struct video_audio32 { - compat_int_t audio; - __u16 volume; - __u16 bass, treble; - __u32 flags; - __u8 name[16]; - __u16 mode; - __u16 balance; - __u16 step; -}; - -static int get_video_audio32(struct video_audio *kp, - struct video_audio32 __user *up) -{ - if (!access_ok(VERIFY_READ, up, sizeof(struct video_audio32)) || - get_user(kp->audio, &up->audio) || - get_user(kp->volume, &up->volume) || - get_user(kp->bass, &up->bass) || - get_user(kp->treble, &up->treble) || - get_user(kp->flags, &up->flags) || - copy_from_user(kp->name, up->name, sizeof(up->name)) || - get_user(kp->mode, &up->mode) || - get_user(kp->balance, &up->balance) || - get_user(kp->step, &up->step)) - return -EFAULT; - - return 0; -} - -static int put_video_audio32(struct video_audio *kp, - struct video_audio32 __user *up) -{ - if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_audio32)) || - put_user(kp->audio, &up->audio) || - put_user(kp->volume, &up->volume) || - put_user(kp->bass, &up->bass) || - put_user(kp->treble, &up->treble) || - put_user(kp->flags, &up->flags) || - copy_to_user(kp->name, up->name, sizeof(up->name)) || - put_user(kp->mode, &up->mode) || - put_user(kp->balance, &up->balance) || - put_user(kp->step, &up->step)) - return -EFAULT; - - return 0; -} -#endif - struct video_buffer32 { compat_caddr_t base; compat_int_t height, width, depth, bytesperline; @@ -148,7 +101,7 @@ static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __u } struct video_clip32 { - s32 x, y, width, height; /* Its really s32 in videodev.h */ + s32 x, y, width, height; /* It's really s32 in videodev.h */ compat_caddr_t next; }; @@ -157,29 +110,72 @@ struct video_window32 { compat_caddr_t clips; compat_int_t clipcount; }; -#endif -static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static int get_video_window32(struct video_window *kp, struct video_window32 __user *up) { - int ret = -ENOIOCTLCMD; + struct video_clip __user *uclips; + struct video_clip __user *kclips; + compat_caddr_t p; + int nclips; - if (file->f_op->unlocked_ioctl) - ret = file->f_op->unlocked_ioctl(file, cmd, arg); - else if (file->f_op->ioctl) { - lock_kernel(); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg); -#else - ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg); -#endif - unlock_kernel(); + if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32))) + return -EFAULT; + + if (get_user(nclips, &up->clipcount)) + return -EFAULT; + + if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)) || + get_user(kp->x, &up->x) || + get_user(kp->y, &up->y) || + get_user(kp->width, &up->width) || + get_user(kp->height, &up->height) || + get_user(kp->chromakey, &up->chromakey) || + get_user(kp->flags, &up->flags) || + get_user(kp->clipcount, &up->clipcount)) + return -EFAULT; + + nclips = kp->clipcount; + kp->clips = NULL; + + if (nclips == 0) + return 0; + if (get_user(p, &up->clips)) + return -EFAULT; + uclips = compat_ptr(p); + + /* If nclips < 0, then it is a clipping bitmap of size + VIDEO_CLIPMAP_SIZE */ + if (nclips < 0) { + if (!access_ok(VERIFY_READ, uclips, VIDEO_CLIPMAP_SIZE)) + return -EFAULT; + kp->clips = compat_alloc_user_space(VIDEO_CLIPMAP_SIZE); + if (copy_in_user(kp->clips, uclips, VIDEO_CLIPMAP_SIZE)) + return -EFAULT; + return 0; } - return ret; -} + /* Otherwise it is an array of video_clip structs. */ + if (!access_ok(VERIFY_READ, uclips, nclips * sizeof(struct video_clip))) + return -EFAULT; + kp->clips = compat_alloc_user_space(nclips * sizeof(struct video_clip)); + kclips = kp->clips; + while (nclips--) { + int err; + + err = copy_in_user(&kclips->x, &uclips->x, sizeof(kclips->x)); + err |= copy_in_user(&kclips->y, &uclips->y, sizeof(kclips->y)); + err |= copy_in_user(&kclips->width, &uclips->width, sizeof(kclips->width)); + err |= copy_in_user(&kclips->height, &uclips->height, sizeof(kclips->height)); + kclips->next = NULL; + if (err) + return -EFAULT; + kclips++; + uclips++; + } + return 0; +} -#ifdef CONFIG_VIDEO_V4L1_COMPAT /* You get back everything except the clips... */ static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) { @@ -194,8 +190,59 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u return -EFAULT; return 0; } + +struct video_code32 { + char loadwhat[16]; /* name or tag of file being passed */ + compat_int_t datasize; + unsigned char *data; +}; + +static int get_microcode32(struct video_code *kp, struct video_code32 __user *up) +{ + if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || + copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) || + get_user(kp->datasize, &up->datasize) || + copy_from_user(kp->data, up->data, up->datasize)) + return -EFAULT; + return 0; +} + +#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) +#define VIDIOCSTUNER32 _IOW('v', 5, struct video_tuner32) +#define VIDIOCGWIN32 _IOR('v', 9, struct video_window32) +#define VIDIOCSWIN32 _IOW('v', 10, struct video_window32) +#define VIDIOCGFBUF32 _IOR('v', 11, struct video_buffer32) +#define VIDIOCSFBUF32 _IOW('v', 12, struct video_buffer32) +#define VIDIOCGFREQ32 _IOR('v', 14, u32) +#define VIDIOCSFREQ32 _IOW('v', 15, u32) +#define VIDIOCSMICROCODE32 _IOW('v', 27, struct video_code32) + +#define VIDIOCCAPTURE32 _IOW('v', 8, s32) +#define VIDIOCSYNC32 _IOW('v', 18, s32) +#define VIDIOCSWRITEMODE32 _IOW('v', 25, s32) + #endif +static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = -ENOIOCTLCMD; + + if (file->f_op->unlocked_ioctl) + ret = file->f_op->unlocked_ioctl(file, cmd, arg); + else if (file->f_op->ioctl) { + lock_kernel(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg); +#else + ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg); +#endif + unlock_kernel(); + } + + return ret; +} + + struct v4l2_clip32 { struct v4l2_rect c; compat_caddr_t next; @@ -282,12 +329,27 @@ static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vb return 0; } +static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) +{ + if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format))) + return -EFAULT; + return 0; +} + +static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) +{ + if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format))) + return -EFAULT; + return 0; +} + struct v4l2_format32 { enum v4l2_buf_type type; union { - struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ - struct v4l2_window32 win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ - struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ + struct v4l2_pix_format pix; + struct v4l2_window32 win; + struct v4l2_vbi_format vbi; + struct v4l2_sliced_vbi_format sliced; __u8 raw_data[200]; /* user-defined */ } fmt; }; @@ -299,15 +361,27 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user return -EFAULT; switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); + case V4L2_BUF_TYPE_PRIVATE: + if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data))) + return -EFAULT; + return 0; + case 0: + return -EINVAL; default: - printk(KERN_INFO "compat_ioctl: unexpected VIDIOC_FMT type %d\n", + printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); - return -ENXIO; + return -EINVAL; } } @@ -318,31 +392,30 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user return -EFAULT; switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); + case V4L2_BUF_TYPE_PRIVATE: + if (copy_to_user(up, kp, sizeof(up->fmt.raw_data))) + return -EFAULT; + return 0; + case 0: + return -EINVAL; default: - return -ENXIO; + printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", + kp->type); + return -EINVAL; } } -static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_standard))) - return -EFAULT; - return 0; - -} - -static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_standard))) - return -EFAULT; - return 0; -} - struct v4l2_standard32 { __u32 index; __u32 id[2]; /* __u64 would get the alignment wrong */ @@ -374,21 +447,6 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 return 0; } -static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_tuner))) - return -EFAULT; - return 0; - -} - -static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_tuner))) - return -EFAULT; - return 0; -} - struct v4l2_buffer32 { __u32 index; enum v4l2_buf_type type; @@ -512,149 +570,143 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame return 0; } -static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) +struct v4l2_input32 { + __u32 index; /* Which input */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of input */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 tuner; /* Associated tuner */ + v4l2_std_id std; + __u32 status; + __u32 reserved[4]; +} __attribute__ ((packed)); + +/* The 64-bit v4l2_input struct has extra padding at the end of the struct. + Otherwise it is identical to the 32-bit version. */ +static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) { - if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) + if (copy_from_user(kp, up, sizeof(struct v4l2_input32))) return -EFAULT; return 0; } -static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) +static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) { - if (copy_from_user(kp, up, sizeof(struct v4l2_input))) + if (copy_to_user(up, kp, sizeof(struct v4l2_input32))) return -EFAULT; return 0; } -static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_input))) - return -EFAULT; - return 0; -} - -#ifdef CONFIG_VIDEO_V4L1_COMPAT -struct video_code32 { - char loadwhat[16]; /* name or tag of file being passed */ - compat_int_t datasize; - unsigned char *data; +struct v4l2_ext_controls32 { + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ }; -static inline int microcode32(struct video_code *kp, struct video_code32 __user *up) +static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || - copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) || - get_user(kp->datasize, &up->datasize) || - copy_from_user(kp->data, up->data, up->datasize)) + struct v4l2_ext_control __user *ucontrols; + struct v4l2_ext_control __user *kcontrols; + int n; + compat_caddr_t p; + + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || + get_user(kp->ctrl_class, &up->ctrl_class) || + get_user(kp->count, &up->count) || + get_user(kp->error_idx, &up->error_idx) || + copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) + return -EFAULT; + n = kp->count; + if (n == 0) { + kp->controls = NULL; + return 0; + } + if (get_user(p, &up->controls)) + return -EFAULT; + ucontrols = compat_ptr(p); + if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(struct v4l2_ext_control))) + return -EFAULT; + kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); + kp->controls = kcontrols; + while (--n >= 0) { + if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32))) return -EFAULT; + if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2))) + return -EFAULT; + /* Note: if the void * part of the union ever becomes relevant + then we need to know the type of the control in order to do + the right thing here. Luckily, that is not yet an issue. */ + if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value))) + return -EFAULT; + ucontrols++; + kcontrols++; + } return 0; } -#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) -#define VIDIOCSTUNER32 _IOW('v', 5, struct video_tuner32) -#define VIDIOCGWIN32 _IOR('v', 9, struct video_window32) -#define VIDIOCSWIN32 _IOW('v', 10, struct video_window32) -#define VIDIOCGFBUF32 _IOR('v', 11, struct video_buffer32) -#define VIDIOCSFBUF32 _IOW('v', 12, struct video_buffer32) -#define VIDIOCGFREQ32 _IOR('v', 14, u32) -#define VIDIOCSFREQ32 _IOW('v', 15, u32) -#define VIDIOCSMICROCODE32 _IOW('v', 27, struct video_code32) - -#endif - -/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */ -#define VIDIOC_ENUMINPUT32 (VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)) -#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32) -#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32) -#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32) -#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) -#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) -/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */ -#define VIDIOC_OVERLAY32 _IOWR ('V', 14, compat_int_t) -#define VIDIOC_QBUF32 _IOWR ('V', 15, struct v4l2_buffer32) -#define VIDIOC_DQBUF32 _IOWR ('V', 17, struct v4l2_buffer32) -#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t) -#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t) -#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32) -/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */ -#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control) -#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) -#define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t) -#define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32) - -#ifdef CONFIG_VIDEO_V4L1_COMPAT -enum { - MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip) -}; - -static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg) +static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) { - struct video_window32 __user *up = compat_ptr(arg); - struct video_window __user *vw; - struct video_clip __user *p; - int nclips; - u32 n; - - if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32))) - return -EFAULT; + struct v4l2_ext_control __user *ucontrols; + struct v4l2_ext_control __user *kcontrols = kp->controls; + int n = kp->count; + compat_caddr_t p; + + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || + put_user(kp->ctrl_class, &up->ctrl_class) || + put_user(kp->count, &up->count) || + put_user(kp->error_idx, &up->error_idx) || + copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) + return -EFAULT; + if (!kp->count) + return 0; - if (get_user(nclips, &up->clipcount)) + if (get_user(p, &up->controls)) return -EFAULT; - - /* Peculiar interface... */ - if (nclips < 0) - nclips = VIDEO_CLIPMAP_SIZE; - - if (nclips > MaxClips) - return -ENOMEM; - - vw = compat_alloc_user_space(sizeof(struct video_window) + - nclips * sizeof(struct video_clip)); - - p = nclips ? (struct video_clip __user *)(vw + 1) : NULL; - - if (get_user(n, &up->x) || put_user(n, &vw->x) || - get_user(n, &up->y) || put_user(n, &vw->y) || - get_user(n, &up->width) || put_user(n, &vw->width) || - get_user(n, &up->height) || put_user(n, &vw->height) || - get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) || - get_user(n, &up->flags) || put_user(n, &vw->flags) || - get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) || - get_user(n, &up->clips) || put_user(p, &vw->clips)) + ucontrols = compat_ptr(p); + if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(struct v4l2_ext_control))) return -EFAULT; - if (nclips) { - struct video_clip32 __user *u = compat_ptr(n); - int i; - if (!u) - return -EINVAL; - for (i = 0; i < nclips; i++, u++, p++) { - s32 v; - if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) || - !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) || - get_user(v, &u->x) || - put_user(v, &p->x) || - get_user(v, &u->y) || - put_user(v, &p->y) || - get_user(v, &u->width) || - put_user(v, &p->width) || - get_user(v, &u->height) || - put_user(v, &p->height) || - put_user(NULL, &p->next)) - return -EFAULT; - } + while (--n >= 0) { + if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32))) + return -EFAULT; + if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2, + sizeof(ucontrols->reserved2))) + return -EFAULT; + /* Note: if the void * part of the union ever becomes relevant + then we need to know the type of the control in order to do + the right thing here. Luckily, that is not yet an issue. */ + if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value))) + return -EFAULT; + ucontrols++; + kcontrols++; } - - return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw); + return 0; } -#endif + +#define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) +#define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) +#define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) +#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) +#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) +#define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) +#define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) +#define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) +#define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) +#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) +#define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) +#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) +#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) + +#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32) +#define VIDIOC_OVERLAY32_OLD _IOWR('V', 14, s32) +#define VIDIOC_STREAMON32 _IOW ('V', 18, s32) +#define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32) +#define VIDIOC_G_INPUT32 _IOR ('V', 38, s32) +#define VIDIOC_S_INPUT32 _IOWR('V', 39, s32) +#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32) +#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32) static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -669,45 +721,51 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg struct v4l2_format v2f; struct v4l2_buffer v2b; struct v4l2_framebuffer v2fb; - struct v4l2_standard v2s; struct v4l2_input v2i; - struct v4l2_tuner v2t; + struct v4l2_standard v2s; + struct v4l2_ext_controls v2ecs; unsigned long vx; + int vi; } karg; void __user *up = compat_ptr(arg); int compatible_arg = 1; int err = 0; - int realcmd = cmd; /* First, convert the command. */ switch (cmd) { #ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGTUNER32: realcmd = cmd = VIDIOCGTUNER; break; - case VIDIOCSTUNER32: realcmd = cmd = VIDIOCSTUNER; break; - case VIDIOCGWIN32: realcmd = cmd = VIDIOCGWIN; break; - case VIDIOCGFBUF32: realcmd = cmd = VIDIOCGFBUF; break; - case VIDIOCSFBUF32: realcmd = cmd = VIDIOCSFBUF; break; - case VIDIOCGFREQ32: realcmd = cmd = VIDIOCGFREQ; break; - case VIDIOCSFREQ32: realcmd = cmd = VIDIOCSFREQ; break; - case VIDIOCSMICROCODE32: realcmd = cmd = VIDIOCSMICROCODE; break; + case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; + case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; + case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; + case VIDIOCSWIN32: cmd = VIDIOCSWIN; break; + case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; + case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; + case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; + case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; + case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break; #endif - case VIDIOC_G_FMT32: realcmd = cmd = VIDIOC_G_FMT; break; - case VIDIOC_S_FMT32: realcmd = cmd = VIDIOC_S_FMT; break; - case VIDIOC_QUERYBUF32: realcmd = cmd = VIDIOC_QUERYBUF; break; - case VIDIOC_QBUF32: realcmd = cmd = VIDIOC_QBUF; break; - case VIDIOC_DQBUF32: realcmd = cmd = VIDIOC_DQBUF; break; - case VIDIOC_STREAMON32: realcmd = cmd = VIDIOC_STREAMON; break; - case VIDIOC_STREAMOFF32: realcmd = cmd = VIDIOC_STREAMOFF; break; - case VIDIOC_G_FBUF32: realcmd = cmd = VIDIOC_G_FBUF; break; - case VIDIOC_S_FBUF32: realcmd = cmd = VIDIOC_S_FBUF; break; - case VIDIOC_OVERLAY32: realcmd = cmd = VIDIOC_OVERLAY; break; - case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break; - case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break; - case VIDIOC_S_CTRL32: realcmd = cmd = VIDIOC_S_CTRL; break; - case VIDIOC_G_INPUT32: realcmd = cmd = VIDIOC_G_INPUT; break; - case VIDIOC_S_INPUT32: realcmd = cmd = VIDIOC_S_INPUT; break; - case VIDIOC_TRY_FMT32: realcmd = cmd = VIDIOC_TRY_FMT; break; - }; + case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; + case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; + case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; + case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; + case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; + case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break; + case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break; + case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break; + case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break; + case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; + case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break; + case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break; + case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break; + case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; + case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break; + case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; + case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; + case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; + case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; + case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break; + case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break; + } switch (cmd) { #ifdef CONFIG_VIDEO_V4L1_COMPAT @@ -715,7 +773,6 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg case VIDIOCGTUNER: err = get_video_tuner32(&karg.vt, up); compatible_arg = 0; - break; case VIDIOCSFBUF: @@ -723,25 +780,42 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg compatible_arg = 0; break; -#if 0 /*FIXME*/ - case VIDIOCSAUDIO: - err = get_video_audio32(&karg.va, up); + case VIDIOCSWIN: + err = get_video_window32(&karg.vw, up); + compatible_arg = 0; + break; + + case VIDIOCGWIN: + case VIDIOCGFBUF: + case VIDIOCGFREQ: + compatible_arg = 0; + break; + + case VIDIOCSMICROCODE: + err = get_microcode32(&karg.vc, up); compatible_arg = 0; break; -#endif case VIDIOCSFREQ: + err = get_user(karg.vx, (u32 __user *)up); + compatible_arg = 0; + break; + + case VIDIOCCAPTURE: + case VIDIOCSYNC: + case VIDIOCSWRITEMODE: #endif - case VIDIOC_S_INPUT: case VIDIOC_OVERLAY: case VIDIOC_STREAMON: case VIDIOC_STREAMOFF: - err = get_user(karg.vx, (u32 __user *)up); - compatible_arg = 1; + case VIDIOC_S_INPUT: + case VIDIOC_S_OUTPUT: + err = get_user(karg.vi, (s32 __user *)up); + compatible_arg = 0; break; - case VIDIOC_S_FBUF: - err = get_v4l2_framebuffer32(&karg.v2fb, up); + case VIDIOC_G_INPUT: + case VIDIOC_G_OUTPUT: compatible_arg = 0; break; @@ -759,127 +833,108 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg compatible_arg = 0; break; - case VIDIOC_ENUMSTD: - err = get_v4l2_standard(&karg.v2s, up); + case VIDIOC_S_FBUF: + err = get_v4l2_framebuffer32(&karg.v2fb, up); compatible_arg = 0; break; - case VIDIOC_ENUMSTD32: - err = get_v4l2_standard32(&karg.v2s, up); + case VIDIOC_G_FBUF: compatible_arg = 0; break; - case VIDIOC_ENUMINPUT: - err = get_v4l2_input(&karg.v2i, up); + case VIDIOC_ENUMSTD: + err = get_v4l2_standard32(&karg.v2s, up); compatible_arg = 0; break; - case VIDIOC_ENUMINPUT32: + case VIDIOC_ENUMINPUT: err = get_v4l2_input32(&karg.v2i, up); compatible_arg = 0; break; - case VIDIOC_G_TUNER: - case VIDIOC_S_TUNER: - err = get_v4l2_tuner(&karg.v2t, up); + case VIDIOC_G_EXT_CTRLS: + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: + err = get_v4l2_ext_controls32(&karg.v2ecs, up); compatible_arg = 0; break; - -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGWIN: - case VIDIOCGFBUF: - case VIDIOCGFREQ: -#endif - case VIDIOC_G_FBUF: - case VIDIOC_G_INPUT: - compatible_arg = 0; - break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCSMICROCODE: - err = microcode32(&karg.vc, up); - compatible_arg = 0; - break; -#endif - }; + } if (err) - goto out; + return err; if (compatible_arg) - err = native_ioctl(file, realcmd, (unsigned long)up); + err = native_ioctl(file, cmd, (unsigned long)up); else { mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); - err = native_ioctl(file, realcmd, (unsigned long)&karg); + err = native_ioctl(file, cmd, (unsigned long)&karg); set_fs(old_fs); } - if (err == 0) { - switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGTUNER: - err = put_video_tuner32(&karg.vt, up); - break; - - case VIDIOCGWIN: - err = put_video_window32(&karg.vw, up); - break; - - case VIDIOCGFBUF: - err = put_video_buffer32(&karg.vb, up); - break; -#if 0 /*FIXME*/ - case VIDIOCGAUDIO: - err = put_video_audio32(&karg.va, up); - break; -#endif -#endif - case VIDIOC_G_FBUF: - err = put_v4l2_framebuffer32(&karg.v2fb, up); - break; - - case VIDIOC_G_FMT: - case VIDIOC_S_FMT: - case VIDIOC_TRY_FMT: - err = put_v4l2_format32(&karg.v2f, up); - break; - - case VIDIOC_QUERYBUF: - case VIDIOC_QBUF: - case VIDIOC_DQBUF: - err = put_v4l2_buffer32(&karg.v2b, up); - break; - - case VIDIOC_ENUMSTD: - err = put_v4l2_standard(&karg.v2s, up); - break; - - case VIDIOC_ENUMSTD32: - err = put_v4l2_standard32(&karg.v2s, up); - break; - - case VIDIOC_G_TUNER: - case VIDIOC_S_TUNER: - err = put_v4l2_tuner(&karg.v2t, up); - break; - - case VIDIOC_ENUMINPUT: - err = put_v4l2_input(&karg.v2i, up); - break; - - case VIDIOC_ENUMINPUT32: - err = put_v4l2_input32(&karg.v2i, up); - break; + /* Special case: even after an error we need to put the + results back for these ioctls since the error_idx will + contain information on which control failed. */ + switch (cmd) { + case VIDIOC_G_EXT_CTRLS: + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: + if (put_v4l2_ext_controls32(&karg.v2ecs, up)) + err = -EFAULT; + break; + } + if (err) + return err; + switch (cmd) { #ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGFREQ: + case VIDIOCGTUNER: + err = put_video_tuner32(&karg.vt, up); + break; + + case VIDIOCGWIN: + err = put_video_window32(&karg.vw, up); + break; + + case VIDIOCGFBUF: + err = put_video_buffer32(&karg.vb, up); + break; + + case VIDIOCGFREQ: + err = put_user(((u32)karg.vx), (u32 __user *)up); + break; #endif - case VIDIOC_G_INPUT: - err = put_user(((u32)karg.vx), (u32 __user *)up); - break; - }; + case VIDIOC_S_INPUT: + case VIDIOC_S_OUTPUT: + case VIDIOC_G_INPUT: + case VIDIOC_G_OUTPUT: + err = put_user(((s32)karg.vi), (s32 __user *)up); + break; + + case VIDIOC_G_FBUF: + err = put_v4l2_framebuffer32(&karg.v2fb, up); + break; + + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: + err = put_v4l2_format32(&karg.v2f, up); + break; + + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + case VIDIOC_DQBUF: + err = put_v4l2_buffer32(&karg.v2b, up); + break; + + case VIDIOC_ENUMSTD: + err = put_v4l2_standard32(&karg.v2s, up); + break; + + case VIDIOC_ENUMINPUT: + err = put_v4l2_input32(&karg.v2i, up); + break; } -out: return err; } @@ -892,26 +947,48 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { #ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCSWIN32: - ret = do_set_window(file, cmd, arg); - break; + case VIDIOCGCAP: + case VIDIOCGCHAN: + case VIDIOCSCHAN: case VIDIOCGTUNER32: case VIDIOCSTUNER32: + case VIDIOCGPICT: + case VIDIOCSPICT: + case VIDIOCCAPTURE32: case VIDIOCGWIN32: + case VIDIOCSWIN32: case VIDIOCGFBUF32: case VIDIOCSFBUF32: + case VIDIOCKEY: case VIDIOCGFREQ32: case VIDIOCSFREQ32: case VIDIOCGAUDIO: case VIDIOCSAUDIO: + case VIDIOCSYNC32: + case VIDIOCMCAPTURE: + case VIDIOCGMBUF: + case VIDIOCGUNIT: + case VIDIOCGCAPTURE: + case VIDIOCSCAPTURE: + case VIDIOCSPLAYMODE: + case VIDIOCSWRITEMODE32: + case VIDIOCGPLAYINFO: + case VIDIOCSMICROCODE32: case VIDIOCGVBIFMT: case VIDIOCSVBIFMT: +#endif +#ifdef __OLD_VIDIOC_ + case VIDIOC_OVERLAY32_OLD: + case VIDIOC_S_PARM_OLD: + case VIDIOC_S_CTRL_OLD: + case VIDIOC_G_AUDIO_OLD: + case VIDIOC_G_AUDOUT_OLD: + case VIDIOC_CROPCAP_OLD: #endif case VIDIOC_QUERYCAP: + case VIDIOC_RESERVED: case VIDIOC_ENUM_FMT: case VIDIOC_G_FMT32: - case VIDIOC_CROPCAP: - case VIDIOC_S_CROP: case VIDIOC_S_FMT32: case VIDIOC_REQBUFS: case VIDIOC_QUERYBUF32: @@ -926,43 +1003,56 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_S_PARM: case VIDIOC_G_STD: case VIDIOC_S_STD: - case VIDIOC_G_TUNER: - case VIDIOC_S_TUNER: - case VIDIOC_ENUMSTD: case VIDIOC_ENUMSTD32: - case VIDIOC_ENUMINPUT: case VIDIOC_ENUMINPUT32: case VIDIOC_G_CTRL: case VIDIOC_S_CTRL: - case VIDIOC_S_CTRL32: - case VIDIOC_S_FREQUENCY: - case VIDIOC_G_FREQUENCY: + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + case VIDIOC_G_AUDIO: + case VIDIOC_S_AUDIO: case VIDIOC_QUERYCTRL: + case VIDIOC_QUERYMENU: case VIDIOC_G_INPUT32: case VIDIOC_S_INPUT32: + case VIDIOC_G_OUTPUT32: + case VIDIOC_S_OUTPUT32: + case VIDIOC_ENUMOUTPUT: + case VIDIOC_G_AUDOUT: + case VIDIOC_S_AUDOUT: + case VIDIOC_G_MODULATOR: + case VIDIOC_S_MODULATOR: + case VIDIOC_S_FREQUENCY: + case VIDIOC_G_FREQUENCY: + case VIDIOC_CROPCAP: + case VIDIOC_G_CROP: + case VIDIOC_S_CROP: + case VIDIOC_G_JPEGCOMP: + case VIDIOC_S_JPEGCOMP: + case VIDIOC_QUERYSTD: case VIDIOC_TRY_FMT32: - case VIDIOC_S_HW_FREQ_SEEK: + case VIDIOC_ENUMAUDIO: + case VIDIOC_ENUMAUDOUT: + case VIDIOC_G_PRIORITY: + case VIDIOC_S_PRIORITY: + case VIDIOC_G_SLICED_VBI_CAP: + case VIDIOC_LOG_STATUS: + case VIDIOC_G_EXT_CTRLS32: + case VIDIOC_S_EXT_CTRLS32: + case VIDIOC_TRY_EXT_CTRLS32: case VIDIOC_ENUM_FRAMESIZES: case VIDIOC_ENUM_FRAMEINTERVALS: + case VIDIOC_G_ENC_INDEX: + case VIDIOC_ENCODER_CMD: + case VIDIOC_TRY_ENCODER_CMD: + case VIDIOC_DBG_S_REGISTER: + case VIDIOC_DBG_G_REGISTER: + case VIDIOC_G_CHIP_IDENT: + case VIDIOC_S_HW_FREQ_SEEK: ret = do_video_ioctl(file, cmd, arg); break; #ifdef CONFIG_VIDEO_V4L1_COMPAT - /* Little v, the video4linux ioctls (conflict?) */ - case VIDIOCGCAP: - case VIDIOCGCHAN: - case VIDIOCSCHAN: - case VIDIOCGPICT: - case VIDIOCSPICT: - case VIDIOCCAPTURE: - case VIDIOCKEY: - case VIDIOCSYNC: - case VIDIOCMCAPTURE: - case VIDIOCGMBUF: - case VIDIOCGUNIT: - case VIDIOCGCAPTURE: - case VIDIOCSCAPTURE: - /* BTTV specific... */ case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]): case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]): diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 6ee771108..09cfcc43c 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1465,6 +1465,8 @@ struct v4l2_chip_ident { #define VIDIOC_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_chip_ident) #endif #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) +/* Reminder: when adding new ioctls please add support for them to + drivers/media/video/v4l2-compat-ioctl32.c as well! */ #ifdef __OLD_VIDIOC_ /* for compatibility, will go away some day */ -- cgit v1.2.3 From 1d90c2c80c8473756389c25bd3871c3a1eebbf3c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 21 Dec 2008 14:38:12 +0100 Subject: ioctl-test: Support all ioctls, improve output and add additional checks From: Hans Verkuil Improved ioctl-test so that it can be used for compat32 testing. Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/test/ioctl-test.c | 352 ++++++++++++++++++++++++-------------------- 1 file changed, 192 insertions(+), 160 deletions(-) diff --git a/v4l2-apps/test/ioctl-test.c b/v4l2-apps/test/ioctl-test.c index 99ad717e5..37a0e2374 100644 --- a/v4l2-apps/test/ioctl-test.c +++ b/v4l2-apps/test/ioctl-test.c @@ -2,9 +2,6 @@ v4l-ioctl-test - This small utility sends dumb v4l2 ioctl to a device. It is meant to check ioctl debug messages generated and to check if a function is implemented by that device. - flag INTERNAL will send v4l internal messages, defined at v4l2-common.h - and v4l_decoder.h. These messages shouldn't be handled by video - driver itself, but for internal video and/or audio decoders. Copyright (C) 2005 Mauro Carvalho Chehab @@ -23,212 +20,247 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - * Internal ioctl doesn't work anymore, due to the changes at - * v4l2-dev.h. - */ -//#define INTERNAL 1 /* meant for testing ioctl debug msgs */ - #include #include #include +#include #include #include #include #include -#include "linux/videodev.h" -#ifdef INTERNAL -typedef __u8 u8; -typedef __u32 u32; -#include -#include -#include -#else -typedef u_int32_t u32; -#endif +#define __OLD_VIDIOC_ +#include "linux/videodev.h" /* All possible parameters used on v4l ioctls */ union v4l_parms { int i; - unsigned long u64; - u32 u32; + unsigned long ulong; + u_int32_t u32; v4l2_std_id id; + enum v4l2_priority prio; #ifdef CONFIG_VIDEO_V4L1_COMPAT /* V4L1 structs */ - struct vbi_format p_vbi_format; - struct video_audio p_video_audio; - struct video_buffer p_video_buffer; struct video_capability p_video_capability; - struct video_capture p_video_capture; struct video_channel p_video_channel; - struct video_code p_video_code; - struct video_info p_video_info; + struct video_tuner p_video_tuner; + struct video_picture p_video_picture; + struct video_window p_video_window; + struct video_buffer p_video_buffer; struct video_key p_video_key; - struct video_mbuf p_video_mbuf; + struct video_audio p_video_audio; struct video_mmap p_video_mmap; - struct video_picture p_video_picture; - struct video_play_mode p_video_play_mode; - struct video_tuner p_video_tuner; + struct video_mbuf p_video_mbuf; struct video_unit p_video_unit; - struct video_window p_video_window; + struct video_capture p_video_capture; + struct video_play_mode p_video_play_mode; + struct video_info p_video_info; + struct video_code p_video_code; + struct vbi_format p_vbi_format; #endif /* V4L2 structs */ - struct v4l2_audioout p_v4l2_audioout; - struct v4l2_audio p_v4l2_audio; - struct v4l2_buffer p_v4l2_buffer; - struct v4l2_control p_v4l2_control; - struct v4l2_cropcap p_v4l2_cropcap; - struct v4l2_crop p_v4l2_crop; + struct v4l2_capability p_v4l2_capability; struct v4l2_fmtdesc p_v4l2_fmtdesc; struct v4l2_format p_v4l2_format; - struct v4l2_frequency p_v4l2_frequency; - struct v4l2_input p_v4l2_input; - struct v4l2_modulator p_v4l2_modulator; - struct v4l2_output p_v4l2_output; - struct v4l2_queryctrl p_v4l2_queryctrl; - struct v4l2_querymenu p_v4l2_querymenu; struct v4l2_requestbuffers p_v4l2_requestbuffers; - struct v4l2_standard p_v4l2_standard; + struct v4l2_buffer p_v4l2_buffer; + struct v4l2_framebuffer p_v4l2_framebuffer; struct v4l2_streamparm p_v4l2_streamparm; + struct v4l2_standard p_v4l2_standard; + struct v4l2_input p_v4l2_input; + struct v4l2_control p_v4l2_control; struct v4l2_tuner p_v4l2_tuner; - -#ifdef INTERNAL - /* Decoder structs */ - - struct video_decoder_capability p_video_decoder_capability; - struct video_decoder_init p_video_decoder_init; - - /* Internal V4L2 structs */ + struct v4l2_audio p_v4l2_audio; + struct v4l2_queryctrl p_v4l2_queryctrl; + struct v4l2_querymenu p_v4l2_querymenu; + struct v4l2_output p_v4l2_output; + struct v4l2_audioout p_v4l2_audioout; + struct v4l2_modulator p_v4l2_modulator; + struct v4l2_frequency p_v4l2_frequency; + struct v4l2_cropcap p_v4l2_cropcap; + struct v4l2_crop p_v4l2_crop; + struct v4l2_jpegcompression p_v4l2_jpegcompression; + struct v4l2_sliced_vbi_cap p_v4l2_sliced_vbi_cap; + struct v4l2_ext_controls p_v4l2_ext_controls; + struct v4l2_frmsizeenum p_v4l2_frmsizeenum; + struct v4l2_frmivalenum p_v4l2_frmivalenum; + struct v4l2_enc_idx p_v4l2_enc_idx; + struct v4l2_encoder_cmd p_v4l2_encoder_cmd; struct v4l2_register p_v4l2_register; - struct v4l2_sliced_vbi_data p_v4l2_sliced_vbi_data; -#endif + struct v4l2_chip_ident p_v4l2_chip_ident; + struct v4l2_hw_freq_seek p_v4l2_hw_freq_seek; }; +#define ioc(cmd) { cmd, #cmd } + /* All defined ioctls */ -int ioctls[] = { +static const struct { + u_int32_t cmd; + const char *name; +} ioctls[] = { #ifdef CONFIG_VIDEO_V4L1_COMPAT - /* V4L ioctls */ - VIDIOCCAPTURE,/* int */ - VIDIOCGAUDIO,/* struct video_audio */ - VIDIOCGCAP,/* struct video_capability */ - VIDIOCGCAPTURE,/* struct video_capture */ - VIDIOCGCHAN,/* struct video_channel */ - VIDIOCGFBUF,/* struct video_buffer */ - VIDIOCGFREQ,/* unsigned long */ - VIDIOCGMBUF,/* struct video_mbuf */ - VIDIOCGPICT,/* struct video_picture */ - VIDIOCGPLAYINFO,/* struct video_info */ - VIDIOCGTUNER,/* struct video_tuner */ - VIDIOCGUNIT,/* struct video_unit */ - VIDIOCGVBIFMT,/* struct vbi_format */ - VIDIOCGWIN,/* struct video_window */ - VIDIOCKEY,/* struct video_key */ - VIDIOCMCAPTURE,/* struct video_mmap */ - VIDIOCSAUDIO,/* struct video_audio */ - VIDIOCSCAPTURE,/* struct video_capture */ - VIDIOCSCHAN,/* struct video_channel */ - VIDIOCSFBUF,/* struct video_buffer */ - VIDIOCSFREQ,/* unsigned long */ - VIDIOCSMICROCODE,/* struct video_code */ - VIDIOCSPICT,/* struct video_picture */ - VIDIOCSPLAYMODE,/* struct video_play_mode */ - VIDIOCSTUNER,/* struct video_tuner */ - VIDIOCSVBIFMT,/* struct vbi_format */ - VIDIOCSWIN,/* struct video_window */ - VIDIOCSWRITEMODE,/* int */ - VIDIOCSYNC,/* int */ + /* V4L1 ioctls */ + ioc(VIDIOCGCAP), /* struct video_capability */ + ioc(VIDIOCGCHAN), /* struct video_channel */ + ioc(VIDIOCSCHAN), /* struct video_channel */ + ioc(VIDIOCGTUNER), /* struct video_tuner */ + ioc(VIDIOCSTUNER), /* struct video_tuner */ + ioc(VIDIOCGPICT), /* struct video_picture */ + ioc(VIDIOCSPICT), /* struct video_picture */ + ioc(VIDIOCCAPTURE), /* int */ + ioc(VIDIOCGWIN), /* struct video_window */ + ioc(VIDIOCSWIN), /* struct video_window */ + ioc(VIDIOCGFBUF), /* struct video_buffer */ + ioc(VIDIOCSFBUF), /* struct video_buffer */ + ioc(VIDIOCKEY), /* struct video_key */ + ioc(VIDIOCGFREQ), /* unsigned long */ + ioc(VIDIOCSFREQ), /* unsigned long */ + ioc(VIDIOCGAUDIO), /* struct video_audio */ + ioc(VIDIOCSAUDIO), /* struct video_audio */ + ioc(VIDIOCSYNC), /* int */ + ioc(VIDIOCMCAPTURE), /* struct video_mmap */ + ioc(VIDIOCGMBUF), /* struct video_mbuf */ + ioc(VIDIOCGUNIT), /* struct video_unit */ + ioc(VIDIOCGCAPTURE), /* struct video_capture */ + ioc(VIDIOCSCAPTURE), /* struct video_capture */ + ioc(VIDIOCSPLAYMODE), /* struct video_play_mode */ + ioc(VIDIOCSWRITEMODE), /* int */ + ioc(VIDIOCGPLAYINFO), /* struct video_info */ + ioc(VIDIOCSMICROCODE), /* struct video_code */ + ioc(VIDIOCGVBIFMT), /* struct vbi_format */ + ioc(VIDIOCSVBIFMT), /* struct vbi_format */ #endif /* V4L2 ioctls */ - - VIDIOC_CROPCAP,/* struct v4l2_cropcap */ - VIDIOC_DQBUF,/* struct v4l2_buffer */ - VIDIOC_ENUMAUDIO,/* struct v4l2_audio */ - VIDIOC_ENUMAUDOUT,/* struct v4l2_audioout */ - VIDIOC_ENUM_FMT,/* struct v4l2_fmtdesc */ - VIDIOC_ENUMINPUT,/* struct v4l2_input */ - VIDIOC_G_INPUT,/* int */ - VIDIOC_S_INPUT,/* int */ - VIDIOC_ENUMOUTPUT,/* struct v4l2_output */ - VIDIOC_ENUMSTD,/* struct v4l2_standard */ - VIDIOC_G_STD, /*v4l2_std_id */ - VIDIOC_S_STD, /*v4l2_std_id */ - VIDIOC_G_CROP,/* struct v4l2_crop */ - VIDIOC_G_CTRL,/* struct v4l2_control */ - VIDIOC_G_FMT,/* struct v4l2_format */ - VIDIOC_G_FREQUENCY,/* struct v4l2_frequency */ - VIDIOC_G_MODULATOR,/* struct v4l2_modulator */ - VIDIOC_G_PARM,/* struct v4l2_streamparm */ - VIDIOC_G_TUNER,/* struct v4l2_tuner */ - VIDIOC_QBUF,/* struct v4l2_buffer */ - VIDIOC_QUERYBUF,/* struct v4l2_buffer */ - VIDIOC_QUERYCTRL,/* struct v4l2_queryctrl */ - VIDIOC_QUERYMENU,/* struct v4l2_querymenu */ - VIDIOC_REQBUFS,/* struct v4l2_requestbuffers */ - VIDIOC_S_CTRL,/* struct v4l2_control */ - VIDIOC_S_FMT,/* struct v4l2_format */ - VIDIOC_S_INPUT,/* int */ - VIDIOC_S_OUTPUT,/* int */ - VIDIOC_S_PARM,/* struct v4l2_streamparm */ - VIDIOC_TRY_FMT,/* struct v4l2_format */ - -#if 0 - VIDIOC_G_AUDIO_OLD,/* struct v4l2_audio */ - VIDIOC_G_AUDOUT_OLD,/* struct v4l2_audioout */ - VIDIOC_OVERLAY_OLD,/* int */ -#endif - -#ifdef INTERNAL - /* V4L2 internal ioctls */ - AUDC_SET_RADIO,/* no args */ - TDA9887_SET_CONFIG,/* int */ - TUNER_SET_STANDBY,/* int */ - TUNER_SET_TYPE_ADDR,/* int */ - - VIDIOC_INT_AUDIO_CLOCK_FREQ,/* u32 */ - VIDIOC_INT_G_CHIP_IDENT,/* enum v4l2_chip_ident * */ - VIDIOC_INT_I2S_CLOCK_FREQ,/* u32 */ - VIDIOC_INT_S_REGISTER,/* struct v4l2_register */ - VIDIOC_INT_S_VBI_DATA,/* struct v4l2_sliced_vbi_data */ - - /* Decoder ioctls */ - DECODER_ENABLE_OUTPUT,/* int */ - DECODER_GET_CAPABILITIES,/* struct video_decoder_capability */ - DECODER_GET_STATUS,/* int */ - DECODER_INIT,/* struct video_decoder_init */ - DECODER_SET_GPIO,/* int */ - DECODER_SET_INPUT,/* int */ - DECODER_SET_NORM,/* int */ - DECODER_SET_OUTPUT,/* int */ - DECODER_SET_PICTURE,/* struct video_picture */ - DECODER_SET_VBI_BYPASS,/* int */ + ioc(VIDIOC_QUERYCAP), /* struct v4l2_capability */ + ioc(VIDIOC_RESERVED), + ioc(VIDIOC_ENUM_FMT), /* struct v4l2_fmtdesc */ + ioc(VIDIOC_G_FMT), /* struct v4l2_format */ + ioc(VIDIOC_S_FMT), /* struct v4l2_format */ + ioc(VIDIOC_REQBUFS), /* struct v4l2_requestbuffers */ + ioc(VIDIOC_QUERYBUF), /* struct v4l2_buffer */ + ioc(VIDIOC_G_FBUF), /* struct v4l2_framebuffer */ + ioc(VIDIOC_S_FBUF), /* struct v4l2_framebuffer */ + ioc(VIDIOC_OVERLAY), /* int */ + ioc(VIDIOC_QBUF), /* struct v4l2_buffer */ + ioc(VIDIOC_DQBUF), /* struct v4l2_buffer */ + ioc(VIDIOC_STREAMON), /* int */ + ioc(VIDIOC_STREAMOFF), /* int */ + ioc(VIDIOC_G_PARM), /* struct v4l2_streamparm */ + ioc(VIDIOC_S_PARM), /* struct v4l2_streamparm */ + ioc(VIDIOC_G_STD), /* v4l2_std_id */ + ioc(VIDIOC_S_STD), /* v4l2_std_id */ + ioc(VIDIOC_ENUMSTD), /* struct v4l2_standard */ + ioc(VIDIOC_ENUMINPUT), /* struct v4l2_input */ + ioc(VIDIOC_G_CTRL), /* struct v4l2_control */ + ioc(VIDIOC_S_CTRL), /* struct v4l2_control */ + ioc(VIDIOC_G_TUNER), /* struct v4l2_tuner */ + ioc(VIDIOC_S_TUNER), /* struct v4l2_tuner */ + ioc(VIDIOC_G_AUDIO), /* struct v4l2_audio */ + ioc(VIDIOC_S_AUDIO), /* struct v4l2_audio */ + ioc(VIDIOC_QUERYCTRL), /* struct v4l2_queryctrl */ + ioc(VIDIOC_QUERYMENU), /* struct v4l2_querymenu */ + ioc(VIDIOC_G_INPUT), /* int */ + ioc(VIDIOC_S_INPUT), /* int */ + ioc(VIDIOC_G_OUTPUT), /* int */ + ioc(VIDIOC_S_OUTPUT), /* int */ + ioc(VIDIOC_ENUMOUTPUT), /* struct v4l2_output */ + ioc(VIDIOC_G_AUDOUT), /* struct v4l2_audioout */ + ioc(VIDIOC_S_AUDOUT), /* struct v4l2_audioout */ + ioc(VIDIOC_G_MODULATOR), /* struct v4l2_modulator */ + ioc(VIDIOC_S_MODULATOR), /* struct v4l2_modulator */ + ioc(VIDIOC_G_FREQUENCY), /* struct v4l2_frequency */ + ioc(VIDIOC_S_FREQUENCY), /* struct v4l2_frequency */ + ioc(VIDIOC_CROPCAP), /* struct v4l2_cropcap */ + ioc(VIDIOC_G_CROP), /* struct v4l2_crop */ + ioc(VIDIOC_S_CROP), /* struct v4l2_crop */ + ioc(VIDIOC_G_JPEGCOMP), /* struct v4l2_jpegcompression */ + ioc(VIDIOC_S_JPEGCOMP), /* struct v4l2_jpegcompression */ + ioc(VIDIOC_QUERYSTD), /* v4l2_std_id */ + ioc(VIDIOC_TRY_FMT), /* struct v4l2_format */ + ioc(VIDIOC_ENUMAUDIO), /* struct v4l2_audio */ + ioc(VIDIOC_ENUMAUDOUT), /* struct v4l2_audioout */ + ioc(VIDIOC_G_PRIORITY), /* enum v4l2_priority */ + ioc(VIDIOC_S_PRIORITY), /* enum v4l2_priority */ + ioc(VIDIOC_G_SLICED_VBI_CAP), /* struct v4l2_sliced_vbi_cap */ + ioc(VIDIOC_LOG_STATUS), + ioc(VIDIOC_G_EXT_CTRLS), /* struct v4l2_ext_controls */ + ioc(VIDIOC_S_EXT_CTRLS), /* struct v4l2_ext_controls */ + ioc(VIDIOC_TRY_EXT_CTRLS), /* struct v4l2_ext_controls */ + ioc(VIDIOC_ENUM_FRAMESIZES), /* struct v4l2_frmsizeenum */ + ioc(VIDIOC_ENUM_FRAMEINTERVALS),/* struct v4l2_frmivalenum */ + ioc(VIDIOC_G_ENC_INDEX), /* struct v4l2_enc_idx */ + ioc(VIDIOC_ENCODER_CMD), /* struct v4l2_encoder_cmd */ + ioc(VIDIOC_TRY_ENCODER_CMD), /* struct v4l2_encoder_cmd */ + ioc(VIDIOC_DBG_S_REGISTER), /* struct v4l2_register */ + ioc(VIDIOC_DBG_G_REGISTER), /* struct v4l2_register */ + ioc(VIDIOC_G_CHIP_IDENT), /* struct v4l2_chip_ident */ + ioc(VIDIOC_S_HW_FREQ_SEEK), /* struct v4l2_hw_freq_seek */ +#ifdef __OLD_VIDIOC_ + ioc(VIDIOC_OVERLAY_OLD), /* int */ + ioc(VIDIOC_S_PARM_OLD), /* struct v4l2_streamparm */ + ioc(VIDIOC_S_CTRL_OLD), /* struct v4l2_control */ + ioc(VIDIOC_G_AUDIO_OLD), /* struct v4l2_audio */ + ioc(VIDIOC_G_AUDOUT_OLD), /* struct v4l2_audioout */ + ioc(VIDIOC_CROPCAP_OLD), /* struct v4l2_cropcap */ #endif }; #define S_IOCTLS sizeof(ioctls)/sizeof(ioctls[0]) /********************************************************************/ -int main (void) +int main(int argc, char **argv) { - int fd=0, ret=0; + int fd = 0, ret = 0; unsigned i; - char *device="/dev/video0"; - union v4l_parms p; + unsigned maxlen = 0; + char *device = "/dev/video0"; + char marker[8] = { 0xde, 0xad, 0xbe, 0xef, 0xad, 0xbc, 0xcb, 0xda }; + char p[sizeof(union v4l_parms) + 2 * sizeof(marker)]; + static const char *dirs[] = { + " IO", + " IOW", + " IOR", + "IOWR" + }; + if (argv[1]) + device = argv[1]; if ((fd = open(device, O_RDONLY)) < 0) { - perror("Couldn't open video0"); - return(-1); + fprintf(stderr, "Couldn't open %s\n", device); + return -1; } - for (i=0;i maxlen) + maxlen = strlen(ioctls[i].name); } - close (fd); + for (i = 0; i < S_IOCTLS; i++) { + char buf[maxlen + 100]; + const char *name = ioctls[i].name; + u_int32_t cmd = ioctls[i].cmd; + int dir = _IOC_DIR(cmd); + char type = _IOC_TYPE(cmd); + int nr = _IOC_NR(cmd); + int sz = _IOC_SIZE(cmd); - return (0); + /* Check whether the front and back markers aren't overwritten. + Useful to verify the compat32 code. */ + memset(&p, 0, sizeof(p)); + memcpy(p, marker, sizeof(marker)); + memcpy(p + sz + sizeof(marker), marker, sizeof(marker)); + sprintf(buf, "ioctl 0x%08x = %s('%c', %2d, %4d) = %-*s", + cmd, dirs[dir], type, nr, sz, maxlen, name); + errno = 0; + ret = ioctl(fd, cmd, (void *)&p[sizeof(marker)]); + perror(buf); + if (memcmp(p, marker, sizeof(marker))) + fprintf(stderr, "%s: front marker overwritten!\n", name); + if (memcmp(p + sizeof(marker) + sz, marker, sizeof(marker))) + fprintf(stderr, "%s: back marker overwritten!\n", name); + } + close (fd); + return 0; } -- cgit v1.2.3 From 1fe56e49c1de689d7f2bcc334ff2eea0f4d794bd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 21 Dec 2008 14:44:24 +0100 Subject: v4l2-compat32: add two additional #ifdef __OLD_VIDIOC_ lines From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-compat-ioctl32.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index 7a0c6b6a4..c9cb73a06 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -700,7 +700,9 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32) +#ifdef __OLD_VIDIOC_ #define VIDIOC_OVERLAY32_OLD _IOWR('V', 14, s32) +#endif #define VIDIOC_STREAMON32 _IOW ('V', 18, s32) #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32) #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32) @@ -758,7 +760,9 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break; case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break; case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; +#ifdef __OLD_VIDIOC_ case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break; +#endif case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; -- cgit v1.2.3 From a48a5ef826d2948a3b2a17d024cf853f1ed3b931 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 21 Dec 2008 15:58:05 +0100 Subject: gspca: t613: Bad loop in om6802 reset. From: Roel Kluin Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index d2d6ad9d1..452ca1d16 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -499,7 +499,7 @@ static void om6802_sensor_init(struct gspca_dev *gspca_dev) reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); msleep(5); i = 4; - while (--i < 0) { + while (--i > 0) { byte = reg_r(gspca_dev, 0x0060); if (!(byte & 0x01)) break; -- cgit v1.2.3 From e3ed9d5ccedc1a7a60c7cf106fbfb795448b32ea Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 21 Dec 2008 19:02:54 +0100 Subject: gspca - ov534 and m5602: Set static some functions/variables. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 2 +- linux/drivers/media/video/gspca/ov534.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index fd6ce384b..059c4d2ff 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -24,7 +24,7 @@ /* Kernel module parameters */ int force_sensor; -int dump_bridge; +static int dump_bridge; int dump_sensor; static const __devinitdata struct usb_device_id m5602_table[] = { diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 7332947cb..0eeb417d4 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -499,8 +499,8 @@ discard: } /* get stream parameters (framerate) */ -int sd_get_streamparm(struct gspca_dev *gspca_dev, - struct v4l2_streamparm *parm) +static int sd_get_streamparm(struct gspca_dev *gspca_dev, + struct v4l2_streamparm *parm) { struct v4l2_captureparm *cp = &parm->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; @@ -517,8 +517,8 @@ int sd_get_streamparm(struct gspca_dev *gspca_dev, } /* set stream parameters (framerate) */ -int sd_set_streamparm(struct gspca_dev *gspca_dev, - struct v4l2_streamparm *parm) +static int sd_set_streamparm(struct gspca_dev *gspca_dev, + struct v4l2_streamparm *parm) { struct v4l2_captureparm *cp = &parm->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; -- cgit v1.2.3 From 8b7f844e3d8b6c9ef3b5159f3b23fc79466df0ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 21 Dec 2008 21:25:25 +0100 Subject: Add a start sending hook in the sensor struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 3 +++ linux/drivers/media/video/gspca/m5602/m5602_sensor.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index fd4a1b419..0a43d9383 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -242,6 +242,9 @@ static int m5602_start_transfer(struct gspca_dev *gspca_dev) /* Send start command to the camera */ const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01}; + if (sd->sensor->start) + sd->sensor->start(sd); + memcpy(buf, buffer, sizeof(buffer)); err = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 23c0ef948..261623f0d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -58,6 +58,9 @@ struct m5602_sensor { /* Performs a initialization sequence */ int (*init)(struct sd *sd); + /* Executed when the camera starts to send data */ + int (*start)(struct sd *sd); + /* Performs a power down sequence */ int (*power_down)(struct sd *sd); -- cgit v1.2.3 From 5ca26578c58186e1afc2948a9403220edf75fd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 21 Dec 2008 22:07:59 +0100 Subject: ov9650: Prepare the sensor to set multiple resolutions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 24 +++++++++ .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 59 ++++++++++++---------- 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 115529f41..7cf18e305 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -145,6 +145,30 @@ int ov9650_init(struct sd *sd) return err; } +int ov9650_start(struct sd *sd) +{ + int i, err = 0; + struct cam *cam = &sd->gspca_dev.cam; + + switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) + { + default: + case 640: + PDEBUG(D_V4L2, "Configuring camera for VGA mode"); + + for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) { + u8 data = VGA_ov9650[i][2]; + if (VGA_ov9650[i][0] == SENSOR) + err = m5602_write_sensor(sd, + VGA_ov9650[i][1], &data, 1); + else + err = m5602_write_bridge(sd, VGA_ov9650[i][1], data); + } + break; + } + return err; +} + int ov9650_power_down(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 9360b8bd9..17f3382af 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -124,6 +124,7 @@ extern int dump_sensor; int ov9650_probe(struct sd *sd); int ov9650_init(struct sd *sd); +int ov9650_start(struct sd *sd); int ov9650_power_down(struct sd *sd); int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); @@ -151,6 +152,7 @@ static struct m5602_sensor ov9650 = { .i2c_regW = 1, .probe = ov9650_probe, .init = ov9650_init, + .start = ov9650_start, .power_down = ov9650_power_down, .nctrls = 8, @@ -259,15 +261,15 @@ static struct m5602_sensor ov9650 = { .nmodes = 1, .modes = { { - M5602_DEFAULT_FRAME_WIDTH, - M5602_DEFAULT_FRAME_HEIGHT, + 640, + 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .sizeimage = - M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, - .bytesperline = M5602_DEFAULT_FRAME_WIDTH, + 640 * 480, + .bytesperline = 640, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 + .priv = 0 } } }; @@ -414,27 +416,6 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_GAIN, GAIN_DEFAULT}, {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT}, {SENSOR, OV9650_RED, RED_GAIN_DEFAULT}, - - {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL}, - {SENSOR, OV9650_COM5, OV9650_SYSTEM_CLK_SEL}, - - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - /* Moves the view window in a vertical orientation */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x64}, /* 100 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 100 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0xe4} }; static const unsigned char power_down_ov9650[][3] = @@ -457,4 +438,30 @@ static const unsigned char power_down_ov9650[][3] = {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0} }; +static const unsigned char VGA_ov9650[][3] = +{ + {SENSOR, OV9650_COM7, OV9650_VGA_SELECT | + OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT}, + + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + + /* Moves the view window in a vertical orientation */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x64}, /* 100 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 100 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0xe4} +}; + #endif -- cgit v1.2.3 From a47d14089127cf096b56de570d96ac0d2611f679 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 07:14:31 -0200 Subject: em28xx: Fix bad locks on error condition From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 9fb9363dc..de4065bd7 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -825,8 +825,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, vidioc_try_fmt_vid_cap(file, priv, f); fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) - return -EINVAL; + if (!fmt) { + rc = -EINVAL; + goto out; + } if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); @@ -1317,10 +1319,8 @@ static int vidioc_streamon(struct file *file, void *priv, mutex_lock(&dev->lock); rc = res_get(fh); - if (unlikely(rc < 0)) - return rc; - - rc = videobuf_streamon(&fh->vb_vidq); + if (likely(rc >= 0)) + rc = videobuf_streamon(&fh->vb_vidq); mutex_unlock(&dev->lock); -- cgit v1.2.3 From 290fdd37a2914bb6aa8e67179c1d539c5cddd81c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 07:20:32 -0200 Subject: em28xx: de-obfuscate vidioc_g_ctrl logic From: Mauro Carvalho Chehab vidioc_g_ctrl() were using an uneeded confusing logic. Instead, use the direct approach. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index de4065bd7..7531a20f7 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1069,18 +1069,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv, rc = check_dev(dev); if (rc < 0) return rc; + rc = 0; mutex_lock(&dev->lock); - if (!dev->board.has_msp34xx) - rc = em28xx_get_ctrl(dev, ctrl); - else - rc = -EINVAL; - - if (rc == -EINVAL) { + if (dev->board.has_msp34xx) em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl); - rc = 0; - } + else + rc = em28xx_get_ctrl(dev, ctrl); mutex_unlock(&dev->lock); return rc; -- cgit v1.2.3 From cdf96638de5ab84aa3c30176add8d458d4344014 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 08:54:05 -0200 Subject: tuner-core: remove a no longer needed hack From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 8d1f8bebf..8f1ca6567 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -933,11 +933,6 @@ static int tuner_ioctl(struct v4l2_subdev *sd, int cmd, void *arg) } return -ENOIOCTLCMD; } -#else -static int tuner_ioctl(struct v4l2_subdev *sd, int cmd, void *arg) -{ - return -ENOIOCTLCMD; -} #endif static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg) -- cgit v1.2.3 From eb7bc99b0b15c28d8d0bd3dd4be26710d03dac2a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 09:36:29 -0200 Subject: v4l2-dbg: fix --list-symbols option From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index 31206a562..c1e107de1 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -706,9 +706,9 @@ list_done: else { printf("Symbols for driver %s:\n", vcap.driver); for (int i = 0; i < curr_bd->regs_size; i++) - printf("0x%08x: %s\n", curr_bd->regs[i], curr_bd->regs[i].name); + printf("0x%08x: %s\n", curr_bd->regs[i].reg, curr_bd->regs[i].name); for (int i = 0; i < curr_bd->alt_regs_size; i++) - printf("0x%08x: %s\n", curr_bd->alt_regs[i], curr_bd->alt_regs[i].name); + printf("0x%08x: %s\n", curr_bd->alt_regs[i].reg, curr_bd->alt_regs[i].name); } } -- cgit v1.2.3 From d0dd746a466cef43b09aba57033f390dcc417967 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 09:53:53 -0200 Subject: v4l2-dbg: print register name when known From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index c1e107de1..87044e851 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -293,6 +293,21 @@ static unsigned long long parse_reg(const struct board_list *curr_bd, const std: return strtoull(reg.c_str(), NULL, 0); } +static const char *reg_name(const struct board_list *curr_bd, unsigned long long reg) +{ + if (curr_bd) { + for (int i = 0; i < curr_bd->regs_size; i++) { + if (reg == curr_bd->regs[i].reg) + return curr_bd->regs[i].name; + } + for (int i = 0; i < curr_bd->alt_regs_size; i++) { + if (reg == curr_bd->regs[i].reg) + return curr_bd->regs[i].name; + } + } + return NULL; +} + static const char *binary(unsigned long long val) { static char bin[80]; @@ -582,9 +597,19 @@ int main(int argc, char **argv) if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0) fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER " "failed for 0x%llx\n", get_reg.reg); - else - printf("%llx = %llxh = %lldd = %sb\n", get_reg.reg, + else { + const char *name = reg_name(curr_bd, get_reg.reg); + + printf("Register "); + + if (name) + printf("%s", name); + else + printf("0x%08llx", get_reg.reg); + + printf(" = %llxh (%lldd %sb)\n", get_reg.val, get_reg.val, binary(get_reg.val)); + } } } -- cgit v1.2.3 From 585b4e51209e77b24d2d03f4dd30af1ec34e9002 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 10:17:16 -0200 Subject: v4l2-dbg: print register name and fix doioctl check From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index 87044e851..620702858 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -549,8 +549,21 @@ int main(int argc, char **argv) while (optind < argc) { set_reg.val = strtoull(argv[optind++], NULL, 0); if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &set_reg, - "VIDIOC_DBG_S_REGISTER") == 0) - printf("register 0x%llx set to 0x%llx\n", set_reg.reg, set_reg.val); + "VIDIOC_DBG_S_REGISTER") >= 0) { + const char *name = reg_name(curr_bd, set_reg.reg); + + printf("Register "); + + if (name) + printf("%s", name); + else + printf("0x%08llx", set_reg.reg); + + printf(" set to 0x%llx\n", set_reg.val); + } else { + printf("Failed to set register 0x%08llx value 0x%llx\n", + set_reg.reg, set_reg.val); + } set_reg.reg++; } } -- cgit v1.2.3 From b041d4c5cfa27296e25d7719299bb0e745fc45cf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 10:19:13 -0200 Subject: v4l2-dbg: print also register number when name is available From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index 620702858..1841e677b 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -555,7 +555,7 @@ int main(int argc, char **argv) printf("Register "); if (name) - printf("%s", name); + printf("%s (0x%08llx)", name, set_reg.reg); else printf("0x%08llx", set_reg.reg); @@ -616,7 +616,7 @@ int main(int argc, char **argv) printf("Register "); if (name) - printf("%s", name); + printf("%s (0x%08llx)", name, get_reg.reg); else printf("0x%08llx", get_reg.reg); -- cgit v1.2.3 From 71447659e72af9641c95885d7b92a568e7ce8dfc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 10:22:42 -0200 Subject: v4l2-dbg: em2800 registers are not very common nowadays. Use it as alternate names From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg-em28xx.h | 7 +++++-- v4l2-apps/util/v4l2-dbg.cpp | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/v4l2-apps/util/v4l2-dbg-em28xx.h b/v4l2-apps/util/v4l2-dbg-em28xx.h index c5117c6e7..3a0413b70 100644 --- a/v4l2-apps/util/v4l2-dbg-em28xx.h +++ b/v4l2-apps/util/v4l2-dbg-em28xx.h @@ -24,8 +24,6 @@ #define EM28XX_PREFIX "EM28XX_" static struct board_regs em28xx_regs[] = { - {0x08, EM2800_PREFIX "AUDIOSRC", 1}, - {0x04, EM2880_PREFIX "GPO", 1}, {0x08, EM28XX_PREFIX "GPIO", 1}, {0x06, EM28XX_PREFIX "I2C_CLK", 1}, @@ -82,3 +80,8 @@ static struct board_regs em28xx_regs[] = { {0x10, EM28XX_PREFIX "LINE_IN_AC97", 1}, {0x14, EM28XX_PREFIX "VIDEO_AC97", 1}, }; + +static struct board_regs em28xx_alt_regs[] = { + {0x08, EM2800_PREFIX "AUDIOSRC", 1}, + {0x04, EM2880_PREFIX "GPO", 1}, +}; \ No newline at end of file diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index 1841e677b..dfeae8cea 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -79,8 +79,8 @@ static const struct board_list boards[] = { sizeof(EM28XX_PREFIX) - 1, em28xx_regs, ARRAY_SIZE(em28xx_regs), - NULL, - 0, + em28xx_alt_regs, + ARRAY_SIZE(em28xx_alt_regs), }, }; -- cgit v1.2.3 From 786d73eb9aad6efa7ddd89150d18a689d08f4e07 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 14:18:27 -0200 Subject: em28xx: Add suport for debugging AC97 anciliary chips From: Mauro Carvalho Chehab The em28xx driver can be coupled to an anciliary AC97 chip. This patch allows read/write AC97 registers directly. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-core.c | 4 ++-- linux/drivers/media/video/em28xx/em28xx-video.c | 19 +++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 3 +++ linux/include/linux/videodev2.h | 1 + 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 2c975ffa4..025a54bb7 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -259,7 +259,7 @@ static int em28xx_is_ac97_ready(struct em28xx *dev) * em28xx_read_ac97() * write a 16 bit value to the specified AC97 address (LSB first!) */ -static int em28xx_read_ac97(struct em28xx *dev, u8 reg) +int em28xx_read_ac97(struct em28xx *dev, u8 reg) { int ret; u8 addr = (reg & 0x7f) | 0x80; @@ -285,7 +285,7 @@ static int em28xx_read_ac97(struct em28xx *dev, u8 reg) * em28xx_write_ac97() * write a 16 bit value to the specified AC97 address (LSB first!) */ -static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val) +int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val) { int ret; u8 addr = reg & 0x7f; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 7531a20f7..4d9b167e6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1233,6 +1233,17 @@ static int vidioc_g_register(struct file *file, void *priv, struct em28xx *dev = fh->dev; int ret; + if (reg->match_type == V4L2_CHIP_MATCH_AC97) { + mutex_lock(&dev->lock); + ret = em28xx_read_ac97(dev, reg->reg); + mutex_unlock(&dev->lock); + if (ret < 0) + return ret; + + reg->val = ret; + return 0; + } + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; @@ -1268,6 +1279,14 @@ static int vidioc_s_register(struct file *file, void *priv, __le64 buf; int rc; + if (reg->match_type == V4L2_CHIP_MATCH_AC97) { + mutex_lock(&dev->lock); + rc = em28xx_write_ac97(dev, reg->reg, reg->val); + mutex_unlock(&dev->lock); + + return rc; + } + buf = cpu_to_le64(reg->val); mutex_lock(&dev->lock); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index ae511ed7e..84f49934a 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -577,6 +577,9 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val); +int em28xx_read_ac97(struct em28xx *dev, u8 reg); +int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val); + int em28xx_audio_analog_set(struct em28xx *dev); int em28xx_audio_setup(struct em28xx *dev); diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index f64a3f780..018894814 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1376,6 +1376,7 @@ struct v4l2_streamparm { #define V4L2_CHIP_MATCH_HOST 0 /* Match against chip ID on host (0 for the host) */ #define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver ID */ #define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ +#define V4L2_CHIP_MATCH_AC97 3 /* Match against anciliary AC97 chip */ struct v4l2_register { __u32 match_type; /* Match type */ -- cgit v1.2.3 From 1d183a32a6fbcd8812f35d0eeca02347de4223bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 14:49:07 -0200 Subject: em28xx: update regiters on v4l2-dbg debug util From: Mauro Carvalho Chehab Some ac97 registers where presented as if they are em28xx ones. Also, add mising em2874 registers. The code were generated by the following command: $ more em28xx-reg.h |perl -ne 'if (m/(EM2[A-Z0-9]..)_R.._([^\s]+)\s+(0x[0-9A-Fa-f].)/) { printf "\t{$3, $1_PREFIX \"$2\", 1},\n"; }' |grep -v EM2800_PREFIX|sort >/tmp/registers Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg-em28xx.h | 15 ++++++++++----- v4l2-apps/util/v4l2-dbg.cpp | 6 ++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/v4l2-apps/util/v4l2-dbg-em28xx.h b/v4l2-apps/util/v4l2-dbg-em28xx.h index 3a0413b70..ae83a3181 100644 --- a/v4l2-apps/util/v4l2-dbg-em28xx.h +++ b/v4l2-apps/util/v4l2-dbg-em28xx.h @@ -20,10 +20,13 @@ /* Register name prefix */ #define EM2800_PREFIX "EM2800_" +#define EM2874_PREFIX "EM2874_" #define EM2880_PREFIX "EM2880_" #define EM28XX_PREFIX "EM28XX_" static struct board_regs em28xx_regs[] = { + {0x00, EM28XX_PREFIX "CHIPCFG", 1}, + {0x04, EM2880_PREFIX "GPO", 1}, {0x08, EM28XX_PREFIX "GPIO", 1}, {0x06, EM28XX_PREFIX "I2C_CLK", 1}, @@ -76,12 +79,14 @@ static struct board_regs em28xx_regs[] = { {0x42, EM28XX_PREFIX "AC97ADDR", 1}, {0x43, EM28XX_PREFIX "AC97BUSY", 1}, - {0x02, EM28XX_PREFIX "MASTER_AC97", 1}, - {0x10, EM28XX_PREFIX "LINE_IN_AC97", 1}, - {0x14, EM28XX_PREFIX "VIDEO_AC97", 1}, + {0x45, EM28XX_PREFIX "IR", 1}, + + {0x50, EM2874_PREFIX "IR_CONFIG", 1}, + {0x51, EM2874_PREFIX "IR", 1}, + {0x5f, EM2874_PREFIX "TS_ENABLE", 1}, + {0x80, EM2874_PREFIX "GPIO", 1}, }; static struct board_regs em28xx_alt_regs[] = { {0x08, EM2800_PREFIX "AUDIOSRC", 1}, - {0x04, EM2880_PREFIX "GPO", 1}, -}; \ No newline at end of file +}; diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index dfeae8cea..e05be1f03 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -158,6 +158,7 @@ static void usage(void) " It can be one of:\n" " I2C driver ID (see --list-driverids)\n" " I2C 7-bit address\n" + " AC97: for ac97 anciliary mixer\n" " host: host chip number \n" " host (default): same as host0\n" " -l, --list-registers[=min=[,max=]]\n" @@ -448,6 +449,11 @@ int main(int argc, char **argv) match_chip = strtoul(optarg + 4, NULL, 0); break; } + if (!strcasecmp(optarg, "ac97")) { + match_type = V4L2_CHIP_MATCH_AC97; + match_chip = strtoul(optarg + 4, NULL, 0); + break; + } match_type = V4L2_CHIP_MATCH_I2C_DRIVER; match_chip = parse_chip(optarg); if (!match_chip) { -- cgit v1.2.3 From 5b8cbae207001dd7cd7e4a4f09a987b4194d0a8f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 15:06:33 -0200 Subject: v4l2-dbg: Add support for get/set ac97 registers From: Mauro Carvalho Chehab em28xx devices can have an ac97 anciliary chip. This patch allows get/set ac97 registers Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg-ac97.h | 67 ++++++++++++++++++++++++++++++++++++++++++ v4l2-apps/util/v4l2-dbg.cpp | 23 +++++++++++---- 2 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 v4l2-apps/util/v4l2-dbg-ac97.h diff --git a/v4l2-apps/util/v4l2-dbg-ac97.h b/v4l2-apps/util/v4l2-dbg-ac97.h new file mode 100644 index 000000000..809abe469 --- /dev/null +++ b/v4l2-apps/util/v4l2-dbg-ac97.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2008 Mauro Carvalho Chehab + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "v4l2-dbg.h" + +#define AC97_IDENT "ac97" + +/* Register name prefix */ +#define AC97_PREFIX "AC97_" +#define EM202_PREFIX "EM202_" + +static struct board_regs ac97_regs[] = { + /* general ac97 registers */ + {0x00, AC97_PREFIX "RESET", 2}, + {0x02, AC97_PREFIX "MASTER_VOL", 2}, + {0x04, AC97_PREFIX "LINE_LEVEL_VOL", 2}, + {0x06, AC97_PREFIX "MASTER_MONO_VOL", 2}, + {0x0a, AC97_PREFIX "PC_BEEP_VOL", 2}, + {0x0c, AC97_PREFIX "PHONE_VOL", 2}, + {0x0e, AC97_PREFIX "MIC_VOL", 2}, + {0x10, AC97_PREFIX "LINEIN_VOL", 2}, + {0x12, AC97_PREFIX "CD_VOL", 2}, + {0x14, AC97_PREFIX "VIDEO_VOL", 2}, + {0x16, AC97_PREFIX "AUX_VOL", 2}, + {0x18, AC97_PREFIX "PCM_OUT_VOL", 2}, + {0x1a, AC97_PREFIX "RECORD_SELECT", 2}, + {0x1c, AC97_PREFIX "RECORD_GAIN", 2}, + {0x20, AC97_PREFIX "GENERAL_PURPOSE", 2}, + {0x22, AC97_PREFIX "3D_CTRL", 2}, + {0x24, AC97_PREFIX "AUD_INT_AND_PAG", 2}, + {0x26, AC97_PREFIX "POWER_DOWN_CTRL", 2}, + {0x28, AC97_PREFIX "EXT_AUD_ID", 2}, + {0x2a, AC97_PREFIX "EXT_AUD_CTRL", 2}, + {0x2c, AC97_PREFIX "PCM_OUT_FRONT_SRATE", 2}, + {0x2e, AC97_PREFIX "PCM_OUT_SURR_SRATE", 2}, + {0x30, AC97_PREFIX "PCM_OUT_LFE_SRATE", 2}, + {0x32, AC97_PREFIX "PCM_IN_SRATE", 2}, + {0x36, AC97_PREFIX "LFE_MASTER_VOL", 2}, + {0x38, AC97_PREFIX "SURR_MASTER_VOL", 2}, + {0x3a, AC97_PREFIX "SPDIF_OUT_CTRL", 2}, + {0x7c, AC97_PREFIX "VENDOR_ID1", 2}, + {0x7e, AC97_PREFIX "VENDOR_ID2", 2}, + + /* em202 vendor specific registers */ + {0x3e, EM202_PREFIX "EXT_MODEM_CTRL", 2}, + {0x4c, EM202_PREFIX "GPIO_CONF", 2}, + {0x4e, EM202_PREFIX "GPIO_POLARITY", 2}, + {0x50, EM202_PREFIX "GPIO_STICKY", 2}, + {0x52, EM202_PREFIX "GPIO_MASK", 2}, + {0x54, EM202_PREFIX "GPIO_STATUS", 2}, + {0x6a, EM202_PREFIX "SPDIF_OUT_SEL", 2}, + {0x72, EM202_PREFIX "ANTIPOP", 2}, + {0x74, EM202_PREFIX "EAPD_GPIO_ACCESS", 2}, +}; diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index e05be1f03..412d3bea5 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -45,6 +45,7 @@ #include "v4l2-dbg-bttv.h" #include "v4l2-dbg-saa7134.h" #include "v4l2-dbg-em28xx.h" +#include "v4l2-dbg-ac97.h" #define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0]))) @@ -58,6 +59,15 @@ struct board_list { }; static const struct board_list boards[] = { +#define AC97_BOARD 0 + { /* From ac97-dbg.h */ + AC97_IDENT, + sizeof(AC97_PREFIX) - 1, + ac97_regs, + ARRAY_SIZE(ac97_regs), + NULL, + 0, + }, { /* From bttv-dbg.h */ BTTV_IDENT, sizeof(BTTV_PREFIX) - 1, @@ -451,7 +461,6 @@ int main(int argc, char **argv) } if (!strcasecmp(optarg, "ac97")) { match_type = V4L2_CHIP_MATCH_AC97; - match_chip = strtoul(optarg + 4, NULL, 0); break; } match_type = V4L2_CHIP_MATCH_I2C_DRIVER; @@ -537,10 +546,14 @@ int main(int argc, char **argv) printf("%s", cap2s(vcap.capabilities).c_str()); } - for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) { - if (!strcasecmp((char *)vcap.driver, boards[board].name)) { - curr_bd = &boards[board]; - break; + if (match_type == V4L2_CHIP_MATCH_AC97) { + curr_bd = &boards[AC97_BOARD]; + } else { + for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) { + if (!strcasecmp((char *)vcap.driver, boards[board].name)) { + curr_bd = &boards[board]; + break; + } } } -- cgit v1.2.3 From 508d4c2d232f61a3ffc92c05bee7a9afe7559081 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 16:01:46 -0200 Subject: v4l2-dbg: Use aliases for debug, on available chips From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index 412d3bea5..c7ef1206b 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -487,6 +487,7 @@ int main(int argc, char **argv) subs = optarg; if (subs == NULL) break; + while (*subs != '\0') { static const char * const subopts[] = { "min", @@ -658,6 +659,43 @@ int main(int argc, char **argv) } printf("ioctl: VIDIOC_DBG_G_REGISTER\n"); + if (curr_bd) { + if (reg_min_arg.empty()) + reg_min = 0; + else + reg_min = parse_reg(curr_bd, reg_min_arg); + + + if (reg_max_arg.empty()) + reg_max = 1<<31 - 1; + else + reg_max = parse_reg(curr_bd, reg_max_arg); + + for (int i = 0; i < curr_bd->regs_size; i++) { + if (reg_min_arg.empty() || ((curr_bd->regs[i].reg >= reg_min) && curr_bd->regs[i].reg <= reg_max)) { + get_reg.reg = curr_bd->regs[i].reg; + + if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0) + fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER " + "failed for 0x%llx\n", get_reg.reg); + else { + const char *name = reg_name(curr_bd, get_reg.reg); + + printf("Register "); + + if (name) + printf("%s (0x%08llx)", name, get_reg.reg); + else + printf("0x%08llx", get_reg.reg); + + printf(" = %llxh (%lldd %sb)\n", + get_reg.val, get_reg.val, binary(get_reg.val)); + } + } + } + goto list_done; + } + if (!reg_min_arg.empty()) { reg_min = parse_reg(curr_bd, reg_min_arg); if (reg_max_arg.empty()) @@ -668,6 +706,7 @@ int main(int argc, char **argv) print_regs(fd, &get_reg, reg_min, reg_max, stride); goto list_done; } + /* try to match the i2c chip */ switch (get_reg.match_chip) { case I2C_DRIVERID_SAA711X: -- cgit v1.2.3 From 07760c68eee57f1102db8fc8f4b60802737b9539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 22 Dec 2008 20:06:29 +0100 Subject: Add QVGA mode for the ov9650 sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 14 +++++++- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 40 ++++++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 7cf18e305..28045c18c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -152,7 +152,6 @@ int ov9650_start(struct sd *sd) switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { - default: case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); @@ -165,6 +164,19 @@ int ov9650_start(struct sd *sd) err = m5602_write_bridge(sd, VGA_ov9650[i][1], data); } break; + + case 320: + PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); + + for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) { + u8 data = QVGA_ov9650[i][2]; + if (QVGA_ov9650[i][0] == SENSOR) + err = m5602_write_sensor(sd, + QVGA_ov9650[i][1], &data, 1); + else + err = m5602_write_bridge(sd, QVGA_ov9650[i][1], data); + } + break; } return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 17f3382af..636dce61c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -20,7 +20,6 @@ #define M5602_OV9650_H_ #include - #include "m5602_sensor.h" /*****************************************************************************/ @@ -94,6 +93,7 @@ #define OV9650_REGISTER_RESET (1 << 7) #define OV9650_VGA_SELECT (1 << 6) +#define OV9650_QVGA_SELECT (1 << 4) #define OV9650_RGB_SELECT (1 << 2) #define OV9650_RAW_RGB_SELECT (1 << 0) @@ -258,9 +258,19 @@ static struct m5602_sensor ov9650 = { } }, - .nmodes = 1, + .nmodes = 2, .modes = { { + 320, + 240, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 320 * 240, + .bytesperline = 320, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, { 640, 480, V4L2_PIX_FMT_SBGGR8, @@ -464,4 +474,30 @@ static const unsigned char VGA_ov9650[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0xe4} }; +static const unsigned char QVGA_ov9650[][3] = +{ + {SENSOR, OV9650_COM7, OV9650_QVGA_SELECT | + OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT}, + + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + + /* Moves the view window in a vertical orientation */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xf0}, /* 240 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 50 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 320 + 50 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x71} +}; + #endif -- cgit v1.2.3 From 64fe35cc0bcee9c48cfab4d8f813996d8c2c0369 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 21:34:18 -0200 Subject: tvp5150: add support for VIDIOC_G_CHIP_IDENT ioctl From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tvp5150.c | 16 ++++++++++++++++ linux/include/media/v4l2-chip-ident.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index 37421fb03..404df4aa2 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "tvp5150_reg.h" @@ -1028,6 +1029,20 @@ static int tvp5150_decode_vbi_line(struct v4l2_subdev *sd, } #endif +static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_chip_ident *chip) +{ + int rev; + struct i2c_client *client = v4l2_get_subdevdata(sd); + + rev = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER) << 8 | + tvp5150_read(sd, TVP5150_ROM_MINOR_VER); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP5150, + rev); +} + + #ifdef CONFIG_VIDEO_ADV_DEBUG static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) { @@ -1093,6 +1108,7 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { .s_ctrl = tvp5150_s_ctrl, .queryctrl = tvp5150_queryctrl, .reset = tvp5150_reset, + .g_chip_ident = tvp5150_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = tvp5150_g_register, .s_register = tvp5150_s_register, diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index bfe5142e6..e3e5b5393 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -70,6 +70,9 @@ enum { /* module vp27smpx: just ident 2700 */ V4L2_IDENT_VP27SMPX = 2700, + /* module tvp5150 */ + V4L2_IDENT_TVP5150 = 5150, + /* module cs5345: just ident 5345 */ V4L2_IDENT_CS5345 = 5345, -- cgit v1.2.3 From 57f1a4de9c25fb0d892c1dfd2369b99fa84b1406 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 21:58:41 -0200 Subject: em28xx: Allow get/set registers for debug on i2c slave chips From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 46 ++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 4d9b167e6..9a7f57c8b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -39,6 +39,7 @@ #include "em28xx.h" #include #include +#include #include #include @@ -1226,6 +1227,21 @@ static int em28xx_reg_len(int reg) } } +static int vidioc_g_chip_ident(struct file *file, void *priv, + struct v4l2_chip_ident *chip) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + + em28xx_i2c_call_clients(dev, VIDIOC_G_CHIP_IDENT, chip); + + return 0; +} + + static int vidioc_g_register(struct file *file, void *priv, struct v4l2_register *reg) { @@ -1233,7 +1249,8 @@ static int vidioc_g_register(struct file *file, void *priv, struct em28xx *dev = fh->dev; int ret; - if (reg->match_type == V4L2_CHIP_MATCH_AC97) { + switch (reg->match_type) { + case V4L2_CHIP_MATCH_AC97: mutex_lock(&dev->lock); ret = em28xx_read_ac97(dev, reg->reg); mutex_unlock(&dev->lock); @@ -1242,11 +1259,18 @@ static int vidioc_g_register(struct file *file, void *priv, reg->val = ret; return 0; - } - - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + case V4L2_CHIP_MATCH_I2C_DRIVER: + em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_REGISTER, reg); + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* Not supported yet */ return -EINVAL; + default: + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + } + /* Match host */ if (em28xx_reg_len(reg->reg) == 1) { mutex_lock(&dev->lock); ret = em28xx_read_reg(dev, reg->reg); @@ -1279,14 +1303,25 @@ static int vidioc_s_register(struct file *file, void *priv, __le64 buf; int rc; - if (reg->match_type == V4L2_CHIP_MATCH_AC97) { + switch (reg->match_type) { + case V4L2_CHIP_MATCH_AC97: mutex_lock(&dev->lock); rc = em28xx_write_ac97(dev, reg->reg, reg->val); mutex_unlock(&dev->lock); return rc; + case V4L2_CHIP_MATCH_I2C_DRIVER: + em28xx_i2c_call_clients(dev, VIDIOC_DBG_S_REGISTER, reg); + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* Not supported yet */ + return -EINVAL; + default: + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; } + /* Match host */ buf = cpu_to_le64(reg->val); mutex_lock(&dev->lock); @@ -1996,6 +2031,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, + .vidioc_g_chip_ident = vidioc_g_chip_ident, #endif #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, -- cgit v1.2.3 From 43e99e5ec6d0b7bc9249119867ff553cba80b0ee Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Dec 2008 22:00:03 -0200 Subject: v4l2-dbg: allow debug tvp5150 registers From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg-tvp5150.h | 97 +++++++++++++++++++++++++++++++++++++++ v4l2-apps/util/v4l2-dbg.cpp | 21 ++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 v4l2-apps/util/v4l2-dbg-tvp5150.h diff --git a/v4l2-apps/util/v4l2-dbg-tvp5150.h b/v4l2-apps/util/v4l2-dbg-tvp5150.h new file mode 100644 index 000000000..ed5793b72 --- /dev/null +++ b/v4l2-apps/util/v4l2-dbg-tvp5150.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2008 Mauro Carvalho Chehab + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "v4l2-dbg.h" + +#define TVP5150_IDENT "tvp5150" + +/* Register name prefix */ +#define TVP5150_PREFIX "TVP5150_" + +static struct board_regs tvp5150_regs[] = { + {0x00, TVP5150_PREFIX "VD_IN_SRC_SEL_1", 1}, + {0x01, TVP5150_PREFIX "ANAL_CHL_CTL", 1}, + {0x02, TVP5150_PREFIX "OP_MODE_CTL", 1}, + {0x03, TVP5150_PREFIX "MISC_CTL", 1}, + {0x04, TVP5150_PREFIX "AUTOSW_MSK", 1}, + {0x06, TVP5150_PREFIX "COLOR_KIL_THSH_CTL", 1}, + {0x07, TVP5150_PREFIX "LUMA_PROC_CTL_1", 1}, + {0x08, TVP5150_PREFIX "LUMA_PROC_CTL_2", 1}, + {0x09, TVP5150_PREFIX "BRIGHT_CTL", 1}, + {0x0a, TVP5150_PREFIX "SATURATION_CTL", 1}, + {0x0b, TVP5150_PREFIX "HUE_CTL", 1}, + {0x0c, TVP5150_PREFIX "CONTRAST_CTL", 1}, + {0x0d, TVP5150_PREFIX "DATA_RATE_SEL", 1}, + {0x0e, TVP5150_PREFIX "LUMA_PROC_CTL_3", 1}, + {0x0f, TVP5150_PREFIX "CONF_SHARED_PIN", 1}, + {0x11, TVP5150_PREFIX "ACT_VD_CROP_ST_MSB", 1}, + {0x12, TVP5150_PREFIX "ACT_VD_CROP_ST_LSB", 1}, + {0x13, TVP5150_PREFIX "ACT_VD_CROP_STP_MSB", 1}, + {0x14, TVP5150_PREFIX "ACT_VD_CROP_STP_LSB", 1}, + {0x15, TVP5150_PREFIX "GENLOCK", 1}, + {0x16, TVP5150_PREFIX "HORIZ_SYNC_START", 1}, + {0x18, TVP5150_PREFIX "VERT_BLANKING_START", 1}, + {0x19, TVP5150_PREFIX "VERT_BLANKING_STOP", 1}, + {0x1a, TVP5150_PREFIX "CHROMA_PROC_CTL_1", 1}, + {0x1b, TVP5150_PREFIX "CHROMA_PROC_CTL_2", 1}, + {0x1c, TVP5150_PREFIX "INT_RESET_REG_B", 1}, + {0x1d, TVP5150_PREFIX "INT_ENABLE_REG_B", 1}, + {0x1e, TVP5150_PREFIX "INTT_CONFIG_REG_B", 1}, + {0x28, TVP5150_PREFIX "VIDEO_STD", 1}, + {0x2c, TVP5150_PREFIX "CB_GAIN_FACT", 1}, + {0x2d, TVP5150_PREFIX "CR_GAIN_FACTOR", 1}, + {0x2e, TVP5150_PREFIX "MACROVISION_ON_CTR", 1}, + {0x2f, TVP5150_PREFIX "MACROVISION_OFF_CTR", 1}, + {0x30, TVP5150_PREFIX "REV_SELECT", 1}, + {0x80, TVP5150_PREFIX "MSB_DEV_ID", 1}, + {0x81, TVP5150_PREFIX "LSB_DEV_ID", 1}, + {0x82, TVP5150_PREFIX "ROM_MAJOR_VER", 1}, + {0x83, TVP5150_PREFIX "ROM_MINOR_VER", 1}, + {0x84, TVP5150_PREFIX "VERT_LN_COUNT_MSB", 1}, + {0x85, TVP5150_PREFIX "VERT_LN_COUNT_LSB", 1}, + {0x86, TVP5150_PREFIX "INT_STATUS_REG_B", 1}, + {0x87, TVP5150_PREFIX "INT_ACTIVE_REG_B", 1}, + {0x88, TVP5150_PREFIX "STATUS_REG_1", 1}, + {0x89, TVP5150_PREFIX "STATUS_REG_2", 1}, + {0x8a, TVP5150_PREFIX "STATUS_REG_3", 1}, + {0x8b, TVP5150_PREFIX "STATUS_REG_4", 1}, + {0x8c, TVP5150_PREFIX "STATUS_REG_5", 1}, + {0x90, TVP5150_PREFIX "CC_DATA", 4}, + {0x94, TVP5150_PREFIX "WSS_DATA", 6}, + {0x9a, TVP5150_PREFIX "VPS_DATA", 13}, + {0xa7, TVP5150_PREFIX "VITC_DATA", 9}, + {0xb0, TVP5150_PREFIX "VBI_FIFO_READ_DATA", 1}, + {0xb1, TVP5150_PREFIX "TELETEXT_FIL1", 5}, + {0xb6, TVP5150_PREFIX "TELETEXT_FIL2", 5}, + {0xbb, TVP5150_PREFIX "TELETEXT_FIL_ENA", 1}, + {0xc0, TVP5150_PREFIX "INT_STATUS_REG_A", 1}, + {0xc1, TVP5150_PREFIX "INT_ENABLE_REG_A", 1}, + {0xc2, TVP5150_PREFIX "INT_CONF", 1}, + {0xc3, TVP5150_PREFIX "VDP_CONF_RAM_DATA", 1}, + {0xc4, TVP5150_PREFIX "CONF_RAM_ADDR_LOW", 1}, + {0xc5, TVP5150_PREFIX "CONF_RAM_ADDR_HIGH", 1}, + {0xc6, TVP5150_PREFIX "VDP_STATUS_REG", 1}, + {0xc7, TVP5150_PREFIX "FIFO_WORD_COUNT", 1}, + {0xc8, TVP5150_PREFIX "FIFO_INT_THRESHOLD", 1}, + {0xc9, TVP5150_PREFIX "FIFO_RESET", 1}, + {0xca, TVP5150_PREFIX "LINE_NUMBER_INT", 1}, + {0xcb, TVP5150_PREFIX "PIX_ALIGN_REG_LOW", 1}, + {0xcc, TVP5150_PREFIX "PIX_ALIGN_REG_HIGH", 1}, + {0xcd, TVP5150_PREFIX "FIFO_OUT_CTRL", 1}, + {0xcf, TVP5150_PREFIX "FULL_FIELD_ENA", 1}, + {0xd0, TVP5150_PREFIX "LINE_MODE", 43}, + {0xfc, TVP5150_PREFIX "FULL_FIELD_MODE_REG", 1}, +}; diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index c7ef1206b..577c8585e 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -46,6 +46,7 @@ #include "v4l2-dbg-saa7134.h" #include "v4l2-dbg-em28xx.h" #include "v4l2-dbg-ac97.h" +#include "v4l2-dbg-tvp5150.h" #define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0]))) @@ -92,6 +93,14 @@ static const struct board_list boards[] = { em28xx_alt_regs, ARRAY_SIZE(em28xx_alt_regs), }, + { /* From tvp5150-dbg.h */ + TVP5150_IDENT, + sizeof(TVP5150_PREFIX) - 1, + tvp5150_regs, + ARRAY_SIZE(tvp5150_regs), + NULL, + 0, + }, }; struct driverid { @@ -406,6 +415,7 @@ int main(int argc, char **argv) std::vector get_regs; int match_type = V4L2_CHIP_MATCH_HOST; int match_chip = 0; + char driver[255]; memset(&set_reg, 0, sizeof(set_reg)); memset(&get_reg, 0, sizeof(get_reg)); @@ -464,6 +474,7 @@ int main(int argc, char **argv) break; } match_type = V4L2_CHIP_MATCH_I2C_DRIVER; + strcpy(driver, optarg); match_chip = parse_chip(optarg); if (!match_chip) { fprintf(stderr, "unknown driver ID %s\n", optarg); @@ -549,13 +560,20 @@ int main(int argc, char **argv) if (match_type == V4L2_CHIP_MATCH_AC97) { curr_bd = &boards[AC97_BOARD]; - } else { + } else if (match_type == V4L2_CHIP_MATCH_HOST) { for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) { if (!strcasecmp((char *)vcap.driver, boards[board].name)) { curr_bd = &boards[board]; break; } } + } else if (match_type == V4L2_CHIP_MATCH_I2C_DRIVER) { + for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) { + if (!strcasecmp(driver, boards[board].name)) { + curr_bd = &boards[board]; + break; + } + } } /* Set options */ @@ -651,6 +669,7 @@ int main(int argc, char **argv) get_reg.match_type = match_type; get_reg.match_chip = match_chip; + if (forcedstride) { stride = forcedstride; } else { -- cgit v1.2.3 From bba7ba66b44e9f98fbf2c6019be85b8448f0a3a7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Dec 2008 01:38:23 +0000 Subject: v4l: usbvideo, fix module ref count check From: Jiri Slaby usbvideo_ClientIncModCount may return value < 0 in the case of error, not > 0. Signed-off-by: Jiri Slaby Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/usbvideo/usbvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/usbvideo/usbvideo.c b/linux/drivers/media/video/usbvideo/usbvideo.c index 332929bb2..85409c624 100644 --- a/linux/drivers/media/video/usbvideo/usbvideo.c +++ b/linux/drivers/media/video/usbvideo/usbvideo.c @@ -1123,7 +1123,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) if (uvd->debug > 1) dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); - if (0 < usbvideo_ClientIncModCount(uvd)) + if (usbvideo_ClientIncModCount(uvd) < 0) return -ENODEV; mutex_lock(&uvd->lock); -- cgit v1.2.3 From 85eea3e7c4e6c0b3196466d9b14a8965cc751003 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2008 11:35:17 +0100 Subject: v4l2-dev: allow drivers to pass v4l2_device as parent From: Hans Verkuil Drivers that use v4l2_device can set that as parent pointer in the v4l2_dev field instead of using the struct device parent field. This allows v4l2-dev.c to check whether this driver is v4l2_device based, and if so then it can offer additional services. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-dev.c | 3 +++ linux/include/media/v4l2-dev.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index f877d3f86..0b832f210 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -30,6 +30,7 @@ #include #include +#include #include "compat.h" #define VIDEO_NUM_DEVICES 256 @@ -445,6 +446,8 @@ int video_register_device_index(struct video_device *vdev, int type, int nr, vdev->vfl_type = type; vdev->cdev = NULL; + if (vdev->v4l2_dev) + vdev->parent = vdev->v4l2_dev->dev; /* Part 2: find a free minor, kernel number and device index. */ #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES diff --git a/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h index 6d76f0bce..c6cf5b1b2 100644 --- a/linux/include/media/v4l2-dev.h +++ b/linux/include/media/v4l2-dev.h @@ -25,6 +25,7 @@ #define VFL_TYPE_MAX 4 struct v4l2_ioctl_callbacks; +struct v4l2_device; /* Flag to mark the video_device struct as unregistered. Drivers can set this flag if they want to block all future @@ -49,7 +50,10 @@ struct video_device struct class_device dev; #endif struct cdev *cdev; /* character device */ + + /* Set either parent or v4l2_dev if your driver uses v4l2_device */ struct device *parent; /* device parent */ + struct v4l2_device *v4l2_dev; /* v4l2_device parent */ /* device info */ char name[32]; -- cgit v1.2.3 From 43cea8a5c34e5756adad03ee6522853203b48433 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2008 11:35:45 +0100 Subject: ivtv: set v4l2_dev instead of parent. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ivtv/ivtv-streams.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c index 76279ed30..f77d76470 100644 --- a/linux/drivers/media/video/ivtv/ivtv-streams.c +++ b/linux/drivers/media/video/ivtv/ivtv-streams.c @@ -209,7 +209,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) itv->device.name, s->name); s->v4l2dev->num = num; - s->v4l2dev->parent = &itv->dev->dev; + s->v4l2dev->v4l2_dev = &itv->device; s->v4l2dev->fops = ivtv_stream_info[type].fops; s->v4l2dev->release = video_device_release; s->v4l2dev->tvnorms = V4L2_STD_ALL; -- cgit v1.2.3 From b6ab90fc51826a92e71823d52ccce6120d644bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 23 Dec 2008 18:08:07 +0100 Subject: Tweak the hsync. Remove redundant init sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 636dce61c..b577017f6 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -328,6 +328,7 @@ static const unsigned char init_ov9650[][3] = {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, + /* Reset chip */ {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, /* Enable double clock */ @@ -335,8 +336,6 @@ static const unsigned char init_ov9650[][3] = /* Do something out of spec with the power */ {SENSOR, OV9650_OFON, 0x40}, - /* Set QQVGA */ - {SENSOR, OV9650_COM1, 0x20}, /* Set fast AGC/AEC algorithm with unlimited step size */ {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC | OV9650_AEC_UNLIM_STEP_SIZE | @@ -409,10 +408,6 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_VSTOP, 0x7e}, /* Set complementing vertical frame control */ {SENSOR, OV9650_VREF, 0x10}, - /* Set raw RGB output format with VGA resolution */ - {SENSOR, OV9650_COM7, OV9650_VGA_SELECT | - OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT}, {SENSOR, OV9650_ADC, 0x04}, {SENSOR, OV9650_HV, 0x40}, /* Enable denoise, and white-pixel erase */ @@ -469,9 +464,9 @@ static const unsigned char VGA_ov9650[][3] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x64}, /* 100 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 100 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0xe4} + {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 98 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0xe2} }; static const unsigned char QVGA_ov9650[][3] = -- cgit v1.2.3 From e24e42af1b491ab65f5667383d5282faf13d8be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 23 Dec 2008 21:07:58 +0100 Subject: ov9650: Add CIF mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 13 ++++++++ .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 39 +++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 28045c18c..f2fa24174 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -165,6 +165,19 @@ int ov9650_start(struct sd *sd) } break; + case 352: + PDEBUG(D_V4L2, "Configuring camera for CIF mode"); + + for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) { + u8 data = CIF_ov9650[i][2]; + if (CIF_ov9650[i][0] == SENSOR) + err = m5602_write_sensor(sd, + CIF_ov9650[i][1], &data, 1); + else + err = m5602_write_bridge(sd, CIF_ov9650[i][1], data); + } + break; + case 320: PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index b577017f6..9e955691a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -93,6 +93,7 @@ #define OV9650_REGISTER_RESET (1 << 7) #define OV9650_VGA_SELECT (1 << 6) +#define OV9650_CIF_SELECT (1 << 5) #define OV9650_QVGA_SELECT (1 << 4) #define OV9650_RGB_SELECT (1 << 2) #define OV9650_RAW_RGB_SELECT (1 << 0) @@ -258,7 +259,7 @@ static struct m5602_sensor ov9650 = { } }, - .nmodes = 2, + .nmodes = 3, .modes = { { 320, @@ -270,6 +271,16 @@ static struct m5602_sensor ov9650 = { .bytesperline = 320, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0 + }, { + 352, + 288, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 352 * 288, + .bytesperline = 352, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 }, { 640, 480, @@ -469,6 +480,32 @@ static const unsigned char VGA_ov9650[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0xe2} }; +static const unsigned char CIF_ov9650[][3] = +{ + {SENSOR, OV9650_COM7, OV9650_CIF_SELECT | + OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT}, + + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + + /* Moves the view window in a vertical orientation */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x20}, /* 288 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 352 + 98 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0xc2} +}; + static const unsigned char QVGA_ov9650[][3] = { {SENSOR, OV9650_COM7, OV9650_QVGA_SELECT | -- cgit v1.2.3 From 9a93d80c962c9118675ff97cdc3244b8a1749f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 23 Dec 2008 21:15:19 +0100 Subject: ov9650: Activate variopixel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 9e955691a..9d01bc259 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -35,6 +35,7 @@ #define OV9650_PID 0x0a #define OV9650_VER 0x0b #define OV9650_COM3 0x0c +#define OV9650_COM4 0x0d #define OV9650_COM5 0x0e #define OV9650_COM6 0x0f #define OV9650_AECH 0x10 @@ -109,6 +110,8 @@ #define OV9650_SYSTEM_CLK_SEL (1 << 7) #define OV9650_SLAM_MODE (1 << 4) +#define OV9650_QVGA_VARIOPIXEL (1 << 7) + #define OV9650_VFLIP (1 << 4) #define OV9650_HFLIP (1 << 5) @@ -427,6 +430,10 @@ static const unsigned char init_ov9650[][3] = /* Set the high bits of the exposure value */ {SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)}, + /* Enable VARIOPIXEL */ + {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL}, + {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL}, + /* Set the low bits of the exposure value */ {SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)}, {SENSOR, OV9650_GAIN, GAIN_DEFAULT}, -- cgit v1.2.3 From cbd16cf5e7e4aae60ca283ad27bafae1fcb21102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 23 Dec 2008 22:06:37 +0100 Subject: Rework parts of the resolution initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 8 ++- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 59 +++++++++------------- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index f2fa24174..dde5075ed 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -141,7 +141,6 @@ int ov9650_init(struct sd *sd) data = 0x30; err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1); } - return err; } @@ -150,6 +149,13 @@ int ov9650_start(struct sd *sd) int i, err = 0; struct cam *cam = &sd->gspca_dev.cam; + for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { + u8 data = res_init_ov9650[i][1]; + err = m5602_write_bridge(sd, res_init_ov9650[i][0], data); + } + if (err < 0) + return err; + switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { case 640: diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 9d01bc259..f4b33b8e8 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -458,21 +458,20 @@ static const unsigned char power_down_ov9650[][3] = {BRIDGE, M5602_XB_GPIO_EN_L, 0x06}, {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0} + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, }; -static const unsigned char VGA_ov9650[][3] = +static const unsigned char res_init_ov9650[][2] = { - {SENSOR, OV9650_COM7, OV9650_VGA_SELECT | - OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT}, - - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {M5602_XB_LINE_OF_FRAME_H, 0x82}, + {M5602_XB_LINE_OF_FRAME_L, 0x00}, + {M5602_XB_PIX_OF_LINE_H, 0x82}, + {M5602_XB_PIX_OF_LINE_L, 0x00}, + {M5602_XB_SIG_INI, 0x01} +}; +static const unsigned char VGA_ov9650[][3] = +{ /* Moves the view window in a vertical orientation */ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, @@ -484,21 +483,15 @@ static const unsigned char VGA_ov9650[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 98 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0xe2} -}; + {BRIDGE, M5602_XB_HSYNC_PARA, 0xe2}, -static const unsigned char CIF_ov9650[][3] = -{ - {SENSOR, OV9650_COM7, OV9650_CIF_SELECT | + {SENSOR, OV9650_COM7, OV9650_VGA_SELECT | OV9650_RGB_SELECT | OV9650_RAW_RGB_SELECT}, +}; - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - +static const unsigned char CIF_ov9650[][3] = +{ /* Moves the view window in a vertical orientation */ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, @@ -510,21 +503,15 @@ static const unsigned char CIF_ov9650[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */ {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 352 + 98 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0xc2} -}; + {BRIDGE, M5602_XB_HSYNC_PARA, 0xc2}, -static const unsigned char QVGA_ov9650[][3] = -{ - {SENSOR, OV9650_COM7, OV9650_QVGA_SELECT | + {SENSOR, OV9650_COM7, OV9650_CIF_SELECT | OV9650_RGB_SELECT | OV9650_RAW_RGB_SELECT}, +}; - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - +static const unsigned char QVGA_ov9650[][3] = +{ /* Moves the view window in a vertical orientation */ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, @@ -536,7 +523,11 @@ static const unsigned char QVGA_ov9650[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 50 */ {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 320 + 50 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x71} + {BRIDGE, M5602_XB_HSYNC_PARA, 0x71}, + + {SENSOR, OV9650_COM7, OV9650_QVGA_SELECT | + OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT}, }; #endif -- cgit v1.2.3 From ea96a72d92acdc90a2f7f8cc2638e2061ca2846c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 24 Dec 2008 09:50:04 +0100 Subject: gspca - main: Don't lock the kernel on ioctl. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 5d2f0ab93..5adbe7301 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1818,7 +1818,7 @@ static struct file_operations dev_fops = { .release = dev_close, .read = dev_read, .mmap = dev_mmap, - .ioctl = video_ioctl2, + .unlocked_ioctl = __video_ioctl2, #ifdef CONFIG_COMPAT .compat_ioctl = v4l_compat_ioctl32, #endif -- cgit v1.2.3 From f4e951ff2cd4af2e6739e89af37c8b052976a4e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 25 Dec 2008 10:04:52 +0000 Subject: stkwebcam: Implement VIDIOC_ENUM_FRAMESIZES ioctl From: Jaime Velasco Juan This patch implements VIDIOC_ENUM_FRAMESIZES, it is used at least by gstreamer. Signed-off-by: Jaime Velasco Juan Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/stk-webcam.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 9615b7678..bfd0ddb63 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1263,6 +1263,25 @@ static int stk_vidioc_g_parm(struct file *filp, return 0; } +static int stk_vidioc_enum_framesizes(struct file *filp, + void *priv, struct v4l2_frmsizeenum *frms) +{ + if (frms->index >= ARRAY_SIZE(stk_sizes)) + return -EINVAL; + switch (frms->pixel_format) { + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_SBGGR8: + frms->type = V4L2_FRMSIZE_TYPE_DISCRETE; + frms->discrete.width = stk_sizes[frms->index].w; + frms->discrete.height = stk_sizes[frms->index].h; + return 0; + default: return -EINVAL; + } +} + static struct file_operations v4l_stk_fops = { .owner = THIS_MODULE, .open = v4l_stk_open, @@ -1297,6 +1316,7 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { .vidioc_g_ctrl = stk_vidioc_g_ctrl, .vidioc_s_ctrl = stk_vidioc_s_ctrl, .vidioc_g_parm = stk_vidioc_g_parm, + .vidioc_enum_framesizes = stk_vidioc_enum_framesizes, }; static void stk_v4l_dev_release(struct video_device *vd) -- cgit v1.2.3 From c60eeb90b566a1e86113d543f98af82a5a8b58b4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Dec 2008 08:07:39 -0200 Subject: Kbuild: fix compilation when dib7000p is not defined From: Mauro Carvalho Chehab dib7000p.h defines a few extern symbols when CONFIG_DVB_DIB7000P is not set. since the header is used on more than one driver, this causes symbol duplication, as pointed by Ingo Molnar : drivers/media/dvb/built-in.o: In function `dib7000p_set_gpio': (.text+0x3f242): multiple definition of `dib7000p_set_gpio' drivers/media/video/built-in.o:(.text+0xb8c1e): first defined here drivers/media/dvb/built-in.o: In function `dib7000p_i2c_enumeration': (.text+0x3f282): multiple definition of `dib7000p_i2c_enumeration' drivers/media/video/built-in.o:(.text+0xb8c3e): first defined here drivers/media/dvb/built-in.o: In function `dib7000p_set_wbd_ref': (.text+0x3f1c1): multiple definition of `dib7000p_set_wbd_ref' drivers/media/video/built-in.o:(.text+0xb8bfe): first defined here LD drivers/net/built-in.o make[2]: *** [drivers/media/built-in.o] Error 1 Priority: normal CC: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/dib7000p.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/dib7000p.h b/linux/drivers/media/dvb/frontends/dib7000p.h index 3e8126857..aab8112e2 100644 --- a/linux/drivers/media/dvb/frontends/dib7000p.h +++ b/linux/drivers/media/dvb/frontends/dib7000p.h @@ -66,7 +66,8 @@ struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, return NULL; } -extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, +static inline +int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) { @@ -74,13 +75,15 @@ extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, return -ENODEV; } -extern int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) +static inline +int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -extern int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value) +static inline +int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; -- cgit v1.2.3 From b534c4ad1a43513f11c89d68a1f5ef481e56d9db Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 26 Dec 2008 18:41:48 +0100 Subject: gspca - zc3xx: Webcam 046d:089d added. From: Fabio Rossi Priority: normal Signed-off-by: Fabio Rossi Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/zc3xx.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index ec00740e6..f34155f33 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -53,6 +53,7 @@ zc3xx 0461:0a00 MicroInnovation WebCam320 spca500 046d:0890 Logitech QuickCam traveler vc032x 046d:0892 Logitech Orbicam vc032x 046d:0896 Logitech Orbicam +zc3xx 046d:089d Logitech QuickCam E2500 zc3xx 046d:08a0 Logitech QC IM zc3xx 046d:08a1 Logitech QC IM 0x08A1 +sound zc3xx 046d:08a2 Labtec Webcam Pro diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index 678070b93..13e34fc7b 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -7542,6 +7542,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0458, 0x700c)}, {USB_DEVICE(0x0458, 0x700f)}, {USB_DEVICE(0x0461, 0x0a00)}, + {USB_DEVICE(0x046d, 0x089d), .driver_info = SENSOR_MC501CB}, {USB_DEVICE(0x046d, 0x08a0)}, {USB_DEVICE(0x046d, 0x08a1)}, {USB_DEVICE(0x046d, 0x08a2)}, -- cgit v1.2.3 From 0e4e71624fa8143d6840b338a1f6812bb34dcfb6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 27 Dec 2008 07:43:53 +0100 Subject: gspca - pac7311: Webcam 093a:2620 added. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/pac7311.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index f34155f33..5daf2c801 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -218,6 +218,7 @@ pac7311 093a:2603 PAC7312 pac7311 093a:2608 Trust WB-3300p pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 pac7311 093a:260f SnakeCam +pac7311 093a:2620 Apollo AC-905 pac7311 093a:2621 PAC731x pac7311 093a:2622 Genius Eye 312 pac7311 093a:2624 PAC7302 diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 51c8203e3..0a3c91301 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -1078,6 +1078,7 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2620), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302}, -- cgit v1.2.3 From 1467b595408ac678d4b03fbc57f42cce86e1f346 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 22:30:34 -0200 Subject: radio-mr800: correct unplug, fix to previous patch From: Alexey Klimov This patch corrects unplug procedure, that was implemented wrong in previous patch. New function usb_amradio_device_release added. Disconnect lock removed. Priority: high Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index dbce57c26..ff0d5240c 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -142,7 +142,6 @@ struct amradio_device { unsigned char *buffer; struct mutex lock; /* buffer locking */ - struct mutex disconnect_lock; int curfreq; int stereo; int users; @@ -305,16 +304,12 @@ static void usb_amradio_disconnect(struct usb_interface *intf) { struct amradio_device *radio = usb_get_intfdata(intf); - mutex_lock(&radio->disconnect_lock); + mutex_lock(&radio->lock); radio->removed = 1; - usb_set_intfdata(intf, NULL); + mutex_unlock(&radio->lock); - if (radio->users == 0) { - video_unregister_device(radio->videodev); - kfree(radio->buffer); - kfree(radio); - } - mutex_unlock(&radio->disconnect_lock); + usb_set_intfdata(intf, NULL); + video_unregister_device(radio->videodev); } /* vidioc_querycap - query device capabilities */ @@ -532,7 +527,7 @@ static int usb_amradio_open(struct inode *inode, struct file *file) return 0; } -/*close device - free driver structures */ +/*close device */ static int usb_amradio_close(struct inode *inode, struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); @@ -541,21 +536,15 @@ static int usb_amradio_close(struct inode *inode, struct file *file) if (!radio) return -ENODEV; - mutex_lock(&radio->disconnect_lock); radio->users = 0; - if (radio->removed) { - video_unregister_device(radio->videodev); - kfree(radio->buffer); - kfree(radio); - } else { + if (!radio->removed) { retval = amradio_stop(radio); if (retval < 0) amradio_dev_warn(&radio->videodev->dev, "amradio_stop failed\n"); } - mutex_unlock(&radio->disconnect_lock); return 0; } @@ -612,12 +601,24 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; +static void usb_amradio_device_release(struct video_device *videodev) +{ + struct amradio_device *radio = video_get_drvdata(videodev); + + /* we call v4l to free radio->videodev */ + video_device_release(videodev); + + /* free rest memory */ + kfree(radio->buffer); + kfree(radio); +} + /* V4L2 interface */ static struct video_device amradio_videodev_template = { .name = "AverMedia MR 800 USB FM Radio", .fops = &usb_amradio_fops, .ioctl_ops = &usb_amradio_ioctl_ops, - .release = video_device_release, + .release = usb_amradio_device_release, }; /* check if the device is present and register with v4l and @@ -655,7 +656,6 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->usbdev = interface_to_usbdev(intf); radio->curfreq = 95.16 * FREQ_MUL; - mutex_init(&radio->disconnect_lock); mutex_init(&radio->lock); video_set_drvdata(radio->videodev, radio); -- cgit v1.2.3 From c99b0d4ab60926ec7ee706857729a13d2c7fc866 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 22:31:49 -0200 Subject: radio-mr800: disable autosuspend support From: Alexey Klimov Because this device doesn't provide any powermanagment capabilities(may be they exist but unknown to me yet, so they are not implemented), we should turn them off. Patch sets support_autosuspend equal to 0. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index ff0d5240c..7683af18d 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -169,7 +169,7 @@ static struct usb_driver usb_amradio_driver = { .reset_resume = usb_amradio_resume, #endif .id_table = usb_amradio_device_table, - .supports_autosuspend = 1, + .supports_autosuspend = 0, }; /* switch on radio. Send 8 bytes to device. */ -- cgit v1.2.3 From 2a3f275c9ca7bd715686173b8bd62375da481bf7 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 22:32:49 -0200 Subject: dsbr100: fix unplug oops From: Alexey Klimov This patch corrects unplug procedure. Patch adds usb_dsbr100_video_device_release, new macros - videodev_to_radio, mutex lock and a lot of safety checks. Struct video_device videodev is embedded in dsbr100_device structure. Priority: high Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 106 ++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 29 deletions(-) diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index d1865b164..a13f4eeba 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -146,6 +146,7 @@ devices, that would be 76 and 91. */ #define FREQ_MAX 108.0 #define FREQ_MUL 16000 +#define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev) static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id); @@ -162,8 +163,9 @@ module_param(radio_nr, int, 0); /* Data for one (physical) device */ struct dsbr100_device { struct usb_device *usbdev; - struct video_device *videodev; + struct video_device videodev; u8 *transfer_buffer; + struct mutex lock; /* buffer locking */ int curfreq; int stereo; int users; @@ -198,6 +200,7 @@ static struct usb_driver usb_dsbr100_driver = { /* switch on radio */ static int dsbr100_start(struct dsbr100_device *radio) { + mutex_lock(&radio->lock); if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, @@ -205,9 +208,13 @@ static int dsbr100_start(struct dsbr100_device *radio) usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), DSB100_ONOFF, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x01, 0x00, radio->transfer_buffer, 8, 300) < 0) + 0x01, 0x00, radio->transfer_buffer, 8, 300) < 0) { + mutex_unlock(&radio->lock); return -1; + } + radio->muted=0; + mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; } @@ -215,6 +222,7 @@ static int dsbr100_start(struct dsbr100_device *radio) /* switch off radio */ static int dsbr100_stop(struct dsbr100_device *radio) { + mutex_lock(&radio->lock); if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, @@ -222,9 +230,13 @@ static int dsbr100_stop(struct dsbr100_device *radio) usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), DSB100_ONOFF, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0x00, radio->transfer_buffer, 8, 300) < 0) + 0x00, 0x00, radio->transfer_buffer, 8, 300) < 0) { + mutex_unlock(&radio->lock); return -1; + } + radio->muted=1; + mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; } @@ -232,6 +244,7 @@ static int dsbr100_stop(struct dsbr100_device *radio) static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) { freq = (freq / 16 * 80) / 1000 + 856; + mutex_lock(&radio->lock); if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), DSB100_TUNE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, @@ -246,9 +259,12 @@ static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x00, 0x24, radio->transfer_buffer, 8, 300) < 0) { radio->stereo = -1; + mutex_unlock(&radio->lock); return -1; } + radio->stereo = !((radio->transfer_buffer)[0] & 0x01); + mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; } @@ -256,6 +272,7 @@ static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) sees a stereo signal or not. Pity. */ static void dsbr100_getstat(struct dsbr100_device *radio) { + mutex_lock(&radio->lock); if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, @@ -263,6 +280,7 @@ static void dsbr100_getstat(struct dsbr100_device *radio) radio->stereo = -1; else radio->stereo = !(radio->transfer_buffer[0] & 0x01); + mutex_unlock(&radio->lock); } @@ -277,16 +295,12 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf) struct dsbr100_device *radio = usb_get_intfdata(intf); usb_set_intfdata (intf, NULL); - if (radio) { - video_unregister_device(radio->videodev); - radio->videodev = NULL; - if (radio->users) { - kfree(radio->transfer_buffer); - kfree(radio); - } else { - radio->removed = 1; - } - } + + mutex_lock(&radio->lock); + radio->removed = 1; + mutex_unlock(&radio->lock); + + video_unregister_device(&radio->videodev); } @@ -306,6 +320,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); + /* safety check */ + if (radio->removed) + return -EIO; + if (v->index > 0) return -EINVAL; @@ -327,6 +345,12 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct dsbr100_device *radio = video_drvdata(file); + + /* safety check */ + if (radio->removed) + return -EIO; + if (v->index > 0) return -EINVAL; @@ -338,6 +362,10 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); + /* safety check */ + if (radio->removed) + return -EIO; + radio->curfreq = f->frequency; if (dsbr100_setfreq(radio, radio->curfreq) == -1) dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); @@ -349,6 +377,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); + /* safety check */ + if (radio->removed) + return -EIO; + f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; return 0; @@ -373,6 +405,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); + /* safety check */ + if (radio->removed) + return -EIO; + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = radio->muted; @@ -386,6 +422,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); + /* safety check */ + if (radio->removed) + return -EIO; + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { @@ -467,13 +507,19 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) static int usb_dsbr100_close(struct inode *inode, struct file *file) { struct dsbr100_device *radio = video_drvdata(file); + int retval; if (!radio) return -ENODEV; + radio->users = 0; - if (radio->removed) { - kfree(radio->transfer_buffer); - kfree(radio); + if (!radio->removed) { + retval = dsbr100_stop(radio); + if (retval == -1) { + dev_warn(&radio->usbdev->dev, + "dsbr100_stop failed\n"); + } + } return 0; } @@ -508,6 +554,14 @@ static int usb_dsbr100_resume(struct usb_interface *intf) return 0; } +static void usb_dsbr100_video_device_release(struct video_device *videodev) +{ + struct dsbr100_device *radio = videodev_to_radio(videodev); + + kfree(radio->transfer_buffer); + kfree(radio); +} + /* File system interface */ static const struct file_operations usb_dsbr100_fops = { .owner = THIS_MODULE, @@ -536,11 +590,11 @@ static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = { }; /* V4L2 interface */ -static struct video_device dsbr100_videodev_template = { +static struct video_device dsbr100_videodev_data = { .name = "D-Link DSB-R 100", .fops = &usb_dsbr100_fops, .ioctl_ops = &usb_dsbr100_ioctl_ops, - .release = video_device_release, + .release = usb_dsbr100_video_device_release, }; /* check if the device is present and register with v4l and @@ -561,23 +615,17 @@ static int usb_dsbr100_probe(struct usb_interface *intf, kfree(radio); return -ENOMEM; } - radio->videodev = video_device_alloc(); - if (!(radio->videodev)) { - kfree(radio->transfer_buffer); - kfree(radio); - return -ENOMEM; - } - memcpy(radio->videodev, &dsbr100_videodev_template, - sizeof(dsbr100_videodev_template)); + mutex_init(&radio->lock); + radio->videodev = dsbr100_videodev_data; + radio->removed = 0; radio->users = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = FREQ_MIN * FREQ_MUL; - video_set_drvdata(radio->videodev, radio); - if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) { + video_set_drvdata(&radio->videodev, radio); + if (video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) { dev_warn(&intf->dev, "Could not register video device\n"); - video_device_release(radio->videodev); kfree(radio->transfer_buffer); kfree(radio); return -EIO; -- cgit v1.2.3 From 2fce60b794e95c209f73647f95a0bd5dc1f4f2b1 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 22:38:14 -0200 Subject: em28xx: Add entry for PixelView PlayTV Box 4 From: Douglas Schilling Landgraf Added board PixelView PlayTV Box 4 Thanks to Vildenei Negrao Pereira for testing and data collection. Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/Documentation/video4linux/CARDLIST.em28xx | 1 + linux/drivers/media/video/em28xx/em28xx-cards.c | 22 ++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 24 insertions(+) diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index 0c4c721da..96b1eb8ac 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -59,3 +59,4 @@ 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] 59 -> Pinnacle PCTV HD Mini (em2874) [2304:023f] 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] + 61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index c14fca841..210d60ba4 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -975,6 +975,27 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2] = { + .name = "Pixelview PlayTV Box 4 USB 2.0", + .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_YMEC_TVF_5533MF, + .decoder = EM28XX_SAA711X, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = SAA7115_COMPOSITE2, + .amux = EM28XX_AMUX_VIDEO, + .aout = EM28XX_AOUT_MONO | /* I2S */ + EM28XX_AOUT_MASTER, /* Line out pin */ + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { .name = "Pixelview Prolink PlayTV USB 2.0", .tda9887_conf = TDA9887_PRESENT, @@ -1410,6 +1431,7 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); static struct em28xx_hash_table em28xx_eeprom_hash [] = { /* P/N: SA 60002070465 Tuner: TVF7533-MF */ {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, + {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, }; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 84f49934a..f71d3509b 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -100,6 +100,7 @@ #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 #define EM2874_BOARD_PINNACLE_PCTV_80E 59 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 +#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From 975cc95f066211fa3f9bd4dd089e84f02926db4d Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 22:39:35 -0200 Subject: em28xx: Add snapshot feature for Pixelview Prolink PlayTV USB 2.0 From: Douglas Schilling Landgraf Added snapshot feature for Pixelview Prolink PlayTV USB 2.0 Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 210d60ba4..3ce87135b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -998,6 +998,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { .name = "Pixelview Prolink PlayTV USB 2.0", + .has_snapshot_button = 1, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, .decoder = EM28XX_SAA711X, -- cgit v1.2.3 From ac1912bfe46fe3f4b3df242c7a8c374dfc168508 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 22:42:39 -0200 Subject: dsbr100: place dev_warn instead of printk From: Alexey Klimov Remove printk in one line and place dev_warn there. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index a13f4eeba..be64c2a93 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -498,7 +498,8 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) retval = dsbr100_setfreq(radio, radio->curfreq); if (retval == -1) - printk(KERN_WARNING KBUILD_MODNAME ": Set frequency failed\n"); + dev_warn(&radio->usbdev->dev, + "set frequency failed\n"); unlock_kernel(); return 0; -- cgit v1.2.3 From 6c6ccd49549ab4ce83c314808d285c3834d9da7e Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 23:30:29 -0200 Subject: dsbr100: fix codingstyle, add dev_err messages From: Alexey Klimov We should make if-constructions more clear. Introduce int retval variables in some functions to make it this way. Also a lot of useful dev_err messages added. And now we check every returned value after usb_control_msg. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 184 +++++++++++++++++++++++++++--------- 1 file changed, 137 insertions(+), 47 deletions(-) diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index be64c2a93..24b91cfc7 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -200,86 +200,169 @@ static struct usb_driver usb_dsbr100_driver = { /* switch on radio */ static int dsbr100_start(struct dsbr100_device *radio) { + int retval; + int request; + mutex_lock(&radio->lock); - if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0xC7, radio->transfer_buffer, 8, 300) < 0 || - usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_ONOFF, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x01, 0x00, radio->transfer_buffer, 8, 300) < 0) { - mutex_unlock(&radio->lock); - return -1; + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0xC7, radio->transfer_buffer, 8, 300); + + if (retval < 0) { + request = USB_REQ_GET_STATUS; + goto usb_control_msg_failed; } - radio->muted=0; + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_ONOFF, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x01, 0x00, radio->transfer_buffer, 8, 300); + + if (retval < 0) { + request = DSB100_ONOFF; + goto usb_control_msg_failed; + } + + radio->muted = 0; mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; + +usb_control_msg_failed: + mutex_unlock(&radio->lock); + dev_err(&radio->usbdev->dev, + "%s - usb_control_msg returned %i, request %i\n", + __func__, retval, request); + return -1; + } /* switch off radio */ static int dsbr100_stop(struct dsbr100_device *radio) { + int retval; + int request; + mutex_lock(&radio->lock); - if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x16, 0x1C, radio->transfer_buffer, 8, 300) < 0 || - usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_ONOFF, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0x00, radio->transfer_buffer, 8, 300) < 0) { - mutex_unlock(&radio->lock); - return -1; + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x16, 0x1C, radio->transfer_buffer, 8, 300); + + if (retval < 0) { + request = USB_REQ_GET_STATUS; + goto usb_control_msg_failed; + } + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_ONOFF, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0x00, radio->transfer_buffer, 8, 300); + + if (retval < 0) { + request = DSB100_ONOFF; + goto usb_control_msg_failed; } - radio->muted=1; + radio->muted = 1; mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; + +usb_control_msg_failed: + mutex_unlock(&radio->lock); + dev_err(&radio->usbdev->dev, + "%s - usb_control_msg returned %i, request %i\n", + __func__, retval, request); + return -1; + } /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) { + int retval; + int request; + freq = (freq / 16 * 80) / 1000 + 856; mutex_lock(&radio->lock); - if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_TUNE, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - (freq >> 8) & 0x00ff, freq & 0xff, - radio->transfer_buffer, 8, 300) < 0 || - usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x96, 0xB7, radio->transfer_buffer, 8, 300) < 0 || - usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0x24, radio->transfer_buffer, 8, 300) < 0) { - radio->stereo = -1; - mutex_unlock(&radio->lock); - return -1; + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_TUNE, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + (freq >> 8) & 0x00ff, freq & 0xff, + radio->transfer_buffer, 8, 300); + + if (retval < 0) { + request = DSB100_TUNE; + goto usb_control_msg_failed; + } + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x96, 0xB7, radio->transfer_buffer, 8, 300); + + if (retval < 0) { + request = USB_REQ_GET_STATUS; + goto usb_control_msg_failed; + } + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0x24, radio->transfer_buffer, 8, 300); + + if (retval < 0) { + request = USB_REQ_GET_STATUS; + goto usb_control_msg_failed; } radio->stereo = !((radio->transfer_buffer)[0] & 0x01); mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; + +usb_control_msg_failed: + radio->stereo = -1; + mutex_unlock(&radio->lock); + dev_err(&radio->usbdev->dev, + "%s - usb_control_msg returned %i, request %i\n", + __func__, retval, request); + return -1; } /* return the device status. This is, in effect, just whether it sees a stereo signal or not. Pity. */ static void dsbr100_getstat(struct dsbr100_device *radio) { + int retval; + mutex_lock(&radio->lock); - if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00 , 0x24, radio->transfer_buffer, 8, 300) < 0) + 0x00 , 0x24, radio->transfer_buffer, 8, 300); + + if (retval < 0) { radio->stereo = -1; - else + dev_err(&radio->usbdev->dev, + "%s - usb_control_msg returned %i, request %i\n", + __func__, retval, USB_REQ_GET_STATUS); + } else { radio->stereo = !(radio->transfer_buffer[0] & 0x01); + } + mutex_unlock(&radio->lock); } @@ -361,13 +444,15 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct dsbr100_device *radio = video_drvdata(file); + int retval; /* safety check */ if (radio->removed) return -EIO; radio->curfreq = f->frequency; - if (dsbr100_setfreq(radio, radio->curfreq) == -1) + retval = dsbr100_setfreq(radio, radio->curfreq); + if (retval == -1) dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); return 0; } @@ -421,6 +506,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct dsbr100_device *radio = video_drvdata(file); + int retval; /* safety check */ if (radio->removed) @@ -429,13 +515,15 @@ static int vidioc_s_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { - if (dsbr100_stop(radio) == -1) { + retval = dsbr100_stop(radio); + if (retval == -1) { dev_warn(&radio->usbdev->dev, "Radio did not respond properly\n"); return -EBUSY; } } else { - if (dsbr100_start(radio) == -1) { + retval = dsbr100_start(radio); + if (retval == -1) { dev_warn(&radio->usbdev->dev, "Radio did not respond properly\n"); return -EBUSY; @@ -487,7 +575,8 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) radio->users = 1; radio->muted = 1; - if (dsbr100_start(radio) < 0) { + retval = dsbr100_start(radio); + if (retval < 0) { dev_warn(&radio->usbdev->dev, "Radio did not start up properly\n"); radio->users = 0; @@ -496,7 +585,6 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) } retval = dsbr100_setfreq(radio, radio->curfreq); - if (retval == -1) dev_warn(&radio->usbdev->dev, "set frequency failed\n"); @@ -604,6 +692,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct dsbr100_device *radio; + int retval; radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL); @@ -625,7 +714,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf, radio->usbdev = interface_to_usbdev(intf); radio->curfreq = FREQ_MIN * FREQ_MUL; video_set_drvdata(&radio->videodev, radio); - if (video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) { + retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr); + if (retval < 0) { dev_warn(&intf->dev, "Could not register video device\n"); kfree(radio->transfer_buffer); kfree(radio); -- cgit v1.2.3 From 5a80a7e549fb418c40e01a22a76f3c3f3ec8e4dd Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 23:31:52 -0200 Subject: dsbr100: dev_err instead of dev_warn From: Alexey Klimov We should use dev_err (not dev_warn) if video_register_device fails. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index 24b91cfc7..29d237f73 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -716,7 +716,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf, video_set_drvdata(&radio->videodev, radio); retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr); if (retval < 0) { - dev_warn(&intf->dev, "Could not register video device\n"); + dev_err(&intf->dev, "couldn't register video device\n"); kfree(radio->transfer_buffer); kfree(radio); return -EIO; -- cgit v1.2.3 From 6cf7941d5a00a305c31d4ff7e56288e60313797c Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 23:33:54 -0200 Subject: dsbr100: fix and add rigth comments From: Alexey Klimov Fix and add right comments. Few empty lines removed. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index 29d237f73..88ffd8151 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -1,5 +1,5 @@ -/* A driver for the D-Link DSB-R100 USB radio. The R100 plugs - into both the USB and an analog audio input, so this thing +/* A driver for the D-Link DSB-R100 USB radio and Gemtek USB Radio 21. + The device plugs into both the USB and an analog audio input, so this thing only deals with initialisation and frequency setting, the audio data has to be handled by a sound driver. @@ -173,7 +173,6 @@ struct dsbr100_device { int muted; }; - static struct usb_device_id usb_dsbr100_device_table [] = { { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, { } /* Terminating entry */ @@ -240,7 +239,6 @@ usb_control_msg_failed: } - /* switch off radio */ static int dsbr100_stop(struct dsbr100_device *radio) { @@ -366,13 +364,14 @@ static void dsbr100_getstat(struct dsbr100_device *radio) mutex_unlock(&radio->lock); } - /* USB subsystem interface begins here */ -/* handle unplugging of the device, release data structures -if nothing keeps us from doing it. If something is still -keeping us busy, the release callback of v4l will take care -of releasing it. */ +/* + * Handle unplugging of the device. + * We call video_unregister_device in any case. + * The last function called in this procedure is + * usb_dsbr100_video_device_release + */ static void usb_dsbr100_disconnect(struct usb_interface *intf) { struct dsbr100_device *radio = usb_get_intfdata(intf); @@ -643,6 +642,7 @@ static int usb_dsbr100_resume(struct usb_interface *intf) return 0; } +/* free data structures */ static void usb_dsbr100_video_device_release(struct video_device *videodev) { struct dsbr100_device *radio = videodev_to_radio(videodev); @@ -686,8 +686,7 @@ static struct video_device dsbr100_videodev_data = { .release = usb_dsbr100_video_device_release, }; -/* check if the device is present and register with v4l and -usb if it is */ +/* check if the device is present and register with v4l and usb if it is */ static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id) { -- cgit v1.2.3 From 54642f50524632245726a4bdf347ac8ff766c188 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 23:35:21 -0200 Subject: dsbr100: increase driver version From: Alexey Klimov Due to a lot of patches for dsbr100 last time we should update version of driver. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index 88ffd8151..ed71f1d35 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -33,6 +33,10 @@ History: + Version 0.44: + Add suspend/resume functions, fix unplug of device, + a lot of cleanups and fixes by Alexey Klimov + Version 0.43: Oliver Neukum: avoided DMA coherency issue @@ -94,8 +98,8 @@ */ #include /* for KERNEL_VERSION MACRO */ -#define DRIVER_VERSION "v0.43" -#define RADIO_VERSION KERNEL_VERSION(0, 4, 3) +#define DRIVER_VERSION "v0.44" +#define RADIO_VERSION KERNEL_VERSION(0, 4, 4) static struct v4l2_queryctrl radio_qctrl[] = { { -- cgit v1.2.3 From 67e8d5340faf1ee4bbce414e75c9d5a8dfa81781 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 27 Dec 2008 23:40:57 -0200 Subject: dsbr100: change return values in 3 functions From: Alexey Klimov Patch replace return -1; with return retval; in 3 functions. And we also change if-checks for this returned values. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index ed71f1d35..9c8e96f81 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -239,7 +239,7 @@ usb_control_msg_failed: dev_err(&radio->usbdev->dev, "%s - usb_control_msg returned %i, request %i\n", __func__, retval, request); - return -1; + return retval; } @@ -282,7 +282,7 @@ usb_control_msg_failed: dev_err(&radio->usbdev->dev, "%s - usb_control_msg returned %i, request %i\n", __func__, retval, request); - return -1; + return retval; } @@ -339,7 +339,7 @@ usb_control_msg_failed: dev_err(&radio->usbdev->dev, "%s - usb_control_msg returned %i, request %i\n", __func__, retval, request); - return -1; + return retval; } /* return the device status. This is, in effect, just whether it @@ -455,7 +455,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, radio->curfreq = f->frequency; retval = dsbr100_setfreq(radio, radio->curfreq); - if (retval == -1) + if (retval < 0) dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); return 0; } @@ -519,14 +519,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv, case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { retval = dsbr100_stop(radio); - if (retval == -1) { + if (retval < 0) { dev_warn(&radio->usbdev->dev, "Radio did not respond properly\n"); return -EBUSY; } } else { retval = dsbr100_start(radio); - if (retval == -1) { + if (retval < 0) { dev_warn(&radio->usbdev->dev, "Radio did not respond properly\n"); return -EBUSY; @@ -588,7 +588,7 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) } retval = dsbr100_setfreq(radio, radio->curfreq); - if (retval == -1) + if (retval < 0) dev_warn(&radio->usbdev->dev, "set frequency failed\n"); @@ -607,7 +607,7 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file) radio->users = 0; if (!radio->removed) { retval = dsbr100_stop(radio); - if (retval == -1) { + if (retval < 0) { dev_warn(&radio->usbdev->dev, "dsbr100_stop failed\n"); } @@ -623,7 +623,7 @@ static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) int retval; retval = dsbr100_stop(radio); - if (retval == -1) + if (retval < 0) dev_warn(&intf->dev, "dsbr100_stop failed\n"); dev_info(&intf->dev, "going into suspend..\n"); @@ -638,7 +638,7 @@ static int usb_dsbr100_resume(struct usb_interface *intf) int retval; retval = dsbr100_start(radio); - if (retval == -1) + if (retval < 0) dev_warn(&intf->dev, "dsbr100_start failed\n"); dev_info(&intf->dev, "coming out of suspend..\n"); -- cgit v1.2.3 From 5287d8eaafc2554aea15da6ff8c13fb58efdffc8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 28 Dec 2008 10:51:37 +0100 Subject: gspca - ov534: Remove empty line in trace. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 0eeb417d4..d5c74d65c 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -131,7 +131,7 @@ static int sccb_check_status(struct usb_device *udev) case 0x03: break; default: - PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5\n", + PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5", data, i + 1); } } -- cgit v1.2.3 From 326c879e45fc05f8c257a51ac785cf14dda01b28 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 29 Dec 2008 00:26:32 +0100 Subject: uvcvideo: Ignore interrupt endpoint for built-in iSight webcams. From: Laurent Pinchart Built-in iSight webcams have an interrupt endpoint but spit proprietary data that don't conform to the UVC status endpoint messages. Don't try to handle the interrupt endpoint for those cameras. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 343792f0f..d75bc915a 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1147,8 +1147,13 @@ next_descriptor: buffer += buffer[0]; } - /* Check if the optional status endpoint is present. */ - if (alts->desc.bNumEndpoints == 1) { + /* Check if the optional status endpoint is present. Built-in iSight + * webcams have an interrupt endpoint but spit proprietary data that + * don't conform to the UVC status endpoint messages. Don't try to + * handle the interrupt endpoint for those cameras. + */ + if (alts->desc.bNumEndpoints == 1 && + !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) { struct usb_host_endpoint *ep = &alts->endpoint[0]; struct usb_endpoint_descriptor *desc = &ep->desc; -- cgit v1.2.3 From 3766a9a9af7ff55a75166176dc58d5a7546e4d63 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Dec 2008 23:18:14 -0200 Subject: em28xx: move usb probe code to a proper place From: Mauro Carvalho Chehab em28xx-video were holding several code that are not specific to V4L2 interface. This patch moves the core code for em28xx-core, and usb probing code into em28xx-cards. This opens the possibility of breaking em28xx into a core module and a V4L2 module, loaded only on devices that have analog interfaces. Some cleanup may be done at em28xx-cards to optimize the config code. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 444 +++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-core.c | 143 ++++++ linux/drivers/media/video/em28xx/em28xx-video.c | 637 ++---------------------- linux/drivers/media/video/em28xx/em28xx.h | 16 +- 4 files changed, 649 insertions(+), 591 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index c14fca841..63a7082a0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -38,6 +38,8 @@ #include "em28xx.h" +#define DRIVER_NAME "em28xx" + static int tuner = -1; module_param(tuner, int, 0444); MODULE_PARM_DESC(tuner, "tuner type"); @@ -46,6 +48,13 @@ static unsigned int disable_ir; module_param(disable_ir, int, 0444); MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); +static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; +module_param_array(card, int, NULL, 0444); +MODULE_PARM_DESC(card, "card type"); + +/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ +static unsigned long em28xx_devused; + struct em28xx_hash_table { unsigned long hash; unsigned int model; @@ -1870,3 +1879,438 @@ void em28xx_card_setup(struct em28xx *dev) em28xx_ir_init(dev); } + +#if defined(CONFIG_MODULES) && defined(MODULE) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void request_module_async(void *ptr) +{ + struct em28xx *dev = (struct em28xx *)ptr; +#else +static void request_module_async(struct work_struct *work) +{ + struct em28xx *dev = container_of(work, + struct em28xx, request_module_wk); +#endif + + if (dev->has_audio_class) + request_module("snd-usb-audio"); + else if (dev->has_alsa_audio) + request_module("em28xx-alsa"); + + if (dev->board.has_dvb) + request_module("em28xx-dvb"); +} + +static void request_modules(struct em28xx *dev) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&dev->request_module_wk, request_module_async, + (void *)dev); +#else + INIT_WORK(&dev->request_module_wk, request_module_async); +#endif + schedule_work(&dev->request_module_wk); +} +#else +#define request_modules(dev) +#endif /* CONFIG_MODULES */ + +/* + * em28xx_realease_resources() + * unregisters the v4l2,i2c and usb devices + * called when the device gets disconected or at module unload +*/ +void em28xx_release_resources(struct em28xx *dev) +{ + if (dev->sbutton_input_dev) + em28xx_deregister_snapshot_button(dev); + + if (dev->ir) + em28xx_ir_fini(dev); + + /*FIXME: I2C IR should be disconnected */ + + em28xx_release_analog_resources(dev); + + em28xx_remove_from_devlist(dev); + + em28xx_i2c_unregister(dev); + usb_put_dev(dev->udev); + + /* Mark device as unused */ + em28xx_devused &= ~(1 << dev->devno); +}; + +/* + * em28xx_init_dev() + * allocates and inits the device structs, registers i2c bus and v4l device + */ +int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, + int minor) +{ + struct em28xx *dev = *devhandle; + int retval = -ENOMEM; + int errCode; + + dev->udev = udev; + mutex_init(&dev->ctrl_urb_lock); + spin_lock_init(&dev->slock); + init_waitqueue_head(&dev->open); + init_waitqueue_head(&dev->wait_frame); + init_waitqueue_head(&dev->wait_stream); + + dev->em28xx_write_regs = em28xx_write_regs; + dev->em28xx_read_reg = em28xx_read_reg; + dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; + dev->em28xx_write_regs_req = em28xx_write_regs_req; + dev->em28xx_read_reg_req = em28xx_read_reg_req; + dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; + + em28xx_pre_card_setup(dev); + + if (!dev->board.is_em2800) { + /* Sets I2C speed to 100 KHz */ + retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); + if (retval < 0) { + em28xx_errdev("%s: em28xx_write_regs_req failed!" + " retval [%d]\n", + __func__, retval); + return retval; + } + } + + /* register i2c bus */ + errCode = em28xx_i2c_register(dev); + if (errCode < 0) { + em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* Do board specific init and eeprom reading */ + em28xx_card_setup(dev); + + /* Configure audio */ + errCode = em28xx_audio_setup(dev); + if (errCode < 0) { + em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", + __func__, errCode); + } + + /* wake i2c devices */ + em28xx_wake_i2c(dev); + + /* init video dma queues */ + INIT_LIST_HEAD(&dev->vidq.active); + INIT_LIST_HEAD(&dev->vidq.queued); + +#if 0 + video_set_drvdata(dev->vbi_dev, dev); +#endif + + if (dev->board.has_msp34xx) { + /* Send a reset to other chips via gpio */ + errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); + if (errCode < 0) { + em28xx_errdev("%s: em28xx_write_regs_req - " + "msp34xx(1) failed! errCode [%d]\n", + __func__, errCode); + return errCode; + } + msleep(3); + + errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + if (errCode < 0) { + em28xx_errdev("%s: em28xx_write_regs_req - " + "msp34xx(2) failed! errCode [%d]\n", + __func__, errCode); + return errCode; + } + msleep(3); + } + + em28xx_add_into_devlist(dev); + + errCode = em28xx_analog_config(dev); + if (errCode) { + em28xx_errdev("error configuring device\n"); + return -ENOMEM; + } + + retval = em28xx_register_analog_devices(dev); + if (retval < 0) { + em28xx_release_resources(dev); + goto fail_reg_devices; + } + + em28xx_init_extension(dev); + + /* Save some power by putting tuner to sleep */ + em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + + return 0; + +fail_reg_devices: + return retval; +} + +/* + * em28xx_usb_probe() + * checks for supported devices + */ +static int em28xx_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + const struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev; + struct usb_interface *uif; + struct em28xx *dev = NULL; + int retval = -ENODEV; + int i, nr, ifnum, isoc_pipe; + char *speed; + char descr[255] = ""; + + udev = usb_get_dev(interface_to_usbdev(interface)); + ifnum = interface->altsetting[0].desc.bInterfaceNumber; + + /* Check to see next free device and mark as used */ + nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS); + em28xx_devused |= 1<altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { + em28xx_err(DRIVER_NAME " audio device (%04x:%04x): " + "interface %i, class %i\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + ifnum, + interface->altsetting[0].desc.bInterfaceClass); + + em28xx_devused &= ~(1<cur_altsetting->endpoint[0].desc; + + /* check if the device has the iso in endpoint at the correct place */ + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC && + (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) { + /* It's a newer em2874/em2875 device */ + isoc_pipe = 0; + } else { + int check_interface = 1; + isoc_pipe = 1; + endpoint = &interface->cur_altsetting->endpoint[1].desc; + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + USB_ENDPOINT_XFER_ISOC) + check_interface = 0; + + if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) + check_interface = 0; + + if (!check_interface) { + em28xx_err(DRIVER_NAME " video device (%04x:%04x): " + "interface %i, class %i found.\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + ifnum, + interface->altsetting[0].desc.bInterfaceClass); + + em28xx_err(DRIVER_NAME " This is an anciliary " + "interface not used by the driver\n"); + + em28xx_devused &= ~(1<speed) { + case USB_SPEED_LOW: + speed = "1.5"; + break; + case USB_SPEED_UNKNOWN: + case USB_SPEED_FULL: + speed = "12"; + break; + case USB_SPEED_HIGH: + speed = "480"; + break; + default: + speed = "unknown"; + } + + if (udev->manufacturer) + strlcpy(descr, udev->manufacturer, sizeof(descr)); + + if (udev->product) { + if (*descr) + strlcat(descr, " ", sizeof(descr)); + strlcat(descr, udev->product, sizeof(descr)); + } + if (*descr) + strlcat(descr, " ", sizeof(descr)); + + printk(DRIVER_NAME ": New device %s@ %s Mbps " + "(%04x:%04x, interface %d, class %d)\n", + descr, + speed, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + ifnum, + interface->altsetting->desc.bInterfaceNumber); + + if (nr >= EM28XX_MAXBOARDS) { + printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", + EM28XX_MAXBOARDS); + em28xx_devused &= ~(1<name, 29, "em28xx #%d", nr); + dev->devno = nr; + dev->model = id->driver_info; + dev->alt = -1; + + /* Checks if audio is provided by some interface */ + for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { + uif = udev->config->interface[i]; + if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { + dev->has_audio_class = 1; + break; + } + } + + /* compute alternate max packet sizes */ + uif = udev->actconfig->interface[0]; + + dev->num_alt = uif->num_altsetting; + dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); + + if (dev->alt_max_pkt_size == NULL) { + em28xx_errdev("out of memory!\n"); + em28xx_devused &= ~(1<num_alt ; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); + dev->alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + } + + if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) + dev->model = card[nr]; + + /* allocate device struct */ + mutex_init(&dev->lock); + mutex_lock(&dev->lock); + retval = em28xx_init_dev(&dev, udev, nr); + if (retval) { + em28xx_devused &= ~(1<devno); + kfree(dev); + + return retval; + } + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + request_modules(dev); + + /* Should be the last thing to do, to avoid newer udev's to + open the device before fully initializing it + */ + mutex_unlock(&dev->lock); + + return 0; +} + +/* + * em28xx_usb_disconnect() + * called when the device gets diconencted + * video device will be unregistered on v4l2_close in case it is still open + */ +static void em28xx_usb_disconnect(struct usb_interface *interface) +{ + struct em28xx *dev; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + if (!dev) + return; + + em28xx_info("disconnecting %s\n", dev->vdev->name); + + /* wait until all current v4l2 io is finished then deallocate + resources */ + mutex_lock(&dev->lock); + + wake_up_interruptible_all(&dev->open); + + if (dev->users) { + em28xx_warn + ("device /dev/video%d is open! Deregistration and memory " + "deallocation are deferred on close.\n", + dev->vdev->num); + + dev->state |= DEV_MISCONFIGURED; + em28xx_uninit_isoc(dev); + dev->state |= DEV_DISCONNECTED; + wake_up_interruptible(&dev->wait_frame); + wake_up_interruptible(&dev->wait_stream); + } else { + dev->state |= DEV_DISCONNECTED; + em28xx_release_resources(dev); + } + + em28xx_close_extension(dev); + + mutex_unlock(&dev->lock); + + if (!dev->users) { + kfree(dev->alt_max_pkt_size); + kfree(dev); + } +} + +static struct usb_driver em28xx_usb_driver = { + .name = "em28xx", + .probe = em28xx_usb_probe, + .disconnect = em28xx_usb_disconnect, + .id_table = em28xx_id_table, +}; + +static int __init em28xx_module_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&em28xx_usb_driver); + if (result) + em28xx_err(DRIVER_NAME + " usb_register failed. Error number %d.\n", result); + + printk(KERN_INFO DRIVER_NAME " driver loaded\n"); + + return result; +} + +static void __exit em28xx_module_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&em28xx_usb_driver); +} + +module_init(em28xx_module_init); +module_exit(em28xx_module_exit); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 025a54bb7..1183519eb 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "em28xx.h" @@ -983,3 +984,145 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, return 0; } EXPORT_SYMBOL_GPL(em28xx_init_isoc); + +/* + * em28xx_wake_i2c() + * configure i2c attached devices + */ +void em28xx_wake_i2c(struct em28xx *dev) +{ + struct v4l2_routing route; + int zero = 0; + + route.input = INPUT(dev->ctl_input)->vmux; + route.output = 0; + em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero); + em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); + em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); +} + +/* + * Device control list + */ + +static LIST_HEAD(em28xx_devlist); +static DEFINE_MUTEX(em28xx_devlist_mutex); + +struct em28xx *em28xx_get_device(struct inode *inode, + enum v4l2_buf_type *fh_type, + int *has_radio) +{ + struct em28xx *h, *dev = NULL; + int minor = iminor(inode); + + *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + *has_radio = 0; + + mutex_lock(&em28xx_devlist_mutex); + list_for_each_entry(h, &em28xx_devlist, devlist) { + if (h->vdev->minor == minor) + dev = h; + if (h->vbi_dev->minor == minor) { + dev = h; + *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; + } + if (h->radio_dev && + h->radio_dev->minor == minor) { + dev = h; + *has_radio = 1; + } + } + mutex_unlock(&em28xx_devlist_mutex); + + return dev; +} + +/* + * em28xx_realease_resources() + * unregisters the v4l2,i2c and usb devices + * called when the device gets disconected or at module unload +*/ +void em28xx_remove_from_devlist(struct em28xx *dev) +{ + mutex_lock(&em28xx_devlist_mutex); + list_del(&dev->devlist); + mutex_unlock(&em28xx_devlist_mutex); +}; + +void em28xx_add_into_devlist(struct em28xx *dev) +{ + mutex_lock(&em28xx_devlist_mutex); + list_add_tail(&dev->devlist, &em28xx_devlist); + mutex_unlock(&em28xx_devlist_mutex); +}; + +/* + * Extension interface + */ + +static LIST_HEAD(em28xx_extension_devlist); +static DEFINE_MUTEX(em28xx_extension_devlist_lock); + +int em28xx_register_extension(struct em28xx_ops *ops) +{ + struct em28xx *dev = NULL; + + mutex_lock(&em28xx_devlist_mutex); + mutex_lock(&em28xx_extension_devlist_lock); + list_add_tail(&ops->next, &em28xx_extension_devlist); + list_for_each_entry(dev, &em28xx_devlist, devlist) { + if (dev) + ops->init(dev); + } + printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); + mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); + return 0; +} +EXPORT_SYMBOL(em28xx_register_extension); + +void em28xx_unregister_extension(struct em28xx_ops *ops) +{ + struct em28xx *dev = NULL; + + mutex_lock(&em28xx_devlist_mutex); + list_for_each_entry(dev, &em28xx_devlist, devlist) { + if (dev) + ops->fini(dev); + } + + mutex_lock(&em28xx_extension_devlist_lock); + printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); + list_del(&ops->next); + mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); +} +EXPORT_SYMBOL(em28xx_unregister_extension); + +void em28xx_init_extension(struct em28xx *dev) +{ + struct em28xx_ops *ops = NULL; + + mutex_lock(&em28xx_extension_devlist_lock); + if (!list_empty(&em28xx_extension_devlist)) { + list_for_each_entry(ops, &em28xx_extension_devlist, next) { + if (ops->init) + ops->init(dev); + } + } + mutex_unlock(&em28xx_extension_devlist_lock); +} + +void em28xx_close_extension(struct em28xx *dev) +{ + struct em28xx_ops *ops = NULL; + + mutex_lock(&em28xx_extension_devlist_lock); + if (!list_empty(&em28xx_extension_devlist)) { + list_for_each_entry(ops, &em28xx_extension_devlist, next) { + if (ops->fini) + ops->fini(dev); + } + } + mutex_unlock(&em28xx_extension_devlist_lock); +} diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 9a7f57c8b..3e9fa0517 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -48,9 +48,8 @@ "Mauro Carvalho Chehab , " \ "Sascha Sommer " -#define DRIVER_NAME "em28xx" #define DRIVER_DESC "Empia em28xx based USB video device driver" -#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 0) +#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 1) #define em28xx_videodbg(fmt, arg...) do {\ if (video_debug) \ @@ -73,19 +72,13 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -static LIST_HEAD(em28xx_devlist); -static DEFINE_MUTEX(em28xx_devlist_mutex); - -static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; -module_param_array(card, int, NULL, 0444); module_param_array(video_nr, int, NULL, 0444); module_param_array(vbi_nr, int, NULL, 0444); module_param_array(radio_nr, int, NULL, 0444); -MODULE_PARM_DESC(card, "card type"); MODULE_PARM_DESC(video_nr, "video device numbers"); MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); @@ -94,9 +87,6 @@ static unsigned int video_debug; module_param(video_debug, int, 0644); MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); -/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ -static unsigned long em28xx_devused; - /* supported video standards */ static struct em28xx_fmt format[] = { { @@ -131,8 +121,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { } }; -static struct usb_driver em28xx_usb_driver; - /* ------------------------------------------------------------------ DMA and thread functions ------------------------------------------------------------------*/ @@ -523,58 +511,6 @@ static struct videobuf_queue_ops em28xx_video_qops = { /********************* v4l2 interface **************************************/ -/* - * em28xx_config() - * inits registers with sane defaults - */ -static int em28xx_config(struct em28xx *dev) -{ - int retval; - - /* Sets I2C speed to 100 KHz */ - if (!dev->board.is_em2800) { - retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); - if (retval < 0) { - em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n", - __func__, retval); - return retval; - } - } - -#if 1 - /* enable vbi capturing */ - -/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ -/* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */ - em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); -#endif - - dev->mute = 1; /* maybe not the right place... */ - dev->volume = 0x1f; - - em28xx_set_outfmt(dev); - em28xx_colorlevels_set_default(dev); - em28xx_compression_disable(dev); - - return 0; -} - -/* - * em28xx_config_i2c() - * configure i2c attached devices - */ -static void em28xx_config_i2c(struct em28xx *dev) -{ - struct v4l2_routing route; - int zero = 0; - - route.input = INPUT(dev->ctl_input)->vmux; - route.output = 0; - em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero); - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); - em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); -} - static void video_mux(struct em28xx *dev, int index) { struct v4l2_routing route; @@ -1696,28 +1632,12 @@ static int radio_queryctrl(struct file *file, void *priv, static int em28xx_v4l2_open(struct inode *inode, struct file *filp) { int minor = iminor(inode); - int errCode = 0, radio = 0; - struct em28xx *h, *dev = NULL; + int errCode = 0, radio; + struct em28xx *dev; + enum v4l2_buf_type fh_type; struct em28xx_fh *fh; - enum v4l2_buf_type fh_type = 0; - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(h, &em28xx_devlist, devlist) { - if (h->vdev->minor == minor) { - dev = h; - fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - if (h->vbi_dev->minor == minor) { - dev = h; - fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; - } - if (h->radio_dev && - h->radio_dev->minor == minor) { - radio = 1; - dev = h; - } - } - mutex_unlock(&em28xx_devlist_mutex); + dev = em28xx_get_device(inode, &fh_type, &radio); if (NULL == dev) return -ENODEV; @@ -1760,7 +1680,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) /* Needed, since GPIO might have disabled power of some i2c device */ - em28xx_config_i2c(dev); + em28xx_wake_i2c(dev); #if 0 /* device needs to be initialized before isoc transfer */ @@ -1791,18 +1711,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) * unregisters the v4l2,i2c and usb devices * called when the device gets disconected or at module unload */ -static void em28xx_release_resources(struct em28xx *dev) +void em28xx_release_analog_resources(struct em28xx *dev) { /*FIXME: I2C IR should be disconnected */ - list_del(&dev->devlist); - if (dev->sbutton_input_dev) - em28xx_deregister_snapshot_button(dev); - - if (dev->ir) - em28xx_ir_fini(dev); - if (dev->radio_dev) { if (-1 != dev->radio_dev->minor) video_unregister_device(dev->radio_dev); @@ -1828,11 +1741,6 @@ static void em28xx_release_resources(struct em28xx *dev) video_device_release(dev->vdev); dev->vdev = NULL; } - em28xx_i2c_unregister(dev); - usb_put_dev(dev->udev); - - /* Mark device as unused */ - em28xx_devused &= ~(1<devno); } /* @@ -2087,44 +1995,6 @@ static struct video_device em28xx_radio_template = { /******************************** usb interface ******************************/ -static LIST_HEAD(em28xx_extension_devlist); -static DEFINE_MUTEX(em28xx_extension_devlist_lock); - -int em28xx_register_extension(struct em28xx_ops *ops) -{ - struct em28xx *dev = NULL; - - mutex_lock(&em28xx_devlist_mutex); - mutex_lock(&em28xx_extension_devlist_lock); - list_add_tail(&ops->next, &em28xx_extension_devlist); - list_for_each_entry(dev, &em28xx_devlist, devlist) { - if (dev) - ops->init(dev); - } - printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); - mutex_unlock(&em28xx_extension_devlist_lock); - mutex_unlock(&em28xx_devlist_mutex); - return 0; -} -EXPORT_SYMBOL(em28xx_register_extension); - -void em28xx_unregister_extension(struct em28xx_ops *ops) -{ - struct em28xx *dev = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(dev, &em28xx_devlist, devlist) { - if (dev) - ops->fini(dev); - } - - mutex_lock(&em28xx_extension_devlist_lock); - printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); - list_del(&ops->next); - mutex_unlock(&em28xx_extension_devlist_lock); - mutex_unlock(&em28xx_devlist_mutex); -} -EXPORT_SYMBOL(em28xx_unregister_extension); static struct video_device *em28xx_vdev_init(struct em28xx *dev, const struct video_device *template, @@ -2147,7 +2017,47 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, return vfd; } -static int register_analog_devices(struct em28xx *dev) +int em28xx_analog_config(struct em28xx *dev) +{ + printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n", + dev->name, + (EM28XX_VERSION_CODE >> 16) & 0xff, + (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); + + /* Analog specific initialization */ + dev->format = &format[0]; + video_mux(dev, 0); + +#if 1 + /* enable vbi capturing */ + +/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ +/* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */ + em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); +#endif + + dev->mute = 1; /* maybe not the right place... */ + dev->volume = 0x1f; + + em28xx_set_outfmt(dev); + em28xx_colorlevels_set_default(dev); + em28xx_compression_disable(dev); + + /* set default norm */ + dev->norm = em28xx_video_template.current_norm; + dev->width = norm_maxw(dev); + dev->height = norm_maxh(dev); + dev->interlaced = EM28XX_INTERLACED_DEFAULT; + dev->hscale = 0; + dev->vscale = 0; + + /* FIXME: This is a very bad hack! Not all devices have TV on input 2 */ + dev->ctl_input = 2; + + return 0; +} + +int em28xx_register_analog_devices(struct em28xx *dev) { int ret; @@ -2199,454 +2109,3 @@ static int register_analog_devices(struct em28xx *dev) return 0; } - - -/* - * em28xx_init_dev() - * allocates and inits the device structs, registers i2c bus and v4l device - */ -static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, - int minor) -{ - struct em28xx_ops *ops = NULL; - struct em28xx *dev = *devhandle; - int retval = -ENOMEM; - int errCode; - unsigned int maxh, maxw; - - dev->udev = udev; - mutex_init(&dev->ctrl_urb_lock); - spin_lock_init(&dev->slock); - init_waitqueue_head(&dev->open); - init_waitqueue_head(&dev->wait_frame); - init_waitqueue_head(&dev->wait_stream); - - dev->em28xx_write_regs = em28xx_write_regs; - dev->em28xx_read_reg = em28xx_read_reg; - dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; - dev->em28xx_write_regs_req = em28xx_write_regs_req; - dev->em28xx_read_reg_req = em28xx_read_reg_req; - dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; - dev->format = &format[0]; - - em28xx_pre_card_setup(dev); - - errCode = em28xx_config(dev); - if (errCode) { - em28xx_errdev("error configuring device\n"); - return -ENOMEM; - } - - /* register i2c bus */ - errCode = em28xx_i2c_register(dev); - if (errCode < 0) { - em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* Do board specific init and eeprom reading */ - em28xx_card_setup(dev); - - /* Configure audio */ - errCode = em28xx_audio_setup(dev); - if (errCode < 0) { - em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", - __func__, errCode); - } - - /* configure the device */ - em28xx_config_i2c(dev); - - /* set default norm */ - dev->norm = em28xx_video_template.current_norm; - - maxw = norm_maxw(dev); - maxh = norm_maxh(dev); - - /* set default image size */ - dev->width = maxw; - dev->height = maxh; - dev->interlaced = EM28XX_INTERLACED_DEFAULT; - dev->hscale = 0; - dev->vscale = 0; - dev->ctl_input = 2; - - errCode = em28xx_config(dev); - if (errCode < 0) { - em28xx_errdev("%s: em28xx_config - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vidq.queued); - -#if 0 - video_set_drvdata(dev->vbi_dev, dev); -#endif - - if (dev->board.has_msp34xx) { - /* Send a reset to other chips via gpio */ - errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); - if (errCode < 0) { - em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n", - __func__, errCode); - return errCode; - } - msleep(3); - - errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); - if (errCode < 0) { - em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n", - __func__, errCode); - return errCode; - } - msleep(3); - } - - video_mux(dev, 0); - - mutex_lock(&em28xx_devlist_mutex); - list_add_tail(&dev->devlist, &em28xx_devlist); - retval = register_analog_devices(dev); - if (retval < 0) { - em28xx_release_resources(dev); - mutex_unlock(&em28xx_devlist_mutex); - goto fail_reg_devices; - } - - mutex_lock(&em28xx_extension_devlist_lock); - if (!list_empty(&em28xx_extension_devlist)) { - list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->id) - ops->init(dev); - } - } - mutex_unlock(&em28xx_extension_devlist_lock); - mutex_unlock(&em28xx_devlist_mutex); - - /* Save some power by putting tuner to sleep */ - em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); - - return 0; - -fail_reg_devices: - return retval; -} - -#if defined(CONFIG_MODULES) && defined(MODULE) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -static void request_module_async(void *ptr) -{ - struct em28xx *dev = (struct em28xx *)ptr; -#else -static void request_module_async(struct work_struct *work) -{ - struct em28xx *dev = container_of(work, - struct em28xx, request_module_wk); -#endif - - if (dev->has_audio_class) - request_module("snd-usb-audio"); - else if (dev->has_alsa_audio) - request_module("em28xx-alsa"); - - if (dev->board.has_dvb) - request_module("em28xx-dvb"); -} - -static void request_modules(struct em28xx *dev) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - INIT_WORK(&dev->request_module_wk, request_module_async, - (void *)dev); -#else - INIT_WORK(&dev->request_module_wk, request_module_async); -#endif - schedule_work(&dev->request_module_wk); -} -#else -#define request_modules(dev) -#endif /* CONFIG_MODULES */ - -/* - * em28xx_usb_probe() - * checks for supported devices - */ -static int em28xx_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - const struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev; - struct usb_interface *uif; - struct em28xx *dev = NULL; - int retval = -ENODEV; - int i, nr, ifnum, isoc_pipe; - char *speed; - char descr[255] = ""; - - udev = usb_get_dev(interface_to_usbdev(interface)); - ifnum = interface->altsetting[0].desc.bInterfaceNumber; - - /* Check to see next free device and mark as used */ - nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS); - em28xx_devused |= 1<altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - em28xx_err(DRIVER_NAME " audio device (%04x:%04x): " - "interface %i, class %i\n", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting[0].desc.bInterfaceClass); - - em28xx_devused &= ~(1<cur_altsetting->endpoint[0].desc; - - /* check if the device has the iso in endpoint at the correct place */ - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC && - (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) - { - /* It's a newer em2874/em2875 device */ - isoc_pipe = 0; - } else { - int check_interface = 1; - isoc_pipe = 1; - endpoint = &interface->cur_altsetting->endpoint[1].desc; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != - USB_ENDPOINT_XFER_ISOC) - check_interface = 0; - - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) - check_interface = 0; - - if (!check_interface) { - em28xx_err(DRIVER_NAME " video device (%04x:%04x): " - "interface %i, class %i found.\n", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting[0].desc.bInterfaceClass); - - em28xx_err(DRIVER_NAME " This is an anciliary " - "interface not used by the driver\n"); - - em28xx_devused &= ~(1<speed) { - case USB_SPEED_LOW: - speed = "1.5"; - break; - case USB_SPEED_UNKNOWN: - case USB_SPEED_FULL: - speed = "12"; - break; - case USB_SPEED_HIGH: - speed = "480"; - break; - default: - speed = "unknown"; - } - - if (udev->manufacturer) - strlcpy(descr, udev->manufacturer, sizeof(descr)); - - if (udev->product) { - if (*descr) - strlcat(descr, " ", sizeof(descr)); - strlcat(descr, udev->product, sizeof(descr)); - } - if (*descr) - strlcat(descr, " ", sizeof(descr)); - - printk(DRIVER_NAME ": New device %s@ %s Mbps " - "(%04x:%04x, interface %d, class %d)\n", - descr, - speed, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting->desc.bInterfaceNumber); - - if (nr >= EM28XX_MAXBOARDS) { - printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", - EM28XX_MAXBOARDS); - em28xx_devused &= ~(1<name, 29, "em28xx #%d", nr); - dev->devno = nr; - dev->model = id->driver_info; - dev->alt = -1; - - /* Checks if audio is provided by some interface */ - for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { - uif = udev->config->interface[i]; - if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - dev->has_audio_class = 1; - break; - } - } - - /* compute alternate max packet sizes */ - uif = udev->actconfig->interface[0]; - - dev->num_alt = uif->num_altsetting; - em28xx_videodbg("Alternate settings: %i\n", dev->num_alt); -/* dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */ - dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); - - if (dev->alt_max_pkt_size == NULL) { - em28xx_errdev("out of memory!\n"); - em28xx_devused &= ~(1<num_alt ; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. - wMaxPacketSize); - dev->alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - em28xx_videodbg("Alternate setting %i, max size= %i\n", i, - dev->alt_max_pkt_size[i]); - } - - if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) - dev->model = card[nr]; - - /* allocate device struct */ - mutex_init(&dev->lock); - mutex_lock(&dev->lock); - retval = em28xx_init_dev(&dev, udev, nr); - if (retval) { - em28xx_devused &= ~(1<devno); - kfree(dev); - - return retval; - } - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - request_modules(dev); - - /* Should be the last thing to do, to avoid newer udev's to - open the device before fully initializing it - */ - mutex_unlock(&dev->lock); - - return 0; -} - -/* - * em28xx_usb_disconnect() - * called when the device gets diconencted - * video device will be unregistered on v4l2_close in case it is still open - */ -static void em28xx_usb_disconnect(struct usb_interface *interface) -{ - struct em28xx *dev; - struct em28xx_ops *ops = NULL; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - em28xx_info("disconnecting %s\n", dev->vdev->name); - - /* wait until all current v4l2 io is finished then deallocate - resources */ - mutex_lock(&dev->lock); - - wake_up_interruptible_all(&dev->open); - - if (dev->users) { - em28xx_warn - ("device /dev/video%d is open! Deregistration and memory " - "deallocation are deferred on close.\n", - dev->vdev->num); - - dev->state |= DEV_MISCONFIGURED; - em28xx_uninit_isoc(dev); - dev->state |= DEV_DISCONNECTED; - wake_up_interruptible(&dev->wait_frame); - wake_up_interruptible(&dev->wait_stream); - } else { - dev->state |= DEV_DISCONNECTED; - em28xx_release_resources(dev); - } - mutex_unlock(&dev->lock); - - mutex_lock(&em28xx_extension_devlist_lock); - if (!list_empty(&em28xx_extension_devlist)) { - list_for_each_entry(ops, &em28xx_extension_devlist, next) { - ops->fini(dev); - } - } - mutex_unlock(&em28xx_extension_devlist_lock); - - if (!dev->users) { - kfree(dev->alt_max_pkt_size); - kfree(dev); - } -} - -static struct usb_driver em28xx_usb_driver = { - .name = "em28xx", - .probe = em28xx_usb_probe, - .disconnect = em28xx_usb_disconnect, - .id_table = em28xx_id_table, -}; - -static int __init em28xx_module_init(void) -{ - int result; - - printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n", - (EM28XX_VERSION_CODE >> 16) & 0xff, - (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); -#ifdef SNAPSHOT - printk(KERN_INFO DRIVER_NAME " snapshot date %04d-%02d-%02d\n", - SNAPSHOT / 10000, (SNAPSHOT / 100) % 100, SNAPSHOT % 100); -#endif - - /* register this driver with the USB subsystem */ - result = usb_register(&em28xx_usb_driver); - if (result) - em28xx_err(DRIVER_NAME - " usb_register failed. Error number %d.\n", result); - - return result; -} - -static void __exit em28xx_module_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&em28xx_usb_driver); -} - -module_init(em28xx_module_init); -module_exit(em28xx_module_exit); - diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 84f49934a..866f7a272 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -594,10 +594,21 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, void em28xx_uninit_isoc(struct em28xx *dev); int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); - -/* Provided by em28xx-video.c */ +void em28xx_wake_i2c(struct em28xx *dev); +void em28xx_remove_from_devlist(struct em28xx *dev); +void em28xx_add_into_devlist(struct em28xx *dev); +struct em28xx *em28xx_get_device(struct inode *inode, + enum v4l2_buf_type *fh_type, + int *has_radio); int em28xx_register_extension(struct em28xx_ops *dev); void em28xx_unregister_extension(struct em28xx_ops *dev); +void em28xx_init_extension(struct em28xx *dev); +void em28xx_close_extension(struct em28xx *dev); + +/* Provided by em28xx-video.c */ +int em28xx_analog_config(struct em28xx *dev); +int em28xx_register_analog_devices(struct em28xx *dev); +void em28xx_release_analog_resources(struct em28xx *dev); /* Provided by em28xx-cards.c */ extern int em2800_variant_detect(struct usb_device *udev, int model); @@ -608,6 +619,7 @@ extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); int em28xx_tuner_callback(void *ptr, int component, int command, int arg); +void em28xx_release_resources(struct em28xx *dev); /* Provided by em28xx-input.c */ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); -- cgit v1.2.3 From 9b4cfe3aca4123a0279d63449c540a2fdd5fddca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Dec 2008 23:26:36 -0200 Subject: em28xx: simplify analog logic From: Mauro Carvalho Chehab Now, just two routines are enough for analog: the first one configs the analog part and register V4L2 devices, and the second one release analog devices. After this patch, it will be easier to transform em28xx-video into an em28xx extension, loaded only on analog devices. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 6 ------ linux/drivers/media/video/em28xx/em28xx-video.c | 11 +++-------- linux/drivers/media/video/em28xx/em28xx.h | 1 - 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 63a7082a0..0c0571d0c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2031,12 +2031,6 @@ int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_add_into_devlist(dev); - errCode = em28xx_analog_config(dev); - if (errCode) { - em28xx_errdev("error configuring device\n"); - return -ENOMEM; - } - retval = em28xx_register_analog_devices(dev); if (retval < 0) { em28xx_release_resources(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 3e9fa0517..8be7aadac 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2017,8 +2017,10 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, return vfd; } -int em28xx_analog_config(struct em28xx *dev) +int em28xx_register_analog_devices(struct em28xx *dev) { + int ret; + printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n", dev->name, (EM28XX_VERSION_CODE >> 16) & 0xff, @@ -2054,13 +2056,6 @@ int em28xx_analog_config(struct em28xx *dev) /* FIXME: This is a very bad hack! Not all devices have TV on input 2 */ dev->ctl_input = 2; - return 0; -} - -int em28xx_register_analog_devices(struct em28xx *dev) -{ - int ret; - /* allocate and fill video video_device struct */ dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); if (!dev->vdev) { diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 866f7a272..a94ec33a2 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -606,7 +606,6 @@ void em28xx_init_extension(struct em28xx *dev); void em28xx_close_extension(struct em28xx *dev); /* Provided by em28xx-video.c */ -int em28xx_analog_config(struct em28xx *dev); int em28xx_register_analog_devices(struct em28xx *dev); void em28xx_release_analog_resources(struct em28xx *dev); -- cgit v1.2.3 From 081fc36b5da81564c839d81f79dbe2e75b05c2b7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 29 Dec 2008 02:32:29 +0100 Subject: uvcvideo: Add support for video output devices From: Laurent Pinchart Extend the range of supported UVC devices by allowing video output devices matching the following structure: TT_STREAMING -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> OTT_* Video output devices are reported with the V4L2_CAP_VIDEO_OUTPUT capability flag and are subject to the same restrictions as video input devices. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 109 ++++++++++++++++++++--------- linux/drivers/media/video/uvc/uvc_queue.c | 23 ++++-- linux/drivers/media/video/uvc/uvc_v4l2.c | 81 +++++++++++++-------- linux/drivers/media/video/uvc/uvc_video.c | 102 +++++++++++++++++++++++++-- linux/drivers/media/video/uvc/uvcvideo.h | 12 +++- 5 files changed, 247 insertions(+), 80 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index d75bc915a..540f57baa 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -12,8 +12,8 @@ */ /* - * This driver aims to support video input devices compliant with the 'USB - * Video Class' specification. + * This driver aims to support video input and ouput devices compliant with the + * 'USB Video Class' specification. * * The driver doesn't support the deprecated v4l1 interface. It implements the * mmap capture method only, and doesn't do any image format conversion in @@ -609,46 +609,55 @@ static int uvc_parse_streaming(struct uvc_device *dev, } /* Parse the header descriptor. */ - if (buffer[2] == VS_OUTPUT_HEADER) { + switch (buffer[2]) { + case VS_OUTPUT_HEADER: + streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + size = 9; + break; + + case VS_INPUT_HEADER: + streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + size = 13; + break; + + default: uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " - "%d OUTPUT HEADER descriptor is not supported.\n", - dev->udev->devnum, alts->desc.bInterfaceNumber); + "%d HEADER descriptor not found.\n", dev->udev->devnum, + alts->desc.bInterfaceNumber); goto error; - } else if (buffer[2] == VS_INPUT_HEADER) { - p = buflen >= 5 ? buffer[3] : 0; - n = buflen >= 12 ? buffer[12] : 0; + } - if (buflen < 13 + p*n || buffer[2] != VS_INPUT_HEADER) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d INPUT HEADER descriptor is " - "invalid.\n", dev->udev->devnum, - alts->desc.bInterfaceNumber); - goto error; - } + p = buflen >= 4 ? buffer[3] : 0; + n = buflen >= size ? buffer[size-1] : 0; + + if (buflen < size + p*n) { + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " + "interface %d HEADER descriptor is invalid.\n", + dev->udev->devnum, alts->desc.bInterfaceNumber); + goto error; + } - streaming->header.bNumFormats = p; - streaming->header.bEndpointAddress = buffer[6]; + streaming->header.bNumFormats = p; + streaming->header.bEndpointAddress = buffer[6]; + if (buffer[2] == VS_INPUT_HEADER) { streaming->header.bmInfo = buffer[7]; streaming->header.bTerminalLink = buffer[8]; streaming->header.bStillCaptureMethod = buffer[9]; streaming->header.bTriggerSupport = buffer[10]; streaming->header.bTriggerUsage = buffer[11]; - streaming->header.bControlSize = n; - - streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL); - if (streaming->header.bmaControls == NULL) { - ret = -ENOMEM; - goto error; - } - - memcpy(streaming->header.bmaControls, &buffer[13], p*n); } else { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " - "%d HEADER descriptor not found.\n", dev->udev->devnum, - alts->desc.bInterfaceNumber); + streaming->header.bTerminalLink = buffer[7]; + } + streaming->header.bControlSize = n; + + streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL); + if (streaming->header.bmaControls == NULL) { + ret = -ENOMEM; goto error; } + memcpy(streaming->header.bmaControls, &buffer[size], p*n); + buflen -= buffer[0]; buffer += buffer[0]; @@ -1258,6 +1267,26 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, list_add_tail(&entity->chain, &video->iterms); break; + case TT_STREAMING: + if (uvc_trace_param & UVC_TRACE_PROBE) + printk(" <- IT %d\n", entity->id); + + if (!UVC_ENTITY_IS_ITERM(entity)) { + uvc_trace(UVC_TRACE_DESCR, "Unsupported input " + "terminal %u.\n", entity->id); + return -1; + } + + if (video->sterm != NULL) { + uvc_trace(UVC_TRACE_DESCR, "Found multiple streaming " + "entities in chain.\n"); + return -1; + } + + list_add_tail(&entity->chain, &video->iterms); + video->sterm = entity; + break; + default: uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type " "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity)); @@ -1368,6 +1397,10 @@ static int uvc_scan_chain(struct uvc_video_device *video) entity = video->oterm; uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); + + if (UVC_ENTITY_TYPE(entity) == TT_STREAMING) + video->sterm = entity; + id = entity->output.bSourceID; while (id != 0) { prev = entity; @@ -1396,8 +1429,11 @@ static int uvc_scan_chain(struct uvc_video_device *video) return id; } - /* Initialize the video buffers queue. */ - uvc_queue_init(&video->queue); + if (video->sterm == NULL) { + uvc_trace(UVC_TRACE_DESCR, "No streaming entity found in " + "chain.\n"); + return -1; + } return 0; } @@ -1408,7 +1444,8 @@ static int uvc_scan_chain(struct uvc_video_device *video) * The driver currently supports a single video device per control interface * only. The terminal and units must match the following structure: * - * ITT_CAMERA -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING + * ITT_* -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING + * TT_STREAMING -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> OTT_* * * The Extension Units, if present, must have a single input pin. The * Processing Unit and Extension Units can be in any order. Additional @@ -1425,7 +1462,7 @@ static int uvc_register_video(struct uvc_device *dev) list_for_each_entry(term, &dev->entities, list) { struct uvc_streaming *streaming; - if (UVC_ENTITY_TYPE(term) != TT_STREAMING) + if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term)) continue; memset(&dev->video, 0, sizeof dev->video); @@ -1438,7 +1475,8 @@ static int uvc_register_video(struct uvc_device *dev) continue; list_for_each_entry(streaming, &dev->streaming, list) { - if (streaming->header.bTerminalLink == term->id) { + if (streaming->header.bTerminalLink == + dev->video.sterm->id) { dev->video.streaming = streaming; found = 1; break; @@ -1464,6 +1502,9 @@ static int uvc_register_video(struct uvc_device *dev) printk(" -> %d).\n", dev->video.oterm->id); } + /* Initialize the video buffers queue. */ + uvc_queue_init(&dev->video.queue, dev->video.streaming->type); + /* Initialize the streaming interface with default streaming * parameters. */ diff --git a/linux/drivers/media/video/uvc/uvc_queue.c b/linux/drivers/media/video/uvc/uvc_queue.c index 5646a6a32..42546342e 100644 --- a/linux/drivers/media/video/uvc/uvc_queue.c +++ b/linux/drivers/media/video/uvc/uvc_queue.c @@ -79,12 +79,13 @@ * */ -void uvc_queue_init(struct uvc_video_queue *queue) +void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) { mutex_init(&queue->mutex); spin_lock_init(&queue->irqlock); INIT_LIST_HEAD(&queue->mainqueue); INIT_LIST_HEAD(&queue->irqqueue); + queue->type = type; } /* @@ -132,7 +133,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, queue->buffer[i].buf.index = i; queue->buffer[i].buf.m.offset = i * bufsize; queue->buffer[i].buf.length = buflength; - queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + queue->buffer[i].buf.type = queue->type; queue->buffer[i].buf.sequence = 0; queue->buffer[i].buf.field = V4L2_FIELD_NONE; queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; @@ -226,7 +227,7 @@ int uvc_queue_buffer(struct uvc_video_queue *queue, uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index); - if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + if (v4l2_buf->type != queue->type || v4l2_buf->memory != V4L2_MEMORY_MMAP) { uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " "and/or memory (%u).\n", v4l2_buf->type, @@ -249,6 +250,13 @@ int uvc_queue_buffer(struct uvc_video_queue *queue, goto done; } + if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + v4l2_buf->bytesused > buf->buf.length) { + uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); + ret = -EINVAL; + goto done; + } + spin_lock_irqsave(&queue->irqlock, flags); if (queue->flags & UVC_QUEUE_DISCONNECTED) { spin_unlock_irqrestore(&queue->irqlock, flags); @@ -256,7 +264,11 @@ int uvc_queue_buffer(struct uvc_video_queue *queue, goto done; } buf->state = UVC_BUF_STATE_QUEUED; - buf->buf.bytesused = 0; + if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + buf->buf.bytesused = 0; + else + buf->buf.bytesused = v4l2_buf->bytesused; + list_add_tail(&buf->stream, &queue->mainqueue); list_add_tail(&buf->queue, &queue->irqqueue); spin_unlock_irqrestore(&queue->irqlock, flags); @@ -289,7 +301,7 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf; int ret = 0; - if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + if (v4l2_buf->type != queue->type || v4l2_buf->memory != V4L2_MEMORY_MMAP) { uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " "and/or memory (%u).\n", v4l2_buf->type, @@ -397,6 +409,7 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable) } queue->sequence = 0; queue->flags |= UVC_QUEUE_STREAMING; + queue->buf_used = 0; } else { uvc_queue_cancel(queue, 0); INIT_LIST_HEAD(&queue->mainqueue); diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index b6ee9aac6..662039b99 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -110,7 +110,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, int ret = 0; __u8 *fcc; - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fmt->type != video->streaming->type) return -EINVAL; fcc = (__u8 *)&fmt->fmt.pix.pixelformat; @@ -216,7 +216,7 @@ static int uvc_v4l2_get_format(struct uvc_video_device *video, struct uvc_format *format = video->streaming->cur_format; struct uvc_frame *frame = video->streaming->cur_frame; - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fmt->type != video->streaming->type) return -EINVAL; if (format == NULL || frame == NULL) @@ -242,7 +242,7 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video, struct uvc_frame *frame; int ret; - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fmt->type != video->streaming->type) return -EINVAL; if (uvc_queue_streaming(&video->queue)) @@ -264,7 +264,7 @@ static int uvc_v4l2_get_streamparm(struct uvc_video_device *video, { uint32_t numerator, denominator; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (parm->type != video->streaming->type) return -EINVAL; numerator = video->streaming->ctrl.dwFrameInterval; @@ -272,13 +272,21 @@ static int uvc_v4l2_get_streamparm(struct uvc_video_device *video, uvc_simplify_fraction(&numerator, &denominator, 8, 333); memset(parm, 0, sizeof *parm); - parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - parm->parm.capture.capturemode = 0; - parm->parm.capture.timeperframe.numerator = numerator; - parm->parm.capture.timeperframe.denominator = denominator; - parm->parm.capture.extendedmode = 0; - parm->parm.capture.readbuffers = 0; + parm->type = video->streaming->type; + + if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + parm->parm.capture.capturemode = 0; + parm->parm.capture.timeperframe.numerator = numerator; + parm->parm.capture.timeperframe.denominator = denominator; + parm->parm.capture.extendedmode = 0; + parm->parm.capture.readbuffers = 0; + } else { + parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + parm->parm.output.outputmode = 0; + parm->parm.output.timeperframe.numerator = numerator; + parm->parm.output.timeperframe.denominator = denominator; + } return 0; } @@ -288,24 +296,27 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, { struct uvc_frame *frame = video->streaming->cur_frame; struct uvc_streaming_control probe; + struct v4l2_fract timeperframe; uint32_t interval; int ret; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (parm->type != video->streaming->type) return -EINVAL; if (uvc_queue_streaming(&video->queue)) return -EBUSY; + if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + timeperframe = parm->parm.capture.timeperframe; + else + timeperframe = parm->parm.output.timeperframe; + memcpy(&probe, &video->streaming->ctrl, sizeof probe); - interval = uvc_fraction_to_interval( - parm->parm.capture.timeperframe.numerator, - parm->parm.capture.timeperframe.denominator); + interval = uvc_fraction_to_interval(timeperframe.numerator, + timeperframe.denominator); uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n", - parm->parm.capture.timeperframe.numerator, - parm->parm.capture.timeperframe.denominator, - interval); + timeperframe.numerator, timeperframe.denominator, interval); probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); /* Probe the device with the new settings. */ @@ -315,11 +326,15 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, memcpy(&video->streaming->ctrl, &probe, sizeof probe); /* Return the actual frame period. */ - parm->parm.capture.timeperframe.numerator = probe.dwFrameInterval; - parm->parm.capture.timeperframe.denominator = 10000000; - uvc_simplify_fraction(&parm->parm.capture.timeperframe.numerator, - &parm->parm.capture.timeperframe.denominator, - 8, 333); + timeperframe.numerator = probe.dwFrameInterval; + timeperframe.denominator = 10000000; + uvc_simplify_fraction(&timeperframe.numerator, + &timeperframe.denominator, 8, 333); + + if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + parm->parm.capture.timeperframe = timeperframe; + else + parm->parm.output.timeperframe = timeperframe; return 0; } @@ -482,8 +497,12 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) strncpy(cap->bus_info, video->dev->udev->bus->bus_name, sizeof cap->bus_info); cap->version = DRIVER_VERSION_NUMBER; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE - | V4L2_CAP_STREAMING; + if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE + | V4L2_CAP_STREAMING; + else + cap->capabilities = V4L2_CAP_VIDEO_OUTPUT + | V4L2_CAP_STREAMING; break; } @@ -661,7 +680,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_fmtdesc *fmt = arg; struct uvc_format *format; - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + if (fmt->type != video->streaming->type || fmt->index >= video->streaming->nformats) return -EINVAL; @@ -800,7 +819,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_cropcap *ccap = arg; struct uvc_frame *frame = video->streaming->cur_frame; - if (ccap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (ccap->type != video->streaming->type) return -EINVAL; ccap->bounds.left = 0; @@ -826,7 +845,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) unsigned int bufsize = video->streaming->ctrl.dwMaxVideoFrameSize; - if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + if (rb->type != video->streaming->type || rb->memory != V4L2_MEMORY_MMAP) return -EINVAL; @@ -846,7 +865,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_buffer *buf = arg; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (buf->type != video->streaming->type) return -EINVAL; if (!uvc_has_privileges(handle)) @@ -872,7 +891,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { int *type = arg; - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (*type != video->streaming->type) return -EINVAL; if (!uvc_has_privileges(handle)) @@ -887,7 +906,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { int *type = arg; - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (*type != video->streaming->type) return -EINVAL; if (!uvc_has_privileges(handle)) diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 3cb91444e..e6f7c3178 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -453,6 +453,34 @@ static void uvc_video_decode_end(struct uvc_video_device *video, } } +static int uvc_video_encode_header(struct uvc_video_device *video, + struct uvc_buffer *buf, __u8 *data, int len) +{ + data[0] = 2; /* Header length */ + data[1] = UVC_STREAM_EOH | UVC_STREAM_EOF + | (video->last_fid & UVC_STREAM_FID); + return 2; +} + +static int uvc_video_encode_data(struct uvc_video_device *video, + struct uvc_buffer *buf, __u8 *data, int len) +{ + struct uvc_video_queue *queue = &video->queue; + unsigned int nbytes; + void *mem; + + /* Copy video data to the URB buffer. */ + mem = queue->mem + buf->buf.m.offset + queue->buf_used; + nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used); + nbytes = min(video->bulk.max_payload_size - video->bulk.payload_size, + nbytes); + memcpy(data, mem, nbytes); + + queue->buf_used += nbytes; + + return nbytes; +} + /* ------------------------------------------------------------------------ * URB handling */ @@ -559,6 +587,48 @@ static void uvc_video_decode_bulk(struct urb *urb, } } +static void uvc_video_encode_bulk(struct urb *urb, + struct uvc_video_device *video, struct uvc_buffer *buf) +{ + u8 *mem = urb->transfer_buffer; + int len = video->urb_size, ret; + + if (buf == NULL) { + urb->transfer_buffer_length = 0; + return; + } + + /* If the URB is the first of its payload, add the header. */ + if (video->bulk.header_size == 0) { + ret = uvc_video_encode_header(video, buf, mem, len); + video->bulk.header_size = ret; + video->bulk.payload_size += ret; + mem += ret; + len -= ret; + } + + /* Process video data. */ + ret = uvc_video_encode_data(video, buf, mem, len); + + video->bulk.payload_size += ret; + len -= ret; + + if (buf->buf.bytesused == video->queue.buf_used || + video->bulk.payload_size == video->bulk.max_payload_size) { + if (buf->buf.bytesused == video->queue.buf_used) { + video->queue.buf_used = 0; + buf->state = UVC_BUF_STATE_DONE; + uvc_queue_next_buffer(&video->queue, buf); + video->last_fid ^= UVC_STREAM_FID; + } + + video->bulk.header_size = 0; + video->bulk.payload_size = 0; + } + + urb->transfer_buffer_length = video->urb_size - len; +} + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) static void uvc_video_complete(struct urb *urb, struct pt_regs *regs) #else @@ -760,7 +830,15 @@ static int uvc_init_video_bulk(struct uvc_video_device *video, if (uvc_alloc_urb_buffers(video, size) < 0) return -ENOMEM; - pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress); + if (usb_endpoint_dir_in(&ep->desc)) + pipe = usb_rcvbulkpipe(video->dev->udev, + ep->desc.bEndpointAddress); + else + pipe = usb_sndbulkpipe(video->dev->udev, + ep->desc.bEndpointAddress); + + if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + size = 0; for (i = 0; i < UVC_URBS; ++i) { urb = usb_alloc_urb(0, gfp_flags); @@ -981,12 +1059,22 @@ int uvc_video_init(struct uvc_video_device *video) atomic_set(&video->active, 0); /* Select the video decoding function */ - if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) - video->decode = uvc_video_decode_isight; - else if (video->streaming->intf->num_altsetting > 1) - video->decode = uvc_video_decode_isoc; - else - video->decode = uvc_video_decode_bulk; + if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) + video->decode = uvc_video_decode_isight; + else if (video->streaming->intf->num_altsetting > 1) + video->decode = uvc_video_decode_isoc; + else + video->decode = uvc_video_decode_bulk; + } else { + if (video->streaming->intf->num_altsetting == 1) + video->decode = uvc_video_encode_bulk; + else { + uvc_printk(KERN_INFO, "Isochronous endpoints are not " + "supported for video output devices.\n"); + return -EINVAL; + } + } return 0; } diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 549d09fd3..a045fa40d 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -529,6 +529,7 @@ struct uvc_streaming { __u16 maxpsize; struct uvc_streaming_header header; + enum v4l2_buf_type type; unsigned int nformats; struct uvc_format *format; @@ -564,12 +565,15 @@ struct uvc_buffer { #define UVC_QUEUE_DROP_INCOMPLETE (1 << 2) struct uvc_video_queue { + enum v4l2_buf_type type; + void *mem; unsigned int flags; __u32 sequence; unsigned int count; unsigned int buf_size; + unsigned int buf_used; struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS]; struct mutex mutex; /* protects buffers and mainqueue */ spinlock_t irqlock; /* protects irqqueue */ @@ -584,8 +588,9 @@ struct uvc_video_device { atomic_t active; unsigned int frozen : 1; - struct list_head iterms; - struct uvc_entity *oterm; + struct list_head iterms; /* Input terminals */ + struct uvc_entity *oterm; /* Output terminal */ + struct uvc_entity *sterm; /* USB streaming terminal */ struct uvc_entity *processing; struct uvc_entity *selector; struct list_head extensions; @@ -726,7 +731,8 @@ extern struct uvc_driver uvc_driver; extern void uvc_delete(struct kref *kref); /* Video buffers queue management. */ -extern void uvc_queue_init(struct uvc_video_queue *queue); +extern void uvc_queue_init(struct uvc_video_queue *queue, + enum v4l2_buf_type type); extern int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, unsigned int buflength); extern int uvc_free_buffers(struct uvc_video_queue *queue); -- cgit v1.2.3 From aa34e3dd9265d2d80d237efb9c2df91e0f138638 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 29 Dec 2008 10:04:06 +0100 Subject: Add tw9910 driver From: Kuninori Morimoto This patch adds tw9910 driver that use soc_camera framework. It was tested on SH Migo-r board and mplayer. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/Kconfig | 6 + drivers/media/video/Makefile | 1 + drivers/media/video/tw9910.c | 941 +++++++++++++++++++++++++++++++++++++++ include/media/tw9910.h | 39 ++ include/media/v4l2-chip-ident.h | 3 + 5 files changed, 990 insertions(+), 0 deletions(-) create mode 100644 drivers/media/video/tw9910.c create mode 100644 include/media/tw9910.h --- linux/drivers/media/video/Kconfig | 6 + linux/drivers/media/video/Makefile | 1 + linux/drivers/media/video/tw9910.c | 941 ++++++++++++++++++++++++++++++++++ linux/include/media/tw9910.h | 39 ++ linux/include/media/v4l2-chip-ident.h | 3 + 5 files changed, 990 insertions(+) create mode 100644 linux/drivers/media/video/tw9910.c create mode 100644 linux/include/media/tw9910.h diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index e6c89cdfe..ce68b5d4b 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -755,6 +755,12 @@ config MT9V022_PCA9536_SWITCH Select this if your MT9V022 camera uses a PCA9536 I2C GPIO extender to switch between 8 and 10 bit datawidth modes +config SOC_CAMERA_TW9910 + tristate "tw9910 support" + depends on SOC_CAMERA && I2C + help + This is a tw9910 video driver + config SOC_CAMERA_PLATFORM tristate "platform camera support" depends on SOC_CAMERA diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 84a2be0cb..40c69afcd 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -140,6 +140,7 @@ obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o +obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o obj-$(CONFIG_VIDEO_AU0828) += au0828/ diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c new file mode 100644 index 000000000..75cfde02d --- /dev/null +++ b/linux/drivers/media/video/tw9910.c @@ -0,0 +1,941 @@ +/* + * tw9910 Video Driver + * + * Copyright (C) 2008 Renesas Solutions Corp. + * Kuninori Morimoto + * + * Based on ov772x driver, + * + * Copyright (C) 2008 Kuninori Morimoto + * Copyright 2006-7 Jonathan Corbet + * Copyright (C) 2008 Magnus Damm + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GET_ID(val) ((val & 0xF8) >> 3) +#define GET_ReV(val) (val & 0x07) + +/* + * register offset + */ +#define ID 0x00 /* Product ID Code Register */ +#define STATUS1 0x01 /* Chip Status Register I */ +#define INFORM 0x02 /* Input Format */ +#define OPFORM 0x03 /* Output Format Control Register */ +#define DLYCTR 0x04 /* Hysteresis and HSYNC Delay Control */ +#define OUTCTR1 0x05 /* Output Control I */ +#define ACNTL1 0x06 /* Analog Control Register 1 */ +#define CROP_HI 0x07 /* Cropping Register, High */ +#define VDELAY_LO 0x08 /* Vertical Delay Register, Low */ +#define VACTIVE_LO 0x09 /* Vertical Active Register, Low */ +#define HDELAY_LO 0x0A /* Horizontal Delay Register, Low */ +#define HACTIVE_LO 0x0B /* Horizontal Active Register, Low */ +#define CNTRL1 0x0C /* Control Register I */ +#define VSCALE_LO 0x0D /* Vertical Scaling Register, Low */ +#define SCALE_HI 0x0E /* Scaling Register, High */ +#define HSCALE_LO 0x0F /* Horizontal Scaling Register, Low */ +#define BRIGHT 0x10 /* BRIGHTNESS Control Register */ +#define CONTRAST 0x11 /* CONTRAST Control Register */ +#define SHARPNESS 0x12 /* SHARPNESS Control Register I */ +#define SAT_U 0x13 /* Chroma (U) Gain Register */ +#define SAT_V 0x14 /* Chroma (V) Gain Register */ +#define HUE 0x15 /* Hue Control Register */ +#define CORING1 0x17 +#define CORING2 0x18 /* Coring and IF compensation */ +#define VBICNTL 0x19 /* VBI Control Register */ +#define ACNTL2 0x1A /* Analog Control 2 */ +#define OUTCTR2 0x1B /* Output Control 2 */ +#define SDT 0x1C /* Standard Selection */ +#define SDTR 0x1D /* Standard Recognition */ +#define TEST 0x1F /* Test Control Register */ +#define CLMPG 0x20 /* Clamping Gain */ +#define IAGC 0x21 /* Individual AGC Gain */ +#define AGCGAIN 0x22 /* AGC Gain */ +#define PEAKWT 0x23 /* White Peak Threshold */ +#define CLMPL 0x24 /* Clamp level */ +#define SYNCT 0x25 /* Sync Amplitude */ +#define MISSCNT 0x26 /* Sync Miss Count Register */ +#define PCLAMP 0x27 /* Clamp Position Register */ +#define VCNTL1 0x28 /* Vertical Control I */ +#define VCNTL2 0x29 /* Vertical Control II */ +#define CKILL 0x2A /* Color Killer Level Control */ +#define COMB 0x2B /* Comb Filter Control */ +#define LDLY 0x2C /* Luma Delay and H Filter Control */ +#define MISC1 0x2D /* Miscellaneous Control I */ +#define LOOP 0x2E /* LOOP Control Register */ +#define MISC2 0x2F /* Miscellaneous Control II */ +#define MVSN 0x30 /* Macrovision Detection */ +#define STATUS2 0x31 /* Chip STATUS II */ +#define HFREF 0x32 /* H monitor */ +#define CLMD 0x33 /* CLAMP MODE */ +#define IDCNTL 0x34 /* ID Detection Control */ +#define CLCNTL1 0x35 /* Clamp Control I */ +#define ANAPLLCTL 0x4C +#define VBIMIN 0x4D +#define HSLOWCTL 0x4E +#define WSS3 0x4F +#define FILLDATA 0x50 +#define SDID 0x51 +#define DID 0x52 +#define WSS1 0x53 +#define WSS2 0x54 +#define VVBI 0x55 +#define LCTL6 0x56 +#define LCTL7 0x57 +#define LCTL8 0x58 +#define LCTL9 0x59 +#define LCTL10 0x5A +#define LCTL11 0x5B +#define LCTL12 0x5C +#define LCTL13 0x5D +#define LCTL14 0x5E +#define LCTL15 0x5F +#define LCTL16 0x60 +#define LCTL17 0x61 +#define LCTL18 0x62 +#define LCTL19 0x63 +#define LCTL20 0x64 +#define LCTL21 0x65 +#define LCTL22 0x66 +#define LCTL23 0x67 +#define LCTL24 0x68 +#define LCTL25 0x69 +#define LCTL26 0x6A +#define HSGEGIN 0x6B +#define HSEND 0x6C +#define OVSDLY 0x6D +#define OVSEND 0x6E +#define VBIDELAY 0x6F + +/* + * register detail + */ + +/* INFORM */ +#define FC27_ON 0x40 /* 1 : Input crystal clock frequency is 27MHz */ +#define FC27_FF 0x00 /* 0 : Square pixel mode. */ + /* Must use 24.54MHz for 60Hz field rate */ + /* source or 29.5MHz for 50Hz field rate */ +#define IFSEL_S 0x10 /* 01 : S-video decoding */ +#define IFSEL_C 0x00 /* 00 : Composite video decoding */ + /* Y input video selection */ +#define YSEL_M0 0x00 /* 00 : Mux0 selected */ +#define YSEL_M1 0x04 /* 01 : Mux1 selected */ +#define YSEL_M2 0x08 /* 10 : Mux2 selected */ +#define YSEL_M3 0x10 /* 11 : Mux3 selected */ + +/* OPFORM */ +#define MODE 0x80 /* 0 : CCIR601 compatible YCrCb 4:2:2 format */ + /* 1 : ITU-R-656 compatible data sequence format */ +#define LEN 0x40 /* 0 : 8-bit YCrCb 4:2:2 output format */ + /* 1 : 16-bit YCrCb 4:2:2 output format.*/ +#define LLCMODE 0x20 /* 1 : LLC output mode. */ + /* 0 : free-run output mode */ +#define AINC 0x10 /* Serial interface auto-indexing control */ + /* 0 : auto-increment */ + /* 1 : non-auto */ +#define VSCTL 0x08 /* 1 : Vertical out ctrl by DVALID */ + /* 0 : Vertical out ctrl by HACTIVE and DVALID */ +#define OEN 0x04 /* Output Enable together with TRI_SEL. */ + +/* OUTCTR1 */ +#define VSP_LO 0x00 /* 0 : VS pin output polarity is active low */ +#define VSP_HI 0x80 /* 1 : VS pin output polarity is active high. */ + /* VS pin output control */ +#define VSSL_VSYNC 0x00 /* 0 : VSYNC */ +#define VSSL_VACT 0x10 /* 1 : VACT */ +#define VSSL_FIELD 0x20 /* 2 : FIELD */ +#define VSSL_VVALID 0x30 /* 3 : VVALID */ +#define VSSL_ZERO 0x70 /* 7 : 0 */ +#define HSP_LOW 0x00 /* 0 : HS pin output polarity is active low */ +#define HSP_HI 0x08 /* 1 : HS pin output polarity is active high.*/ + /* HS pin output control */ +#define HSSL_HACT 0x00 /* 0 : HACT */ +#define HSSL_HSYNC 0x01 /* 1 : HSYNC */ +#define HSSL_DVALID 0x02 /* 2 : DVALID */ +#define HSSL_HLOCK 0x03 /* 3 : HLOCK */ +#define HSSL_ASYNCW 0x04 /* 4 : ASYNCW */ +#define HSSL_ZERO 0x07 /* 7 : 0 */ + +/* ACNTL1 */ +#define SRESET 0x80 /* resets the device to its default state + * but all register content remain unchanged. + * This bit is self-resetting. + */ + +/* VBICNTL */ +/* RTSEL : control the real time signal +* output from the MPOUT pin +*/ +#define RTSEL_MASK 0x07 +#define RTSEL_VLOSS 0x00 /* 0000 = Video loss */ +#define RTSEL_HLOCK 0x01 /* 0001 = H-lock */ +#define RTSEL_SLOCK 0x02 /* 0010 = S-lock */ +#define RTSEL_VLOCK 0x03 /* 0011 = V-lock */ +#define RTSEL_MONO 0x04 /* 0100 = MONO */ +#define RTSEL_DET50 0x05 /* 0101 = DET50 */ +#define RTSEL_FIELD 0x06 /* 0110 = FIELD */ +#define RTSEL_RTCO 0x07 /* 0111 = RTCO ( Real Time Control ) */ + +/* + * structure + */ + +struct regval_list { + unsigned char reg_num; + unsigned char value; +}; + +struct tw9910_scale_ctrl { + char *name; + unsigned short width; + unsigned short height; + u16 hscale; + u16 vscale; +}; + +struct tw9910_cropping_ctrl { + u16 vdelay; + u16 vactive; + u16 hdelay; + u16 hactive; +}; + +struct tw9910_hsync_ctrl { + u16 start; + u16 end; +}; + +struct tw9910_priv { + struct tw9910_video_info *info; + struct i2c_client *client; + struct soc_camera_device icd; + const struct tw9910_scale_ctrl *scale; +}; + +/* + * register settings + */ + +#define ENDMARKER { 0xff, 0xff } + +static const struct regval_list tw9910_default_regs[] = +{ + { OPFORM, 0x00 }, + { OUTCTR1, VSP_LO | VSSL_VVALID | HSP_HI | HSSL_HSYNC }, + ENDMARKER, +}; + +static const struct soc_camera_data_format tw9910_color_fmt[] = { + { + .name = "VYUY", + .fourcc = V4L2_PIX_FMT_VYUY, + .depth = 16, + .colorspace = V4L2_COLORSPACE_SMPTE170M, + } +}; + +static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = { + { + .name = "NTSC SQ", + .width = 640, + .height = 480, + .hscale = 0x0100, + .vscale = 0x0100, + }, + { + .name = "NTSC CCIR601", + .width = 720, + .height = 480, + .hscale = 0x0100, + .vscale = 0x0100, + }, + { + .name = "NTSC SQ (CIF)", + .width = 320, + .height = 240, + .hscale = 0x0200, + .vscale = 0x0200, + }, + { + .name = "NTSC CCIR601 (CIF)", + .width = 360, + .height = 240, + .hscale = 0x0200, + .vscale = 0x0200, + }, + { + .name = "NTSC SQ (QCIF)", + .width = 160, + .height = 120, + .hscale = 0x0400, + .vscale = 0x0400, + }, + { + .name = "NTSC CCIR601 (QCIF)", + .width = 180, + .height = 120, + .hscale = 0x0400, + .vscale = 0x0400, + }, +}; + +static const struct tw9910_scale_ctrl tw9910_pal_scales[] = { + { + .name = "PAL SQ", + .width = 768, + .height = 576, + .hscale = 0x0100, + .vscale = 0x0100, + }, + { + .name = "PAL CCIR601", + .width = 720, + .height = 576, + .hscale = 0x0100, + .vscale = 0x0100, + }, + { + .name = "PAL SQ (CIF)", + .width = 384, + .height = 288, + .hscale = 0x0200, + .vscale = 0x0200, + }, + { + .name = "PAL CCIR601 (CIF)", + .width = 360, + .height = 288, + .hscale = 0x0200, + .vscale = 0x0200, + }, + { + .name = "PAL SQ (QCIF)", + .width = 192, + .height = 144, + .hscale = 0x0400, + .vscale = 0x0400, + }, + { + .name = "PAL CCIR601 (QCIF)", + .width = 180, + .height = 144, + .hscale = 0x0400, + .vscale = 0x0400, + }, +}; + +static const struct tw9910_cropping_ctrl tw9910_cropping_ctrl = { + .vdelay = 0x0012, + .vactive = 0x00F0, + .hdelay = 0x0010, + .hactive = 0x02D0, +}; + +static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { + .start = 0x0260, + .end = 0x0300, +}; + +/* + * general function + */ +static int tw9910_set_scale(struct i2c_client *client, + const struct tw9910_scale_ctrl *scale) +{ + int ret; + + ret = i2c_smbus_write_byte_data(client, SCALE_HI, + (scale->vscale & 0x0F00) >> 4 | + (scale->hscale & 0x0F00) >> 8); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, HSCALE_LO, + scale->hscale & 0x00FF); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, VSCALE_LO, + scale->vscale & 0x00FF); + + return ret; +} + +static int tw9910_set_cropping(struct i2c_client *client, + const struct tw9910_cropping_ctrl *cropping) +{ + int ret; + + ret = i2c_smbus_write_byte_data(client, CROP_HI, + (cropping->vdelay & 0x0300) >> 2 | + (cropping->vactive & 0x0300) >> 4 | + (cropping->hdelay & 0x0300) >> 6 | + (cropping->hactive & 0x0300) >> 8); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, VDELAY_LO, + cropping->vdelay & 0x00FF); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, VACTIVE_LO, + cropping->vactive & 0x00FF); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, HDELAY_LO, + cropping->hdelay & 0x00FF); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, HACTIVE_LO, + cropping->hactive & 0x00FF); + + return ret; +} + +static int tw9910_set_hsync(struct i2c_client *client, + const struct tw9910_hsync_ctrl *hsync) +{ + int ret; + + /* bit 10 - 3 */ + ret = i2c_smbus_write_byte_data(client, HSGEGIN, + (hsync->start & 0x07F8) >> 3); + if (ret < 0) + return ret; + + /* bit 10 - 3 */ + ret = i2c_smbus_write_byte_data(client, HSEND, + (hsync->end & 0x07F8) >> 3); + if (ret < 0) + return ret; + + /* bit 2 - 0 */ + ret = i2c_smbus_read_byte_data(client, HSLOWCTL); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, HSLOWCTL, + (ret & 0x88) | + (hsync->start & 0x0007) << 4 | + (hsync->end & 0x0007)); + + return ret; +} + +static int tw9910_write_array(struct i2c_client *client, + const struct regval_list *vals) +{ + while (vals->reg_num != 0xff) { + int ret = i2c_smbus_write_byte_data(client, + vals->reg_num, + vals->value); + if (ret < 0) + return ret; + vals++; + } + return 0; +} + +static int tw9910_mask_set(struct i2c_client *client, u8 command, + u8 mask, u8 set) +{ + s32 val = i2c_smbus_read_byte_data(client, command); + + val &= ~mask; + val |= set; + + return i2c_smbus_write_byte_data(client, command, val); +} + +static void tw9910_reset(struct i2c_client *client) +{ + i2c_smbus_write_byte_data(client, ACNTL1, SRESET); + msleep(1); +} + +static const struct tw9910_scale_ctrl* +tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) +{ + const struct tw9910_scale_ctrl *scale; + const struct tw9910_scale_ctrl *ret = NULL; + v4l2_std_id norm = icd->vdev->current_norm; + __u32 diff = 0xffffffff, tmp; + int size, i; + + if (norm & V4L2_STD_NTSC) { + scale = tw9910_ntsc_scales; + size = ARRAY_SIZE(tw9910_ntsc_scales); + } else if (norm & V4L2_STD_PAL) { + scale = tw9910_pal_scales; + size = ARRAY_SIZE(tw9910_pal_scales); + } else { + return NULL; + } + + for (i = 0; i < size; i++) { + tmp = abs(width - scale[i].width) + + abs(height - scale[i].height); + if (tmp < diff) { + diff = tmp; + ret = scale + i; + } + } + + return ret; +} + +/* + * soc_camera_ops function + */ +static int tw9910_init(struct soc_camera_device *icd) +{ + struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + int ret = 0; + + if (priv->info->link.power) { + ret = priv->info->link.power(&priv->client->dev, 1); + if (ret < 0) + return ret; + } + + if (priv->info->link.reset) + ret = priv->info->link.reset(&priv->client->dev); + + return ret; +} + +static int tw9910_release(struct soc_camera_device *icd) +{ + struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + int ret = 0; + + if (priv->info->link.power) + ret = priv->info->link.power(&priv->client->dev, 0); + + return ret; +} + +static int tw9910_start_capture(struct soc_camera_device *icd) +{ + struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + + if (!priv->scale) { + dev_err(&icd->dev, "norm select error\n"); + return -EPERM; + } + + dev_dbg(&icd->dev, "%s %dx%d\n", + priv->scale->name, + priv->scale->width, + priv->scale->height); + + return 0; +} + +static int tw9910_stop_capture(struct soc_camera_device *icd) +{ + return 0; +} + +static int tw9910_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) +{ + return 0; +} + +static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) +{ + struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct soc_camera_link *icl = priv->client->dev.platform_data; + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; + + return soc_camera_apply_sensor_flags(icl, flags); +} + +static int tw9910_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + id->ident = V4L2_IDENT_TW9910; + id->revision = 0; + + return 0; +} + +static int tw9910_set_std(struct soc_camera_device *icd, + v4l2_std_id *a) +{ + int ret = -EINVAL; + + if (*a & (V4L2_STD_NTSC | V4L2_STD_PAL)) + ret = 0; + + return ret; +} + +static int tw9910_enum_input(struct soc_camera_device *icd, + struct v4l2_input *inp) +{ + inp->type = V4L2_INPUT_TYPE_TUNER; + inp->std = V4L2_STD_UNKNOWN; + strcpy(inp->name, "Video"); + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int tw9910_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + int ret; + + if (reg->reg > 0xff) + return -EINVAL; + + ret = i2c_smbus_read_byte_data(priv->client, reg->reg); + if (ret < 0) + return ret; + + /* ret = int + * reg->val = __u64 + */ + reg->val = (__u64)ret; + + return 0; +} + +static int tw9910_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + + if (reg->reg > 0xff || + reg->val > 0xff) + return -EINVAL; + + return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); +} +#endif + +static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, + struct v4l2_rect *rect) +{ + struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + int ret = -EINVAL; + u8 val; + + /* + * select suitable norm + */ + priv->scale = tw9910_select_norm(icd, rect->width, rect->height); + if (!priv->scale) + return ret; + + /* + * reset hardware + */ + tw9910_reset(priv->client); + ret = tw9910_write_array(priv->client, tw9910_default_regs); + if (ret < 0) + return ret; + /* + * set bus width + */ + val = 0x00; + if (SOCAM_DATAWIDTH_16 == priv->info->buswidth) + val = LEN; + + ret = tw9910_mask_set(priv->client, OPFORM, LEN, val); + if (ret < 0) + return ret; + + /* + * select MPOUT behavior + */ + switch (priv->info->mpout) { + case TW9910_MPO_VLOSS: + val = RTSEL_VLOSS; break; + case TW9910_MPO_HLOCK: + val = RTSEL_HLOCK; break; + case TW9910_MPO_SLOCK: + val = RTSEL_SLOCK; break; + case TW9910_MPO_VLOCK: + val = RTSEL_VLOCK; break; + case TW9910_MPO_MONO: + val = RTSEL_MONO; break; + case TW9910_MPO_DET50: + val = RTSEL_DET50; break; + case TW9910_MPO_FIELD: + val = RTSEL_FIELD; break; + case TW9910_MPO_RTCO: + val = RTSEL_RTCO; break; + default: + val = 0; + } + + ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val); + if (ret < 0) + return ret; + + /* + * set scale + */ + ret = tw9910_set_scale(priv->client, priv->scale); + if (ret < 0) + return ret; + + /* + * set cropping + */ + ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl); + if (ret < 0) + return ret; + + /* + * set hsync + */ + ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl); + + return ret; +} + +static int tw9910_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_pix_format *pix = &f->fmt.pix; + const struct tw9910_scale_ctrl *scale; + + if (V4L2_FIELD_ANY == pix->field) { + pix->field = V4L2_FIELD_INTERLACED; + } else if (V4L2_FIELD_INTERLACED != pix->field) { + dev_err(&icd->dev, "Field type invalid.\n"); + return -EINVAL; + } + + /* + * select suitable norm + */ + scale = tw9910_select_norm(icd, pix->width, pix->height); + if (!scale) + return -EINVAL; + + pix->width = scale->width; + pix->height = scale->height; + + return 0; +} + +static int tw9910_video_probe(struct soc_camera_device *icd) +{ + struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + s32 val; + int ret; + + /* + * We must have a parent by now. And it cannot be a wrong one. + * So this entire test is completely redundant. + */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* + * tw9910 only use 8 or 16 bit bus width + */ + if (SOCAM_DATAWIDTH_16 != priv->info->buswidth && + SOCAM_DATAWIDTH_8 != priv->info->buswidth) { + dev_err(&icd->dev, "bus width error\n"); + return -ENODEV; + } + + icd->formats = tw9910_color_fmt; + icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); + + /* + * check and show Product ID + */ + val = i2c_smbus_read_byte_data(priv->client, ID); + if (0x0B != GET_ID(val) || + 0x00 != GET_ReV(val)) { + dev_err(&icd->dev, + "Product ID error %x:%x\n", GET_ID(val), GET_ReV(val)); + return -ENODEV; + } + + dev_info(&icd->dev, + "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); + + ret = soc_camera_video_start(icd); + if (ret < 0) + return ret; + + icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; + icd->vdev->current_norm = V4L2_STD_NTSC; + + return ret; +} + +static void tw9910_video_remove(struct soc_camera_device *icd) +{ + soc_camera_video_stop(icd); +} + +static struct soc_camera_ops tw9910_ops = { + .owner = THIS_MODULE, + .probe = tw9910_video_probe, + .remove = tw9910_video_remove, + .init = tw9910_init, + .release = tw9910_release, + .start_capture = tw9910_start_capture, + .stop_capture = tw9910_stop_capture, + .set_fmt = tw9910_set_fmt, + .try_fmt = tw9910_try_fmt, + .set_bus_param = tw9910_set_bus_param, + .query_bus_param = tw9910_query_bus_param, + .get_chip_id = tw9910_get_chip_id, + .set_std = tw9910_set_std, + .enum_input = tw9910_enum_input, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = tw9910_get_register, + .set_register = tw9910_set_register, +#endif +}; + +/* + * i2c_driver function + */ + +static int tw9910_probe(struct i2c_client *client, + const struct i2c_device_id *did) + +{ + struct tw9910_priv *priv; + struct tw9910_video_info *info; + struct soc_camera_device *icd; + const struct tw9910_scale_ctrl *scale; + int i, ret; + + info = client->dev.platform_data; + if (!info) + return -EINVAL; + + if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent), + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, + "I2C-Adapter doesn't support " + "I2C_FUNC_SMBUS_BYTE_DATA\n"); + return -EIO; + } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->info = info; + priv->client = client; + i2c_set_clientdata(client, priv); + + icd = &priv->icd; + icd->ops = &tw9910_ops; + icd->control = &client->dev; + icd->iface = info->link.bus_id; + + /* + * set width and height + */ + icd->width_max = tw9910_ntsc_scales[0].width; /* set default */ + icd->width_min = tw9910_ntsc_scales[0].width; + icd->height_max = tw9910_ntsc_scales[0].height; + icd->height_min = tw9910_ntsc_scales[0].height; + + scale = tw9910_ntsc_scales; + for (i = 0; i < ARRAY_SIZE(tw9910_ntsc_scales); i++) { + icd->width_max = max(scale[i].width, icd->width_max); + icd->width_min = min(scale[i].width, icd->width_min); + icd->height_max = max(scale[i].height, icd->height_max); + icd->height_min = min(scale[i].height, icd->height_min); + } + scale = tw9910_pal_scales; + for (i = 0; i < ARRAY_SIZE(tw9910_pal_scales); i++) { + icd->width_max = max(scale[i].width, icd->width_max); + icd->width_min = min(scale[i].width, icd->width_min); + icd->height_max = max(scale[i].height, icd->height_max); + icd->height_min = min(scale[i].height, icd->height_min); + } + + ret = soc_camera_device_register(icd); + + if (ret) { + i2c_set_clientdata(client, NULL); + kfree(priv); + } + + return ret; +} + +static int tw9910_remove(struct i2c_client *client) +{ + struct tw9910_priv *priv = i2c_get_clientdata(client); + + soc_camera_device_unregister(&priv->icd); + i2c_set_clientdata(client, NULL); + kfree(priv); + return 0; +} + +static const struct i2c_device_id tw9910_id[] = { + { "tw9910", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tw9910_id); + +static struct i2c_driver tw9910_i2c_driver = { + .driver = { + .name = "tw9910", + }, + .probe = tw9910_probe, + .remove = tw9910_remove, + .id_table = tw9910_id, +}; + +/* + * module function + */ +static int __init tw9910_module_init(void) +{ + return i2c_add_driver(&tw9910_i2c_driver); +} + +static void __exit tw9910_module_exit(void) +{ + i2c_del_driver(&tw9910_i2c_driver); +} + +module_init(tw9910_module_init); +module_exit(tw9910_module_exit); + +MODULE_DESCRIPTION("SoC Camera driver for tw9910"); +MODULE_AUTHOR("Kuninori Morimoto"); +MODULE_LICENSE("GPL v2"); diff --git a/linux/include/media/tw9910.h b/linux/include/media/tw9910.h new file mode 100644 index 000000000..73231e788 --- /dev/null +++ b/linux/include/media/tw9910.h @@ -0,0 +1,39 @@ +/* + * tw9910 Driver header + * + * Copyright (C) 2008 Renesas Solutions Corp. + * Kuninori Morimoto + * + * Based on ov772x.h + * + * Copyright (C) Kuninori Morimoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __TW9910_H__ +#define __TW9910_H__ + +#include + +enum tw9910_mpout_pin { + TW9910_MPO_VLOSS, + TW9910_MPO_HLOCK, + TW9910_MPO_SLOCK, + TW9910_MPO_VLOCK, + TW9910_MPO_MONO, + TW9910_MPO_DET50, + TW9910_MPO_FIELD, + TW9910_MPO_RTCO, +}; + +struct tw9910_video_info { + unsigned long buswidth; + enum tw9910_mpout_pin mpout; + struct soc_camera_link link; +}; + + +#endif /* __TW9910_H__ */ diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index 52e778ded..1078fb24e 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -84,6 +84,9 @@ enum { /* module wm8775: just ident 8775 */ V4L2_IDENT_WM8775 = 8775, + /* module tw9910: just ident 9910 */ + V4L2_IDENT_TW9910 = 9910, + /* module cs53132a: just ident 53132 */ V4L2_IDENT_CS53l32A = 53132, -- cgit v1.2.3 From 9a90cc2150ab680bc52a345322a79e901ae22eed Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 29 Dec 2008 10:04:16 +0100 Subject: The failure of set_fmt is solved in tw9910 From: Kuninori Morimoto priv->scale is checked in start_capture. Therefore, it should be NULL if failing in set_fmt. This patch resolve this problem. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/tw9910.c | 22 ++++++++++++++++------ 1 files changed, 16 insertions(+), 6 deletions(-) --- linux/drivers/media/video/tw9910.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 75cfde02d..d5cdc4be1 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -651,7 +651,7 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, */ priv->scale = tw9910_select_norm(icd, rect->width, rect->height); if (!priv->scale) - return ret; + goto tw9910_set_fmt_error; /* * reset hardware @@ -659,7 +659,8 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, tw9910_reset(priv->client); ret = tw9910_write_array(priv->client, tw9910_default_regs); if (ret < 0) - return ret; + goto tw9910_set_fmt_error; + /* * set bus width */ @@ -669,7 +670,7 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, ret = tw9910_mask_set(priv->client, OPFORM, LEN, val); if (ret < 0) - return ret; + goto tw9910_set_fmt_error; /* * select MPOUT behavior @@ -697,26 +698,35 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val); if (ret < 0) - return ret; + goto tw9910_set_fmt_error; /* * set scale */ ret = tw9910_set_scale(priv->client, priv->scale); if (ret < 0) - return ret; + goto tw9910_set_fmt_error; /* * set cropping */ ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl); if (ret < 0) - return ret; + goto tw9910_set_fmt_error; /* * set hsync */ ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl); + if (ret < 0) + goto tw9910_set_fmt_error; + + return ret; + +tw9910_set_fmt_error: + + tw9910_reset(priv->client); + priv->scale = NULL; return ret; } -- cgit v1.2.3 From 4b9ee102f4db5d14a70062f25e53207638940b5d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 29 Dec 2008 10:04:22 +0100 Subject: ov772x: change dev_info to dev_dbg From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) --- linux/drivers/media/video/ov772x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index bed830aed..5df4b0ff0 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -637,7 +637,6 @@ static int ov772x_start_capture(struct soc_camera_device *icd) struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); int ret; - if (!priv->win) priv->win = &ov772x_win_vga; if (!priv->fmt) @@ -690,7 +689,7 @@ static int ov772x_start_capture(struct soc_camera_device *icd) goto start_end; } - dev_info(&icd->dev, + dev_dbg(&icd->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); start_end: -- cgit v1.2.3 From 9b0f12a43cdb0ac98249bf19752f1d8e02811bea Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 29 Dec 2008 10:04:37 +0100 Subject: ov772x: clear i2c client data on error and remove From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) --- linux/drivers/media/video/ov772x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 5df4b0ff0..b6f6a79b7 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -946,8 +946,10 @@ static int ov772x_probe(struct i2c_client *client, ret = soc_camera_device_register(icd); - if (ret) + if (ret) { + i2c_set_clientdata(client, NULL); kfree(priv); + } return ret; } @@ -957,6 +959,7 @@ static int ov772x_remove(struct i2c_client *client) struct ov772x_priv *priv = i2c_get_clientdata(client); soc_camera_device_unregister(&priv->icd); + i2c_set_clientdata(client, NULL); kfree(priv); return 0; } -- cgit v1.2.3 From 7aeeb9dfa1051e4cf394771242f1122f18e8fda1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 29 Dec 2008 10:04:44 +0100 Subject: ov772x: fix try_fmt calculation method From: Kuninori Morimoto Don't modify driver's state in try_fmt, just verify format acceptability or adjust it to driver's capabilities. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 55 ++++++++++++++++++++++++++--------------- 1 files changed, 35 insertions(+), 20 deletions(-) --- linux/drivers/media/video/ov772x.c | 55 ++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index b6f6a79b7..932444623 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -766,6 +766,27 @@ static int ov772x_set_register(struct soc_camera_device *icd, } #endif +static const struct ov772x_win_size* +ov772x_select_win(u32 width, u32 height) +{ + __u32 diff; + const struct ov772x_win_size *win; + + /* default is QVGA */ + diff = abs(width - ov772x_win_qvga.width) + + abs(height - ov772x_win_qvga.height); + win = &ov772x_win_qvga; + + /* VGA */ + if (diff > + abs(width - ov772x_win_vga.width) + + abs(height - ov772x_win_vga.height)) + win = &ov772x_win_vga; + + return win; +} + + static int ov772x_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) @@ -786,34 +807,28 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, } } + /* + * select win + */ + priv->win = ov772x_select_win(rect->width, rect->height); + return ret; } static int ov772x_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct v4l2_pix_format *pix = &f->fmt.pix; - struct ov772x_priv *priv; - - priv = container_of(icd, struct ov772x_priv, icd); - - /* QVGA */ - if (pix->width <= ov772x_win_qvga.width || - pix->height <= ov772x_win_qvga.height) { - priv->win = &ov772x_win_qvga; - pix->width = ov772x_win_qvga.width; - pix->height = ov772x_win_qvga.height; - } + struct v4l2_pix_format *pix = &f->fmt.pix; + const struct ov772x_win_size *win; - /* VGA */ - else if (pix->width <= ov772x_win_vga.width || - pix->height <= ov772x_win_vga.height) { - priv->win = &ov772x_win_vga; - pix->width = ov772x_win_vga.width; - pix->height = ov772x_win_vga.height; - } + /* + * select suitable win + */ + win = ov772x_select_win(pix->width, pix->height); - pix->field = V4L2_FIELD_NONE; + pix->width = win->width; + pix->height = win->height; + pix->field = V4L2_FIELD_NONE; return 0; } -- cgit v1.2.3 From a3f770256b79b9d59770a94bef4d01d4a1390a50 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 29 Dec 2008 10:04:59 +0100 Subject: soc-camera: add support for MT9T031 CMOS camera sensor from Micron From: Guennadi Liakhovetski This camera is rather similar to MT9M001, but also has a couple of enhanced features, like pixel binning. Signed-off-by: Guennadi Liakhovetski Acked-by: Jean Delvare --- drivers/media/video/Kconfig | 6 + drivers/media/video/Makefile | 1 + drivers/media/video/mt9t031.c | 736 +++++++++++++++++++++++++++++++++++++++ include/media/v4l2-chip-ident.h | 1 + 4 files changed, 744 insertions(+), 0 deletions(-) create mode 100644 drivers/media/video/mt9t031.c --- linux/drivers/media/video/Kconfig | 6 + linux/drivers/media/video/Makefile | 1 + linux/drivers/media/video/mt9t031.c | 736 ++++++++++++++++++++++++++++++++++ linux/include/media/v4l2-chip-ident.h | 1 + 4 files changed, 744 insertions(+) create mode 100644 linux/drivers/media/video/mt9t031.c diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index ce68b5d4b..631112e28 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -741,6 +741,12 @@ config SOC_CAMERA_MT9M111 help This driver supports MT9M111 and MT9M112 cameras from Micron +config SOC_CAMERA_MT9T031 + tristate "mt9t031 support" + depends on SOC_CAMERA && I2C + help + This driver supports MT9T031 cameras from Micron. + config SOC_CAMERA_MT9V022 tristate "mt9v022 support" depends on SOC_CAMERA && I2C diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 40c69afcd..1611c33b1 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -137,6 +137,7 @@ obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o +obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c new file mode 100644 index 000000000..1a9d53966 --- /dev/null +++ b/linux/drivers/media/video/mt9t031.c @@ -0,0 +1,736 @@ +/* + * Driver for MT9T031 CMOS Image Sensor from Micron + * + * Copyright (C) 2008, Guennadi Liakhovetski, DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* mt9t031 i2c address 0x5d + * The platform has to define i2c_board_info + * and call i2c_register_board_info() */ + +/* mt9t031 selected register addresses */ +#define MT9T031_CHIP_VERSION 0x00 +#define MT9T031_ROW_START 0x01 +#define MT9T031_COLUMN_START 0x02 +#define MT9T031_WINDOW_HEIGHT 0x03 +#define MT9T031_WINDOW_WIDTH 0x04 +#define MT9T031_HORIZONTAL_BLANKING 0x05 +#define MT9T031_VERTICAL_BLANKING 0x06 +#define MT9T031_OUTPUT_CONTROL 0x07 +#define MT9T031_SHUTTER_WIDTH_UPPER 0x08 +#define MT9T031_SHUTTER_WIDTH 0x09 +#define MT9T031_PIXEL_CLOCK_CONTROL 0x0a +#define MT9T031_FRAME_RESTART 0x0b +#define MT9T031_SHUTTER_DELAY 0x0c +#define MT9T031_RESET 0x0d +#define MT9T031_READ_MODE_1 0x1e +#define MT9T031_READ_MODE_2 0x20 +#define MT9T031_READ_MODE_3 0x21 +#define MT9T031_ROW_ADDRESS_MODE 0x22 +#define MT9T031_COLUMN_ADDRESS_MODE 0x23 +#define MT9T031_GLOBAL_GAIN 0x35 +#define MT9T031_CHIP_ENABLE 0xF8 + +#define MT9T031_MAX_HEIGHT 1536 +#define MT9T031_MAX_WIDTH 2048 +#define MT9T031_MIN_HEIGHT 2 +#define MT9T031_MIN_WIDTH 2 +#define MT9T031_HORIZONTAL_BLANK 142 +#define MT9T031_VERTICAL_BLANK 25 +#define MT9T031_COLUMN_SKIP 32 +#define MT9T031_ROW_SKIP 20 + +#define MT9T031_BUS_PARAM (SOCAM_PCLK_SAMPLE_RISING | \ + SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | \ + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | \ + SOCAM_MASTER | SOCAM_DATAWIDTH_10) + +static const struct soc_camera_data_format mt9t031_colour_formats[] = { + { + .name = "Bayer (sRGB) 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_SGRBG10, + .colorspace = V4L2_COLORSPACE_SRGB, + } +}; + +struct mt9t031 { + struct i2c_client *client; + struct soc_camera_device icd; + int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ + unsigned char autoexposure; + u16 xskip; + u16 yskip; +}; + +static int reg_read(struct soc_camera_device *icd, const u8 reg) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = mt9t031->client; + s32 data = i2c_smbus_read_word_data(client, reg); + return data < 0 ? data : swab16(data); +} + +static int reg_write(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + return i2c_smbus_write_word_data(mt9t031->client, reg, swab16(data)); +} + +static int reg_set(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret | data); +} + +static int reg_clear(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret & ~data); +} + +static int set_shutter(struct soc_camera_device *icd, const u32 data) +{ + int ret; + + ret = reg_write(icd, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16); + + if (ret >= 0) + ret = reg_write(icd, MT9T031_SHUTTER_WIDTH, data & 0xffff); + + return ret; +} + +static int get_shutter(struct soc_camera_device *icd, u32 *data) +{ + int ret; + + ret = reg_read(icd, MT9T031_SHUTTER_WIDTH_UPPER); + *data = ret << 16; + + if (ret >= 0) + ret = reg_read(icd, MT9T031_SHUTTER_WIDTH); + *data |= ret & 0xffff; + + return ret < 0 ? ret : 0; +} + +static int mt9t031_init(struct soc_camera_device *icd) +{ + int ret; + + /* Disable chip output, synchronous option update */ + dev_dbg(icd->vdev->parent, "%s\n", __func__); + + ret = reg_write(icd, MT9T031_RESET, 1); + if (ret >= 0) + ret = reg_write(icd, MT9T031_RESET, 0); + if (ret >= 0) + ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3); + + return ret >= 0 ? 0 : -EIO; +} + +static int mt9t031_release(struct soc_camera_device *icd) +{ + /* Disable the chip */ + reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3); + return 0; +} + +static int mt9t031_start_capture(struct soc_camera_device *icd) +{ + /* Switch to master "normal" mode */ + if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 3) < 0) + return -EIO; + return 0; +} + +static int mt9t031_stop_capture(struct soc_camera_device *icd) +{ + /* Stop sensor readout */ + if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3) < 0) + return -EIO; + return 0; +} + +static int mt9t031_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) +{ + /* The caller should have queried our parameters, check anyway */ + if (flags & ~MT9T031_BUS_PARAM) + return -EINVAL; + + if (flags & SOCAM_PCLK_SAMPLE_FALLING) + reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); + else + reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); + + return 0; +} + +static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct soc_camera_link *icl = mt9t031->client->dev.platform_data; + + return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); +} + +static int mt9t031_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + int ret; + const u16 hblank = MT9T031_HORIZONTAL_BLANK, + vblank = MT9T031_VERTICAL_BLANK; + u16 xbin, xskip = mt9t031->xskip, ybin, yskip = mt9t031->yskip, + width = rect->width * xskip, height = rect->height * yskip; + + if (pixfmt) { + /* S_FMT - use binning and skipping for scaling, recalculate */ + /* Is this more optimal than just a division? */ + for (xskip = 8; xskip > 1; xskip--) + if (rect->width * xskip <= icd->width_max) + break; + + for (yskip = 8; yskip > 1; yskip--) + if (rect->height * yskip <= icd->height_max) + break; + + width = rect->width * xskip; + height = rect->height * yskip; + + dev_dbg(&icd->dev, "xskip %u, width %u, yskip %u, height %u\n", + xskip, width, yskip, height); + } + + xbin = min(xskip, (u16)3); + ybin = min(yskip, (u16)3); + + /* Make sure we don't exceed frame limits */ + if (rect->left + width > icd->width_max) + rect->left = (icd->width_max - width) / 2; + + if (rect->top + height > icd->height_max) + rect->top = (icd->height_max - height) / 2; + + /* Could just do roundup(rect->left, [xy]bin); but this is cheaper */ + switch (xbin) { + case 2: + rect->left = (rect->left + 1) & ~1; + break; + case 3: + rect->left = roundup(rect->left, 3); + } + + switch (ybin) { + case 2: + rect->top = (rect->top + 1) & ~1; + break; + case 3: + rect->top = roundup(rect->top, 3); + } + + /* Blanking and start values - default... */ + ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank); + if (ret >= 0) + ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank); + + if (pixfmt) { + /* Binning, skipping */ + if (ret >= 0) + ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE, + ((xbin - 1) << 4) | (xskip - 1)); + if (ret >= 0) + ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE, + ((ybin - 1) << 4) | (yskip - 1)); + } + dev_dbg(&icd->dev, "new left %u, top %u\n", rect->left, rect->top); + + /* The caller provides a supported format, as guaranteed by + * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ + if (ret >= 0) + ret = reg_write(icd, MT9T031_COLUMN_START, rect->left); + if (ret >= 0) + ret = reg_write(icd, MT9T031_ROW_START, rect->top); + if (ret >= 0) + ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1); + if (ret >= 0) + ret = reg_write(icd, MT9T031_WINDOW_HEIGHT, + height + icd->y_skip_top - 1); + if (ret >= 0 && mt9t031->autoexposure) { + ret = set_shutter(icd, height + icd->y_skip_top + vblank); + if (ret >= 0) { + const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; + const struct v4l2_queryctrl *qctrl = + soc_camera_find_qctrl(icd->ops, + V4L2_CID_EXPOSURE); + icd->exposure = (shutter_max / 2 + (height + + icd->y_skip_top + vblank - 1) * + (qctrl->maximum - qctrl->minimum)) / + shutter_max + qctrl->minimum; + } + } + + if (!ret && pixfmt) { + mt9t031->xskip = xskip; + mt9t031->yskip = yskip; + } + + return ret < 0 ? ret : 0; +} + +static int mt9t031_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (pix->height < icd->height_min) + pix->height = icd->height_min; + if (pix->height > icd->height_max) + pix->height = icd->height_max; + if (pix->width < icd->width_min) + pix->width = icd->width_min; + if (pix->width > icd->width_max) + pix->width = icd->width_max; + + pix->width &= ~0x01; /* has to be even */ + pix->height &= ~0x01; /* has to be even */ + + return 0; +} + +static int mt9t031_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + + if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match_chip != mt9t031->client->addr) + return -ENODEV; + + id->ident = mt9t031->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9t031_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9t031->client->addr) + return -ENODEV; + + reg->val = reg_read(icd, reg->reg); + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int mt9t031_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9t031->client->addr) + return -ENODEV; + + if (reg_write(icd, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static const struct v4l2_queryctrl mt9t031_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 64, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 1, + .maximum = 255, + .step = 1, + .default_value = 255, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + } +}; + +static int mt9t031_video_probe(struct soc_camera_device *); +static void mt9t031_video_remove(struct soc_camera_device *); +static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *); +static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *); + +static struct soc_camera_ops mt9t031_ops = { + .owner = THIS_MODULE, + .probe = mt9t031_video_probe, + .remove = mt9t031_video_remove, + .init = mt9t031_init, + .release = mt9t031_release, + .start_capture = mt9t031_start_capture, + .stop_capture = mt9t031_stop_capture, + .set_fmt = mt9t031_set_fmt, + .try_fmt = mt9t031_try_fmt, + .set_bus_param = mt9t031_set_bus_param, + .query_bus_param = mt9t031_query_bus_param, + .controls = mt9t031_controls, + .num_controls = ARRAY_SIZE(mt9t031_controls), + .get_control = mt9t031_get_control, + .set_control = mt9t031_set_control, + .get_chip_id = mt9t031_get_chip_id, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = mt9t031_get_register, + .set_register = mt9t031_set_register, +#endif +}; + +static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + data = reg_read(icd, MT9T031_READ_MODE_2); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x8000); + break; + case V4L2_CID_HFLIP: + data = reg_read(icd, MT9T031_READ_MODE_2); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x4000); + break; + case V4L2_CID_EXPOSURE_AUTO: + ctrl->value = mt9t031->autoexposure; + break; + } + return 0; +} + +static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + const struct v4l2_queryctrl *qctrl; + int data; + + qctrl = soc_camera_find_qctrl(&mt9t031_ops, ctrl->id); + + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (ctrl->value) + data = reg_set(icd, MT9T031_READ_MODE_2, 0x8000); + else + data = reg_clear(icd, MT9T031_READ_MODE_2, 0x8000); + if (data < 0) + return -EIO; + break; + case V4L2_CID_HFLIP: + if (ctrl->value) + data = reg_set(icd, MT9T031_READ_MODE_2, 0x4000); + else + data = reg_clear(icd, MT9T031_READ_MODE_2, 0x4000); + if (data < 0) + return -EIO; + break; + case V4L2_CID_GAIN: + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + /* See Datasheet Table 7, Gain settings. */ + if (ctrl->value <= qctrl->default_value) { + /* Pack it into 0..1 step 0.125, register values 0..8 */ + unsigned long range = qctrl->default_value - qctrl->minimum; + data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; + + dev_dbg(&icd->dev, "Setting gain %d\n", data); + data = reg_write(icd, MT9T031_GLOBAL_GAIN, data); + if (data < 0) + return -EIO; + } else { + /* Pack it into 1.125..15 variable step, register values 9..67 */ + /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ + unsigned long range = qctrl->maximum - qctrl->default_value - 1; + unsigned long gain = ((ctrl->value - qctrl->default_value - 1) * + 111 + range / 2) / range + 9; + + if (gain <= 32) + data = gain; + else if (gain <= 64) + data = ((gain - 32) * 16 + 16) / 32 + 80; + else + data = ((gain - 64) * 7 + 28) / 56 + 96; + + dev_dbg(&icd->dev, "Setting gain from %d to %d\n", + reg_read(icd, MT9T031_GLOBAL_GAIN), data); + data = reg_write(icd, MT9T031_GLOBAL_GAIN, data); + if (data < 0) + return -EIO; + } + + /* Success */ + icd->gain = ctrl->value; + break; + case V4L2_CID_EXPOSURE: + /* mt9t031 has maximum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + const unsigned long range = qctrl->maximum - qctrl->minimum; + const u32 shutter = ((ctrl->value - qctrl->minimum) * 1048 + + range / 2) / range + 1; + u32 old; + + get_shutter(icd, &old); + dev_dbg(&icd->dev, "Setting shutter width from %u to %u\n", + old, shutter); + if (set_shutter(icd, shutter) < 0) + return -EIO; + icd->exposure = ctrl->value; + mt9t031->autoexposure = 0; + } + break; + case V4L2_CID_EXPOSURE_AUTO: + if (ctrl->value) { + const u16 vblank = MT9T031_VERTICAL_BLANK; + const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; + if (set_shutter(icd, icd->height + + icd->y_skip_top + vblank) < 0) + return -EIO; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = (shutter_max / 2 + (icd->height + + icd->y_skip_top + vblank - 1) * + (qctrl->maximum - qctrl->minimum)) / + shutter_max + qctrl->minimum; + mt9t031->autoexposure = 1; + } else + mt9t031->autoexposure = 0; + break; + } + return 0; +} + +/* Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one */ +static int mt9t031_video_probe(struct soc_camera_device *icd) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + s32 data; + int ret; + + /* We must have a parent by now. And it cannot be a wrong one. + * So this entire test is completely redundant. */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* Enable the chip */ + data = reg_write(icd, MT9T031_CHIP_ENABLE, 1); + dev_dbg(&icd->dev, "write: %d\n", data); + + /* Read out the chip version register */ + data = reg_read(icd, MT9T031_CHIP_VERSION); + + switch (data) { + case 0x1621: + mt9t031->model = V4L2_IDENT_MT9T031; + icd->formats = mt9t031_colour_formats; + icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); + break; + default: + ret = -ENODEV; + dev_err(&icd->dev, + "No MT9T031 chip detected, register read %x\n", data); + goto ei2c; + } + + dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data); + + /* Now that we know the model, we can start video */ + ret = soc_camera_video_start(icd); + if (ret) + goto evstart; + + return 0; + +evstart: +ei2c: + return ret; +} + +static void mt9t031_video_remove(struct soc_camera_device *icd) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr, + icd->dev.parent, icd->vdev); + soc_camera_video_stop(icd); +} + +static int mt9t031_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct mt9t031 *mt9t031; + struct soc_camera_device *icd; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl = client->dev.platform_data; + int ret; + + if (!icl) { + dev_err(&client->dev, "MT9T031 driver needs platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + mt9t031 = kzalloc(sizeof(struct mt9t031), GFP_KERNEL); + if (!mt9t031) + return -ENOMEM; + + mt9t031->client = client; + i2c_set_clientdata(client, mt9t031); + + /* Second stage probe - when a capture adapter is there */ + icd = &mt9t031->icd; + icd->ops = &mt9t031_ops; + icd->control = &client->dev; + icd->x_min = MT9T031_COLUMN_SKIP; + icd->y_min = MT9T031_ROW_SKIP; + icd->x_current = icd->x_min; + icd->y_current = icd->y_min; + icd->width_min = MT9T031_MIN_WIDTH; + icd->width_max = MT9T031_MAX_WIDTH; + icd->height_min = MT9T031_MIN_HEIGHT; + icd->height_max = MT9T031_MAX_HEIGHT; + icd->y_skip_top = 0; + icd->iface = icl->bus_id; + /* Simulated autoexposure. If enabled, we calculate shutter width + * ourselves in the driver based on vertical blanking and frame width */ + mt9t031->autoexposure = 1; + + mt9t031->xskip = 1; + mt9t031->yskip = 1; + + ret = soc_camera_device_register(icd); + if (ret) + goto eisdr; + + return 0; + +eisdr: + i2c_set_clientdata(client, NULL); + kfree(mt9t031); + return ret; +} + +static int mt9t031_remove(struct i2c_client *client) +{ + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + + soc_camera_device_unregister(&mt9t031->icd); + i2c_set_clientdata(client, NULL); + kfree(mt9t031); + + return 0; +} + +static const struct i2c_device_id mt9t031_id[] = { + { "mt9t031", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mt9t031_id); + +static struct i2c_driver mt9t031_i2c_driver = { + .driver = { + .name = "mt9t031", + }, + .probe = mt9t031_probe, + .remove = mt9t031_remove, + .id_table = mt9t031_id, +}; + +static int __init mt9t031_mod_init(void) +{ + return i2c_add_driver(&mt9t031_i2c_driver); +} + +static void __exit mt9t031_mod_exit(void) +{ + i2c_del_driver(&mt9t031_i2c_driver); +} + +module_init(mt9t031_mod_init); +module_exit(mt9t031_mod_exit); + +MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL v2"); diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index 1078fb24e..173e9af5f 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -174,6 +174,7 @@ enum { V4L2_IDENT_MT9M112 = 45008, V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ + V4L2_IDENT_MT9T031 = 45020, }; #endif -- cgit v1.2.3 From 1f181a1b26f6f36b4a546e0fa57f64df8274b4b3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 29 Dec 2008 10:19:43 +0100 Subject: gspca - ov534: Use the gspca usb buf for usb control messages. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 104 ++++++++++++++++---------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index d5c74d65c..406f6bc12 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -63,65 +63,66 @@ static struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; -static void ov534_reg_write(struct usb_device *udev, u16 reg, u8 val) +static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) { - u8 data = val; + struct usb_device *udev = gspca_dev->dev; int ret; PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val); + gspca_dev->usb_buf[0] = val; ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x1, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, reg, &data, 1, CTRL_TIMEOUT); + 0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); if (ret < 0) PDEBUG(D_ERR, "write failed"); } -static u8 ov534_reg_read(struct usb_device *udev, u16 reg) +static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg) { - u8 data; + struct usb_device *udev = gspca_dev->dev; int ret; ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x1, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, reg, &data, 1, CTRL_TIMEOUT); - PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, data); + 0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); + PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]); if (ret < 0) PDEBUG(D_ERR, "read failed"); - return data; + return gspca_dev->usb_buf[0]; } /* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. * (direction and output)? */ -static void ov534_set_led(struct usb_device *udev, int status) +static void ov534_set_led(struct gspca_dev *gspca_dev, int status) { u8 data; PDEBUG(D_CONF, "led status: %d", status); - data = ov534_reg_read(udev, 0x21); + data = ov534_reg_read(gspca_dev, 0x21); data |= 0x80; - ov534_reg_write(udev, 0x21, data); + ov534_reg_write(gspca_dev, 0x21, data); - data = ov534_reg_read(udev, 0x23); + data = ov534_reg_read(gspca_dev, 0x23); if (status) data |= 0x80; else data &= ~(0x80); - ov534_reg_write(udev, 0x23, data); + ov534_reg_write(gspca_dev, 0x23, data); } -static int sccb_check_status(struct usb_device *udev) +static int sccb_check_status(struct gspca_dev *gspca_dev) { u8 data; int i; for (i = 0; i < 5; i++) { - data = ov534_reg_read(udev, OV534_REG_STATUS); + data = ov534_reg_read(gspca_dev, OV534_REG_STATUS); switch (data) { case 0x00: @@ -138,30 +139,30 @@ static int sccb_check_status(struct usb_device *udev) return 0; } -static void sccb_reg_write(struct usb_device *udev, u16 reg, u8 val) +static void sccb_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) { PDEBUG(D_USBO, "reg: 0x%04x, val: 0x%02x", reg, val); - ov534_reg_write(udev, OV534_REG_SUBADDR, reg); - ov534_reg_write(udev, OV534_REG_WRITE, val); - ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_WRITE_3); + ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); + ov534_reg_write(gspca_dev, OV534_REG_WRITE, val); + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); - if (!sccb_check_status(udev)) + if (!sccb_check_status(gspca_dev)) PDEBUG(D_ERR, "sccb_reg_write failed"); } #ifdef GSPCA_DEBUG -static u8 sccb_reg_read(struct usb_device *udev, u16 reg) +static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg) { - ov534_reg_write(udev, OV534_REG_SUBADDR, reg); - ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_WRITE_2); - if (!sccb_check_status(udev)) + ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); + if (!sccb_check_status(gspca_dev)) PDEBUG(D_ERR, "sccb_reg_read failed 1"); - ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_READ_2); - if (!sccb_check_status(udev)) + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); + if (!sccb_check_status(gspca_dev)) PDEBUG(D_ERR, "sccb_reg_read failed 2"); - return ov534_reg_read(udev, OV534_REG_READ); + return ov534_reg_read(gspca_dev, OV534_REG_READ); } #endif @@ -318,26 +319,26 @@ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) switch (fr) { case 50: - sccb_reg_write(gspca_dev->dev, 0x11, 0x01); - sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); - ov534_reg_write(gspca_dev->dev, 0xe5, 0x02); + sccb_reg_write(gspca_dev, 0x11, 0x01); + sccb_reg_write(gspca_dev, 0x0d, 0x41); + ov534_reg_write(gspca_dev, 0xe5, 0x02); break; case 40: - sccb_reg_write(gspca_dev->dev, 0x11, 0x02); - sccb_reg_write(gspca_dev->dev, 0x0d, 0xc1); - ov534_reg_write(gspca_dev->dev, 0xe5, 0x04); + sccb_reg_write(gspca_dev, 0x11, 0x02); + sccb_reg_write(gspca_dev, 0x0d, 0xc1); + ov534_reg_write(gspca_dev, 0xe5, 0x04); break; /* case 30: */ default: fr = 30; - sccb_reg_write(gspca_dev->dev, 0x11, 0x04); - sccb_reg_write(gspca_dev->dev, 0x0d, 0x81); - ov534_reg_write(gspca_dev->dev, 0xe5, 0x02); + sccb_reg_write(gspca_dev, 0x11, 0x04); + sccb_reg_write(gspca_dev, 0x0d, 0x81); + ov534_reg_write(gspca_dev, 0xe5, 0x02); break; case 15: - sccb_reg_write(gspca_dev->dev, 0x11, 0x03); - sccb_reg_write(gspca_dev->dev, 0x0d, 0x41); - ov534_reg_write(gspca_dev->dev, 0xe5, 0x04); + sccb_reg_write(gspca_dev, 0x11, 0x03); + sccb_reg_write(gspca_dev, 0x0d, 0x41); + ov534_reg_write(gspca_dev, 0xe5, 0x04); break; } @@ -346,27 +347,28 @@ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) } /* setup method */ -static void ov534_setup(struct usb_device *udev) +static void ov534_setup(struct gspca_dev *gspca_dev) { int i; /* Initialize bridge chip */ for (i = 0; i < ARRAY_SIZE(ov534_reg_initdata); i++) - ov534_reg_write(udev, ov534_reg_initdata[i][0], + ov534_reg_write(gspca_dev, ov534_reg_initdata[i][0], ov534_reg_initdata[i][1]); PDEBUG(D_PROBE, "sensor is ov%02x%02x", - sccb_reg_read(udev, 0x0a), sccb_reg_read(udev, 0x0b)); + sccb_reg_read(gspca_dev, 0x0a), + sccb_reg_read(gspca_dev, 0x0b)); - ov534_set_led(udev, 1); + ov534_set_led(gspca_dev, 1); /* Initialize sensor */ for (i = 0; i < ARRAY_SIZE(ov772x_reg_initdata); i++) - sccb_reg_write(udev, ov772x_reg_initdata[i][0], + sccb_reg_write(gspca_dev, ov772x_reg_initdata[i][0], ov772x_reg_initdata[i][1]); - ov534_reg_write(udev, 0xe0, 0x09); - ov534_set_led(udev, 0); + ov534_reg_write(gspca_dev, 0xe0, 0x09); + ov534_set_led(gspca_dev, 0); } /* this function is called at probe time */ @@ -390,7 +392,7 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - ov534_setup(gspca_dev->dev); + ov534_setup(gspca_dev); ov534_set_frame_rate(gspca_dev); return 0; @@ -399,8 +401,8 @@ static int sd_init(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { /* start streaming data */ - ov534_set_led(gspca_dev->dev, 1); - ov534_reg_write(gspca_dev->dev, 0xe0, 0x00); + ov534_set_led(gspca_dev, 1); + ov534_reg_write(gspca_dev, 0xe0, 0x00); return 0; } @@ -408,8 +410,8 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { /* stop streaming data */ - ov534_reg_write(gspca_dev->dev, 0xe0, 0x09); - ov534_set_led(gspca_dev->dev, 0); + ov534_reg_write(gspca_dev, 0xe0, 0x09); + ov534_set_led(gspca_dev, 0); } /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ -- cgit v1.2.3 From 4b1f1c3b32a2a577979320acb82f1f610641f4ef Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 29 Dec 2008 11:35:23 +0100 Subject: gspca - stv06xx: New subdriver. From: Erik Andren Priority: normal Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 3 + linux/drivers/media/video/gspca/Kconfig | 1 + linux/drivers/media/video/gspca/Makefile | 2 +- linux/drivers/media/video/gspca/stv06xx/Kconfig | 9 + linux/drivers/media/video/gspca/stv06xx/Makefile | 6 + linux/drivers/media/video/gspca/stv06xx/stv06xx.c | 522 ++++++++++++++++++++ linux/drivers/media/video/gspca/stv06xx/stv06xx.h | 107 +++++ .../media/video/gspca/stv06xx/stv06xx_hdcs.c | 533 +++++++++++++++++++++ .../media/video/gspca/stv06xx/stv06xx_hdcs.h | 263 ++++++++++ .../media/video/gspca/stv06xx/stv06xx_pb0100.c | 430 +++++++++++++++++ .../media/video/gspca/stv06xx/stv06xx_pb0100.h | 297 ++++++++++++ .../media/video/gspca/stv06xx/stv06xx_sensor.h | 92 ++++ .../media/video/gspca/stv06xx/stv06xx_vv6410.c | 251 ++++++++++ .../media/video/gspca/stv06xx/stv06xx_vv6410.h | 315 ++++++++++++ 14 files changed, 2830 insertions(+), 1 deletion(-) create mode 100644 linux/drivers/media/video/gspca/stv06xx/Kconfig create mode 100644 linux/drivers/media/video/gspca/stv06xx/Makefile create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx.c create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx.h create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index 5daf2c801..f54281d78 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -50,6 +50,9 @@ ov519 045e:028c Micro$oft xbox cam spca508 0461:0815 Micro Innovation IC200 sunplus 0461:0821 Fujifilm MV-1 zc3xx 0461:0a00 MicroInnovation WebCam320 +stv06xx 046d:0840 QuickCam Express +stv06xx 046d:0850 LEGO cam / QuickCam Web +stv06xx 046d:0870 Dexxa WebCam USB spca500 046d:0890 Logitech QuickCam traveler vc032x 046d:0892 Logitech Orbicam vc032x 046d:0896 Logitech Orbicam diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index 770fb699d..ee6a691df 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -18,6 +18,7 @@ menuconfig USB_GSPCA if USB_GSPCA && VIDEO_V4L2 source "drivers/media/video/gspca/m5602/Kconfig" +source "drivers/media/video/gspca/stv06xx/Kconfig" config USB_GSPCA_CONEX tristate "Conexant Camera Driver" diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile index 6c8046e23..bd8d9ee40 100644 --- a/linux/drivers/media/video/gspca/Makefile +++ b/linux/drivers/media/video/gspca/Makefile @@ -47,4 +47,4 @@ gspca_vc032x-objs := vc032x.o gspca_zc3xx-objs := zc3xx.o obj-$(CONFIG_USB_M5602) += m5602/ - +obj-$(CONFIG_USB_STV06XX) += stv06xx/ diff --git a/linux/drivers/media/video/gspca/stv06xx/Kconfig b/linux/drivers/media/video/gspca/stv06xx/Kconfig new file mode 100644 index 000000000..634ad38d9 --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/Kconfig @@ -0,0 +1,9 @@ +config USB_STV06XX + tristate "STV06XX USB Camera Driver" + depends on USB_GSPCA + help + Say Y here if you want support for cameras based on + the ST STV06XX chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_stv06xx. diff --git a/linux/drivers/media/video/gspca/stv06xx/Makefile b/linux/drivers/media/video/gspca/stv06xx/Makefile new file mode 100644 index 000000000..8f002b623 --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o + +gspca_stv06xx-objs := stv06xx.o \ + stv06xx_vv6410.o \ + stv06xx_hdcs.o \ + stv06xx_pb0100.o diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c new file mode 100644 index 000000000..29e43718b --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +#include "stv06xx_sensor.h" + +MODULE_AUTHOR("Erik Andrén"); +MODULE_DESCRIPTION("STV06XX USB Camera Driver"); +MODULE_LICENSE("GPL"); + +int dump_bridge; +int dump_sensor; + +int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) +{ + int err; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + u8 len = (i2c_data > 0xff) ? 2 : 1; + + buf[0] = i2c_data & 0xff; + buf[1] = (i2c_data >> 8) & 0xff; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, address, 0, buf, len, + STV06XX_URB_MSG_TIMEOUT); + + + PDEBUG(D_CONF, "Written 0x%x to address 0x%x, status: %d", + i2c_data, address, err); + + return (err < 0) ? err : 0; +} + +int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) +{ + int err; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x04, 0xc0, address, 0, buf, 1, + STV06XX_URB_MSG_TIMEOUT); + + *i2c_data = buf[0]; + + PDEBUG(D_CONF, "Read 0x%x from address 0x%x, status %d", + *i2c_data, address, err); + + return (err < 0) ? err : 0; +} + +/* Wraps the normal write sensor bytes / words functions for writing a + single value */ +int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value) +{ + if (sd->sensor->i2c_len == 2) { + u16 data[2] = { address, value }; + return stv06xx_write_sensor_words(sd, data, 1); + } else { + u8 data[2] = { address, value }; + return stv06xx_write_sensor_bytes(sd, data, 1); + } +} + +static int stv06xx_write_sensor_finish(struct sd *sd) +{ + int err = 0; + + if (IS_850(sd)) { + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + /* Quickam Web needs an extra packet */ + buf[0] = 0; + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x1704, 0, buf, 1, + STV06XX_URB_MSG_TIMEOUT); + } + + return (err < 0) ? err : 0; +} + +int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) +{ + int err, i, j; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + PDEBUG(D_USBO, "I2C: Command buffer contains %d entries", len); + for (i = 0; i < len;) { + /* Build the command buffer */ + memset(buf, 0, I2C_BUFFER_LENGTH); + for (j = 0; j < I2C_MAX_BYTES && i < len; j++, i++) { + buf[j] = data[2*i]; + buf[0x10 + j] = data[2*i+1]; + PDEBUG(D_USBO, "I2C: Writing 0x%02x to reg 0x%02x", + data[2*i+1], data[2*i]); + } + buf[0x20] = sd->sensor->i2c_addr; + buf[0x21] = j - 1; /* Number of commands to send - 1 */ + buf[0x22] = I2C_WRITE_CMD; + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x0400, 0, buf, + I2C_BUFFER_LENGTH, + STV06XX_URB_MSG_TIMEOUT); + if (err < 0) + return err; + } + return stv06xx_write_sensor_finish(sd); +} + +int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) +{ + int err, i, j; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + PDEBUG(D_USBO, "I2C: Command buffer contains %d entries", len); + + for (i = 0; i < len;) { + /* Build the command buffer */ + memset(buf, 0, I2C_BUFFER_LENGTH); + for (j = 0; j < I2C_MAX_WORDS && i < len; j++, i++) { + buf[j] = data[2*i]; + buf[0x10 + j * 2] = data[2*i+1]; + buf[0x10 + j * 2 + 1] = data[2*i+1] >> 8; + PDEBUG(D_USBO, "I2C: Writing 0x%04x to reg 0x%02x", + data[2*i+1], data[2*i]); + } + buf[0x20] = sd->sensor->i2c_addr; + buf[0x21] = j - 1; /* Number of commands to send - 1 */ + buf[0x22] = I2C_WRITE_CMD; + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x0400, 0, buf, + I2C_BUFFER_LENGTH, + STV06XX_URB_MSG_TIMEOUT); + if (err < 0) + return err; + } + return stv06xx_write_sensor_finish(sd); +} + +int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value) +{ + int err; + struct usb_device *udev = sd->gspca_dev.dev; + __u8 *buf = sd->gspca_dev.usb_buf; + + err = stv06xx_write_bridge(sd, STV_I2C_FLUSH, sd->sensor->i2c_flush); + if (err < 0) + return err; + + /* Clear mem */ + memset(buf, 0, I2C_BUFFER_LENGTH); + + buf[0] = address; + buf[0x20] = sd->sensor->i2c_addr; + buf[0x21] = 0; + + /* Read I2C register */ + buf[0x22] = I2C_READ_CMD; + + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH, + STV06XX_URB_MSG_TIMEOUT); + if (err < 0) { + PDEBUG(D_ERR, "I2C Read: error writing address: %d", err); + return err; + } + + err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x04, 0xc0, 0x1410, 0, buf, sd->sensor->i2c_len, + STV06XX_URB_MSG_TIMEOUT); + if (sd->sensor->i2c_len == 2) + *value = buf[0] | (buf[1] << 8); + else + *value = buf[0]; + + PDEBUG(D_USBO, "I2C: Read 0x%x from address 0x%x, status: %d", + *value, address, err); + + return (err < 0) ? err : 0; +} + +/* Dumps all bridge registers */ +static void stv06xx_dump_bridge(struct sd *sd) +{ + int i; + u8 data, buf; + + info("Dumping all stv06xx bridge registers"); + for (i = 0x1400; i < 0x160f; i++) { + stv06xx_read_bridge(sd, i, &data); + + info("Read 0x%x from address 0x%x", data, i); + } + + for (i = 0x1400; i < 0x160f; i++) { + stv06xx_read_bridge(sd, i, &data); + buf = data; + + stv06xx_write_bridge(sd, i, 0xff); + stv06xx_read_bridge(sd, i, &data); + if (data == 0xff) + info("Register 0x%x is read/write", i); + else if (data != buf) + info("Register 0x%x is read/write," + "but only partially", i); + else + info("Register 0x%x is read-only", i); + + stv06xx_write_bridge(sd, i, buf); + } +} + +/* this function is called at probe and resume time */ +static int stv06xx_init(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int err; + + PDEBUG(D_PROBE, "Initializing camera"); + + /* Let the usb init settle for a bit + before performing the initialization */ + msleep(250); + + err = sd->sensor->init(sd); + + if (dump_sensor) + sd->sensor->dump(sd); + + return (err < 0) ? err : 0; +} + +/* Start the camera */ +static int stv06xx_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int err; + + /* Prepare the sensor for start */ + err = sd->sensor->start(sd); + if (err < 0) + goto out; + + /* Start isochronous streaming */ + err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1); + +out: + if (err < 0) + PDEBUG(D_STREAM, "Starting stream failed"); + else + PDEBUG(D_STREAM, "Started streaming"); + + return (err < 0) ? err : 0; +} + +static void stv06xx_stopN(struct gspca_dev *gspca_dev) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + + /* stop ISO-streaming */ + err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0); + if (err < 0) + goto out; + + err = sd->sensor->stop(sd); + if (err < 0) + goto out; + +out: + if (err < 0) + PDEBUG(D_STREAM, "Failed to stop stream"); + else + PDEBUG(D_STREAM, "Stopped streaming"); +} + +/* + * Analyse an USB packet of the data stream and store it appropriately. + * Each packet contains an integral number of chunks. Each chunk has + * 2-bytes identification, followed by 2-bytes that describe the chunk + * length. Known/guessed chunk identifications are: + * 8001/8005/C001/C005 - Begin new frame + * 8002/8006/C002/C006 - End frame + * 0200/4200 - Contains actual image data, bayer or compressed + * 0005 - 11 bytes of unknown data + * 0100 - 2 bytes of unknown data + * The 0005 and 0100 chunks seem to appear only in compressed stream. + */ +static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + PDEBUG(D_PACK, "Packet of length %d arrived", len); + + /* A packet may contain several frames + loop until the whole packet is reached */ + while (len) { + int id, chunk_len; + + if (len < 4) { + PDEBUG(D_PACK, "Packet is smaller than 4 bytes"); + return; + } + + /* Capture the id */ + id = (data[0] << 8) | data[1]; + + /* Capture the chunk length */ + chunk_len = (data[2] << 8) | data[3]; + PDEBUG(D_PACK, "Chunk id: %x, length: %d", id, chunk_len); + + data += 4; + len -= 4; + + if (len < chunk_len) { + PDEBUG(D_ERR, "URB packet length is smaller" + " than the specified chunk length"); + return; + } + + switch (id) { + case 0x0200: + case 0x4200: + PDEBUG(D_PACK, "Frame data packet detected"); + + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, chunk_len); + break; + + case 0x8001: + case 0x8005: + case 0xc001: + case 0xc005: + PDEBUG(D_PACK, "Starting new frame"); + + /* Create a new frame, chunk length should be zero */ + gspca_frame_add(gspca_dev, FIRST_PACKET, + frame, data, 0); + + if (chunk_len) + PDEBUG(D_ERR, "Chunk length is " + "non-zero on a SOF"); + break; + + case 0x8002: + case 0x8006: + case 0xc002: + PDEBUG(D_PACK, "End of frame detected"); + + /* Complete the last frame (if any) */ + gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); + + if (chunk_len) + PDEBUG(D_ERR, "Chunk length is " + "non-zero on a EOF"); + break; + + case 0x0005: + PDEBUG(D_PACK, "Chunk 0x005 detected"); + /* Unknown chunk with 11 bytes of data, + occurs just before end of each frame + in compressed mode */ + break; + + case 0x0100: + PDEBUG(D_PACK, "Chunk 0x0100 detected"); + /* Unknown chunk with 2 bytes of data, + occurs 2-3 times per USB interrupt */ + break; + default: + PDEBUG(D_PACK, "Unknown chunk %d detected", id); + /* Unknown chunk */ + } + data += chunk_len; + len -= chunk_len; + } +} + +static int stv06xx_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id); + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = stv06xx_config, + .init = stv06xx_init, + .start = stv06xx_start, + .stopN = stv06xx_stopN, + .pkt_scan = stv06xx_pkt_scan +}; + +/* This function is called at probe time */ +static int stv06xx_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam; + + PDEBUG(D_PROBE, "Configuring camera"); + + cam = &gspca_dev->cam; + cam->epaddr = STV_ISOC_ENDPOINT_ADDR; + sd->desc = sd_desc; + gspca_dev->sd_desc = &sd->desc; + + if (dump_bridge) + stv06xx_dump_bridge(sd); + + sd->sensor = &stv06xx_sensor_vv6410; + if (!sd->sensor->probe(sd)) + return 0; + + sd->sensor = &stv06xx_sensor_hdcs1x00; + if (!sd->sensor->probe(sd)) + return 0; + + sd->sensor = &stv06xx_sensor_hdcs1020; + if (!sd->sensor->probe(sd)) + return 0; + + sd->sensor = &stv06xx_sensor_pb0100; + if (!sd->sensor->probe(sd)) + return 0; + + sd->sensor = NULL; + return -ENODEV; +} + + + +/* -- module initialisation -- */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x046d, 0x0840)}, /* QuickCam Express */ + {USB_DEVICE(0x046d, 0x0850)}, /* LEGO cam / QuickCam Web */ + {USB_DEVICE(0x046d, 0x0870)}, /* Dexxa WebCam USB */ + {} +}; +MODULE_DEVICE_TABLE(usb, device_table); + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + PDEBUG(D_PROBE, "Probing for a stv06xx device"); + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +void sd_disconnect(struct usb_interface *intf) +{ + struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + struct sd *sd = (struct sd *) gspca_dev; + PDEBUG(D_PROBE, "Disconnecting the stv06xx device"); + + if (sd->sensor->disconnect) + sd->sensor->disconnect(sd); + gspca_disconnect(intf); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = sd_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + if (usb_register(&sd_driver) < 0) + return -1; + PDEBUG(D_PROBE, "registered"); + return 0; +} +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); + +module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); + +module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(dump_sensor, "Dumps all sensor registers at startup"); diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h new file mode 100644 index 000000000..1207e7d17 --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +#ifndef STV06XX_H_ +#define STV06XX_H_ + +#include "gspca.h" + +#define MODULE_NAME "STV06xx" + +#define STV_ISOC_ENDPOINT_ADDR 0x81 + +#ifndef V4L2_PIX_FMT_SGRBG8 +#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') +#endif + +#define STV_REG23 0x0423 + +/* Control registers of the STV0600 ASIC */ +#define STV_I2C_PARTNER 0x1420 +#define STV_I2C_VAL_REG_VAL_PAIRS_MIN1 0x1421 +#define STV_I2C_READ_WRITE_TOGGLE 0x1422 +#define STV_I2C_FLUSH 0x1423 +#define STV_I2C_SUCC_READ_REG_VALS 0x1424 + +#define STV_ISO_ENABLE 0x1440 +#define STV_SCAN_RATE 0x1443 +#define STV_LED_CTRL 0x1445 +#define STV_STV0600_EMULATION 0x1446 +#define STV_REG00 0x1500 +#define STV_REG01 0x1501 +#define STV_REG02 0x1502 +#define STV_REG03 0x1503 +#define STV_REG04 0x1504 + +#define STV_ISO_SIZE_L 0x15c1 +#define STV_ISO_SIZE_H 0x15c2 + +/* Refers to the CIF 352x288 and QCIF 176x144 */ +/* 1: 288 lines, 2: 144 lines */ +#define STV_Y_CTRL 0x15c3 + +/* 0xa: 352 columns, 0x6: 176 columns */ +#define STV_X_CTRL 0x1680 + +#define STV06XX_URB_MSG_TIMEOUT 5000 + +#define I2C_MAX_BYTES 16 +#define I2C_MAX_WORDS 8 + +#define I2C_BUFFER_LENGTH 0x23 +#define I2C_READ_CMD 3 +#define I2C_WRITE_CMD 1 + +#define LED_ON 1 +#define LED_OFF 0 + +/* STV06xx device descriptor */ +struct sd { + struct gspca_dev gspca_dev; + + /* A pointer to the currently connected sensor */ + const struct stv06xx_sensor *sensor; + + /* A pointer to the sd_desc struct */ + struct sd_desc desc; + + /* Sensor private data */ + void *sensor_priv; +}; + +int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data); +int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data); + +int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len); +int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len); + +int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value); +int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value); + +#endif diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c new file mode 100644 index 000000000..1cfe58504 --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * Copyright (c) 2008 Chia-I Wu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +#include "stv06xx_hdcs.h" + +enum hdcs_power_state { + HDCS_STATE_SLEEP, + HDCS_STATE_IDLE, + HDCS_STATE_RUN +}; + +/* no lock? */ +struct hdcs { + enum hdcs_power_state state; + int w, h; + + /* visible area of the sensor array */ + struct { + int left, top; + int width, height; + int border; + } array; + + struct { + /* Column timing overhead */ + u8 cto; + /* Column processing overhead */ + u8 cpo; + /* Row sample period constant */ + u16 rs; + /* Exposure reset duration */ + u16 er; + } exp; + + int psmp; +}; + +static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len) +{ + u8 regs[I2C_MAX_BYTES * 2]; + int i; + + if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) || + (reg + len > 0xff))) + return -EINVAL; + + for (i = 0; i < len; i++, reg++) { + regs[2*i] = reg; + regs[2*i+1] = vals[i]; + } + + return stv06xx_write_sensor_bytes(sd, regs, len); +} + +static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state) +{ + struct hdcs *hdcs = sd->sensor_priv; + u8 val; + int ret; + + if (hdcs->state == state) + return 0; + + /* we need to go idle before running or sleeping */ + if (hdcs->state != HDCS_STATE_IDLE) { + ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0); + if (ret) + return ret; + } + + hdcs->state = HDCS_STATE_IDLE; + + if (state == HDCS_STATE_IDLE) + return 0; + + switch (state) { + case HDCS_STATE_SLEEP: + val = HDCS_SLEEP_MODE; + break; + + case HDCS_STATE_RUN: + val = HDCS_RUN_ENABLE; + break; + + default: + return -EINVAL; + } + + ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val); + if (ret < 0) + hdcs->state = state; + + return ret; +} + +static int hdcs_reset(struct sd *sd) +{ + struct hdcs *hdcs = sd->sensor_priv; + int err; + + err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1); + if (err < 0) + return err; + + err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0); + if (err < 0) + hdcs->state = HDCS_STATE_IDLE; + + return err; +} + +static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct hdcs *hdcs = sd->sensor_priv; + + /* Column time period */ + int ct; + /* Column processing period */ + int cp; + /* Row processing period */ + int rp; + int cycles; + int err; + int rowexp; + u16 data[2]; + + err = stv06xx_read_sensor(sd, HDCS_ROWEXPL, &data[0]); + if (err < 0) + return err; + + err = stv06xx_read_sensor(sd, HDCS_ROWEXPH, &data[1]); + if (err < 0) + return err; + + rowexp = (data[1] << 8) | data[0]; + + ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2); + cp = hdcs->exp.cto + (hdcs->w * ct / 2); + rp = hdcs->exp.rs + cp; + + cycles = rp * rowexp; + *val = cycles / HDCS_CLK_FREQ_MHZ; + PDEBUG(D_V4L2, "Read exposure %d", *val); + return 0; +} + +static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct hdcs *hdcs = sd->sensor_priv; + int rowexp, srowexp; + int max_srowexp; + /* Column time period */ + int ct; + /* Column processing period */ + int cp; + /* Row processing period */ + int rp; + /* Minimum number of column timing periods + within the column processing period */ + int mnct; + int cycles, err; + u8 exp[4]; + + cycles = val * HDCS_CLK_FREQ_MHZ; + + ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2); + cp = hdcs->exp.cto + (hdcs->w * ct / 2); + + /* the cycles one row takes */ + rp = hdcs->exp.rs + cp; + + rowexp = cycles / rp; + + /* the remaining cycles */ + cycles -= rowexp * rp; + + /* calculate sub-row exposure */ + if (IS_1020(sd)) { + /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */ + srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct; + + mnct = (hdcs->exp.er + 12 + ct - 1) / ct; + max_srowexp = hdcs->w - mnct; + } else { + /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */ + srowexp = cp - hdcs->exp.er - 6 - cycles; + + mnct = (hdcs->exp.er + 5 + ct - 1) / ct; + max_srowexp = cp - mnct * ct - 1; + } + + if (srowexp < 0) + srowexp = 0; + else if (srowexp > max_srowexp) + srowexp = max_srowexp; + + if (IS_1020(sd)) { + exp[0] = rowexp & 0xff; + exp[1] = rowexp >> 8; + exp[2] = (srowexp >> 2) & 0xff; + /* this clears exposure error flag */ + exp[3] = 0x1; + err = hdcs_reg_write_seq(sd, HDCS_ROWEXPL, exp, 4); + } else { + exp[0] = rowexp & 0xff; + exp[1] = rowexp >> 8; + exp[2] = srowexp & 0xff; + exp[3] = srowexp >> 8; + err = hdcs_reg_write_seq(sd, HDCS_ROWEXPL, exp, 4); + if (err < 0) + return err; + + /* clear exposure error flag */ + err = stv06xx_write_sensor(sd, + HDCS_STATUS, BIT(4)); + } + PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d", + val, rowexp, srowexp); + return err; +} + +static int hdcs_set_gains(struct sd *sd, u8 r, u8 g, u8 b) +{ + u8 gains[4]; + + /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */ + if (r > 127) + r = 0x80 | (r / 2); + if (g > 127) + g = 0x80 | (g / 2); + if (b > 127) + b = 0x80 | (b / 2); + + gains[0] = g; + gains[1] = r; + gains[2] = b; + gains[3] = g; + + return hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4); +} + +static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + int err; + u16 data; + + err = stv06xx_read_sensor(sd, HDCS_ERECPGA, &data); + + /* Bit 7 doubles the gain */ + if (data & 0x80) + *val = (data & 0x7f) * 2; + else + *val = data; + + PDEBUG(D_V4L2, "Read gain %d", *val); + return err; +} + +static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + PDEBUG(D_V4L2, "Writing gain %d", val); + return hdcs_set_gains((struct sd *) gspca_dev, + val & 0xff, val & 0xff, val & 0xff); +} + +static int hdcs_set_size(struct sd *sd, + unsigned int width, unsigned int height) +{ + struct hdcs *hdcs = sd->sensor_priv; + u8 win[4]; + unsigned int x, y; + int err; + + /* must be multiple of 4 */ + width = (width + 3) & ~0x3; + height = (height + 3) & ~0x3; + + if (width > hdcs->array.width) + width = hdcs->array.width; + + if (IS_1020(sd)) { + /* the borders are also invalid */ + if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP + > hdcs->array.height) + height = hdcs->array.height - 2 * hdcs->array.border - + HDCS_1020_BOTTOM_Y_SKIP; + + y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2 + + hdcs->array.top; + } else if (height > hdcs->array.height) { + height = hdcs->array.height; + y = hdcs->array.top + (hdcs->array.height - height) / 2; + } + + x = hdcs->array.left + (hdcs->array.width - width) / 2; + + win[0] = y / 4; + win[1] = x / 4; + win[2] = (y + height) / 4 - 1; + win[3] = (x + width) / 4 - 1; + + err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4); + if (err < 0) + return err; + + /* Update the current width and height */ + hdcs->w = width; + hdcs->h = height; + return err; +} + +static int hdcs_probe_1x00(struct sd *sd) +{ + struct hdcs *hdcs; + u16 sensor; + int ret; + + ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor); + if (ret < 0 || sensor != 0x08) + return -ENODEV; + + info("HDCS-1000/1100 sensor detected"); + + sd->gspca_dev.cam.cam_mode = stv06xx_sensor_hdcs1x00.modes; + sd->gspca_dev.cam.nmodes = stv06xx_sensor_hdcs1x00.nmodes; + sd->desc.ctrls = stv06xx_sensor_hdcs1x00.ctrls; + sd->desc.nctrls = stv06xx_sensor_hdcs1x00.nctrls; + + hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL); + if (!hdcs) + return -ENOMEM; + + hdcs->array.left = 8; + hdcs->array.top = 8; + hdcs->array.width = HDCS_1X00_DEF_WIDTH; + hdcs->array.height = HDCS_1X00_DEF_HEIGHT; + hdcs->array.border = 4; + + hdcs->exp.cto = 4; + hdcs->exp.cpo = 2; + hdcs->exp.rs = 186; + hdcs->exp.er = 100; + + /* + * Frame rate on HDCS-1000 0x46D:0x840 depends on PSMP: + * 4 = doesn't work at all + * 5 = 7.8 fps, + * 6 = 6.9 fps, + * 8 = 6.3 fps, + * 10 = 5.5 fps, + * 15 = 4.4 fps, + * 31 = 2.8 fps + * + * Frame rate on HDCS-1000 0x46D:0x870 depends on PSMP: + * 15 = doesn't work at all + * 18 = doesn't work at all + * 19 = 7.3 fps + * 20 = 7.4 fps + * 21 = 7.4 fps + * 22 = 7.4 fps + * 24 = 6.3 fps + * 30 = 5.4 fps + */ + hdcs->psmp = IS_870(sd) ? 20 : 5; + + sd->sensor_priv = hdcs; + + return 0; +} + +static int hdcs_probe_1020(struct sd *sd) +{ + struct hdcs *hdcs; + u16 sensor; + int ret; + + ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor); + if (ret < 0 || sensor != 0x10) + return -ENODEV; + + info("HDCS-1020 sensor detected"); + + sd->gspca_dev.cam.cam_mode = stv06xx_sensor_hdcs1020.modes; + sd->gspca_dev.cam.nmodes = stv06xx_sensor_hdcs1020.nmodes; + sd->desc.ctrls = stv06xx_sensor_hdcs1020.ctrls; + sd->desc.nctrls = stv06xx_sensor_hdcs1020.nctrls; + + hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL); + if (!hdcs) + return -ENOMEM; + + /* + * From Andrey's test image: looks like HDCS-1020 upper-left + * visible pixel is at 24,8 (y maybe even smaller?) and lower-right + * visible pixel at 375,299 (x maybe even larger?) + */ + hdcs->array.left = 24; + hdcs->array.top = 4; + hdcs->array.width = HDCS_1020_DEF_WIDTH; + hdcs->array.height = 304; + hdcs->array.border = 4; + + hdcs->psmp = 6; + + hdcs->exp.cto = 3; + hdcs->exp.cpo = 3; + hdcs->exp.rs = 155; + hdcs->exp.er = 96; + + sd->sensor_priv = hdcs; + + return 0; +} + +static int hdcs_start(struct sd *sd) +{ + PDEBUG(D_STREAM, "Starting stream"); + + return hdcs_set_state(sd, HDCS_STATE_RUN); +} + +static int hdcs_stop(struct sd *sd) +{ + PDEBUG(D_STREAM, "Halting stream"); + + return hdcs_set_state(sd, HDCS_STATE_SLEEP); +} + +static void hdcs_disconnect(struct sd *sd) +{ + PDEBUG(D_PROBE, "Disconnecting the sensor"); + kfree(sd->sensor_priv); +} + +static int hdcs_init(struct sd *sd) +{ + struct hdcs *hdcs = sd->sensor_priv; + int i, err = 0; + + /* Set the STV0602AA in STV0600 emulation mode */ + if (IS_870(sd)) + stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1); + + /* Execute the bridge init */ + for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) { + err = stv06xx_write_bridge(sd, stv_bridge_init[i][0], + stv_bridge_init[i][1]); + } + if (err < 0) + return err; + + /* sensor soft reset */ + hdcs_reset(sd); + + /* Execute the sensor init */ + for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) { + err = stv06xx_write_sensor(sd, stv_sensor_init[i][0], + stv_sensor_init[i][1]); + } + if (err < 0) + return err; + + /* Enable continous frame capture, bit 2: stop when frame complete */ + err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3)); + if (err < 0) + return err; + + /* Set PGA sample duration + (was 0x7E for IS_870, but caused slow framerate with HDCS-1020) */ + if (IS_1020(sd)) + err = stv06xx_write_sensor(sd, HDCS_TCTRL, + (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp); + else + err = stv06xx_write_sensor(sd, HDCS_TCTRL, + (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp); + if (err < 0) + return err; + + err = hdcs_set_gains(sd, HDCS_DEFAULT_GAIN, HDCS_DEFAULT_GAIN, + HDCS_DEFAULT_GAIN); + if (err < 0) + return err; + + err = hdcs_set_exposure(&sd->gspca_dev, HDCS_DEFAULT_EXPOSURE); + if (err < 0) + return err; + + err = hdcs_set_size(sd, hdcs->array.width, hdcs->array.height); + return err; +} + +static int hdcs_dump(struct sd *sd) +{ + u16 reg, val; + + info("Dumping sensor registers:"); + + for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) { + stv06xx_read_sensor(sd, reg, &val); + info("reg 0x%02x = 0x%02x", reg, val); + } + return 0; +} diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h new file mode 100644 index 000000000..9c7279a4c --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * Copyright (c) 2008 Chia-I Wu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +#ifndef STV06XX_HDCS_H_ +#define STV06XX_HDCS_H_ + +#include "stv06xx_sensor.h" + +#define HDCS_REG_CONFIG(sd) (IS_1020(sd) ? HDCS20_CONFIG : HDCS00_CONFIG) +#define HDCS_REG_CONTROL(sd) (IS_1020(sd) ? HDCS20_CONTROL : HDCS00_CONTROL) + +#define HDCS_1X00_DEF_WIDTH 360 +#define HDCS_1X00_DEF_HEIGHT 296 + +#define HDCS_1020_DEF_WIDTH 352 +#define HDCS_1020_DEF_HEIGHT 292 + +#define HDCS_1020_BOTTOM_Y_SKIP 4 + +#define HDCS_CLK_FREQ_MHZ 25 + +#define HDCS_ADC_START_SIG_DUR 3 + +/* LSB bit of I2C or register address signifies write (0) or read (1) */ +/* I2C Registers common for both HDCS-1000/1100 and HDCS-1020 */ +/* Identifications Register */ +#define HDCS_IDENT (0x00 << 1) +/* Status Register */ +#define HDCS_STATUS (0x01 << 1) +/* Interrupt Mask Register */ +#define HDCS_IMASK (0x02 << 1) +/* Pad Control Register */ +#define HDCS_PCTRL (0x03 << 1) +/* Pad Drive Control Register */ +#define HDCS_PDRV (0x04 << 1) +/* Interface Control Register */ +#define HDCS_ICTRL (0x05 << 1) +/* Interface Timing Register */ +#define HDCS_ITMG (0x06 << 1) +/* Baud Fraction Register */ +#define HDCS_BFRAC (0x07 << 1) +/* Baud Rate Register */ +#define HDCS_BRATE (0x08 << 1) +/* ADC Control Register */ +#define HDCS_ADCCTRL (0x09 << 1) +/* First Window Row Register */ +#define HDCS_FWROW (0x0a << 1) +/* First Window Column Register */ +#define HDCS_FWCOL (0x0b << 1) +/* Last Window Row Register */ +#define HDCS_LWROW (0x0c << 1) +/* Last Window Column Register */ +#define HDCS_LWCOL (0x0d << 1) +/* Timing Control Register */ +#define HDCS_TCTRL (0x0e << 1) +/* PGA Gain Register: Even Row, Even Column */ +#define HDCS_ERECPGA (0x0f << 1) +/* PGA Gain Register: Even Row, Odd Column */ +#define HDCS_EROCPGA (0x10 << 1) +/* PGA Gain Register: Odd Row, Even Column */ +#define HDCS_ORECPGA (0x11 << 1) +/* PGA Gain Register: Odd Row, Odd Column */ +#define HDCS_OROCPGA (0x12 << 1) +/* Row Exposure Low Register */ +#define HDCS_ROWEXPL (0x13 << 1) +/* Row Exposure High Register */ +#define HDCS_ROWEXPH (0x14 << 1) + +/* I2C Registers only for HDCS-1000/1100 */ +/* Sub-Row Exposure Low Register */ +#define HDCS00_SROWEXPL (0x15 << 1) +/* Sub-Row Exposure High Register */ +#define HDCS00_SROWEXPH (0x16 << 1) +/* Configuration Register */ +#define HDCS00_CONFIG (0x17 << 1) +/* Control Register */ +#define HDCS00_CONTROL (0x18 << 1) + +/* I2C Registers only for HDCS-1020 */ +/* Sub-Row Exposure Register */ +#define HDCS20_SROWEXP (0x15 << 1) +/* Error Control Register */ +#define HDCS20_ERROR (0x16 << 1) +/* Interface Timing 2 Register */ +#define HDCS20_ITMG2 (0x17 << 1) +/* Interface Control 2 Register */ +#define HDCS20_ICTRL2 (0x18 << 1) +/* Horizontal Blank Register */ +#define HDCS20_HBLANK (0x19 << 1) +/* Vertical Blank Register */ +#define HDCS20_VBLANK (0x1a << 1) +/* Configuration Register */ +#define HDCS20_CONFIG (0x1b << 1) +/* Control Register */ +#define HDCS20_CONTROL (0x1c << 1) + +#define HDCS_RUN_ENABLE (1 << 2) +#define HDCS_SLEEP_MODE (1 << 1) + +#define HDCS_DEFAULT_EXPOSURE 5000 +#define HDCS_DEFAULT_GAIN 128 + +static int hdcs_probe_1x00(struct sd *sd); +static int hdcs_probe_1020(struct sd *sd); +static int hdcs_start(struct sd *sd); +static int hdcs_init(struct sd *sd); +static int hdcs_stop(struct sd *sd); +static int hdcs_dump(struct sd *sd); +static void hdcs_disconnect(struct sd *sd); + +static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val); +static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val); + +const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = { + .name = "HP HDCS-1000/1100", + .i2c_flush = 0, + .i2c_addr = (0x55 << 1), + .i2c_len = 1, + + .init = hdcs_init, + .probe = hdcs_probe_1x00, + .start = hdcs_start, + .stop = hdcs_stop, + .disconnect = hdcs_disconnect, + .dump = hdcs_dump, + + .nctrls = 2, + .ctrls = { + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0xffff, + .step = 0x1, + .default_value = HDCS_DEFAULT_EXPOSURE, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = hdcs_set_exposure, + .get = hdcs_get_exposure + }, + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = HDCS_DEFAULT_GAIN, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = hdcs_set_gain, + .get = hdcs_get_gain + } + }, + + .nmodes = 1, + .modes = { + { + HDCS_1X00_DEF_WIDTH, + HDCS_1X00_DEF_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT, + .bytesperline = HDCS_1X00_DEF_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + } + } +}; + +const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = { + .name = "HDCS-1020", + .i2c_flush = 0, + .i2c_addr = (0x55 << 1), + .i2c_len = 1, + + .nctrls = 0, + .ctrls = {}, + + .init = hdcs_init, + .probe = hdcs_probe_1020, + .start = hdcs_start, + .stop = hdcs_stop, + .dump = hdcs_dump, + + .nmodes = 1, + .modes = { + { + HDCS_1020_DEF_WIDTH, + HDCS_1020_DEF_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT, + .bytesperline = HDCS_1020_DEF_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + } + } +}; + +static const u16 stv_bridge_init[][2] = { + {STV_ISO_ENABLE, 0}, + {STV_REG23, 0}, + {STV_REG00, 0x1d}, + {STV_REG01, 0xb5}, + {STV_REG02, 0xa8}, + {STV_REG03, 0x95}, + {STV_REG04, 0x07}, + + {STV_SCAN_RATE, 0x20}, + {STV_ISO_SIZE_L, 847}, + {STV_Y_CTRL, 0x01}, + {STV_X_CTRL, 0x0a} +}; + +static const u8 stv_sensor_init[][2] = { + /* Clear status (writing 1 will clear the corresponding status bit) */ + {HDCS_STATUS, BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1)}, + /* Disable all interrupts */ + {HDCS_IMASK, 0x00}, + {HDCS_PCTRL, BIT(6) | BIT(5) | BIT(1) | BIT(0)}, + {HDCS_PDRV, 0x00}, + {HDCS_ICTRL, BIT(5)}, + {HDCS_ITMG, BIT(4) | BIT(1)}, + /* ADC output resolution to 10 bits */ + {HDCS_ADCCTRL, 10} +}; + +#endif diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c new file mode 100644 index 000000000..d0a0f8596 --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +/* + * The spec file for the PB-0100 suggests the following for best quality + * images after the sensor has been reset : + * + * PB_ADCGAINL = R60 = 0x03 (3 dec) : sets low reference of ADC + to produce good black level + * PB_PREADCTRL = R32 = 0x1400 (5120 dec) : Enables global gain changes + through R53 + * PB_ADCMINGAIN = R52 = 0x10 (16 dec) : Sets the minimum gain for + auto-exposure + * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec) : Sets the global gain + * PB_EXPGAIN = R14 = 0x11 (17 dec) : Sets the auto-exposure value + * PB_UPDATEINT = R23 = 0x02 (2 dec) : Sets the speed on + auto-exposure routine + * PB_CFILLIN = R5 = 0x0E (14 dec) : Sets the frame rate + */ + +#include "stv06xx_pb0100.h" + +static int pb0100_probe(struct sd *sd) +{ + u16 sensor; + int i, err; + s32 *sensor_settings; + + err = stv06xx_read_sensor(sd, PB_IDENT, &sensor); + + if (err < 0) + return -ENODEV; + + if ((sensor >> 8) == 0x64) { + sensor_settings = kmalloc( + stv06xx_sensor_pb0100.nctrls * sizeof(s32), + GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + + info("Photobit pb0100 sensor detected"); + + sd->gspca_dev.cam.cam_mode = stv06xx_sensor_pb0100.modes; + sd->gspca_dev.cam.nmodes = stv06xx_sensor_pb0100.nmodes; + sd->desc.ctrls = stv06xx_sensor_pb0100.ctrls; + sd->desc.nctrls = stv06xx_sensor_pb0100.nctrls; + for (i = 0; i < stv06xx_sensor_pb0100.nctrls; i++) + sensor_settings[i] = stv06xx_sensor_pb0100. + ctrls[i].qctrl.default_value; + sd->sensor_priv = sensor_settings; + + return 0; + } + + return -ENODEV; +} + +static int pb0100_start(struct sd *sd) +{ + int err; + struct cam *cam = &sd->gspca_dev.cam; + s32 *sensor_settings = sd->sensor_priv; + u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv; + + /* Setup sensor window */ + if (mode & PB0100_CROP_TO_VGA) { + stv06xx_write_sensor(sd, PB_RSTART, 30); + stv06xx_write_sensor(sd, PB_CSTART, 20); + stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1); + stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1); + } else { + stv06xx_write_sensor(sd, PB_RSTART, 8); + stv06xx_write_sensor(sd, PB_CSTART, 4); + stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1); + stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1); + } + + if (mode & PB0100_SUBSAMPLE) { + stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); /* Wrong, FIXME */ + stv06xx_write_bridge(sd, STV_X_CTRL, 0x06); + + stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10); + } else { + stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01); + stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a); + /* larger -> slower */ + stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20); + } + + /* set_gain also sets red and blue balance */ + pb0100_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + pb0100_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]); + pb0100_set_autogain_target(&sd->gspca_dev, + sensor_settings[AUTOGAIN_TARGET_IDX]); + pb0100_set_autogain(&sd->gspca_dev, sensor_settings[AUTOGAIN_IDX]); + + err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1)); + PDEBUG(D_STREAM, "Started stream, status: %d", err); + + return (err < 0) ? err : 0; +} + +static int pb0100_stop(struct sd *sd) +{ + int err; + + err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1); + + if (err < 0) + goto out; + + /* Set bit 1 to zero */ + err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)); + + PDEBUG(D_STREAM, "Halting stream"); +out: + return (err < 0) ? err : 0; +} + +/* FIXME: Sort the init commands out and put them into tables, + this is only for getting the camera to work */ +/* FIXME: No error handling for now, + add this once the init has been converted to proper tables */ +static int pb0100_init(struct sd *sd) +{ + stv06xx_write_bridge(sd, STV_REG00, 1); + stv06xx_write_bridge(sd, STV_SCAN_RATE, 0); + + /* Reset sensor */ + stv06xx_write_sensor(sd, PB_RESET, 1); + stv06xx_write_sensor(sd, PB_RESET, 0); + + /* Disable chip */ + stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)); + + /* Gain stuff...*/ + stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6)); + stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12); + + /* Set up auto-exposure */ + /* ADC VREF_HI new setting for a transition + from the Expose1 to the Expose2 setting */ + stv06xx_write_sensor(sd, PB_R28, 12); + /* gain max for autoexposure */ + stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180); + /* gain min for autoexposure */ + stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12); + /* Maximum frame integration time (programmed into R8) + allowed for auto-exposure routine */ + stv06xx_write_sensor(sd, PB_R54, 3); + /* Minimum frame integration time (programmed into R8) + allowed for auto-exposure routine */ + stv06xx_write_sensor(sd, PB_R55, 0); + stv06xx_write_sensor(sd, PB_UPDATEINT, 1); + /* R15 Expose0 (maximum that auto-exposure may use) */ + stv06xx_write_sensor(sd, PB_R15, 800); + /* R17 Expose2 (minimum that auto-exposure may use) */ + stv06xx_write_sensor(sd, PB_R17, 10); + + stv06xx_write_sensor(sd, PB_EXPGAIN, 0); + + /* 0x14 */ + stv06xx_write_sensor(sd, PB_VOFFSET, 0); + /* 0x0D */ + stv06xx_write_sensor(sd, PB_ADCGAINH, 11); + /* Set black level (important!) */ + stv06xx_write_sensor(sd, PB_ADCGAINL, 0); + + /* ??? */ + stv06xx_write_bridge(sd, STV_REG00, 0x11); + stv06xx_write_bridge(sd, STV_REG03, 0x45); + stv06xx_write_bridge(sd, STV_REG04, 0x07); + + /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */ + stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847); + + /* Scan/timing for the sensor */ + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); + stv06xx_write_sensor(sd, PB_CFILLIN, 14); + stv06xx_write_sensor(sd, PB_VBL, 0); + stv06xx_write_sensor(sd, PB_FINTTIME, 0); + stv06xx_write_sensor(sd, PB_RINTTIME, 123); + + stv06xx_write_bridge(sd, STV_REG01, 0xc2); + stv06xx_write_bridge(sd, STV_REG02, 0xb0); + return 0; +} + +static int pb0100_dump(struct sd *sd) +{ + return 0; +} + +static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[GAIN_IDX]; + + return 0; +} + +static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + if (sensor_settings[AUTOGAIN_IDX]) + return -EBUSY; + + sensor_settings[GAIN_IDX] = val; + err = stv06xx_write_sensor(sd, PB_G1GAIN, val); + if (!err) + err = stv06xx_write_sensor(sd, PB_G2GAIN, val); + PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err); + + if (!err) + err = pb0100_set_red_balance(gspca_dev, + sensor_settings[RED_BALANCE_IDX]); + if (!err) + err = pb0100_set_blue_balance(gspca_dev, + sensor_settings[BLUE_BALANCE_IDX]); + + return err; +} + +static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[RED_BALANCE_IDX]; + + return 0; +} + +static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + if (sensor_settings[AUTOGAIN_IDX]) + return -EBUSY; + + sensor_settings[RED_BALANCE_IDX] = val; + val += sensor_settings[GAIN_IDX]; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + + err = stv06xx_write_sensor(sd, PB_RGAIN, val); + PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err); + + return err; +} + +static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[BLUE_BALANCE_IDX]; + + return 0; +} + +static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + if (sensor_settings[AUTOGAIN_IDX]) + return -EBUSY; + + sensor_settings[BLUE_BALANCE_IDX] = val; + val += sensor_settings[GAIN_IDX]; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + + err = stv06xx_write_sensor(sd, PB_BGAIN, val); + PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err); + + return err; +} + +static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[EXPOSURE_IDX]; + + return 0; +} + +static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + if (sensor_settings[AUTOGAIN_IDX]) + return -EBUSY; + + sensor_settings[EXPOSURE_IDX] = val; + err = stv06xx_write_sensor(sd, PB_RINTTIME, val); + PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err); + + return err; +} + +static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[AUTOGAIN_IDX]; + + return 0; +} + +static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[AUTOGAIN_IDX] = val; + if (sensor_settings[AUTOGAIN_IDX]) { + if (sensor_settings[NATURAL_IDX]) + val = BIT(6)|BIT(4)|BIT(0); + else + val = BIT(4)|BIT(0); + } else + val = 0; + + err = stv06xx_write_sensor(sd, PB_EXPGAIN, val); + PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d", + sensor_settings[AUTOGAIN_IDX], sensor_settings[NATURAL_IDX], + err); + + return err; +} + +static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[AUTOGAIN_TARGET_IDX]; + + return 0; +} + +static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val) +{ + int err, totalpixels, brightpixels, darkpixels; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[AUTOGAIN_TARGET_IDX] = val; + + /* Number of pixels counted by the sensor when subsampling the pixels. + * Slightly larger than the real value to avoid oscillation */ + totalpixels = gspca_dev->width * gspca_dev->height; + totalpixels = totalpixels/(8*8) + totalpixels/(64*64); + + brightpixels = (totalpixels * val) >> 8; + darkpixels = totalpixels - brightpixels; + err = stv06xx_write_sensor(sd, PB_R21, brightpixels); + if (!err) + err = stv06xx_write_sensor(sd, PB_R22, darkpixels); + + PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err); + + return err; +} + +static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[NATURAL_IDX]; + + return 0; +} + +static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[NATURAL_IDX] = val; + + return pb0100_set_autogain(gspca_dev, sensor_settings[AUTOGAIN_IDX]); +} diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h new file mode 100644 index 000000000..4b47270aa --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +#ifndef STV06XX_PB0100_H_ +#define STV06XX_PB0100_H_ + +#include "stv06xx_sensor.h" + +/* mode priv field flags */ +#define PB0100_CROP_TO_VGA 0x01 +#define PB0100_SUBSAMPLE 0x02 + +/* I2C Registers */ +#define PB_IDENT 0x00 /* Chip Version */ +#define PB_RSTART 0x01 /* Row Window Start */ +#define PB_CSTART 0x02 /* Column Window Start */ +#define PB_RWSIZE 0x03 /* Row Window Size */ +#define PB_CWSIZE 0x04 /* Column Window Size */ +#define PB_CFILLIN 0x05 /* Column Fill-In */ +#define PB_VBL 0x06 /* Vertical Blank Count */ +#define PB_CONTROL 0x07 /* Control Mode */ +#define PB_FINTTIME 0x08 /* Integration Time/Frame Unit Count */ +#define PB_RINTTIME 0x09 /* Integration Time/Row Unit Count */ +#define PB_ROWSPEED 0x0a /* Row Speed Control */ +#define PB_ABORTFRAME 0x0b /* Abort Frame */ +#define PB_R12 0x0c /* Reserved */ +#define PB_RESET 0x0d /* Reset */ +#define PB_EXPGAIN 0x0e /* Exposure Gain Command */ +#define PB_R15 0x0f /* Expose0 */ +#define PB_R16 0x10 /* Expose1 */ +#define PB_R17 0x11 /* Expose2 */ +#define PB_R18 0x12 /* Low0_DAC */ +#define PB_R19 0x13 /* Low1_DAC */ +#define PB_R20 0x14 /* Low2_DAC */ +#define PB_R21 0x15 /* Threshold11 */ +#define PB_R22 0x16 /* Threshold0x */ +#define PB_UPDATEINT 0x17 /* Update Interval */ +#define PB_R24 0x18 /* High_DAC */ +#define PB_R25 0x19 /* Trans0H */ +#define PB_R26 0x1a /* Trans1L */ +#define PB_R27 0x1b /* Trans1H */ +#define PB_R28 0x1c /* Trans2L */ +#define PB_R29 0x1d /* Reserved */ +#define PB_R30 0x1e /* Reserved */ +#define PB_R31 0x1f /* Wait to Read */ +#define PB_PREADCTRL 0x20 /* Pixel Read Control Mode */ +#define PB_R33 0x21 /* IREF_VLN */ +#define PB_R34 0x22 /* IREF_VLP */ +#define PB_R35 0x23 /* IREF_VLN_INTEG */ +#define PB_R36 0x24 /* IREF_MASTER */ +#define PB_R37 0x25 /* IDACP */ +#define PB_R38 0x26 /* IDACN */ +#define PB_R39 0x27 /* DAC_Control_Reg */ +#define PB_R40 0x28 /* VCL */ +#define PB_R41 0x29 /* IREF_VLN_ADCIN */ +#define PB_R42 0x2a /* Reserved */ +#define PB_G1GAIN 0x2b /* Green 1 Gain */ +#define PB_BGAIN 0x2c /* Blue Gain */ +#define PB_RGAIN 0x2d /* Red Gain */ +#define PB_G2GAIN 0x2e /* Green 2 Gain */ +#define PB_R47 0x2f /* Dark Row Address */ +#define PB_R48 0x30 /* Dark Row Options */ +#define PB_R49 0x31 /* Reserved */ +#define PB_R50 0x32 /* Image Test Data */ +#define PB_ADCMAXGAIN 0x33 /* Maximum Gain */ +#define PB_ADCMINGAIN 0x34 /* Minimum Gain */ +#define PB_ADCGLOBALGAIN 0x35 /* Global Gain */ +#define PB_R54 0x36 /* Maximum Frame */ +#define PB_R55 0x37 /* Minimum Frame */ +#define PB_R56 0x38 /* Reserved */ +#define PB_VOFFSET 0x39 /* VOFFSET */ +#define PB_R58 0x3a /* Snap-Shot Sequence Trigger */ +#define PB_ADCGAINH 0x3b /* VREF_HI */ +#define PB_ADCGAINL 0x3c /* VREF_LO */ +#define PB_R61 0x3d /* Reserved */ +#define PB_R62 0x3e /* Reserved */ +#define PB_R63 0x3f /* Reserved */ +#define PB_R64 0x40 /* Red/Blue Gain */ +#define PB_R65 0x41 /* Green 2/Green 1 Gain */ +#define PB_R66 0x42 /* VREF_HI/LO */ +#define PB_R67 0x43 /* Integration Time/Row Unit Count */ +#define PB_R240 0xf0 /* ADC Test */ +#define PB_R241 0xf1 /* Chip Enable */ +#define PB_R242 0xf2 /* Reserved */ + +static int pb0100_probe(struct sd *sd); +static int pb0100_start(struct sd *sd); +static int pb0100_init(struct sd *sd); +static int pb0100_stop(struct sd *sd); +static int pb0100_dump(struct sd *sd); + +/* V4L2 controls supported by the driver */ +static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val); +static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); +static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); +static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val); +static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val); +static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val); +static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val); +static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val); +static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val); + +const struct stv06xx_sensor stv06xx_sensor_pb0100 = { + .name = "PB-0100", + .i2c_flush = 1, + .i2c_addr = 0xba, + .i2c_len = 2, + + .nctrls = 7, + .ctrls = { +#define GAIN_IDX 0 + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 128 + }, + .set = pb0100_set_gain, + .get = pb0100_get_gain + }, +#define RED_BALANCE_IDX 1 + { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = -255, + .maximum = 255, + .step = 1, + .default_value = 0 + }, + .set = pb0100_set_red_balance, + .get = pb0100_get_red_balance + }, +#define BLUE_BALANCE_IDX 2 + { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = -255, + .maximum = 255, + .step = 1, + .default_value = 0 + }, + .set = pb0100_set_blue_balance, + .get = pb0100_get_blue_balance + }, +#define EXPOSURE_IDX 3 + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 511, + .step = 1, + .default_value = 12 + }, + .set = pb0100_set_exposure, + .get = pb0100_get_exposure + }, +#define AUTOGAIN_IDX 4 + { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Gain and Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1 + }, + .set = pb0100_set_autogain, + .get = pb0100_get_autogain + }, +#define AUTOGAIN_TARGET_IDX 5 + { + { + .id = V4L2_CTRL_CLASS_USER + 0x1000, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Automatic Gain Target", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 128 + }, + .set = pb0100_set_autogain_target, + .get = pb0100_get_autogain_target + }, +#define NATURAL_IDX 6 + { + { + .id = V4L2_CTRL_CLASS_USER + 0x1001, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Natural Light Source", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1 + }, + .set = pb0100_set_natural, + .get = pb0100_get_natural + }, + }, + + .init = pb0100_init, + .probe = pb0100_probe, + .start = pb0100_start, + .stop = pb0100_stop, + .dump = pb0100_dump, + + .nmodes = 2, + .modes = { +/* low res / subsample modes disabled as they are only half res horizontal, + halving the vertical resolution does not seem to work */ +#if 0 + { + 160, + 120, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 160 * 120 * 2, + .bytesperline = 160, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = PB0100_CROP_TO_VGA | PB0100_SUBSAMPLE + }, + { + 176, + 144, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 176 * 144 * 2, + .bytesperline = 176, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = PB0100_SUBSAMPLE + }, +#endif + { + 320, + 240, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 320 * 240, + .bytesperline = 320, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = PB0100_CROP_TO_VGA + }, + { + 352, + 288, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 352 * 288, + .bytesperline = 352, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, + } +}; + +#endif diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h new file mode 100644 index 000000000..c726dacef --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +#ifndef STV06XX_SENSOR_H_ +#define STV06XX_SENSOR_H_ + +#include "stv06xx.h" + +#define IS_850(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x850) +#define IS_870(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x870) +#define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020) + +extern const struct stv06xx_sensor stv06xx_sensor_vv6410; +extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00; +extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020; +extern const struct stv06xx_sensor stv06xx_sensor_pb0100; + +#define STV06XX_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10) + +struct stv06xx_sensor { + /* Defines the name of a sensor */ + char name[32]; + + /* Sensor i2c address */ + u8 i2c_addr; + + /* Flush value*/ + u8 i2c_flush; + + /* length of an i2c word */ + u8 i2c_len; + + /* Probes if the sensor is connected */ + int (*probe)(struct sd *sd); + + /* Performs a initialization sequence */ + int (*init)(struct sd *sd); + + /* Executed at device disconnect */ + void (*disconnect)(struct sd *sd); + + /* Reads a sensor register */ + int (*read_sensor)(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + + /* Writes to a sensor register */ + int (*write_sensor)(struct sd *sd, const u8 address, + u8 *i2c_data, const u8 len); + + /* Instructs the sensor to start streaming */ + int (*start)(struct sd *sd); + + /* Instructs the sensor to stop streaming */ + int (*stop)(struct sd *sd); + + /* Instructs the sensor to dump all its contents */ + int (*dump)(struct sd *sd); + + int nctrls; + struct ctrl ctrls[STV06XX_MAX_CTRLS]; + + char nmodes; + struct v4l2_pix_format modes[]; +}; + +#endif diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c new file mode 100644 index 000000000..1ca91f2a6 --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +#include "stv06xx_vv6410.h" + +static int vv6410_probe(struct sd *sd) +{ + u16 data; + int err; + + err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data); + + if (err < 0) + return -ENODEV; + + if (data == 0x19) { + info("vv6410 sensor detected"); + + sd->gspca_dev.cam.cam_mode = stv06xx_sensor_vv6410.modes; + sd->gspca_dev.cam.nmodes = stv06xx_sensor_vv6410.nmodes; + sd->desc.ctrls = stv06xx_sensor_vv6410.ctrls; + sd->desc.nctrls = stv06xx_sensor_vv6410.nctrls; + return 0; + } + + return -ENODEV; +} + +static int vv6410_init(struct sd *sd) +{ + int err = 0, i; + + for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) { + /* if NULL then len contains single value */ + if (stv_bridge_init[i].data == NULL) { + err = stv06xx_write_bridge(sd, + stv_bridge_init[i].start, + stv_bridge_init[i].len); + } else { + int j; + for (j = 0; j < stv_bridge_init[i].len; j++) + err = stv06xx_write_bridge(sd, + stv_bridge_init[i].start + j, + stv_bridge_init[i].data[j]); + } + } + + if (err < 0) + return err; + + err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init, + ARRAY_SIZE(vv6410_sensor_init)); + + return (err < 0) ? err : 0; +} + +static int vv6410_start(struct sd *sd) +{ + int err; + struct cam *cam = &sd->gspca_dev.cam; + u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv; + + if (priv & VV6410_CROP_TO_QVGA) { + PDEBUG(D_CONF, "Cropping to QVGA"); + stv06xx_write_sensor(sd, VV6410_XENDH, 320 - 1); + stv06xx_write_sensor(sd, VV6410_YENDH, 240 - 1); + } else { + stv06xx_write_sensor(sd, VV6410_XENDH, 360 - 1); + stv06xx_write_sensor(sd, VV6410_YENDH, 294 - 1); + } + + if (priv & VV6410_SUBSAMPLE) { + PDEBUG(D_CONF, "Enabling subsampling"); + stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); + stv06xx_write_bridge(sd, STV_X_CTRL, 0x06); + + stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10); + } else { + stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01); + stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a); + + stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20); + } + + /* Turn on LED */ + err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON); + if (err < 0) + return err; + + err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0); + if (err < 0) + return err; + + PDEBUG(D_STREAM, "Starting stream"); + + return 0; +} + +static int vv6410_stop(struct sd *sd) +{ + int err; + + /* Turn off LED */ + err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF); + if (err < 0) + return err; + + err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE); + if (err < 0) + return err; + + PDEBUG(D_STREAM, "Halting stream"); + + return (err < 0) ? err : 0; +} + +static int vv6410_dump(struct sd *sd) +{ + u8 i; + int err = 0; + + info("Dumping all vv6410 sensor registers"); + for (i = 0; i < 0xff && !err; i++) { + u16 data; + err = stv06xx_read_sensor(sd, i, &data); + info("Register 0x%x contained 0x%x", i, data); + } + return (err < 0) ? err : 0; +} + +static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u16 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); + + *val = (i2c_data & VV6410_HFLIP) ? 1 : 0; + + PDEBUG(D_V4L2, "Read horizontal flip %d", *val); + + return (err < 0) ? err : 0; +} + +static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u16 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); + if (err < 0) + return err; + + if (val) + i2c_data |= VV6410_HFLIP; + else + i2c_data &= ~VV6410_HFLIP; + + PDEBUG(D_V4L2, "Set horizontal flip to %d", val); + err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data); + + return (err < 0) ? err : 0; +} + +static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u16 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); + + *val = (i2c_data & VV6410_VFLIP) ? 1 : 0; + + PDEBUG(D_V4L2, "Read vertical flip %d", *val); + + return (err < 0) ? err : 0; +} + +static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u16 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); + if (err < 0) + return err; + + if (val) + i2c_data |= VV6410_VFLIP; + else + i2c_data &= ~VV6410_VFLIP; + + PDEBUG(D_V4L2, "Set vertical flip to %d", val); + err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data); + + return (err < 0) ? err : 0; +} + +static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + int err; + u16 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + + err = stv06xx_read_sensor(sd, VV6410_ANALOGGAIN, &i2c_data); + + *val = i2c_data & 0xf; + + PDEBUG(D_V4L2, "Read analog gain %d", *val); + + return (err < 0) ? err : 0; +} + +static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + + PDEBUG(D_V4L2, "Set analog gain to %d", val); + err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf)); + + return (err < 0) ? err : 0; +} diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h new file mode 100644 index 000000000..3ff8c4ea3 --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * Copyright (c) 2008 Erik Andrén + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * P/N 861037: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 + * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express + * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam + * P/N 861075-0040: Sensor HDCS1000 ASIC + * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB + * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web + */ + +#ifndef STV06XX_VV6410_H_ +#define STV06XX_VV6410_H_ + +#include "stv06xx_sensor.h" + +#define VV6410_COLS 416 +#define VV6410_ROWS 320 + +/* Status registers */ +/* Chip identification number including revision indicator */ +#define VV6410_DEVICEH 0x00 +#define VV6410_DEVICEL 0x01 + +/* User can determine whether timed I2C data + has been consumed by interrogating flag states */ +#define VV6410_STATUS0 0x02 + +/* Current line counter value */ +#define VV6410_LINECOUNTH 0x03 +#define VV6410_LINECOUNTL 0x04 + +/* End x coordinate of image size */ +#define VV6410_XENDH 0x05 +#define VV6410_XENDL 0x06 + +/* End y coordinate of image size */ +#define VV6410_YENDH 0x07 +#define VV6410_YENDL 0x08 + +/* This is the average pixel value returned from the + dark line offset cancellation algorithm */ +#define VV6410_DARKAVGH 0x09 +#define VV6410_DARKAVGL 0x0a + +/* This is the average pixel value returned from the + black line offset cancellation algorithm */ +#define VV6410_BLACKAVGH 0x0b +#define VV6410_BLACKAVGL 0x0c + +/* Flags to indicate whether the x or y image coordinates have been clipped */ +#define VV6410_STATUS1 0x0d + +/* Setup registers */ + +/* Low-power/sleep modes & video timing */ +#define VV6410_SETUP0 0x10 + +/* Various parameters */ +#define VV6410_SETUP1 0x11 + +/* Contains pixel counter reset value used by external sync */ +#define VV6410_SYNCVALUE 0x12 + +/* Frame grabbing modes (FST, LST and QCK) */ +#define VV6410_FGMODES 0x14 + +/* FST and QCK mapping modes. */ +#define VV6410_PINMAPPING 0x15 + +/* Data resolution */ +#define VV6410_DATAFORMAT 0x16 + +/* Output coding formats */ +#define VV6410_OPFORMAT 0x17 + +/* Various mode select bits */ +#define VV6410_MODESELECT 0x18 + +/* Exposure registers */ +/* Fine exposure. */ +#define VV6410_FINEH 0x20 +#define VV6410_FINEL 0x21 + +/* Coarse exposure */ +#define VV6410_COARSEH 0x22 +#define VV6410_COARSEL 0x23 + +/* Analog gain setting */ +#define VV6410_ANALOGGAIN 0x24 + +/* Clock division */ +#define VV6410_CLKDIV 0x25 + +/* Dark line offset cancellation value */ +#define VV6410_DARKOFFSETH 0x2c +#define VV6410_DARKOFFSETL 0x2d + +/* Dark line offset cancellation enable */ +#define VV6410_DARKOFFSETSETUP 0x2e + +/* Video timing registers */ +/* Line Length (Pixel Clocks) */ +#define VV6410_LINELENGTHH 0x52 +#define VV6410_LINELENGTHL 0x53 + +/* X-co-ordinate of top left corner of region of interest (x-offset) */ +#define VV6410_XOFFSETH 0x57 +#define VV6410_XOFFSETL 0x58 + +/* Y-coordinate of top left corner of region of interest (y-offset) */ +#define VV6410_YOFFSETH 0x59 +#define VV6410_YOFFSETL 0x5a + +/* Field length (Lines) */ +#define VV6410_FIELDLENGTHH 0x61 +#define VV6410_FIELDLENGTHL 0x62 + +/* System registers */ +/* Black offset cancellation default value */ +#define VV6410_BLACKOFFSETH 0x70 +#define VV6410_BLACKOFFSETL 0x71 + +/* Black offset cancellation setup */ +#define VV6410_BLACKOFFSETSETUP 0x72 + +/* Analog Control Register 0 */ +#define VV6410_CR0 0x75 + +/* Analog Control Register 1 */ +#define VV6410_CR1 0x76 + +/* ADC Setup Register */ +#define VV6410_AS0 0x77 + +/* Analog Test Register */ +#define VV6410_AT0 0x78 + +/* Audio Amplifier Setup Register */ +#define VV6410_AT1 0x79 + +#define VV6410_HFLIP (1 << 3) +#define VV6410_VFLIP (1 << 4) + +#define VV6410_LOW_POWER_MODE (1 << 0) +#define VV6410_SOFT_RESET (1 << 2) +#define VV6410_PAL_25_FPS (0 << 3) + +#define VV6410_CLK_DIV_2 (1 << 1) + +#define VV6410_FINE_EXPOSURE 320 +#define VV6410_COARSE_EXPOSURE 192 +#define VV6410_DEFAULT_GAIN 5 + +#define VV6410_SUBSAMPLE 0x01 +#define VV6410_CROP_TO_QVGA 0x02 + +static int vv6410_probe(struct sd *sd); +static int vv6410_start(struct sd *sd); +static int vv6410_init(struct sd *sd); +static int vv6410_stop(struct sd *sd); +static int vv6410_dump(struct sd *sd); + +/* V4L2 controls supported by the driver */ +static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val); + +const struct stv06xx_sensor stv06xx_sensor_vv6410 = { + .name = "ST VV6410", + .i2c_flush = 5, + .i2c_addr = 0x20, + .i2c_len = 1, + .init = vv6410_init, + .probe = vv6410_probe, + .start = vv6410_start, + .stop = vv6410_stop, + .dump = vv6410_dump, + + .nctrls = 3, + .ctrls = { + { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = vv6410_set_hflip, + .get = vv6410_get_hflip + }, { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = vv6410_set_vflip, + .get = vv6410_get_vflip + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "analog gain", + .minimum = 0, + .maximum = 15, + .step = 1, + .default_value = 0 + }, + .set = vv6410_set_analog_gain, + .get = vv6410_get_analog_gain + } + }, + + .nmodes = 1, + .modes = { + { + 356, + 292, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = + 356 * 292, + .bytesperline = 356, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } + } +}; + +/* If NULL, only single value to write, stored in len */ +struct stv_init { + const u8 *data; + u16 start; + u8 len; +}; + +static const u8 x1500[] = { /* 0x1500 - 0x150f */ + 0x0b, 0xa7, 0xb7, 0x00, 0x00 +}; + +static const u8 x1536[] = { /* 0x1536 - 0x153b */ + 0x02, 0x00, 0x60, 0x01, 0x20, 0x01 +}; + +static const u8 x15c1[] = { /* 0x15c1 - 0x15c2 */ + 0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */ +}; + +static const struct stv_init stv_bridge_init[] = { + /* This reg is written twice. Some kind of reset? */ + {NULL, 0x1620, 0x80}, + {NULL, 0x1620, 0x00}, + {NULL, 0x1423, 0x04}, + {x1500, 0x1500, ARRAY_SIZE(x1500)}, + {x1536, 0x1536, ARRAY_SIZE(x1536)}, + {x15c1, 0x15c1, ARRAY_SIZE(x15c1)} +}; + +static const u8 vv6410_sensor_init[][2] = { + /* Setup registers */ + {VV6410_SETUP0, VV6410_SOFT_RESET}, + {VV6410_SETUP0, VV6410_LOW_POWER_MODE}, + /* Use shuffled read-out mode */ + {VV6410_SETUP1, BIT(6)}, + /* All modes to 1 */ + {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)}, + {VV6410_PINMAPPING, 0x00}, + /* Pre-clock generator divide off */ + {VV6410_DATAFORMAT, BIT(7) | BIT(0)}, + + /* Exposure registers */ + {VV6410_FINEH, VV6410_FINE_EXPOSURE >> 8}, + {VV6410_FINEL, VV6410_FINE_EXPOSURE & 0xff}, + {VV6410_COARSEH, VV6410_COARSE_EXPOSURE >> 8}, + {VV6410_COARSEL, VV6410_COARSE_EXPOSURE & 0xff}, + {VV6410_ANALOGGAIN, 0xf0 | VV6410_DEFAULT_GAIN}, + {VV6410_CLKDIV, VV6410_CLK_DIV_2}, + + /* System registers */ + /* Enable voltage doubler */ + {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)}, + {VV6410_AT0, 0x00}, + /* Power up audio, differential */ + {VV6410_AT1, BIT(4)|BIT(0)}, +}; + +#endif -- cgit v1.2.3 From f5629a5531c925ba3d87d93df226687316187a4c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 29 Dec 2008 11:49:41 +0100 Subject: gspca - many subdrivers: Set 'const' the pixel format table. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/conex.c | 2 +- linux/drivers/media/video/gspca/etoms.c | 4 ++-- linux/drivers/media/video/gspca/finepix.c | 2 +- linux/drivers/media/video/gspca/gspca.h | 2 +- linux/drivers/media/video/gspca/mars.c | 2 +- linux/drivers/media/video/gspca/ov519.c | 4 ++-- linux/drivers/media/video/gspca/ov534.c | 2 +- linux/drivers/media/video/gspca/pac207.c | 2 +- linux/drivers/media/video/gspca/pac7311.c | 2 +- linux/drivers/media/video/gspca/sonixb.c | 4 ++-- linux/drivers/media/video/gspca/sonixj.c | 2 +- linux/drivers/media/video/gspca/spca500.c | 4 ++-- linux/drivers/media/video/gspca/spca501.c | 2 +- linux/drivers/media/video/gspca/spca505.c | 2 +- linux/drivers/media/video/gspca/spca506.c | 2 +- linux/drivers/media/video/gspca/spca508.c | 2 +- linux/drivers/media/video/gspca/spca561.c | 4 ++-- linux/drivers/media/video/gspca/stk014.c | 2 +- linux/drivers/media/video/gspca/sunplus.c | 6 +++--- linux/drivers/media/video/gspca/t613.c | 2 +- linux/drivers/media/video/gspca/tv8532.c | 2 +- linux/drivers/media/video/gspca/vc032x.c | 6 +++--- linux/drivers/media/video/gspca/zc3xx.c | 4 ++-- 23 files changed, 33 insertions(+), 33 deletions(-) diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c index de28354ea..1753f5bb3 100644 --- a/linux/drivers/media/video/gspca/conex.c +++ b/linux/drivers/media/video/gspca/conex.c @@ -93,7 +93,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/etoms.c b/linux/drivers/media/video/gspca/etoms.c index 28869ef26..84b56c303 100644 --- a/linux/drivers/media/video/gspca/etoms.c +++ b/linux/drivers/media/video/gspca/etoms.c @@ -112,7 +112,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240, @@ -125,7 +125,7 @@ static struct v4l2_pix_format vga_mode[] = { .priv = 0}, */ }; -static struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144, diff --git a/linux/drivers/media/video/gspca/finepix.c b/linux/drivers/media/video/gspca/finepix.c index 03cb94466..afc8b2dd3 100644 --- a/linux/drivers/media/video/gspca/finepix.c +++ b/linux/drivers/media/video/gspca/finepix.c @@ -72,7 +72,7 @@ struct usb_fpix { } /* These cameras only support 320x200. */ -static struct v4l2_pix_format fpix_mode[1] = { +static const struct v4l2_pix_format fpix_mode[1] = { { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index 79cef31a5..c90af9cb1 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -56,7 +56,7 @@ extern int gspca_debug; /* device information - set at probe time */ struct cam { int bulk_size; /* buffer size when image transfer by bulk */ - struct v4l2_pix_format *cam_mode; /* size nmodes */ + const struct v4l2_pix_format *cam_mode; /* size nmodes */ char nmodes; __u8 bulk_nurbs; /* number of URBs in bulk mode * - cannot be > MAX_NURBS diff --git a/linux/drivers/media/video/gspca/mars.c b/linux/drivers/media/video/gspca/mars.c index 492cdd3b5..3d2090e67 100644 --- a/linux/drivers/media/video/gspca/mars.c +++ b/linux/drivers/media/video/gspca/mars.c @@ -39,7 +39,7 @@ struct sd { static struct ctrl sd_ctrls[] = { }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 589, diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 5fb519da2..5e31a9145 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -164,7 +164,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, @@ -176,7 +176,7 @@ static struct v4l2_pix_format vga_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; -static struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 406f6bc12..3bf15e401 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -55,7 +55,7 @@ struct sd { static struct ctrl sd_ctrls[] = { }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 640 * 2, .sizeimage = 640 * 480 * 2, diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c index e46b8e8f0..c90ac852b 100644 --- a/linux/drivers/media/video/gspca/pac207.c +++ b/linux/drivers/media/video/gspca/pac207.c @@ -149,7 +149,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = (176 + 2) * 144, diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 0a3c91301..83ab0df0e 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -226,7 +226,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 3 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/sonixb.c b/linux/drivers/media/video/gspca/sonixb.c index 5ca8ab780..75b44b362 100644 --- a/linux/drivers/media/video/gspca/sonixb.c +++ b/linux/drivers/media/video/gspca/sonixb.c @@ -227,7 +227,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, @@ -249,7 +249,7 @@ static struct v4l2_pix_format vga_mode[] = { .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0}, }; -static struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format sif_mode[] = { {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index ff94cd639..217db0d88 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -225,7 +225,7 @@ static __u32 ctrl_dis[] = { /* SENSOR_OV7660 6 */ }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 4 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/spca500.c b/linux/drivers/media/video/gspca/spca500.c index 2e1c5e50e..6b4865280 100644 --- a/linux/drivers/media/video/gspca/spca500.c +++ b/linux/drivers/media/video/gspca/spca500.c @@ -111,7 +111,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, @@ -124,7 +124,7 @@ static struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; -static struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/spca501.c b/linux/drivers/media/video/gspca/spca501.c index 17dab9859..609459321 100644 --- a/linux/drivers/media/video/gspca/spca501.c +++ b/linux/drivers/media/video/gspca/spca501.c @@ -132,7 +132,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 3 / 2, diff --git a/linux/drivers/media/video/gspca/spca505.c b/linux/drivers/media/video/gspca/spca505.c index c52598e94..854ed1ff5 100644 --- a/linux/drivers/media/video/gspca/spca505.c +++ b/linux/drivers/media/video/gspca/spca505.c @@ -59,7 +59,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 3 / 2, diff --git a/linux/drivers/media/video/gspca/spca506.c b/linux/drivers/media/video/gspca/spca506.c index 645ee9d44..96e2512e0 100644 --- a/linux/drivers/media/video/gspca/spca506.c +++ b/linux/drivers/media/video/gspca/spca506.c @@ -110,7 +110,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 3 / 2, diff --git a/linux/drivers/media/video/gspca/spca508.c b/linux/drivers/media/video/gspca/spca508.c index c9360cdb8..698d4ed95 100644 --- a/linux/drivers/media/video/gspca/spca508.c +++ b/linux/drivers/media/video/gspca/spca508.c @@ -62,7 +62,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format sif_mode[] = { {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 3 / 2, diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c index f518bb02f..499511fa0 100644 --- a/linux/drivers/media/video/gspca/spca561.c +++ b/linux/drivers/media/video/gspca/spca561.c @@ -73,7 +73,7 @@ struct sd { #define AG_CNT_START 13 }; -static struct v4l2_pix_format sif_012a_mode[] = { +static const struct v4l2_pix_format sif_012a_mode[] = { {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, @@ -96,7 +96,7 @@ static struct v4l2_pix_format sif_012a_mode[] = { .priv = 0}, }; -static struct v4l2_pix_format sif_072a_mode[] = { +static const struct v4l2_pix_format sif_072a_mode[] = { {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, diff --git a/linux/drivers/media/video/gspca/stk014.c b/linux/drivers/media/video/gspca/stk014.c index 74f57db53..60de9af87 100644 --- a/linux/drivers/media/video/gspca/stk014.c +++ b/linux/drivers/media/video/gspca/stk014.c @@ -109,7 +109,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 3a972ff1c..3692062d0 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -123,7 +123,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, @@ -136,7 +136,7 @@ static struct v4l2_pix_format vga_mode[] = { .priv = 1}, }; -static struct v4l2_pix_format custom_mode[] = { +static const struct v4l2_pix_format custom_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, @@ -149,7 +149,7 @@ static struct v4l2_pix_format custom_mode[] = { .priv = 1}, }; -static struct v4l2_pix_format vga_mode2[] = { +static const struct v4l2_pix_format vga_mode2[] = { {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index 452ca1d16..2d032aa0e 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -233,7 +233,7 @@ static char *effects_control[] = { "Negative", }; -static struct v4l2_pix_format vga_mode_t16[] = { +static const struct v4l2_pix_format vga_mode_t16[] = { {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 4 / 8 + 590, diff --git a/linux/drivers/media/video/gspca/tv8532.c b/linux/drivers/media/video/gspca/tv8532.c index 4e18f90ba..7d11a0d3e 100644 --- a/linux/drivers/media/video/gspca/tv8532.c +++ b/linux/drivers/media/video/gspca/tv8532.c @@ -73,7 +73,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144, diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 4cc1f69f1..68e0e7955 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -126,7 +126,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vc0321_mode[] = { +static const struct v4l2_pix_format vc0321_mode[] = { {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 2, @@ -138,7 +138,7 @@ static struct v4l2_pix_format vc0321_mode[] = { .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0}, }; -static struct v4l2_pix_format vc0323_mode[] = { +static const struct v4l2_pix_format vc0323_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, @@ -151,7 +151,7 @@ static struct v4l2_pix_format vc0323_mode[] = { .priv = 0}, }; -static struct v4l2_pix_format svga_mode[] = { +static const struct v4l2_pix_format svga_mode[] = { {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 800, .sizeimage = 800 * 600 * 1 / 4 + 590, diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index 13e34fc7b..79d2a776d 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -173,7 +173,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, @@ -186,7 +186,7 @@ static struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; -static struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 590, -- cgit v1.2.3 From 1f3a1c6934978f2be07fe09d01b3e4d1f979a43f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 29 Dec 2008 13:06:09 +0100 Subject: gspca - vc032x: Webcam 046d:0897 added. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/vc032x.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index f54281d78..1c58a7630 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -56,6 +56,7 @@ stv06xx 046d:0870 Dexxa WebCam USB spca500 046d:0890 Logitech QuickCam traveler vc032x 046d:0892 Logitech Orbicam vc032x 046d:0896 Logitech Orbicam +vc032x 046d:0897 Logitech QuickCam for Dell notebooks zc3xx 046d:089d Logitech QuickCam E2500 zc3xx 046d:08a0 Logitech QC IM zc3xx 046d:08a1 Logitech QC IM 0x08A1 +sound diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 68e0e7955..82dc818f4 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -2452,6 +2452,7 @@ static const struct sd_desc sd_desc = { static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x0892), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0896), .driver_info = BRIDGE_VC0321}, + {USB_DEVICE(0x046d, 0x0897), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x0ac8, 0x0321), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x0ac8, 0x0323), .driver_info = BRIDGE_VC0323}, {USB_DEVICE(0x0ac8, 0x0328), .driver_info = BRIDGE_VC0321}, -- cgit v1.2.3 From c3e8ee8a3c518a9fcd46aeb71d03e798beaa283a Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Mon, 29 Dec 2008 14:59:29 +0100 Subject: [PATCH] usb-urb.c: Fix initialization of URB list. From: Thomas Reitmayr Fix the initialization of the URB list for a DVB-USB device to prevent problems on certain platforms (MIPS). Priority: normal Signed-off-by: Thomas Reitmayr Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/usb-urb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/usb-urb.c b/linux/drivers/media/dvb/dvb-usb/usb-urb.c index eb3aaaf7a..5becc5a20 100644 --- a/linux/drivers/media/dvb/dvb-usb/usb-urb.c +++ b/linux/drivers/media/dvb/dvb-usb/usb-urb.c @@ -160,7 +160,8 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream) stream->props.u.bulk.buffersize, usb_urb_complete, stream); - stream->urb_list[i]->transfer_flags = 0; + stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + stream->urb_list[i]->transfer_dma = stream->dma_addr[i]; stream->urbs_initialized++; } return 0; -- cgit v1.2.3 From 0f009089e257b6efff3a202a339e04413132d01f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Dec 2008 19:06:09 -0200 Subject: gscpa - stv06xx: Fix compilation with kernel tree From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/stv06xx/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux/drivers/media/video/gspca/stv06xx/Makefile b/linux/drivers/media/video/gspca/stv06xx/Makefile index 8f002b623..feeaa94ab 100644 --- a/linux/drivers/media/video/gspca/stv06xx/Makefile +++ b/linux/drivers/media/video/gspca/stv06xx/Makefile @@ -4,3 +4,6 @@ gspca_stv06xx-objs := stv06xx.o \ stv06xx_vv6410.o \ stv06xx_hdcs.o \ stv06xx_pb0100.o + +EXTRA_CFLAGS += -Idrivers/media/video/gspca + -- cgit v1.2.3 From e9727f0a3638c9854002f65c0c5b206a815b0ed1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Dec 2008 19:35:51 -0200 Subject: More than one driver defines the same var name (dump_bridge). Add From: Mauro Carvalho Chehab "static" on stv06xx for all static functions and parameters to avoid such troubles. Signed-off-by: Mauro Carvalho Chehab CC: Erik Andren CC: Jean-Francois Moine --- linux/drivers/media/video/gspca/stv06xx/stv06xx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c index 29e43718b..bb18b64c6 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -33,10 +33,10 @@ MODULE_AUTHOR("Erik Andrén"); MODULE_DESCRIPTION("STV06XX USB Camera Driver"); MODULE_LICENSE("GPL"); -int dump_bridge; -int dump_sensor; +static int dump_bridge; +static int dump_sensor; -int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) +static int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) { int err; struct usb_device *udev = sd->gspca_dev.dev; @@ -57,7 +57,7 @@ int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) return (err < 0) ? err : 0; } -int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) +static int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) { int err; struct usb_device *udev = sd->gspca_dev.dev; @@ -77,7 +77,7 @@ int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) /* Wraps the normal write sensor bytes / words functions for writing a single value */ -int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value) +static int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value) { if (sd->sensor->i2c_len == 2) { u16 data[2] = { address, value }; @@ -106,7 +106,7 @@ static int stv06xx_write_sensor_finish(struct sd *sd) return (err < 0) ? err : 0; } -int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) +static int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) { int err, i, j; struct usb_device *udev = sd->gspca_dev.dev; @@ -135,7 +135,7 @@ int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) return stv06xx_write_sensor_finish(sd); } -int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) +static int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) { int err, i, j; struct usb_device *udev = sd->gspca_dev.dev; @@ -166,7 +166,7 @@ int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) return stv06xx_write_sensor_finish(sd); } -int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value) +static int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value) { int err; struct usb_device *udev = sd->gspca_dev.dev; @@ -476,7 +476,7 @@ static int sd_probe(struct usb_interface *intf, THIS_MODULE); } -void sd_disconnect(struct usb_interface *intf) +static void sd_disconnect(struct usb_interface *intf) { struct gspca_dev *gspca_dev = usb_get_intfdata(intf); struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From b9dad285d153c7dd8b54848e7125c1e4987f1484 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Dec 2008 19:51:50 -0200 Subject: stv06xx: partially revert changeset 7504a804618f From: Mauro Carvalho Chehab Some functions shouldn't be static. Priority: normal Signed-off-by: Mauro Carvalho Chehab CC: Erik Andren CC: Jean-Francois Moine --- linux/drivers/media/video/gspca/stv06xx/stv06xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c index bb18b64c6..13a021e3c 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -36,7 +36,7 @@ MODULE_LICENSE("GPL"); static int dump_bridge; static int dump_sensor; -static int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) +int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) { int err; struct usb_device *udev = sd->gspca_dev.dev; @@ -57,7 +57,7 @@ static int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) return (err < 0) ? err : 0; } -static int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) +int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) { int err; struct usb_device *udev = sd->gspca_dev.dev; @@ -77,7 +77,7 @@ static int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) /* Wraps the normal write sensor bytes / words functions for writing a single value */ -static int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value) +int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value) { if (sd->sensor->i2c_len == 2) { u16 data[2] = { address, value }; @@ -106,7 +106,7 @@ static int stv06xx_write_sensor_finish(struct sd *sd) return (err < 0) ? err : 0; } -static int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) +int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) { int err, i, j; struct usb_device *udev = sd->gspca_dev.dev; @@ -135,7 +135,7 @@ static int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) return stv06xx_write_sensor_finish(sd); } -static int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) +int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) { int err, i, j; struct usb_device *udev = sd->gspca_dev.dev; @@ -166,7 +166,7 @@ static int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) return stv06xx_write_sensor_finish(sd); } -static int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value) +int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value) { int err; struct usb_device *udev = sd->gspca_dev.dev; -- cgit v1.2.3 From 33cef62634c7f0a4b54be792d7d1c4e1b807f4d9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Dec 2008 20:02:24 -0200 Subject: anysee: Fix usage of an unitialized function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Mauro Carvalho Chehab drivers/media/dvb/dvb-usb/anysee.c: In function ‘anysee_master_xfer’: drivers/media/dvb/dvb-usb/anysee.c:156: warning: ‘ret’ may be used uninitialized By looking at the function, altrough very unlikely, this might eventually be true if num = 0. So, better to fix the warning by initializing with ret = 0. Signed-off-by: Mauro Carvalho Chehab CC: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/anysee.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/anysee.c b/linux/drivers/media/dvb/dvb-usb/anysee.c index 90a04266a..1dbf132a7 100644 --- a/linux/drivers/media/dvb/dvb-usb/anysee.c +++ b/linux/drivers/media/dvb/dvb-usb/anysee.c @@ -153,7 +153,7 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - int ret, inc, i = 0; + int ret = 0, inc, i = 0; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; -- cgit v1.2.3 From c278ca42f16bc64d3fd053d6dd1b85d0e932bbae Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Dec 2008 20:15:43 -0200 Subject: v4l2-ioctl: Fix warnings when using .unlocked_ioctl = __video_ioctl2 From: Mauro Carvalho Chehab This patch fixes this warning: drivers/media/video/gspca/gspca.c:1811: warning: initialization from incompatible pointer type The reason is that the returned argument should be a long, not an integer. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-ioctl.c | 2 +- linux/include/media/v4l2-ioctl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 86dd04026..9e32a2c56 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -1853,7 +1853,7 @@ static int __video_do_ioctl(struct file *file, return ret; } -int __video_ioctl2(struct file *file, +long __video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg) { char sbuf[128]; diff --git a/linux/include/media/v4l2-ioctl.h b/linux/include/media/v4l2-ioctl.h index c884432f9..fcdb58c4c 100644 --- a/linux/include/media/v4l2-ioctl.h +++ b/linux/include/media/v4l2-ioctl.h @@ -297,7 +297,7 @@ extern int video_usercopy(struct file *file, unsigned int cmd, /* Standard handlers for V4L ioctl's */ /* This prototype is used on fops.unlocked_ioctl */ -extern int __video_ioctl2(struct file *file, +extern long __video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg); /* This prototype is used on fops.ioctl -- cgit v1.2.3 From 6ccda240cb23a33beb59c38cf209db0ccfabc4e8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Dec 2008 20:26:17 -0200 Subject: quickcam_messenger.c: fix a warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Mauro Carvalho Chehab drivers/media/video/usbvideo/quickcam_messenger.c: In function ‘qcm_sensor_init’: drivers/media/video/usbvideo/quickcam_messenger.c:450: warning: operation on ‘ret’ may be undefined Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/usbvideo/quickcam_messenger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/usbvideo/quickcam_messenger.c b/linux/drivers/media/video/usbvideo/quickcam_messenger.c index d363e3d64..9602ba0bd 100644 --- a/linux/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/linux/drivers/media/video/usbvideo/quickcam_messenger.c @@ -460,7 +460,7 @@ static int qcm_sensor_init(struct uvd *uvd) CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1, cpu_to_le16(ISOC_PACKET_SIZE))); CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08)); - CHECK_RET(ret, ret = qcm_stv_setb(uvd->dev, 0x143f, 0x01)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143f, 0x01)); CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); -- cgit v1.2.3 From ea995c822add678fd16748cc6b9d1f180ca3e801 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Oct 2008 17:47:26 -0700 Subject: backport commit 7c510e4b730a92cecf94ada45c989d8be0200d47 From: Mauro Carvalho Chehab Author: Johannes Berg net: convert more to %pM A number of places still use %02x:...:%02x because it's in debug statements or for no real reason. Make a few of them use %pM. kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/b2c2/flexcop.c | 2 +- linux/drivers/media/dvb/bt8xx/dst.c | 4 +--- linux/drivers/media/dvb/dm1105/dm1105.c | 3 +-- linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | 5 +---- linux/drivers/media/dvb/pluto2/pluto2.c | 3 +-- 5 files changed, 5 insertions(+), 12 deletions(-) diff --git a/linux/drivers/media/dvb/b2c2/flexcop.c b/linux/drivers/media/dvb/b2c2/flexcop.c index 5f79c8dc3..676413a91 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop.c +++ b/linux/drivers/media/dvb/b2c2/flexcop.c @@ -270,7 +270,7 @@ int flexcop_device_initialize(struct flexcop_device *fc) /* do the MAC address reading after initializing the dvb_adapter */ if (fc->get_mac_addr(fc, 0) == 0) { u8 *b = fc->dvb_adapter.proposed_mac; - info("MAC address = %02x:%02x:%02x:%02x:%02x:%02x", b[0],b[1],b[2],b[3],b[4],b[5]); + info("MAC address = %pM", b); flexcop_set_mac_filter(fc,b); flexcop_mac_filter_ctrl(fc,1); } else diff --git a/linux/drivers/media/dvb/bt8xx/dst.c b/linux/drivers/media/dvb/bt8xx/dst.c index aa3db57d3..29e8f1546 100644 --- a/linux/drivers/media/dvb/bt8xx/dst.c +++ b/linux/drivers/media/dvb/bt8xx/dst.c @@ -917,9 +917,7 @@ static int dst_get_mac(struct dst_state *state) } memset(&state->mac_address, '\0', 8); memcpy(&state->mac_address, &state->rxbuffer, 6); - dprintk(verbose, DST_ERROR, 1, "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]", - state->mac_address[0], state->mac_address[1], state->mac_address[2], - state->mac_address[4], state->mac_address[5], state->mac_address[6]); + dprintk(verbose, DST_ERROR, 1, "MAC Address=[%pM]", state->mac_address); return 0; } diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c index d7034e6a1..b054d056d 100644 --- a/linux/drivers/media/dvb/dm1105/dm1105.c +++ b/linux/drivers/media/dvb/dm1105/dm1105.c @@ -703,8 +703,7 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) }; dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); - dev_info(&dm1105dvb->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + dev_info(&dm1105dvb->pdev->dev, "MAC %pM\n", mac); } static int __devinit dm1105_probe(struct pci_dev *pdev, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c index ce8cd0c5d..8a7d87bcd 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c @@ -91,10 +91,7 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums) if (adap->dev->props.read_mac_address) { if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0) - info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",adap->dvb_adap.proposed_mac[0], - adap->dvb_adap.proposed_mac[1], adap->dvb_adap.proposed_mac[2], - adap->dvb_adap.proposed_mac[3], adap->dvb_adap.proposed_mac[4], - adap->dvb_adap.proposed_mac[5]); + info("MAC address: %pM",adap->dvb_adap.proposed_mac); else err("MAC address reading failed."); } diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c index cb368e2e0..8522757a5 100644 --- a/linux/drivers/media/dvb/pluto2/pluto2.c +++ b/linux/drivers/media/dvb/pluto2/pluto2.c @@ -568,8 +568,7 @@ static void __devinit pluto_read_mac(struct pluto *pluto, u8 *mac) mac[4] = (val >> 8) & 0xff; mac[5] = (val >> 0) & 0xff; - dev_info(&pluto->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + dev_info(&pluto->pdev->dev, "MAC %pM\n", mac); } static int __devinit pluto_read_serial(struct pluto *pluto) -- cgit v1.2.3 From 313e51a6c4a38ae0441b77f860d48f800bb2e861 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Dec 2008 21:13:13 -0800 Subject: backport commit 0eade1f930fa3ba6461b34baf3ed8fa7c4abc40f From: Mauro Carvalho Chehab Author: Wang Chen dvb: Kill directly reference of netdev->priv Simply replace netdev->priv with netdev_priv(). kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvb_net.c | 39 +++++++++++++++--------------- v4l/compat.h | 4 +++ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-core/dvb_net.c b/linux/drivers/media/dvb/dvb-core/dvb_net.c index e0d60cdc4..f0cd3b8ed 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_net.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_net.c @@ -352,7 +352,7 @@ static inline void reset_ule( struct dvb_net_priv *p ) */ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) { - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); unsigned long skipped = 0L; const u8 *ts, *ts_end, *from_where = NULL; u8 ts_remain = 0, how_much = 0, new_ts = 1; @@ -467,8 +467,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) /* Drop partly decoded SNDU, reset state, resync on PUSI. */ if (priv->ule_skb) { dev_kfree_skb( priv->ule_skb ); - ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; - ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; + priv->stats.rx_errors++; + priv->stats.rx_frame_errors++; } reset_ule(priv); priv->need_pusi = 1; @@ -580,7 +580,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) if (priv->ule_skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - ((struct dvb_net_priv *)dev->priv)->stats.rx_dropped++; + priv->stats.rx_dropped++; return; } @@ -820,7 +820,8 @@ static void dvb_net_sec(struct net_device *dev, { u8 *eth; struct sk_buff *skb; - struct net_device_stats *stats = &(((struct dvb_net_priv *) dev->priv)->stats); + struct net_device_stats *stats = + &((struct dvb_net_priv *) netdev_priv(dev))->stats; int snap = 0; /* note: pkt_len includes a 32bit checksum */ @@ -937,7 +938,7 @@ static int dvb_net_filter_sec_set(struct net_device *dev, struct dmx_section_filter **secfilter, u8 *mac, u8 *mac_mask) { - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); int ret; *secfilter=NULL; @@ -981,7 +982,7 @@ static int dvb_net_filter_sec_set(struct net_device *dev, static int dvb_net_feed_start(struct net_device *dev) { int ret = 0, i; - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); struct dmx_demux *demux = priv->demux; unsigned char *mac = (unsigned char *) dev->dev_addr; @@ -1080,7 +1081,7 @@ error: static int dvb_net_feed_stop(struct net_device *dev) { - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); int i, ret = 0; dprintk("%s\n", __func__); @@ -1133,7 +1134,7 @@ static int dvb_net_feed_stop(struct net_device *dev) static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc) { - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); if (priv->multi_num == DVB_NET_MULTICAST_MAX) return -ENOMEM; @@ -1153,7 +1154,7 @@ static void wq_set_multicast_list (struct work_struct *work) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct net_device *dev = data; - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); #else struct dvb_net_priv *priv = container_of(work, struct dvb_net_priv, set_multicast_list_wq); @@ -1210,7 +1211,7 @@ static void wq_set_multicast_list (struct work_struct *work) static void dvb_net_set_multicast_list (struct net_device *dev) { - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); schedule_work(&priv->set_multicast_list_wq); } @@ -1238,7 +1239,7 @@ static void wq_restart_net_feed (struct work_struct *work) static int dvb_net_set_mac (struct net_device *dev, void *p) { - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); struct sockaddr *addr=p; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); @@ -1252,7 +1253,7 @@ static int dvb_net_set_mac (struct net_device *dev, void *p) static int dvb_net_open(struct net_device *dev) { - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); priv->in_use++; dvb_net_feed_start(dev); @@ -1262,7 +1263,7 @@ static int dvb_net_open(struct net_device *dev) static int dvb_net_stop(struct net_device *dev) { - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = netdev_priv(dev); priv->in_use--; return dvb_net_feed_stop(dev); @@ -1270,7 +1271,7 @@ static int dvb_net_stop(struct net_device *dev) static struct net_device_stats * dvb_net_get_stats(struct net_device *dev) { - return &((struct dvb_net_priv*) dev->priv)->stats; + return &((struct dvb_net_priv *) netdev_priv(dev))->stats; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) @@ -1346,7 +1347,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) dvbnet->device[if_num] = net; - priv = net->priv; + priv = netdev_priv(net); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) priv->net = net; #endif @@ -1386,7 +1387,7 @@ static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num) if (!dvbnet->state[num]) return -EINVAL; - priv = net->priv; + priv = netdev_priv(net); if (priv->in_use) return -EBUSY; @@ -1442,7 +1443,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file, netdev = dvbnet->device[dvbnetif->if_num]; - priv_data = netdev->priv; + priv_data = netdev_priv(netdev); dvbnetif->pid=priv_data->pid; dvbnetif->feedtype=priv_data->feedtype; break; @@ -1493,7 +1494,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file, netdev = dvbnet->device[dvbnetif->if_num]; - priv_data = netdev->priv; + priv_data = netdev_priv(netdev); dvbnetif->pid=priv_data->pid; break; } diff --git a/v4l/compat.h b/v4l/compat.h index 49c89ea2d..de192e8cf 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -339,6 +339,10 @@ usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) +#define netdev_priv(dev) (dev->priv) +#endif + /* * uninitialized_var() macro */ -- cgit v1.2.3 From 0142ec0942134ba65b471a134fcd3f7e13b9d53e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Dec 2008 22:25:09 -0200 Subject: A few kernel sync stuff From: Mauro Carvalho Chehab - b2c2 Kconfig: -git merge happened on a different order; - firmare/Makefile: Update from upstream kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/b2c2/Kconfig | 2 +- linux/firmware/Makefile | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/b2c2/Kconfig b/linux/drivers/media/dvb/b2c2/Kconfig index bd21c3bf2..a8c6249c4 100644 --- a/linux/drivers/media/dvb/b2c2/Kconfig +++ b/linux/drivers/media/dvb/b2c2/Kconfig @@ -13,8 +13,8 @@ config DVB_B2C2_FLEXCOP select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE - select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/linux/firmware/Makefile b/linux/firmware/Makefile index bc3dc8100..6554f2ea8 100644 --- a/linux/firmware/Makefile +++ b/linux/firmware/Makefile @@ -12,7 +12,7 @@ fw-external-y := $(subst ",,$(CONFIG_EXTRA_FIRMWARE)) # There are three cases to care about: # 1. Building kernel with CONFIG_FIRMWARE_IN_KERNEL=y -- $(fw-shipped-y) should # include the firmware files to include, according to .config -# 2. 'make modules_install', which will install firmware for modules, and +# 2. 'make modules_install', which will install firmware for modules, and # _also_ for the in-kernel drivers when CONFIG_FIRMWARE_IN_KERNEL=n # 3. 'make firmware_install', which installs all firmware, unconditionally. @@ -24,6 +24,9 @@ fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin +fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \ + cxgb3/t3c_psram-1.1.0.bin \ + cxgb3/t3fw-7.0.0.bin fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin fw-shipped-$(CONFIG_SMCTR) += tr_smctr.bin fw-shipped-$(CONFIG_SND_KORG1212) += korg/k1212.dsp -- cgit v1.2.3 From 8d2a805ffb2ab0d8b94f0607adca8b695369a2bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 12:20:26 +0900 Subject: backport commit af505b1eab55445e832bebbe5686f5bd22f1b717 From: Mauro Carvalho Chehab Author: Paul Mundt media: sh_mobile_ceu_camera: Add HAVE_CLK dependency. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 631112e28..19cf3b8f6 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -788,7 +788,7 @@ config VIDEO_PXA27x config VIDEO_SH_MOBILE_CEU tristate "SuperH Mobile CEU Interface driver" - depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA + depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK select VIDEOBUF_DMA_CONTIG ---help--- This is a v4l2 driver for the SuperH Mobile CEU Interface -- cgit v1.2.3 From 8f753ccc1d4da5939f7a6b792ca9d47e16024a01 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 08:58:36 +0100 Subject: stv06xx: Avoid having y unitialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén As pointed by gcc: drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c: In function ‘hdcs_set_size’: drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c:301: warning: ‘y’ may be used uninitialized in this function Signed-off-by: Erik Andrén Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c index 1cfe58504..14335a9e4 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c @@ -317,8 +317,10 @@ static int hdcs_set_size(struct sd *sd, y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2 + hdcs->array.top; - } else if (height > hdcs->array.height) { - height = hdcs->array.height; + } else { + if (height > hdcs->array.height) + height = hdcs->array.height; + y = hdcs->array.top + (hdcs->array.height - height) / 2; } -- cgit v1.2.3 From efe8d48c56888677c8f5986e3a0a1a8e3f7dd6b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Dec 2008 19:37:14 +0000 Subject: modify V4L documentation to be a valid XHTML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Németh Márton Modify Documentation/video4linux/API.html to be a valid XHTML 1.0 Strict. The result was verified using the http://validator.w3.org/ service. Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/API.html | 43 ++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/linux/Documentation/video4linux/API.html b/linux/Documentation/video4linux/API.html index afbe9ae7e..d749d41f6 100644 --- a/linux/Documentation/video4linux/API.html +++ b/linux/Documentation/video4linux/API.html @@ -1,16 +1,27 @@ -V4L API -

Video For Linux APIs

- - - -
- -V4L original API - -Obsoleted by V4L2 API -
- -V4L2 API - -Should be used for new projects -
+ + + + + V4L API + + +

Video For Linux APIs

+ + + + + + + + + +
+ V4L original API + + Obsoleted by V4L2 API +
+ V4L2 API + Should be used for new projects +
+ + -- cgit v1.2.3 From 652cff3226732d3592b00645a9adfdae7d78deb1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Dec 2008 02:01:14 +0000 Subject: dvb: remove deprecated use of RW_LOCK_UNLOCKED in frontends From: Steven Rostedt Impact: clean up RW_LOCK_UNLOCKED is deprecated. This patch replaces it with the __RW_LOCK_UNLOCKED(lock) macro. This change was a little trickier than others due to the macro being used in another macro that fills an array. Signed-off-by: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/drx397xD.c | 12 ++++++------ linux/drivers/media/dvb/frontends/drx397xD_fw.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/drx397xD.c b/linux/drivers/media/dvb/frontends/drx397xD.c index 7a2b2d461..48abee27c 100644 --- a/linux/drivers/media/dvb/frontends/drx397xD.c +++ b/linux/drivers/media/dvb/frontends/drx397xD.c @@ -40,7 +40,7 @@ static const char mod_name[] = "drx397xD"; #define F_SET_0D4h 2 enum fw_ix { -#define _FW_ENTRY(a, b) b +#define _FW_ENTRY(a, b, c) b #include "drx397xD_fw.h" }; @@ -73,11 +73,11 @@ static struct { int refcnt; const u8 *data[ARRAY_SIZE(blob_name)]; } fw[] = { -#define _FW_ENTRY(a, b) { \ - .name = a, \ - .file = 0, \ - .lock = RW_LOCK_UNLOCKED, \ - .refcnt = 0, \ +#define _FW_ENTRY(a, b, c) { \ + .name = a, \ + .file = 0, \ + .lock = __RW_LOCK_UNLOCKED(fw[c].lock), \ + .refcnt = 0, \ .data = { } } #include "drx397xD_fw.h" }; diff --git a/linux/drivers/media/dvb/frontends/drx397xD_fw.h b/linux/drivers/media/dvb/frontends/drx397xD_fw.h index 01de02a81..c8b44c1e8 100644 --- a/linux/drivers/media/dvb/frontends/drx397xD_fw.h +++ b/linux/drivers/media/dvb/frontends/drx397xD_fw.h @@ -18,8 +18,8 @@ */ #ifdef _FW_ENTRY - _FW_ENTRY("drx397xD.A2.fw", DRXD_FW_A2 = 0 ), - _FW_ENTRY("drx397xD.B1.fw", DRXD_FW_B1 ), + _FW_ENTRY("drx397xD.A2.fw", DRXD_FW_A2 = 0, DRXD_FW_A2 ), + _FW_ENTRY("drx397xD.B1.fw", DRXD_FW_B1, DRXD_FW_B1 ), #undef _FW_ENTRY #endif /* _FW_ENTRY */ -- cgit v1.2.3 From ff2201e0c9fe05a42a4ef6473a8b744a08f1f9cc Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 29 Dec 2008 20:27:30 -0500 Subject: em28xx: fix corrupted XCLK value From: Devin Heitmueller Correct problem introduced during the board refactoring where the XCLK frequency would get zero'd out. The sequence of events was as follows: em28xx_pre_card_setup() called em28xx_set_model() em28xx_set_model() would memcpy to dev->board configuration em28xx_pre_card_setup() would set the dev->board.xclk if not set em28xx_pre_card_setup() would set the XCLK register based on dev->board.xclk ... em28xx_card_setup() would call em28xx_set_model() em28xx_set_model() would memcpy to dev->board configuration (clearing out value of dev->board.xclk set in em28xx_pre_card_setup) ... em28xx_audio_analog_set() sets the XCLK register based on dev->board.xclk (which now contains zero) The change sets the default XCLK and I2C Clock fields in the board definition inside of em28xx_set_model() so that subsequent calls do not cause the values to be overwritten. Priority: high Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index a4ce360b1..40a85a88e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1472,6 +1472,17 @@ EXPORT_SYMBOL_GPL(em28xx_tuner_callback); static void inline em28xx_set_model(struct em28xx *dev) { memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board)); + + /* Those are the default values for the majority of boards + Use those values if not specified otherwise at boards entry + */ + if (!dev->board.xclk) + dev->board.xclk = EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ; + + if (!dev->board.i2c_speed) + dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_100_KHZ; } /* Since em28xx_pre_card_setup() requires a proper dev->model, @@ -1533,17 +1544,8 @@ void em28xx_pre_card_setup(struct em28xx *dev) if (rc >= 0) dev->reg_gpo = rc; - /* Those are the default values for the majority of boards - Use those values if not specified otherwise at boards entry - */ - if (!dev->board.xclk) - dev->board.xclk = EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ; - - if (!dev->board.i2c_speed) - dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ; - + /* Set the initial XCLK and I2C clock values based on the board + definition */ em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); msleep(50); -- cgit v1.2.3 From 82fa6fab36f911ab758e0ae4efaf3ba0b5d258ac Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 29 Dec 2008 20:34:35 -0500 Subject: em28xx: remove redundant Pinnacle Dazzle DVC 100 profile From: Devin Heitmueller The DVC 100 profile is redundant since we already have an existing identical profile named "Pinnacle Dazzle DVC 90/DVC 100" Priority: normal Signed-off-by: Devin Heitmueller --- linux/Documentation/video4linux/CARDLIST.em28xx | 1 - linux/drivers/media/video/em28xx/em28xx-cards.c | 14 -------------- linux/drivers/media/video/em28xx/em28xx.h | 1 - 3 files changed, 16 deletions(-) diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index 96b1eb8ac..79fd7f97a 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -27,7 +27,6 @@ 26 -> Hercules Smart TV USB 2.0 (em2820/em2840) 27 -> Pinnacle PCTV USB 2 (Philips FM1216ME) (em2820/em2840) 28 -> Leadtek Winfast USB II Deluxe (em2820/em2840) - 29 -> Pinnacle Dazzle DVC 100 (em2820/em2840) 30 -> Videology 20K14XUSB USB2.0 (em2820/em2840) 31 -> Usbgear VD204v9 (em2821) 32 -> Supercomp USB 2.0 TV (em2821) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 40a85a88e..09a42b24a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -352,20 +352,6 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, - [EM2820_BOARD_PINNACLE_DVC_100] = { - .name = "Pinnacle Dazzle DVC 100", - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { .name = "Videology 20K14XUSB USB2.0", .valid = EM28XX_BOARD_NOT_VALIDATED, diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 93c47f260..79bf87952 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -68,7 +68,6 @@ #define EM2820_BOARD_HERCULES_SMART_TV_USB2 26 #define EM2820_BOARD_PINNACLE_USB_2_FM1216ME 27 #define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28 -#define EM2820_BOARD_PINNACLE_DVC_100 29 #define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 #define EM2821_BOARD_USBGEAR_VD204 31 #define EM2821_BOARD_SUPERCOMP_USB_2 32 -- cgit v1.2.3 From 86a622ea545a87c684120263bce4b44449952550 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 29 Dec 2008 20:39:42 -0500 Subject: em28xx: remove worthless Pinnacle PCTV HD Mini 80e device profile From: Devin Heitmueller The Pinnacle 80e cannot be supported since Micronas yanked their driver support for the drx-j chipset at the last minute. Remove the device profile since it cannot work without the drx driver and it being there is only likely to confuse people into thinking the device is supported but not working. Priority: normal Signed-off-by: Devin Heitmueller --- linux/Documentation/video4linux/CARDLIST.em28xx | 1 - linux/drivers/media/video/em28xx/em28xx-cards.c | 34 ------------------------- linux/drivers/media/video/em28xx/em28xx.h | 1 - 3 files changed, 36 deletions(-) diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index 79fd7f97a..75bded8a4 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -56,6 +56,5 @@ 56 -> Pinnacle Hybrid Pro (2) (em2882) [2304:0226] 57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316] 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] - 59 -> Pinnacle PCTV HD Mini (em2874) [2304:023f] 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] 61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 09a42b24a..211305c18 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -123,17 +123,6 @@ static struct em28xx_reg_seq default_tuner_gpio[] = { { -1, -1, -1, -1}, }; -/* Pinnacle PCTV HD Mini (80e) GPIOs - 0-5: not used - 6: demod reset, active low - 7: LED on, active high */ -static struct em28xx_reg_seq em2874_pinnacle_80e_digital[] = { - {EM28XX_R06_I2C_CLK, 0x45, 0xff, 10}, /*400 KHz*/ - {EM2874_R80_GPIO, 0x80, 0xff, 100},/*Demod reset*/ - {EM2874_R80_GPIO, 0xc0, 0xff, 10}, - { -1, -1, -1, -1}, -}; - /* * Board definitions */ @@ -1293,27 +1282,6 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, - - /* em2874 tuners are DVB only */ - - [EM2874_BOARD_PINNACLE_PCTV_80E] = { - .name = "Pinnacle PCTV HD Mini", - .tuner_type = TUNER_ABSENT, - .has_dvb = 1, - .dvb_gpio = em2874_pinnacle_80e_digital, - .ir_codes = ir_codes_pinnacle_pctv_hd, - .decoder = EM28XX_NODECODER, - .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | - EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_FREQ_400_KHZ, -#ifdef DJH_DEBUG - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - } }, -#endif - }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1411,8 +1379,6 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO }, { USB_DEVICE(0x2304, 0x0227), .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, - { USB_DEVICE(0x2304, 0x023f), - .driver_info = EM2874_BOARD_PINNACLE_PCTV_80E }, { USB_DEVICE(0x0413, 0x6023), .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, { USB_DEVICE(0x093b, 0xa005), diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 79bf87952..fb88c7f64 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -97,7 +97,6 @@ #define EM2882_BOARD_PINNACLE_HYBRID_PRO 56 #define EM2883_BOARD_KWORLD_HYBRID_A316 57 #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 -#define EM2874_BOARD_PINNACLE_PCTV_80E 59 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 -- cgit v1.2.3 From 93f9869a5b7ed2fd7ad99619b99212fc8d352f47 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 29 Dec 2008 20:43:55 -0500 Subject: em28xx: don't load em28xx-alsa for em2870 based devices From: Devin Heitmueller Like the em2874, the em2870 does not have any analog support, so don't bother loading the em28xx-alsa module. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 1183519eb..156ebe677 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -465,7 +465,7 @@ int em28xx_audio_setup(struct em28xx *dev) int vid1, vid2, feat, cfg; u32 vid; - if (dev->chip_id == CHIP_ID_EM2874) { + if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874) { /* Digital only device - don't load any alsa module */ dev->audio_mode.has_audio = 0; dev->has_audio_class = 0; -- cgit v1.2.3 From 8811c386c4bb95b9d444b7df58fb45fa10736e97 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 29 Dec 2008 20:52:37 -0500 Subject: em28xx: fix reversed definitions of I2S audio modes From: Devin Heitmueller Noticed when doing the audio support for the Pinnacle PCTV HD Ultimate 808e that the modes were incorrect (the 808e uses I2S in 5 sample mode) Thanks for Ray Lu from Empia for providing the em2860/em2880 datasheet. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index a459b7c6a..2e8767583 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -22,8 +22,8 @@ /* em28xx Chip Configuration 0x00 */ #define EM28XX_CHIPCFG_VENDOR_AUDIO 0x80 #define EM28XX_CHIPCFG_I2S_VOLUME_CAPABLE 0x40 -#define EM28XX_CHIPCFG_I2S_3_SAMPRATES 0x30 -#define EM28XX_CHIPCFG_I2S_5_SAMPRATES 0x20 +#define EM28XX_CHIPCFG_I2S_5_SAMPRATES 0x30 +#define EM28XX_CHIPCFG_I2S_3_SAMPRATES 0x20 #define EM28XX_CHIPCFG_AC97 0x10 #define EM28XX_CHIPCFG_AUDIOMASK 0x30 -- cgit v1.2.3 From 74ecd54caba26722441cfa006deb299bfa1ee6b8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 00:18:31 -0200 Subject: af9013: Fix gcc false warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Mauro Carvalho Chehab drivers/media/dvb/frontends/af9013.c: In function ‘af9013_set_coeff’: drivers/media/dvb/frontends/af9013.c:231: warning: ‘ns_coeff2_8k’ may be used uninitialized in this function drivers/media/dvb/frontends/af9013.c:230: warning: ‘ns_coeff2_2k’ may be used uninitialized in this function drivers/media/dvb/frontends/af9013.c:229: warning: ‘ns_coeff1_8193nu’ may be used uninitialized in this function drivers/media/dvb/frontends/af9013.c:228: warning: ‘ns_coeff1_8192nu’ may be used uninitialized in this function drivers/media/dvb/frontends/af9013.c:227: warning: ‘ns_coeff1_8191nu’ may be used uninitialized in this function drivers/media/dvb/frontends/af9013.c:226: warning: ‘ns_coeff1_2048nu’ may be used uninitialized in this function drivers/media/dvb/frontends/af9013.c: In function ‘af9013_update_snr’: drivers/media/dvb/frontends/af9013.c:1012: warning: ‘snr_table’ may be used uninitialized in this function Priority: normal Signed-off-by: Mauro Carvalho Chehab CC: Antti Palosaari --- linux/drivers/media/dvb/frontends/af9013.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/af9013.c b/linux/drivers/media/dvb/frontends/af9013.c index 692b68a9e..b2b50fb4c 100644 --- a/linux/drivers/media/dvb/frontends/af9013.c +++ b/linux/drivers/media/dvb/frontends/af9013.c @@ -223,12 +223,12 @@ static int af9013_set_coeff(struct af9013_state *state, fe_bandwidth_t bw) int ret = 0; u8 i = 0; u8 buf[24]; - u32 ns_coeff1_2048nu; - u32 ns_coeff1_8191nu; - u32 ns_coeff1_8192nu; - u32 ns_coeff1_8193nu; - u32 ns_coeff2_2k; - u32 ns_coeff2_8k; + u32 uninitialized_var(ns_coeff1_2048nu); + u32 uninitialized_var(ns_coeff1_8191nu); + u32 uninitialized_var(ns_coeff1_8192nu); + u32 uninitialized_var(ns_coeff1_8193nu); + u32 uninitialized_var(ns_coeff2_2k); + u32 uninitialized_var(ns_coeff2_8k); deb_info("%s: adc_clock:%d bw:%d\n", __func__, state->config.adc_clock, bw); @@ -1009,7 +1009,7 @@ static int af9013_update_snr(struct dvb_frontend *fe) int ret; u8 buf[3], i, len; u32 quant = 0; - struct snr_table *snr_table; + struct snr_table *uninitialized_var(snr_table); /* check if quantizer ready (for snr) */ ret = af9013_read_reg_bits(state, 0xd2e1, 3, 1, &buf[0]); -- cgit v1.2.3 From 87fe61efe9940db733854a3b4f80401de8eec3fb Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 29 Dec 2008 21:34:37 -0500 Subject: em28xx: expand output formats available From: Devin Heitmueller Add additional output formats, which will be useful for the Pinnacle PCTV Ultimate 880e integration with the saa7136. Thanks to Ray Lu from Empia for providing the em2860/em2880 datasheet. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-reg.h | 13 +++++++++++++ linux/drivers/media/video/em28xx/em28xx-video.c | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 2e8767583..65dcb91bd 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -97,6 +97,19 @@ #define EM28XX_R26_COMPR 0x26 #define EM28XX_R27_OUTFMT 0x27 +/* em28xx Output Format Register (0x27) */ +#define EM28XX_OUTFMT_RGB_8_RGRG 0x00 +#define EM28XX_OUTFMT_RGB_8_GRGR 0x01 +#define EM28XX_OUTFMT_RGB_8_GBGB 0x02 +#define EM28XX_OUTFMT_RGB_8_BGBG 0x03 +#define EM28XX_OUTFMT_RGB_16_656 0x04 +#define EM28XX_OUTFMT_RGB_8_BAYER 0x08 /* Pattern in Reg 0x10[1-0] */ +#define EM28XX_OUTFMT_YUV211 0x10 +#define EM28XX_OUTFMT_YUV422_Y0UY1V 0x14 +#define EM28XX_OUTFMT_YUV422_Y1UY0V 0x15 +#define EM28XX_OUTFMT_YUV411 0x18 + + #define EM28XX_R28_XMIN 0x28 #define EM28XX_R29_XMAX 0x29 #define EM28XX_R2A_YMIN 0x2a diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 8be7aadac..fe6b6f142 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -93,7 +93,7 @@ static struct em28xx_fmt format[] = { .name = "16bpp YUY2, 4:2:2, packed", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, - .reg = 0x14, + .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, }, }; -- cgit v1.2.3 From e3acd26b88b26b4b6e00b890278c72a66a6b7c10 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 00:36:40 -0200 Subject: Fix compilation for kernels older than 2.6.28 From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l/compat.h | 4 ++-- v4l/scripts/make_config_compat.pl | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/v4l/compat.h b/v4l/compat.h index de192e8cf..22281f6f9 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -339,8 +339,8 @@ usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) -#define netdev_priv(dev) (dev->priv) +#ifdef NEED_NETDEV_PRIV +#define netdev_priv(dev) ((dev)->priv) #endif /* diff --git a/v4l/scripts/make_config_compat.pl b/v4l/scripts/make_config_compat.pl index 3a8bdd81e..8fb7a9441 100755 --- a/v4l/scripts/make_config_compat.pl +++ b/v4l/scripts/make_config_compat.pl @@ -197,6 +197,25 @@ sub check_algo_control() close INNET; } +sub check_net_dev() +{ + my $file = "$kdir/include/linux/netdevice.h"; + my $need_compat = 1; + + open INNET, "<$file" or die "File not found: $file"; + while () { + if (m/netdev_priv/) { + $need_compat = 0; + last; + } + } + + if ($need_compat) { + $out.= "\n#define NEED_NETDEV_PRIV 1\n"; + } + close INNET; +} + sub check_other_dependencies() { check_spin_lock(); @@ -209,6 +228,7 @@ sub check_other_dependencies() check_proc_create(); check_pcm_lock(); check_algo_control(); + check_net_dev(); } # Do the basic rules -- cgit v1.2.3 From b368ca4c3ea78c6d07ee807cbf4f33913adfbc30 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 00:44:20 -0200 Subject: zoran: fix warning for a variable not used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Mauro Carvalho Chehab Fix this warning: drivers/media/video/zoran/zoran_card.c:156: warning: ‘zr36067_pci_tbl’ defined but not used Currently, zoran driver relies on a find routine that doesn't use the pci table. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zoran/zoran_card.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index d5026ae51..639fa55e6 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -154,12 +154,14 @@ MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver"); MODULE_AUTHOR("Serguei Miridonov"); MODULE_LICENSE("GPL"); +#if 0 static struct pci_device_id zr36067_pci_tbl[] = { {PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0} }; MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); +#endif int zoran_num; /* number of Buzs in use */ struct zoran *zoran[BUZ_MAX]; -- cgit v1.2.3 From 9432f298ddeb3d9fd4fa7904e6ec802962e002ff Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 29 Dec 2008 22:17:09 -0500 Subject: em28xx: Don't do AC97 vendor detection for i2s audio devices From: Devin Heitmueller The current code was trying to query the AC97 registers for the vendor information even if it was clearly not a AC97 audio device (resulting in errors in the dmesg output). This was due to a bug in the way we did the check. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 156ebe677..65bc5c8a9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -497,7 +497,8 @@ int em28xx_audio_setup(struct em28xx *dev) dev->audio_mode.i2s_5rates = 1; } - if (!(cfg & EM28XX_CHIPCFG_AC97)) { + if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) != EM28XX_CHIPCFG_AC97) { + /* Skip the code that does AC97 vendor detection */ dev->audio_mode.ac97 = EM28XX_NO_AC97; goto init_audio; } -- cgit v1.2.3 From 78ac8722bb5ff14a0aaa0bd4902a80ca57e20a32 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2008 18:37:43 +0100 Subject: v4l2-compat-ioctl32: remove dependency on videodev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-compat-ioctl32.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index c9cb73a06..ef9ece0d3 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -1070,8 +1070,9 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) break; #endif default: - v4l_print_ioctl("compat_ioctl32", cmd); - printk(KERN_CONT "\n"); + printk(KERN_WARNING "compat_ioctl32: " + "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", + _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); break; } return ret; -- cgit v1.2.3 From 570ee61c1b4f1c0b8d89cd799676f9b7dde51c24 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Dec 2008 13:13:11 +0100 Subject: v4l2-framework: use correct comment style. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index eeae76c22..ba9344294 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -410,7 +410,7 @@ for you. err = video_register_device(vdev, VFL_TYPE_GRABBER, -1); if (err) { - video_device_release(vdev); // or kfree(my_vdev); + video_device_release(vdev); /* or kfree(my_vdev); */ return err; } -- cgit v1.2.3 From d1e126d1421066319ebc9da9c8084c425cfdc762 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2008 16:17:23 +0100 Subject: v4l2 doc: set v4l2_dev instead of parent. From: Hans Verkuil Update the documentation now that the v4l2_dev field is in. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index ba9344294..38d054aa0 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -390,8 +390,7 @@ allocated memory. You should also set these fields: -- parent: set to the parent device (same device as was used to register - v4l2_device). +- v4l2_dev: set to the v4l2_device parent device. - name: set to something descriptive and unique. - fops: set to the file_operations struct. - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance @@ -516,5 +515,4 @@ void *video_drvdata(struct file *file); You can go from a video_device struct to the v4l2_device struct using: -struct v4l2_device *v4l2_dev = dev_get_drvdata(vdev->parent); - +struct v4l2_device *v4l2_dev = vdev->v4l2_dev; -- cgit v1.2.3 From c91fcc9b460397a85a6bd1d8f441d8da5abac415 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Dec 2008 10:58:20 +0100 Subject: v4l2: introduce v4l2_file_operations. From: Hans Verkuil Introduce a struct v4l2_file_operations for v4l2 drivers. Remove the unnecessary inode argument. Move compat32 handling (and llseek) into the v4l2-dev core: this is now handled in the v4l2 core and no longer in the drivers themselves. Note that this changeset reverts an earlier patch that changed the return type of__video_ioctl2 from int to long. This change will be reinstated later in a much improved version. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_fops.c | 21 +++++++------- linux/drivers/media/dvb/ttpci/av7110_v4l.c | 2 +- linux/drivers/media/radio/dsbr100.c | 14 ++++------ linux/drivers/media/radio/radio-aimslab.c | 10 ++----- linux/drivers/media/radio/radio-aztech.c | 10 ++----- linux/drivers/media/radio/radio-cadet.c | 10 ++----- linux/drivers/media/radio/radio-gemtek-pci.c | 10 ++----- linux/drivers/media/radio/radio-gemtek.c | 10 ++----- linux/drivers/media/radio/radio-maestro.c | 10 ++----- linux/drivers/media/radio/radio-maxiradio.c | 10 ++----- linux/drivers/media/radio/radio-mr800.c | 14 ++++------ linux/drivers/media/radio/radio-rtrack2.c | 10 ++----- linux/drivers/media/radio/radio-sf16fmi.c | 10 ++----- linux/drivers/media/radio/radio-sf16fmr2.c | 10 ++----- linux/drivers/media/radio/radio-si470x.c | 10 ++----- linux/drivers/media/radio/radio-terratec.c | 10 ++----- linux/drivers/media/radio/radio-trust.c | 10 ++----- linux/drivers/media/radio/radio-typhoon.c | 10 ++----- linux/drivers/media/radio/radio-zoltrix.c | 10 ++----- linux/drivers/media/video/arv.c | 12 +++----- linux/drivers/media/video/bt8xx/bttv-driver.c | 20 ++++++-------- linux/drivers/media/video/bw-qcam.c | 12 +++----- linux/drivers/media/video/c-qcam.c | 12 +++----- linux/drivers/media/video/cafe_ccic.c | 9 +++--- linux/drivers/media/video/cpia.c | 12 +++----- linux/drivers/media/video/cpia2/cpia2_v4l.c | 12 +++----- linux/drivers/media/video/cx18/cx18-fileops.c | 6 ++-- linux/drivers/media/video/cx18/cx18-fileops.h | 4 +-- linux/drivers/media/video/cx18/cx18-ioctl.c | 4 +-- linux/drivers/media/video/cx18/cx18-ioctl.h | 2 +- linux/drivers/media/video/cx18/cx18-streams.c | 13 ++------- linux/drivers/media/video/cx23885/cx23885-417.c | 10 +++---- linux/drivers/media/video/cx23885/cx23885-video.c | 14 ++++------ linux/drivers/media/video/cx88/cx88-blackbird.c | 13 ++++----- linux/drivers/media/video/cx88/cx88-mpeg.c | 3 +- linux/drivers/media/video/cx88/cx88-video.c | 14 ++++------ linux/drivers/media/video/cx88/cx88.h | 2 +- linux/drivers/media/video/em28xx/em28xx-core.c | 3 +- linux/drivers/media/video/em28xx/em28xx-video.c | 16 ++++------- linux/drivers/media/video/em28xx/em28xx.h | 2 +- linux/drivers/media/video/et61x251/et61x251_core.c | 18 +++++------- linux/drivers/media/video/gspca/gspca.c | 12 +++----- linux/drivers/media/video/ivtv/ivtv-fileops.c | 4 +-- linux/drivers/media/video/ivtv/ivtv-fileops.h | 4 +-- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 2 +- linux/drivers/media/video/ivtv/ivtv-streams.c | 8 ++---- linux/drivers/media/video/meye.c | 10 ++----- linux/drivers/media/video/omap24xxcam.c | 9 +++--- linux/drivers/media/video/ov511.c | 12 +++----- linux/drivers/media/video/pms.c | 12 +++----- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 9 +++--- linux/drivers/media/video/pwc/pwc-if.c | 18 +++++------- linux/drivers/media/video/s2255drv.c | 12 ++++---- linux/drivers/media/video/saa5246a.c | 9 +++--- linux/drivers/media/video/saa5249.c | 12 +++----- .../drivers/media/video/saa7134/saa7134-empress.c | 9 +++--- linux/drivers/media/video/saa7134/saa7134-video.c | 14 ++++------ linux/drivers/media/video/se401.c | 12 +++----- linux/drivers/media/video/sn9c102/sn9c102_core.c | 18 +++++------- linux/drivers/media/video/soc_camera.c | 7 ++--- linux/drivers/media/video/stk-webcam.c | 10 ++----- linux/drivers/media/video/stradis.c | 12 +++----- linux/drivers/media/video/stv680.c | 12 +++----- linux/drivers/media/video/usbvideo/usbvideo.c | 18 +++++------- linux/drivers/media/video/usbvideo/vicam.c | 12 +++----- .../media/video/usbvision/usbvision-video.c | 26 +++++++----------- linux/drivers/media/video/uvc/uvc_v4l2.c | 10 +++---- linux/drivers/media/video/uvc/uvcvideo.h | 2 +- linux/drivers/media/video/v4l2-compat-ioctl32.c | 7 +---- linux/drivers/media/video/v4l2-dev.c | 25 ++++------------- linux/drivers/media/video/v4l2-ioctl.c | 9 +----- linux/drivers/media/video/vino.c | 9 +++--- linux/drivers/media/video/vivi.c | 12 ++++---- linux/drivers/media/video/w9966.c | 14 ++++------ linux/drivers/media/video/w9968cf.c | 32 ++++++++++------------ linux/drivers/media/video/zc0301/zc0301_core.c | 18 +++++------- linux/drivers/media/video/zoran/zoran_driver.c | 21 +++++--------- linux/drivers/media/video/zr364xx.c | 7 ++--- linux/include/media/saa7146_vv.h | 2 +- linux/include/media/v4l2-dev.h | 15 +++++++++- linux/include/media/v4l2-ioctl.h | 15 ++-------- linux/include/sound/tea575x-tuner.h | 2 +- linux/sound/i2c/other/tea575x-tuner.c | 6 ++-- 83 files changed, 331 insertions(+), 572 deletions(-) diff --git a/linux/drivers/media/common/saa7146_fops.c b/linux/drivers/media/common/saa7146_fops.c index cd4f95860..b0e86eebb 100644 --- a/linux/drivers/media/common/saa7146_fops.c +++ b/linux/drivers/media/common/saa7146_fops.c @@ -193,9 +193,9 @@ void saa7146_buffer_timeout(unsigned long data) /********************************************************************************/ /* file operations */ -static int fops_open(struct inode *inode, struct file *file) +static int fops_open(struct file *file) { - unsigned int minor = iminor(inode); + unsigned int minor = video_devdata(file)->minor; struct saa7146_dev *h = NULL, *dev = NULL; struct list_head *list; struct saa7146_fh *fh = NULL; @@ -203,7 +203,7 @@ static int fops_open(struct inode *inode, struct file *file) enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor)); + DEB_EE(("file:%p, minor:%d\n", file, minor)); if (mutex_lock_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; @@ -256,7 +256,7 @@ static int fops_open(struct inode *inode, struct file *file) if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) result = saa7146_vbi_uops.open(dev,file); if (dev->ext_vv_data->vbi_fops.open) - dev->ext_vv_data->vbi_fops.open(inode, file); + dev->ext_vv_data->vbi_fops.open(file); } else { DEB_S(("initializing video...\n")); result = saa7146_video_uops.open(dev,file); @@ -281,12 +281,12 @@ out: return result; } -static int fops_release(struct inode *inode, struct file *file) +static int fops_release(struct file *file) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; - DEB_EE(("inode:%p, file:%p\n",inode,file)); + DEB_EE(("file:%p\n", file)); if (mutex_lock_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; @@ -295,7 +295,7 @@ static int fops_release(struct inode *inode, struct file *file) if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) saa7146_vbi_uops.release(dev,file); if (dev->ext_vv_data->vbi_fops.release) - dev->ext_vv_data->vbi_fops.release(inode, file); + dev->ext_vv_data->vbi_fops.release(file); } else { saa7146_video_uops.release(dev,file); } @@ -309,10 +309,10 @@ static int fops_release(struct inode *inode, struct file *file) return 0; } -static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { /* - DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg)); + DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg)); */ return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl); } @@ -417,7 +417,7 @@ static ssize_t fops_write(struct file *file, const char __user *data, size_t cou } } -static const struct file_operations video_fops = +static const struct v4l2_file_operations video_fops = { .owner = THIS_MODULE, .open = fops_open, @@ -427,7 +427,6 @@ static const struct file_operations video_fops = .poll = fops_poll, .mmap = fops_mmap, .ioctl = fops_ioctl, - .llseek = no_llseek, }; static void vv_callback(struct saa7146_dev *dev, unsigned long status) diff --git a/linux/drivers/media/dvb/ttpci/av7110_v4l.c b/linux/drivers/media/dvb/ttpci/av7110_v4l.c index b4a0cc5dc..315ba6fa0 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c @@ -567,7 +567,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) return 0; } -static int av7110_vbi_reset(struct inode *inode, struct file *file) +static int av7110_vbi_reset(struct file *file) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index 9c8e96f81..bb3f5a855 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -155,8 +155,8 @@ devices, that would be 76 and 91. */ static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id); static void usb_dsbr100_disconnect(struct usb_interface *intf); -static int usb_dsbr100_open(struct inode *inode, struct file *file); -static int usb_dsbr100_close(struct inode *inode, struct file *file); +static int usb_dsbr100_open(struct file *file); +static int usb_dsbr100_close(struct file *file); static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message); static int usb_dsbr100_resume(struct usb_interface *intf); @@ -569,7 +569,7 @@ static int vidioc_s_audio(struct file *file, void *priv, return 0; } -static int usb_dsbr100_open(struct inode *inode, struct file *file) +static int usb_dsbr100_open(struct file *file) { struct dsbr100_device *radio = video_drvdata(file); int retval; @@ -596,7 +596,7 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file) return 0; } -static int usb_dsbr100_close(struct inode *inode, struct file *file) +static int usb_dsbr100_close(struct file *file) { struct dsbr100_device *radio = video_drvdata(file); int retval; @@ -656,15 +656,11 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev) } /* File system interface */ -static const struct file_operations usb_dsbr100_fops = { +static const struct v4l2_file_operations usb_dsbr100_fops = { .owner = THIS_MODULE, .open = usb_dsbr100_open, .release = usb_dsbr100_close, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 4f3886097..384aa928f 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -375,26 +375,22 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct rt_device rtrack_unit; -static int rtrack_exclusive_open(struct inode *inode, struct file *file) +static int rtrack_exclusive_open(struct file *file) { return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0; } -static int rtrack_exclusive_release(struct inode *inode, struct file *file) +static int rtrack_exclusive_release(struct file *file) { clear_bit(0, &rtrack_unit.in_use); return 0; } -static const struct file_operations rtrack_fops = { +static const struct v4l2_file_operations rtrack_fops = { .owner = THIS_MODULE, .open = rtrack_exclusive_open, .release = rtrack_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index 9ce1908ac..d4d5babcd 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -339,26 +339,22 @@ static int vidioc_s_ctrl (struct file *file, void *priv, static struct az_device aztech_unit; -static int aztech_exclusive_open(struct inode *inode, struct file *file) +static int aztech_exclusive_open(struct file *file) { return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0; } -static int aztech_exclusive_release(struct inode *inode, struct file *file) +static int aztech_exclusive_release(struct file *file) { clear_bit(0, &aztech_unit.in_use); return 0; } -static const struct file_operations aztech_fops = { +static const struct v4l2_file_operations aztech_fops = { .owner = THIS_MODULE, .open = aztech_exclusive_open, .release = aztech_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops aztech_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index d05141fd9..7425aef88 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -559,7 +559,7 @@ static int vidioc_s_audio(struct file *file, void *priv, } static int -cadet_open(struct inode *inode, struct file *file) +cadet_open(struct file *file) { users++; if (1 == users) init_waitqueue_head(&read_queue); @@ -567,7 +567,7 @@ cadet_open(struct inode *inode, struct file *file) } static int -cadet_release(struct inode *inode, struct file *file) +cadet_release(struct file *file) { users--; if (0 == users){ @@ -587,17 +587,13 @@ cadet_poll(struct file *file, struct poll_table_struct *wait) } -static const struct file_operations cadet_fops = { +static const struct v4l2_file_operations cadet_fops = { .owner = THIS_MODULE, .open = cadet_open, .release = cadet_release, .read = cadet_read, .ioctl = video_ioctl2, .poll = cadet_poll, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops cadet_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-gemtek-pci.c b/linux/drivers/media/radio/radio-gemtek-pci.c index 06a91be87..7edd3e594 100644 --- a/linux/drivers/media/radio/radio-gemtek-pci.c +++ b/linux/drivers/media/radio/radio-gemtek-pci.c @@ -359,26 +359,22 @@ MODULE_DEVICE_TABLE( pci, gemtek_pci_id ); static int mx = 1; -static int gemtek_pci_exclusive_open(struct inode *inode, struct file *file) +static int gemtek_pci_exclusive_open(struct file *file) { return test_and_set_bit(0, &in_use) ? -EBUSY : 0; } -static int gemtek_pci_exclusive_release(struct inode *inode, struct file *file) +static int gemtek_pci_exclusive_release(struct file *file) { clear_bit(0, &in_use); return 0; } -static const struct file_operations gemtek_pci_fops = { +static const struct v4l2_file_operations gemtek_pci_fops = { .owner = THIS_MODULE, .open = gemtek_pci_exclusive_open, .release = gemtek_pci_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-gemtek.c b/linux/drivers/media/radio/radio-gemtek.c index 5dbd342bf..a1ae890c8 100644 --- a/linux/drivers/media/radio/radio-gemtek.c +++ b/linux/drivers/media/radio/radio-gemtek.c @@ -395,26 +395,22 @@ static struct v4l2_queryctrl radio_qctrl[] = { } }; -static int gemtek_exclusive_open(struct inode *inode, struct file *file) +static int gemtek_exclusive_open(struct file *file) { return test_and_set_bit(0, &in_use) ? -EBUSY : 0; } -static int gemtek_exclusive_release(struct inode *inode, struct file *file) +static int gemtek_exclusive_release(struct file *file) { clear_bit(0, &in_use); return 0; } -static const struct file_operations gemtek_fops = { +static const struct v4l2_file_operations gemtek_fops = { .owner = THIS_MODULE, .open = gemtek_exclusive_open, .release = gemtek_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek }; static int vidioc_querycap(struct file *file, void *priv, diff --git a/linux/drivers/media/radio/radio-maestro.c b/linux/drivers/media/radio/radio-maestro.c index 326405d3b..7442be614 100644 --- a/linux/drivers/media/radio/radio-maestro.c +++ b/linux/drivers/media/radio/radio-maestro.c @@ -80,12 +80,12 @@ static unsigned long in_use; static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -static int maestro_exclusive_open(struct inode *inode, struct file *file) +static int maestro_exclusive_open(struct file *file) { return test_and_set_bit(0, &in_use) ? -EBUSY : 0; } -static int maestro_exclusive_release(struct inode *inode, struct file *file) +static int maestro_exclusive_release(struct file *file) { clear_bit(0, &in_use); return 0; @@ -111,15 +111,11 @@ static struct pci_driver maestro_r_driver = { .remove = __devexit_p(maestro_remove), }; -static const struct file_operations maestro_fops = { +static const struct v4l2_file_operations maestro_fops = { .owner = THIS_MODULE, .open = maestro_exclusive_open, .release = maestro_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; struct radio_device { diff --git a/linux/drivers/media/radio/radio-maxiradio.c b/linux/drivers/media/radio/radio-maxiradio.c index 4aea352cb..cb9d07bc7 100644 --- a/linux/drivers/media/radio/radio-maxiradio.c +++ b/linux/drivers/media/radio/radio-maxiradio.c @@ -101,26 +101,22 @@ static unsigned long in_use; #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) -static int maxiradio_exclusive_open(struct inode *inode, struct file *file) +static int maxiradio_exclusive_open(struct file *file) { return test_and_set_bit(0, &in_use) ? -EBUSY : 0; } -static int maxiradio_exclusive_release(struct inode *inode, struct file *file) +static int maxiradio_exclusive_release(struct file *file) { clear_bit(0, &in_use); return 0; } -static const struct file_operations maxiradio_fops = { +static const struct v4l2_file_operations maxiradio_fops = { .owner = THIS_MODULE, .open = maxiradio_exclusive_open, .release = maxiradio_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct radio_device diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index 7683af18d..6b1794989 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -128,8 +128,8 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int usb_amradio_probe(struct usb_interface *intf, const struct usb_device_id *id); static void usb_amradio_disconnect(struct usb_interface *intf); -static int usb_amradio_open(struct inode *inode, struct file *file); -static int usb_amradio_close(struct inode *inode, struct file *file); +static int usb_amradio_open(struct file *file); +static int usb_amradio_close(struct file *file); static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message); static int usb_amradio_resume(struct usb_interface *intf); @@ -503,7 +503,7 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) } /* open device - amradio_start() and amradio_setfreq() */ -static int usb_amradio_open(struct inode *inode, struct file *file) +static int usb_amradio_open(struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); @@ -528,7 +528,7 @@ static int usb_amradio_open(struct inode *inode, struct file *file) } /*close device */ -static int usb_amradio_close(struct inode *inode, struct file *file) +static int usb_amradio_close(struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); int retval; @@ -575,15 +575,11 @@ static int usb_amradio_resume(struct usb_interface *intf) } /* File system interface */ -static const struct file_operations usb_amradio_fops = { +static const struct v4l2_file_operations usb_amradio_fops = { .owner = THIS_MODULE, .open = usb_amradio_open, .release = usb_amradio_close, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-rtrack2.c b/linux/drivers/media/radio/radio-rtrack2.c index 72413df42..fa9e243c8 100644 --- a/linux/drivers/media/radio/radio-rtrack2.c +++ b/linux/drivers/media/radio/radio-rtrack2.c @@ -281,26 +281,22 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct rt_device rtrack2_unit; -static int rtrack2_exclusive_open(struct inode *inode, struct file *file) +static int rtrack2_exclusive_open(struct file *file) { return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0; } -static int rtrack2_exclusive_release(struct inode *inode, struct file *file) +static int rtrack2_exclusive_release(struct file *file) { clear_bit(0, &rtrack2_unit.in_use); return 0; } -static const struct file_operations rtrack2_fops = { +static const struct v4l2_file_operations rtrack2_fops = { .owner = THIS_MODULE, .open = rtrack2_exclusive_open, .release = rtrack2_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index 20326e7a5..3cce0afb4 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -281,26 +281,22 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct fmi_device fmi_unit; -static int fmi_exclusive_open(struct inode *inode, struct file *file) +static int fmi_exclusive_open(struct file *file) { return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0; } -static int fmi_exclusive_release(struct inode *inode, struct file *file) +static int fmi_exclusive_release(struct file *file) { clear_bit(0, &fmi_unit.in_use); return 0; } -static const struct file_operations fmi_fops = { +static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, .open = fmi_exclusive_open, .release = fmi_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops fmi_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index f5aebc9da..69a28d1ff 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -397,26 +397,22 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct fmr2_device fmr2_unit; -static int fmr2_exclusive_open(struct inode *inode, struct file *file) +static int fmr2_exclusive_open(struct file *file) { return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0; } -static int fmr2_exclusive_release(struct inode *inode, struct file *file) +static int fmr2_exclusive_release(struct file *file) { clear_bit(0, &fmr2_unit.in_use); return 0; } -static const struct file_operations fmr2_fops = { +static const struct v4l2_file_operations fmr2_fops = { .owner = THIS_MODULE, .open = fmr2_exclusive_open, .release = fmr2_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops fmr2_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 5d6237b6d..82c115c18 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1080,7 +1080,7 @@ static unsigned int si470x_fops_poll(struct file *file, /* * si470x_fops_open - file open */ -static int si470x_fops_open(struct inode *inode, struct file *file) +static int si470x_fops_open(struct file *file) { struct si470x_device *radio = video_drvdata(file); int retval; @@ -1110,7 +1110,7 @@ done: /* * si470x_fops_release - file release */ -static int si470x_fops_release(struct inode *inode, struct file *file) +static int si470x_fops_release(struct file *file) { struct si470x_device *radio = video_drvdata(file); int retval = 0; @@ -1152,15 +1152,11 @@ done: /* * si470x_fops - file operations interface */ -static const struct file_operations si470x_fops = { +static const struct v4l2_file_operations si470x_fops = { .owner = THIS_MODULE, - .llseek = no_llseek, .read = si470x_fops_read, .poll = si470x_fops_poll, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .open = si470x_fops_open, .release = si470x_fops_release, }; diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index 3066b08f0..1c2b4db2d 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -353,26 +353,22 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct tt_device terratec_unit; -static int terratec_exclusive_open(struct inode *inode, struct file *file) +static int terratec_exclusive_open(struct file *file) { return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0; } -static int terratec_exclusive_release(struct inode *inode, struct file *file) +static int terratec_exclusive_release(struct file *file) { clear_bit(0, &terratec_unit.in_use); return 0; } -static const struct file_operations terratec_fops = { +static const struct v4l2_file_operations terratec_fops = { .owner = THIS_MODULE, .open = terratec_exclusive_open, .release = terratec_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops terratec_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index a334ce27e..5ce7a9d1d 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -341,26 +341,22 @@ static int vidioc_s_audio(struct file *file, void *priv, return 0; } -static int trust_exclusive_open(struct inode *inode, struct file *file) +static int trust_exclusive_open(struct file *file) { return test_and_set_bit(0, &in_use) ? -EBUSY : 0; } -static int trust_exclusive_release(struct inode *inode, struct file *file) +static int trust_exclusive_release(struct file *file) { clear_bit(0, &in_use); return 0; } -static const struct file_operations trust_fops = { +static const struct v4l2_file_operations trust_fops = { .owner = THIS_MODULE, .open = trust_exclusive_open, .release = trust_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops trust_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-typhoon.c b/linux/drivers/media/radio/radio-typhoon.c index c7ea37389..bf812fbb5 100644 --- a/linux/drivers/media/radio/radio-typhoon.c +++ b/linux/drivers/media/radio/radio-typhoon.c @@ -331,26 +331,22 @@ static struct typhoon_device typhoon_unit = .mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, }; -static int typhoon_exclusive_open(struct inode *inode, struct file *file) +static int typhoon_exclusive_open(struct file *file) { return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0; } -static int typhoon_exclusive_release(struct inode *inode, struct file *file) +static int typhoon_exclusive_release(struct file *file) { clear_bit(0, &typhoon_unit.in_use); return 0; } -static const struct file_operations typhoon_fops = { +static const struct v4l2_file_operations typhoon_fops = { .owner = THIS_MODULE, .open = typhoon_exclusive_open, .release = typhoon_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 61b0366ab..4654ecd8b 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -402,27 +402,23 @@ static int vidioc_s_audio(struct file *file, void *priv, static struct zol_device zoltrix_unit; -static int zoltrix_exclusive_open(struct inode *inode, struct file *file) +static int zoltrix_exclusive_open(struct file *file) { return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0; } -static int zoltrix_exclusive_release(struct inode *inode, struct file *file) +static int zoltrix_exclusive_release(struct file *file) { clear_bit(0, &zoltrix_unit.in_use); return 0; } -static const struct file_operations zoltrix_fops = +static const struct v4l2_file_operations zoltrix_fops = { .owner = THIS_MODULE, .open = zoltrix_exclusive_open, .release = zoltrix_exclusive_release, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { diff --git a/linux/drivers/media/video/arv.c b/linux/drivers/media/video/arv.c index c15dfd37c..cc97a35a8 100644 --- a/linux/drivers/media/video/arv.c +++ b/linux/drivers/media/video/arv.c @@ -540,7 +540,7 @@ static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int ar_ioctl(struct inode *inode, struct file *file, unsigned int cmd, +static int ar_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, ar_do_ioctl); @@ -749,27 +749,23 @@ void ar_release(struct video_device *vfd) ****************************************************************************/ static struct ar_device ardev; -static int ar_exclusive_open(struct inode *inode, struct file *file) +static int ar_exclusive_open(struct file *file) { return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0; } -static int ar_exclusive_release(struct inode *inode, struct file *file) +static int ar_exclusive_release(struct file *file) { clear_bit(0, &ardev.in_use); return 0; } -static const struct file_operations ar_fops = { +static const struct v4l2_file_operations ar_fops = { .owner = THIS_MODULE, .open = ar_exclusive_open, .release = ar_exclusive_release, .read = ar_read, .ioctl = ar_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct video_device ar_template = { diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index e398de6c1..4994afb1e 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -3236,9 +3236,9 @@ err: return POLLERR; } -static int bttv_open(struct inode *inode, struct file *file) +static int bttv_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct bttv *btv = NULL; struct bttv_fh *fh; enum v4l2_buf_type type = 0; @@ -3319,7 +3319,7 @@ static int bttv_open(struct inode *inode, struct file *file) return 0; } -static int bttv_release(struct inode *inode, struct file *file) +static int bttv_release(struct file *file) { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; @@ -3374,14 +3374,12 @@ bttv_mmap(struct file *file, struct vm_area_struct *vma) return videobuf_mmap_mapper(bttv_queue(fh),vma); } -static const struct file_operations bttv_fops = +static const struct v4l2_file_operations bttv_fops = { .owner = THIS_MODULE, .open = bttv_open, .release = bttv_release, .ioctl = video_ioctl2, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, .read = bttv_read, .mmap = bttv_mmap, .poll = bttv_poll, @@ -3450,9 +3448,9 @@ static struct video_device bttv_video_template = { /* ----------------------------------------------------------------------- */ /* radio interface */ -static int radio_open(struct inode *inode, struct file *file) +static int radio_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct bttv *btv = NULL; struct bttv_fh *fh; unsigned int i; @@ -3495,7 +3493,7 @@ static int radio_open(struct inode *inode, struct file *file) return 0; } -static int radio_release(struct inode *inode, struct file *file) +static int radio_release(struct file *file) { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; @@ -3661,15 +3659,13 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) return cmd.result; } -static const struct file_operations radio_fops = +static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = radio_open, .read = radio_read, .release = radio_release, - .compat_ioctl = v4l_compat_ioctl32, .ioctl = video_ioctl2, - .llseek = no_llseek, .poll = radio_poll, }; diff --git a/linux/drivers/media/video/bw-qcam.c b/linux/drivers/media/video/bw-qcam.c index e534eaf39..12d50acbf 100644 --- a/linux/drivers/media/video/bw-qcam.c +++ b/linux/drivers/media/video/bw-qcam.c @@ -864,7 +864,7 @@ static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int qcam_ioctl(struct inode *inode, struct file *file, +static int qcam_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, qcam_do_ioctl); @@ -894,7 +894,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, return len; } -static int qcam_exclusive_open(struct inode *inode, struct file *file) +static int qcam_exclusive_open(struct file *file) { struct video_device *dev = video_devdata(file); struct qcam_device *qcam = (struct qcam_device *)dev; @@ -902,7 +902,7 @@ static int qcam_exclusive_open(struct inode *inode, struct file *file) return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; } -static int qcam_exclusive_release(struct inode *inode, struct file *file) +static int qcam_exclusive_release(struct file *file) { struct video_device *dev = video_devdata(file); struct qcam_device *qcam = (struct qcam_device *)dev; @@ -911,16 +911,12 @@ static int qcam_exclusive_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations qcam_fops = { +static const struct v4l2_file_operations qcam_fops = { .owner = THIS_MODULE, .open = qcam_exclusive_open, .release = qcam_exclusive_release, .ioctl = qcam_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .read = qcam_read, - .llseek = no_llseek, }; static struct video_device qcam_template= { diff --git a/linux/drivers/media/video/c-qcam.c b/linux/drivers/media/video/c-qcam.c index bdad822a5..6e785c3c1 100644 --- a/linux/drivers/media/video/c-qcam.c +++ b/linux/drivers/media/video/c-qcam.c @@ -666,7 +666,7 @@ static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int qcam_ioctl(struct inode *inode, struct file *file, +static int qcam_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, qcam_do_ioctl); @@ -688,7 +688,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, return len; } -static int qcam_exclusive_open(struct inode *inode, struct file *file) +static int qcam_exclusive_open(struct file *file) { struct video_device *dev = video_devdata(file); struct qcam_device *qcam = (struct qcam_device *)dev; @@ -696,7 +696,7 @@ static int qcam_exclusive_open(struct inode *inode, struct file *file) return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; } -static int qcam_exclusive_release(struct inode *inode, struct file *file) +static int qcam_exclusive_release(struct file *file) { struct video_device *dev = video_devdata(file); struct qcam_device *qcam = (struct qcam_device *)dev; @@ -706,16 +706,12 @@ static int qcam_exclusive_release(struct inode *inode, struct file *file) } /* video device template */ -static const struct file_operations qcam_fops = { +static const struct v4l2_file_operations qcam_fops = { .owner = THIS_MODULE, .open = qcam_exclusive_open, .release = qcam_exclusive_release, .ioctl = qcam_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .read = qcam_read, - .llseek = no_llseek, }; static struct video_device qcam_template= diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 1184b9186..48ecd5d35 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -1479,11 +1479,11 @@ static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma) -static int cafe_v4l_open(struct inode *inode, struct file *filp) +static int cafe_v4l_open(struct file *filp) { struct cafe_camera *cam; - cam = cafe_find_dev(iminor(inode)); + cam = cafe_find_dev(video_devdata(filp)->minor); if (cam == NULL) return -ENODEV; filp->private_data = cam; @@ -1501,7 +1501,7 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) } -static int cafe_v4l_release(struct inode *inode, struct file *filp) +static int cafe_v4l_release(struct file *filp) { struct cafe_camera *cam = filp->private_data; @@ -1766,7 +1766,7 @@ static void cafe_v4l_dev_release(struct video_device *vd) * clone it for specific real devices. */ -static const struct file_operations cafe_v4l_fops = { +static const struct v4l2_file_operations cafe_v4l_fops = { .owner = THIS_MODULE, .open = cafe_v4l_open, .release = cafe_v4l_release, @@ -1774,7 +1774,6 @@ static const struct file_operations cafe_v4l_fops = { .poll = cafe_v4l_poll, .mmap = cafe_v4l_mmap, .ioctl = video_ioctl2, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { diff --git a/linux/drivers/media/video/cpia.c b/linux/drivers/media/video/cpia.c index 004f36928..f1b993972 100644 --- a/linux/drivers/media/video/cpia.c +++ b/linux/drivers/media/video/cpia.c @@ -3149,7 +3149,7 @@ static void put_cam(struct cpia_camera_ops* ops) } /* ------------------------- V4L interface --------------------- */ -static int cpia_open(struct inode *inode, struct file *file) +static int cpia_open(struct file *file) { struct video_device *dev = video_devdata(file); struct cam_data *cam = video_get_drvdata(dev); @@ -3226,7 +3226,7 @@ static int cpia_open(struct inode *inode, struct file *file) return err; } -static int cpia_close(struct inode *inode, struct file *file) +static int cpia_close(struct file *file) { struct video_device *dev = file->private_data; struct cam_data *cam = video_get_drvdata(dev); @@ -3721,7 +3721,7 @@ static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg) return retval; } -static int cpia_ioctl(struct inode *inode, struct file *file, +static int cpia_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, cpia_do_ioctl); @@ -3781,17 +3781,13 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -static const struct file_operations cpia_fops = { +static const struct v4l2_file_operations cpia_fops = { .owner = THIS_MODULE, .open = cpia_open, .release = cpia_close, .read = cpia_read, .mmap = cpia_mmap, .ioctl = cpia_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct video_device cpia_template = { diff --git a/linux/drivers/media/video/cpia2/cpia2_v4l.c b/linux/drivers/media/video/cpia2/cpia2_v4l.c index 3c2d7eac1..91870cc9c 100644 --- a/linux/drivers/media/video/cpia2/cpia2_v4l.c +++ b/linux/drivers/media/video/cpia2/cpia2_v4l.c @@ -239,7 +239,7 @@ static struct v4l2_queryctrl controls[] = { * cpia2_open * *****************************************************************************/ -static int cpia2_open(struct inode *inode, struct file *file) +static int cpia2_open(struct file *file) { struct camera_data *cam = video_drvdata(file); int retval = 0; @@ -302,7 +302,7 @@ err_return: * cpia2_close * *****************************************************************************/ -static int cpia2_close(struct inode *inode, struct file *file) +static int cpia2_close(struct file *file) { struct video_device *dev = video_devdata(file); struct camera_data *cam = video_get_drvdata(dev); @@ -1841,7 +1841,7 @@ static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) return retval; } -static int cpia2_ioctl(struct inode *inode, struct file *file, +static int cpia2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, cpia2_do_ioctl); @@ -1912,17 +1912,13 @@ static void reset_camera_struct_v4l(struct camera_data *cam) /*** * The v4l video device structure initialized for this device ***/ -static const struct file_operations fops_template = { +static const struct v4l2_file_operations fops_template = { .owner = THIS_MODULE, .open = cpia2_open, .release = cpia2_close, .read = cpia2_v4l_read, .poll = cpia2_v4l_poll, .ioctl = cpia2_ioctl, - .llseek = no_llseek, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .mmap = cpia2_mmap, }; diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index ef4589ef6..0aaea0e7f 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -590,7 +590,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) } } -int cx18_v4l2_close(struct inode *inode, struct file *filp) +int cx18_v4l2_close(struct file *filp) { struct cx18_open_id *id = filp->private_data; struct cx18 *cx = id->cx; @@ -688,12 +688,12 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) return 0; } -int cx18_v4l2_open(struct inode *inode, struct file *filp) +int cx18_v4l2_open(struct file *filp) { int res, x, y = 0; struct cx18 *cx = NULL; struct cx18_stream *s = NULL; - int minor = iminor(inode); + int minor = video_devdata(filp)->minor; /* Find which card this open was on */ spin_lock(&cx18_cards_lock); diff --git a/linux/drivers/media/video/cx18/cx18-fileops.h b/linux/drivers/media/video/cx18/cx18-fileops.h index 46da0282f..92e2d5dab 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.h +++ b/linux/drivers/media/video/cx18/cx18-fileops.h @@ -22,12 +22,12 @@ */ /* Testing/Debugging */ -int cx18_v4l2_open(struct inode *inode, struct file *filp); +int cx18_v4l2_open(struct file *filp); ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count, loff_t *pos); ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos); -int cx18_v4l2_close(struct inode *inode, struct file *filp); +int cx18_v4l2_close(struct file *filp); unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait); int cx18_start_capture(struct cx18_open_id *id); void cx18_stop_capture(struct cx18_open_id *id, int gop_end); diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index c83fcc0c5..6cde2a7fa 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -888,7 +888,7 @@ static int cx18_default(struct file *file, void *fh, int cmd, void *arg) return 0; } -int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, +int cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct video_device *vfd = video_devdata(filp); @@ -900,7 +900,7 @@ int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, if (cx18_debug & CX18_DBGFLG_IOCTL) vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; - res = video_ioctl2(inode, filp, cmd, arg); + res = video_ioctl2(filp, cmd, arg); vfd->debug = 0; mutex_unlock(&cx->serialize_lock); return res; diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.h b/linux/drivers/media/video/cx18/cx18-ioctl.h index 08fe24e95..50b8d6056 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.h +++ b/linux/drivers/media/video/cx18/cx18-ioctl.h @@ -29,5 +29,5 @@ void cx18_set_funcs(struct video_device *vdev); int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std); int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); int cx18_s_input(struct file *file, void *fh, unsigned int inp); -int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, +int cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index f9e44c0cf..5eb99ea7b 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -37,13 +37,12 @@ #define CX18_DSP0_INTERRUPT_MASK 0xd0004C -static struct file_operations cx18_v4l2_enc_fops = { +static struct v4l2_file_operations cx18_v4l2_enc_fops = { .owner = THIS_MODULE, .read = cx18_v4l2_read, .open = cx18_v4l2_open, /* FIXME change to video_ioctl2 if serialization lock can be removed */ .ioctl = cx18_v4l2_ioctl, - .compat_ioctl = v4l_compat_ioctl32, .release = cx18_v4l2_close, .poll = cx18_v4l2_enc_poll, }; @@ -61,49 +60,41 @@ static struct { int num_offset; int dma; enum v4l2_buf_type buf_type; - struct file_operations *fops; } cx18_stream_info[] = { { /* CX18_ENC_STREAM_TYPE_MPG */ "encoder MPEG", VFL_TYPE_GRABBER, 0, PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE, - &cx18_v4l2_enc_fops }, { /* CX18_ENC_STREAM_TYPE_TS */ "TS", VFL_TYPE_GRABBER, -1, PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE, - &cx18_v4l2_enc_fops }, { /* CX18_ENC_STREAM_TYPE_YUV */ "encoder YUV", VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET, PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE, - &cx18_v4l2_enc_fops }, { /* CX18_ENC_STREAM_TYPE_VBI */ "encoder VBI", VFL_TYPE_VBI, 0, PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE, - &cx18_v4l2_enc_fops }, { /* CX18_ENC_STREAM_TYPE_PCM */ "encoder PCM audio", VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET, PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE, - &cx18_v4l2_enc_fops }, { /* CX18_ENC_STREAM_TYPE_IDX */ "encoder IDX", VFL_TYPE_GRABBER, -1, PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE, - &cx18_v4l2_enc_fops }, { /* CX18_ENC_STREAM_TYPE_RAD */ "encoder radio", VFL_TYPE_RADIO, 0, PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE, - &cx18_v4l2_enc_fops }, }; @@ -184,7 +175,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) s->v4l2dev->num = num; s->v4l2dev->parent = &cx->dev->dev; - s->v4l2dev->fops = cx18_stream_info[type].fops; + s->v4l2dev->fops = &cx18_v4l2_enc_fops; s->v4l2dev->release = video_device_release; s->v4l2dev->tvnorms = V4L2_STD_ALL; cx18_set_funcs(s->v4l2dev); diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index dfe8ddbce..1aa8a9ca3 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -1581,9 +1581,9 @@ static int vidioc_queryctrl(struct file *file, void *priv, return cx23885_queryctrl(dev, c); } -static int mpeg_open(struct inode *inode, struct file *file) +static int mpeg_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct cx23885_dev *h, *dev = NULL; struct list_head *list; struct cx23885_fh *fh; @@ -1625,7 +1625,7 @@ static int mpeg_open(struct inode *inode, struct file *file) return 0; } -static int mpeg_release(struct inode *inode, struct file *file) +static int mpeg_release(struct file *file) { struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; @@ -1702,15 +1702,13 @@ static int mpeg_mmap(struct file *file, struct vm_area_struct *vma) return videobuf_mmap_mapper(&fh->mpegq, vma); } -static struct file_operations mpeg_fops = { +static struct v4l2_file_operations mpeg_fops = { .owner = THIS_MODULE, .open = mpeg_open, .release = mpeg_release, .read = mpeg_read, .poll = mpeg_poll, .mmap = mpeg_mmap, - .ioctl = video_ioctl2, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index 0b5d20481..26f8b8efa 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -774,9 +774,9 @@ static int get_resource(struct cx23885_fh *fh) } } -static int video_open(struct inode *inode, struct file *file) +static int video_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct cx23885_dev *h, *dev = NULL; struct cx23885_fh *fh; struct list_head *list; @@ -905,7 +905,7 @@ static unsigned int video_poll(struct file *file, return 0; } -static int video_release(struct inode *inode, struct file *file) +static int video_release(struct file *file) { struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; @@ -1630,7 +1630,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status) /* ----------------------------------------------------------- */ /* exported stuff */ -static const struct file_operations video_fops = { +static const struct v4l2_file_operations video_fops = { .owner = THIS_MODULE, .open = video_open, .release = video_release, @@ -1638,8 +1638,6 @@ static const struct file_operations video_fops = { .poll = video_poll, .mmap = video_mmap, .ioctl = video_ioctl2, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { @@ -1687,13 +1685,11 @@ static struct video_device cx23885_video_template = { .current_norm = V4L2_STD_NTSC_M, }; -static const struct file_operations radio_fops = { +static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = video_open, .release = video_release, .ioctl = video_ioctl2, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, }; #if 0 diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 561dc7f0b..46e009403 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -1068,16 +1068,16 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) /* FIXME: cx88_ioctl_hook not implemented */ -static int mpeg_open(struct inode *inode, struct file *file) +static int mpeg_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct cx8802_dev *dev = NULL; struct cx8802_fh *fh; struct cx8802_driver *drv = NULL; int err; lock_kernel(); - dev = cx8802_get_device(inode); + dev = cx8802_get_device(minor); dprintk( 1, "%s\n", __func__); @@ -1133,7 +1133,7 @@ static int mpeg_open(struct inode *inode, struct file *file) return 0; } -static int mpeg_release(struct inode *inode, struct file *file) +static int mpeg_release(struct file *file) { struct cx8802_fh *fh = file->private_data; struct cx8802_dev *dev = fh->dev; @@ -1151,7 +1151,7 @@ static int mpeg_release(struct inode *inode, struct file *file) kfree(fh); /* Make sure we release the hardware */ - dev = cx8802_get_device(inode); + dev = cx8802_get_device(video_devdata(file)->minor); if (dev == NULL) return -ENODEV; @@ -1197,7 +1197,7 @@ mpeg_mmap(struct file *file, struct vm_area_struct * vma) return videobuf_mmap_mapper(&fh->mpegq, vma); } -static const struct file_operations mpeg_fops = +static const struct v4l2_file_operations mpeg_fops = { .owner = THIS_MODULE, .open = mpeg_open, @@ -1206,7 +1206,6 @@ static const struct file_operations mpeg_fops = .poll = mpeg_poll, .mmap = mpeg_mmap, .ioctl = video_ioctl2, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index 9d407ac26..999d3bd04 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -618,9 +618,8 @@ static int cx8802_resume_common(struct pci_dev *pci_dev) #if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \ defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE) -struct cx8802_dev * cx8802_get_device(struct inode *inode) +struct cx8802_dev *cx8802_get_device(int minor) { - int minor = iminor(inode); struct cx8802_dev *dev; list_for_each_entry(dev, &cx8802_devlist, devlist) diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 40136a431..0f551f845 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -983,9 +983,9 @@ static int get_ressource(struct cx8800_fh *fh) } } -static int video_open(struct inode *inode, struct file *file) +static int video_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct cx8800_dev *h,*dev = NULL; struct cx88_core *core; struct cx8800_fh *fh; @@ -1130,7 +1130,7 @@ video_poll(struct file *file, struct poll_table_struct *wait) return 0; } -static int video_release(struct inode *inode, struct file *file) +static int video_release(struct file *file) { struct cx8800_fh *fh = file->private_data; struct cx8800_dev *dev = fh->dev; @@ -1963,7 +1963,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id) /* ----------------------------------------------------------- */ /* exported stuff */ -static const struct file_operations video_fops = +static const struct v4l2_file_operations video_fops = { .owner = THIS_MODULE, .open = video_open, @@ -1972,8 +1972,6 @@ static const struct file_operations video_fops = .poll = video_poll, .mmap = video_mmap, .ioctl = video_ioctl2, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { @@ -2022,14 +2020,12 @@ static struct video_device cx8800_video_template = { .current_norm = V4L2_STD_NTSC_M, }; -static const struct file_operations radio_fops = +static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = video_open, .release = video_release, .ioctl = video_ioctl2, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 6f8e575a3..bc26551ca 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -664,7 +664,7 @@ int cx88_audio_thread(void *data); int cx8802_register_driver(struct cx8802_driver *drv); int cx8802_unregister_driver(struct cx8802_driver *drv); -struct cx8802_dev * cx8802_get_device(struct inode *inode); +struct cx8802_dev *cx8802_get_device(int minor); struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); /* ----------------------------------------------------------- */ diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 65bc5c8a9..1da986118 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -1009,12 +1009,11 @@ void em28xx_wake_i2c(struct em28xx *dev) static LIST_HEAD(em28xx_devlist); static DEFINE_MUTEX(em28xx_devlist_mutex); -struct em28xx *em28xx_get_device(struct inode *inode, +struct em28xx *em28xx_get_device(int minor, enum v4l2_buf_type *fh_type, int *has_radio) { struct em28xx *h, *dev = NULL; - int minor = iminor(inode); *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; *has_radio = 0; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index fe6b6f142..dd3f49140 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1629,15 +1629,15 @@ static int radio_queryctrl(struct file *file, void *priv, * em28xx_v4l2_open() * inits the device and starts isoc transfer */ -static int em28xx_v4l2_open(struct inode *inode, struct file *filp) +static int em28xx_v4l2_open(struct file *filp) { - int minor = iminor(inode); + int minor = video_devdata(filp)->minor; int errCode = 0, radio; struct em28xx *dev; enum v4l2_buf_type fh_type; struct em28xx_fh *fh; - dev = em28xx_get_device(inode, &fh_type, &radio); + dev = em28xx_get_device(minor, &fh_type, &radio); if (NULL == dev) return -ENODEV; @@ -1748,7 +1748,7 @@ void em28xx_release_analog_resources(struct em28xx *dev) * stops streaming and deallocates all resources allocated by the v4l2 * calls and ioctls */ -static int em28xx_v4l2_close(struct inode *inode, struct file *filp) +static int em28xx_v4l2_close(struct file *filp) { struct em28xx_fh *fh = filp->private_data; struct em28xx *dev = fh->dev; @@ -1888,7 +1888,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) return rc; } -static const struct file_operations em28xx_v4l_fops = { +static const struct v4l2_file_operations em28xx_v4l_fops = { .owner = THIS_MODULE, .open = em28xx_v4l2_open, .release = em28xx_v4l2_close, @@ -1896,8 +1896,6 @@ static const struct file_operations em28xx_v4l_fops = { .poll = em28xx_v4l2_poll, .mmap = em28xx_v4l2_mmap, .ioctl = video_ioctl2, - .llseek = no_llseek, - .compat_ioctl = v4l_compat_ioctl32, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { @@ -1957,13 +1955,11 @@ static const struct video_device em28xx_video_template = { .current_norm = V4L2_STD_PAL, }; -static const struct file_operations radio_fops = { +static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = em28xx_v4l2_open, .release = em28xx_v4l2_close, .ioctl = video_ioctl2, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index fb88c7f64..1b3b75880 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -596,7 +596,7 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); void em28xx_wake_i2c(struct em28xx *dev); void em28xx_remove_from_devlist(struct em28xx *dev); void em28xx_add_into_devlist(struct em28xx *dev); -struct em28xx *em28xx_get_device(struct inode *inode, +struct em28xx *em28xx_get_device(int minor, enum v4l2_buf_type *fh_type, int *has_radio); int em28xx_register_extension(struct em28xx_ops *dev); diff --git a/linux/drivers/media/video/et61x251/et61x251_core.c b/linux/drivers/media/video/et61x251/et61x251_core.c index 52e0f2710..706f2e630 100644 --- a/linux/drivers/media/video/et61x251/et61x251_core.c +++ b/linux/drivers/media/video/et61x251/et61x251_core.c @@ -1210,7 +1210,7 @@ static void et61x251_release_resources(struct kref *kref) } -static int et61x251_open(struct inode* inode, struct file* filp) +static int et61x251_open(struct file *filp) { struct et61x251_device* cam; int err = 0; @@ -1295,7 +1295,7 @@ out: } -static int et61x251_release(struct inode* inode, struct file* filp) +static int et61x251_release(struct file *filp) { struct et61x251_device* cam; @@ -2396,8 +2396,8 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) } -static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) +static int et61x251_ioctl_v4l2(struct file *filp, + unsigned int cmd, void __user *arg) { struct et61x251_device *cam = video_drvdata(filp); @@ -2491,7 +2491,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, } -static int et61x251_ioctl(struct inode* inode, struct file* filp, +static int et61x251_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct et61x251_device *cam = video_drvdata(filp); @@ -2515,7 +2515,7 @@ static int et61x251_ioctl(struct inode* inode, struct file* filp, V4LDBG(3, "et61x251", cmd); - err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); + err = et61x251_ioctl_v4l2(filp, cmd, (void __user *)arg); mutex_unlock(&cam->fileop_mutex); @@ -2523,18 +2523,14 @@ static int et61x251_ioctl(struct inode* inode, struct file* filp, } -static const struct file_operations et61x251_fops = { +static const struct v4l2_file_operations et61x251_fops = { .owner = THIS_MODULE, .open = et61x251_open, .release = et61x251_release, .ioctl = et61x251_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .read = et61x251_read, .poll = et61x251_poll, .mmap = et61x251_mmap, - .llseek = no_llseek, }; /*****************************************************************************/ diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 5adbe7301..479b4feea 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -885,7 +885,7 @@ static void gspca_release(struct video_device *vfd) kfree(gspca_dev); } -static int dev_open(struct inode *inode, struct file *file) +static int dev_open(struct file *file) { struct gspca_dev *gspca_dev; int ret; @@ -932,7 +932,7 @@ out: return ret; } -static int dev_close(struct inode *inode, struct file *file) +static int dev_close(struct file *file) { struct gspca_dev *gspca_dev = file->private_data; @@ -1812,17 +1812,13 @@ out: return ret; } -static struct file_operations dev_fops = { +static struct v4l2_file_operations dev_fops = { .owner = THIS_MODULE, .open = dev_open, .release = dev_close, .read = dev_read, .mmap = dev_mmap, - .unlocked_ioctl = __video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, + .unlocked_ioctl = video_ioctl2, .poll = dev_poll, }; diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c index 5eb587592..d594bc29f 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.c +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c @@ -831,7 +831,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) ivtv_release_stream(s); } -int ivtv_v4l2_close(struct inode *inode, struct file *filp) +int ivtv_v4l2_close(struct file *filp) { struct ivtv_open_id *id = filp->private_data; struct ivtv *itv = id->itv; @@ -978,7 +978,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) return 0; } -int ivtv_v4l2_open(struct inode *inode, struct file *filp) +int ivtv_v4l2_open(struct file *filp) { int res; struct ivtv *itv = NULL; diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.h b/linux/drivers/media/video/ivtv/ivtv-fileops.h index df81e7901..049a29239 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.h +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.h @@ -22,12 +22,12 @@ #define IVTV_FILEOPS_H /* Testing/Debugging */ -int ivtv_v4l2_open(struct inode *inode, struct file *filp); +int ivtv_v4l2_open(struct file *filp); ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count, loff_t * pos); ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count, loff_t * pos); -int ivtv_v4l2_close(struct inode *inode, struct file *filp); +int ivtv_v4l2_close(struct file *filp); unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait); unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait); int ivtv_start_capture(struct ivtv_open_id *id); diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index cd990a4b8..a6cd02460 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1827,7 +1827,7 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, if (ivtv_debug & IVTV_DBGFLG_IOCTL) vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; - ret = __video_ioctl2(filp, cmd, arg); + ret = video_ioctl2(filp, cmd, arg); vfd->debug = 0; return ret; } diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c index f77d76470..854a950af 100644 --- a/linux/drivers/media/video/ivtv/ivtv-streams.c +++ b/linux/drivers/media/video/ivtv/ivtv-streams.c @@ -43,24 +43,22 @@ #include "ivtv-cards.h" #include "ivtv-streams.h" -static const struct file_operations ivtv_v4l2_enc_fops = { +static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { .owner = THIS_MODULE, .read = ivtv_v4l2_read, .write = ivtv_v4l2_write, .open = ivtv_v4l2_open, .unlocked_ioctl = ivtv_v4l2_ioctl, - .compat_ioctl = v4l_compat_ioctl32, .release = ivtv_v4l2_close, .poll = ivtv_v4l2_enc_poll, }; -static const struct file_operations ivtv_v4l2_dec_fops = { +static const struct v4l2_file_operations ivtv_v4l2_dec_fops = { .owner = THIS_MODULE, .read = ivtv_v4l2_read, .write = ivtv_v4l2_write, .open = ivtv_v4l2_open, .unlocked_ioctl = ivtv_v4l2_ioctl, - .compat_ioctl = v4l_compat_ioctl32, .release = ivtv_v4l2_close, .poll = ivtv_v4l2_dec_poll, }; @@ -78,7 +76,7 @@ static struct { int num_offset; int dma, pio; enum v4l2_buf_type buf_type; - const struct file_operations *fops; + const struct v4l2_file_operations *fops; } ivtv_stream_info[] = { { /* IVTV_ENC_STREAM_TYPE_MPG */ "encoder MPG", diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c index 535443887..649faa796 100644 --- a/linux/drivers/media/video/meye.c +++ b/linux/drivers/media/video/meye.c @@ -846,7 +846,7 @@ again: /* video4linux integration */ /****************************************************************************/ -static int meye_open(struct inode *inode, struct file *file) +static int meye_open(struct file *file) { int i; @@ -868,7 +868,7 @@ static int meye_open(struct inode *inode, struct file *file) return 0; } -static int meye_release(struct inode *inode, struct file *file) +static int meye_release(struct file *file) { mchip_hic_stop(); mchip_dma_free(); @@ -1689,17 +1689,13 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -static const struct file_operations meye_fops = { +static const struct v4l2_file_operations meye_fops = { .owner = THIS_MODULE, .open = meye_open, .release = meye_release, .mmap = meye_mmap, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .poll = meye_poll, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops meye_ioctl_ops = { diff --git a/linux/drivers/media/video/omap24xxcam.c b/linux/drivers/media/video/omap24xxcam.c index 85c3c7c92..73eb656ac 100644 --- a/linux/drivers/media/video/omap24xxcam.c +++ b/linux/drivers/media/video/omap24xxcam.c @@ -1454,9 +1454,9 @@ static int omap24xxcam_mmap(struct file *file, struct vm_area_struct *vma) return rval; } -static int omap24xxcam_open(struct inode *inode, struct file *file) +static int omap24xxcam_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct omap24xxcam_device *cam = omap24xxcam.priv; struct omap24xxcam_fh *fh; struct v4l2_format format; @@ -1511,7 +1511,7 @@ out_try_module_get: return -ENODEV; } -static int omap24xxcam_release(struct inode *inode, struct file *file) +static int omap24xxcam_release(struct file *file) { struct omap24xxcam_fh *fh = file->private_data; struct omap24xxcam_device *cam = fh->cam; @@ -1559,8 +1559,7 @@ static int omap24xxcam_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations omap24xxcam_fops = { - .llseek = no_llseek, +static struct v4l2_file_operations omap24xxcam_fops = { .ioctl = video_ioctl2, .poll = omap24xxcam_poll, .mmap = omap24xxcam_mmap, diff --git a/linux/drivers/media/video/ov511.c b/linux/drivers/media/video/ov511.c index ca3a89616..03ab40832 100644 --- a/linux/drivers/media/video/ov511.c +++ b/linux/drivers/media/video/ov511.c @@ -3919,7 +3919,7 @@ ov51x_dealloc(struct usb_ov511 *ov) ***************************************************************************/ static int -ov51x_v4l1_open(struct inode *inode, struct file *file) +ov51x_v4l1_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct usb_ov511 *ov = video_get_drvdata(vdev); @@ -3976,7 +3976,7 @@ out: } static int -ov51x_v4l1_close(struct inode *inode, struct file *file) +ov51x_v4l1_close(struct file *file) { struct video_device *vdev = file->private_data; struct usb_ov511 *ov = video_get_drvdata(vdev); @@ -4454,7 +4454,7 @@ redo: } static int -ov51x_v4l1_ioctl(struct inode *inode, struct file *file, +ov51x_v4l1_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct video_device *vdev = file->private_data; @@ -4665,17 +4665,13 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -static const struct file_operations ov511_fops = { +static const struct v4l2_file_operations ov511_fops = { .owner = THIS_MODULE, .open = ov51x_v4l1_open, .release = ov51x_v4l1_close, .read = ov51x_v4l1_read, .mmap = ov51x_v4l1_mmap, .ioctl = ov51x_v4l1_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct video_device vdev_template = { diff --git a/linux/drivers/media/video/pms.c b/linux/drivers/media/video/pms.c index 522f75def..da5de81c2 100644 --- a/linux/drivers/media/video/pms.c +++ b/linux/drivers/media/video/pms.c @@ -863,7 +863,7 @@ static int pms_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int pms_ioctl(struct inode *inode, struct file *file, +static int pms_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, pms_do_ioctl); @@ -882,7 +882,7 @@ static ssize_t pms_read(struct file *file, char __user *buf, return len; } -static int pms_exclusive_open(struct inode *inode, struct file *file) +static int pms_exclusive_open(struct file *file) { struct video_device *v = video_devdata(file); struct pms_device *pd = (struct pms_device *)v; @@ -890,7 +890,7 @@ static int pms_exclusive_open(struct inode *inode, struct file *file) return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0; } -static int pms_exclusive_release(struct inode *inode, struct file *file) +static int pms_exclusive_release(struct file *file) { struct video_device *v = video_devdata(file); struct pms_device *pd = (struct pms_device *)v; @@ -899,16 +899,12 @@ static int pms_exclusive_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations pms_fops = { +static const struct v4l2_file_operations pms_fops = { .owner = THIS_MODULE, .open = pms_exclusive_open, .release = pms_exclusive_release, .ioctl = pms_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .read = pms_read, - .llseek = no_llseek, }; static struct video_device pms_template= diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 09fabfd2f..d1a6a9c1b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -949,7 +949,7 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) } -static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file, +static int pvr2_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -961,7 +961,7 @@ static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file, } -static int pvr2_v4l2_release(struct inode *inode, struct file *file) +static int pvr2_v4l2_release(struct file *file) { struct pvr2_v4l2_fh *fhp = file->private_data; struct pvr2_v4l2 *vp = fhp->vhead; @@ -1009,7 +1009,7 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) } -static int pvr2_v4l2_open(struct inode *inode, struct file *file) +static int pvr2_v4l2_open(struct file *file) { struct pvr2_v4l2_dev *dip; /* Our own context pointer */ struct pvr2_v4l2_fh *fhp; @@ -1236,13 +1236,12 @@ static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait) } -static const struct file_operations vdev_fops = { +static const struct v4l2_file_operations vdev_fops = { .owner = THIS_MODULE, .open = pvr2_v4l2_open, .release = pvr2_v4l2_release, .read = pvr2_v4l2_read, .ioctl = pvr2_v4l2_ioctl, - .llseek = no_llseek, .poll = pvr2_v4l2_poll, }; diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index d657e6f8d..cce3ceda1 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -142,16 +142,16 @@ static struct { /***/ -static int pwc_video_open(struct inode *inode, struct file *file); -static int pwc_video_close(struct inode *inode, struct file *file); +static int pwc_video_open(struct file *file); +static int pwc_video_close(struct file *file); static ssize_t pwc_video_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); static unsigned int pwc_video_poll(struct file *file, poll_table *wait); -static int pwc_video_ioctl(struct inode *inode, struct file *file, +static int pwc_video_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg); static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); -static const struct file_operations pwc_fops = { +static const struct v4l2_file_operations pwc_fops = { .owner = THIS_MODULE, .open = pwc_video_open, .release = pwc_video_close, @@ -159,10 +159,6 @@ static const struct file_operations pwc_fops = { .poll = pwc_video_poll, .mmap = pwc_video_mmap, .ioctl = pwc_video_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct video_device pwc_template = { .name = "Philips Webcam", /* Filled in later */ @@ -1108,7 +1104,7 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type) /***************************************************************************/ /* Video4Linux functions */ -static int pwc_video_open(struct inode *inode, struct file *file) +static int pwc_video_open(struct file *file) { int i, ret; struct video_device *vdev = video_devdata(file); @@ -1228,7 +1224,7 @@ static void pwc_cleanup(struct pwc_device *pdev) } /* Note that all cleanup is done in the reverse order as in _open */ -static int pwc_video_close(struct inode *inode, struct file *file) +static int pwc_video_close(struct file *file) { struct video_device *vdev = file->private_data; struct pwc_device *pdev; @@ -1403,7 +1399,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) return 0; } -static int pwc_video_ioctl(struct inode *inode, struct file *file, +static int pwc_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct video_device *vdev = file->private_data; diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index ab9814144..2a2cbb418 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -1503,9 +1503,9 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, dprintk(2, "setting jpeg quality %d\n", jc->quality); return 0; } -static int s2255_open(struct inode *inode, struct file *file) +static int s2255_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct s2255_dev *h, *dev = NULL; struct s2255_fh *fh; struct list_head *list; @@ -1712,11 +1712,11 @@ static void s2255_destroy(struct kref *kref) mutex_unlock(&dev->open_lock); } -static int s2255_close(struct inode *inode, struct file *file) +static int s2255_close(struct file *file) { struct s2255_fh *fh = file->private_data; struct s2255_dev *dev = fh->dev; - int minor = iminor(inode); + int minor = video_devdata(file)->minor; if (!dev) return -ENODEV; @@ -1760,15 +1760,13 @@ static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma) return ret; } -static const struct file_operations s2255_fops_v4l = { +static const struct v4l2_file_operations s2255_fops_v4l = { .owner = THIS_MODULE, .open = s2255_open, .release = s2255_close, .poll = s2255_poll, .ioctl = video_ioctl2, /* V4L2 ioctl handler */ - .compat_ioctl = v4l_compat_ioctl32, .mmap = s2255_mmap_v4l, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops s2255_ioctl_ops = { diff --git a/linux/drivers/media/video/saa5246a.c b/linux/drivers/media/video/saa5246a.c index 086fc807a..78ae8f46e 100644 --- a/linux/drivers/media/video/saa5246a.c +++ b/linux/drivers/media/video/saa5246a.c @@ -945,7 +945,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) /* * Handle the locking */ -static int saa5246a_ioctl(struct inode *inode, struct file *file, +static int saa5246a_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct saa5246a_device *t = video_drvdata(file); @@ -958,7 +958,7 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file, return err; } -static int saa5246a_open(struct inode *inode, struct file *file) +static int saa5246a_open(struct file *file) { struct saa5246a_device *t = video_drvdata(file); @@ -1000,7 +1000,7 @@ static int saa5246a_open(struct inode *inode, struct file *file) return 0; } -static int saa5246a_release(struct inode *inode, struct file *file) +static int saa5246a_release(struct file *file) { struct saa5246a_device *t = video_drvdata(file); @@ -1019,12 +1019,11 @@ static int saa5246a_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations saa_fops = { +static const struct v4l2_file_operations saa_fops = { .owner = THIS_MODULE, .open = saa5246a_open, .release = saa5246a_release, .ioctl = saa5246a_ioctl, - .llseek = no_llseek, }; static struct video_device saa_template = diff --git a/linux/drivers/media/video/saa5249.c b/linux/drivers/media/video/saa5249.c index 86352dbe7..d91fd838d 100644 --- a/linux/drivers/media/video/saa5249.c +++ b/linux/drivers/media/video/saa5249.c @@ -480,7 +480,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) * Handle the locking */ -static int saa5249_ioctl(struct inode *inode, struct file *file, +static int saa5249_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct saa5249_device *t = video_drvdata(file); @@ -493,7 +493,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, return err; } -static int saa5249_open(struct inode *inode, struct file *file) +static int saa5249_open(struct file *file) { struct saa5249_device *t = video_drvdata(file); int pgbuf; @@ -530,7 +530,7 @@ static int saa5249_open(struct inode *inode, struct file *file) -static int saa5249_release(struct inode *inode, struct file *file) +static int saa5249_release(struct file *file) { struct saa5249_device *t = video_drvdata(file); @@ -540,15 +540,11 @@ static int saa5249_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations saa_fops = { +static const struct v4l2_file_operations saa_fops = { .owner = THIS_MODULE, .open = saa5249_open, .release = saa5249_release, .ioctl = saa5249_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct video_device saa_template = diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index 53de5545c..37235c4d0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -83,9 +83,9 @@ static int ts_init_encoder(struct saa7134_dev* dev) /* ------------------------------------------------------------------ */ -static int ts_open(struct inode *inode, struct file *file) +static int ts_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct saa7134_dev *dev; int err; @@ -119,7 +119,7 @@ done: return err; } -static int ts_release(struct inode *inode, struct file *file) +static int ts_release(struct file *file) { struct saa7134_dev *dev = file->private_data; @@ -437,7 +437,7 @@ static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id) return 0; } -static const struct file_operations ts_fops = +static const struct v4l2_file_operations ts_fops = { .owner = THIS_MODULE, .open = ts_open, @@ -446,7 +446,6 @@ static const struct file_operations ts_fops = .poll = ts_poll, .mmap = ts_mmap, .ioctl = video_ioctl2, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops ts_ioctl_ops = { diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 884ef90c3..1fcf2693d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1326,9 +1326,9 @@ static int saa7134_resource(struct saa7134_fh *fh) return 0; } -static int video_open(struct inode *inode, struct file *file) +static int video_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct saa7134_dev *dev; struct saa7134_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1462,7 +1462,7 @@ err: return POLLERR; } -static int video_release(struct inode *inode, struct file *file) +static int video_release(struct file *file) { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; @@ -2384,7 +2384,7 @@ static int radio_queryctrl(struct file *file, void *priv, return 0; } -static const struct file_operations video_fops = +static const struct v4l2_file_operations video_fops = { .owner = THIS_MODULE, .open = video_open, @@ -2393,8 +2393,6 @@ static const struct file_operations video_fops = .poll = video_poll, .mmap = video_mmap, .ioctl = video_ioctl2, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { @@ -2448,13 +2446,11 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { #endif }; -static const struct file_operations radio_fops = { +static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = video_open, .release = video_release, .ioctl = video_ioctl2, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c index 8935c1632..3ca9f31fb 100644 --- a/linux/drivers/media/video/se401.c +++ b/linux/drivers/media/video/se401.c @@ -940,7 +940,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) ***************************************************************************/ -static int se401_open(struct inode *inode, struct file *file) +static int se401_open(struct file *file) { struct video_device *dev = video_devdata(file); struct usb_se401 *se401 = (struct usb_se401 *)dev; @@ -962,7 +962,7 @@ static int se401_open(struct inode *inode, struct file *file) return err; } -static int se401_close(struct inode *inode, struct file *file) +static int se401_close(struct file *file) { struct video_device *dev = file->private_data; struct usb_se401 *se401 = (struct usb_se401 *)dev; @@ -1146,7 +1146,7 @@ static int se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int se401_ioctl(struct inode *inode, struct file *file, +static int se401_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, se401_do_ioctl); @@ -1230,17 +1230,13 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -static const struct file_operations se401_fops = { +static const struct v4l2_file_operations se401_fops = { .owner = THIS_MODULE, .open = se401_open, .release = se401_close, .read = se401_read, .mmap = se401_mmap, .ioctl = se401_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct video_device se401_template = { .name = "se401 USB camera", diff --git a/linux/drivers/media/video/sn9c102/sn9c102_core.c b/linux/drivers/media/video/sn9c102/sn9c102_core.c index 3ce12faf5..1421a644f 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_core.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_core.c @@ -1750,7 +1750,7 @@ static void sn9c102_release_resources(struct kref *kref) } -static int sn9c102_open(struct inode* inode, struct file* filp) +static int sn9c102_open(struct file *filp) { struct sn9c102_device* cam; int err = 0; @@ -1861,7 +1861,7 @@ out: } -static int sn9c102_release(struct inode* inode, struct file* filp) +static int sn9c102_release(struct file *filp) { struct sn9c102_device* cam; @@ -3096,8 +3096,8 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg) } -static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) +static int sn9c102_ioctl_v4l2(struct file *filp, + unsigned int cmd, void __user *arg) { struct sn9c102_device *cam = video_drvdata(filp); @@ -3200,7 +3200,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, } -static int sn9c102_ioctl(struct inode* inode, struct file* filp, +static int sn9c102_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct sn9c102_device *cam = video_drvdata(filp); @@ -3224,7 +3224,7 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, V4LDBG(3, "sn9c102", cmd); - err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); + err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg); mutex_unlock(&cam->fileop_mutex); @@ -3233,18 +3233,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, /*****************************************************************************/ -static const struct file_operations sn9c102_fops = { +static const struct v4l2_file_operations sn9c102_fops = { .owner = THIS_MODULE, .open = sn9c102_open, .release = sn9c102_release, .ioctl = sn9c102_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .read = sn9c102_read, .poll = sn9c102_poll, .mmap = sn9c102_mmap, - .llseek = no_llseek, }; /*****************************************************************************/ diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index ba28c844f..4909b74db 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -257,7 +257,7 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) vfree(icd->user_formats); } -static int soc_camera_open(struct inode *inode, struct file *file) +static int soc_camera_open(struct file *file) { struct video_device *vdev; struct soc_camera_device *icd; @@ -331,7 +331,7 @@ emgd: return ret; } -static int soc_camera_close(struct inode *inode, struct file *file) +static int soc_camera_close(struct file *file) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; @@ -401,7 +401,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) return ici->ops->poll(file, pt); } -static struct file_operations soc_camera_fops = { +static struct v4l2_file_operations soc_camera_fops = { .owner = THIS_MODULE, .open = soc_camera_open, .release = soc_camera_close, @@ -409,7 +409,6 @@ static struct file_operations soc_camera_fops = { .read = soc_camera_read, .mmap = soc_camera_mmap, .poll = soc_camera_poll, - .llseek = no_llseek, }; static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index bfd0ddb63..7b1571262 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -665,7 +665,7 @@ static void stk_free_buffers(struct stk_camera *dev) /* v4l file operations */ -static int v4l_stk_open(struct inode *inode, struct file *fp) +static int v4l_stk_open(struct file *fp) { struct stk_camera *dev; struct video_device *vdev; @@ -685,7 +685,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) return 0; } -static int v4l_stk_release(struct inode *inode, struct file *fp) +static int v4l_stk_release(struct file *fp) { struct stk_camera *dev = fp->private_data; @@ -1282,7 +1282,7 @@ static int stk_vidioc_enum_framesizes(struct file *filp, } } -static struct file_operations v4l_stk_fops = { +static struct v4l2_file_operations v4l_stk_fops = { .owner = THIS_MODULE, .open = v4l_stk_open, .release = v4l_stk_release, @@ -1290,10 +1290,6 @@ static struct file_operations v4l_stk_fops = { .poll = v4l_stk_poll, .mmap = v4l_stk_mmap, .ioctl = video_ioctl2, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek }; static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { diff --git a/linux/drivers/media/video/stradis.c b/linux/drivers/media/video/stradis.c index 0e2b246c7..755c6b517 100644 --- a/linux/drivers/media/video/stradis.c +++ b/linux/drivers/media/video/stradis.c @@ -1280,7 +1280,7 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr) clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y); } -static int saa_ioctl(struct inode *inode, struct file *file, +static int saa_ioctl(struct file *file, unsigned int cmd, unsigned long argl) { struct saa7146 *saa = file->private_data; @@ -1882,7 +1882,7 @@ static ssize_t saa_write(struct file *file, const char __user * buf, return count; } -static int saa_open(struct inode *inode, struct file *file) +static int saa_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev); @@ -1900,7 +1900,7 @@ static int saa_open(struct inode *inode, struct file *file) return 0; } -static int saa_release(struct inode *inode, struct file *file) +static int saa_release(struct file *file) { struct saa7146 *saa = file->private_data; saa->user--; @@ -1911,16 +1911,12 @@ static int saa_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations saa_fops = { +static const struct v4l2_file_operations saa_fops = { .owner = THIS_MODULE, .open = saa_open, .release = saa_release, .ioctl = saa_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .read = saa_read, - .llseek = no_llseek, .write = saa_write, .mmap = saa_mmap, }; diff --git a/linux/drivers/media/video/stv680.c b/linux/drivers/media/video/stv680.c index be5ed5940..715c823e1 100644 --- a/linux/drivers/media/video/stv680.c +++ b/linux/drivers/media/video/stv680.c @@ -1085,7 +1085,7 @@ static int stv680_newframe (struct usb_stv *stv680, int framenr) * Video4Linux *********************************************************************/ -static int stv_open (struct inode *inode, struct file *file) +static int stv_open(struct file *file) { struct video_device *dev = video_devdata(file); struct usb_stv *stv680 = video_get_drvdata(dev); @@ -1111,7 +1111,7 @@ static int stv_open (struct inode *inode, struct file *file) return err; } -static int stv_close (struct inode *inode, struct file *file) +static int stv_close(struct file *file) { struct video_device *dev = file->private_data; struct usb_stv *stv680 = video_get_drvdata(dev); @@ -1304,7 +1304,7 @@ static int stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int stv680_ioctl(struct inode *inode, struct file *file, +static int stv680_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, stv680_do_ioctl); @@ -1396,17 +1396,13 @@ static ssize_t stv680_read (struct file *file, char __user *buf, return realcount; } /* stv680_read */ -static const struct file_operations stv680_fops = { +static const struct v4l2_file_operations stv680_fops = { .owner = THIS_MODULE, .open = stv_open, .release = stv_close, .read = stv680_read, .mmap = stv680_mmap, .ioctl = stv680_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct video_device stv680_template = { .name = "STV0680 USB camera", diff --git a/linux/drivers/media/video/usbvideo/usbvideo.c b/linux/drivers/media/video/usbvideo/usbvideo.c index 85409c624..6d66c95cb 100644 --- a/linux/drivers/media/video/usbvideo/usbvideo.c +++ b/linux/drivers/media/video/usbvideo/usbvideo.c @@ -41,13 +41,13 @@ module_param(video_nr, int, 0); static void usbvideo_Disconnect(struct usb_interface *intf); static void usbvideo_CameraRelease(struct uvd *uvd); -static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, +static int usbvideo_v4l_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); -static int usbvideo_v4l_open(struct inode *inode, struct file *file); +static int usbvideo_v4l_open(struct file *file); static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); -static int usbvideo_v4l_close(struct inode *inode, struct file *file); +static int usbvideo_v4l_close(struct file *file); static int usbvideo_StartDataPump(struct uvd *uvd); static void usbvideo_StopDataPump(struct uvd *uvd); @@ -942,17 +942,13 @@ static int usbvideo_find_struct(struct usbvideo *cams) return rv; } -static const struct file_operations usbvideo_fops = { +static const struct v4l2_file_operations usbvideo_fops = { .owner = THIS_MODULE, .open = usbvideo_v4l_open, .release =usbvideo_v4l_close, .read = usbvideo_v4l_read, .mmap = usbvideo_v4l_mmap, .ioctl = usbvideo_v4l_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static const struct video_device usbvideo_template = { .fops = &usbvideo_fops, @@ -1113,7 +1109,7 @@ static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). */ -static int usbvideo_v4l_open(struct inode *inode, struct file *file) +static int usbvideo_v4l_open(struct file *file) { struct video_device *dev = video_devdata(file); struct uvd *uvd = (struct uvd *) dev; @@ -1233,7 +1229,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. */ -static int usbvideo_v4l_close(struct inode *inode, struct file *file) +static int usbvideo_v4l_close(struct file *file) { struct video_device *dev = file->private_data; struct uvd *uvd = (struct uvd *) dev; @@ -1501,7 +1497,7 @@ static int usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, +static int usbvideo_v4l_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl); diff --git a/linux/drivers/media/video/usbvideo/vicam.c b/linux/drivers/media/video/usbvideo/vicam.c index 77032eaa7..76c7eeaec 100644 --- a/linux/drivers/media/video/usbvideo/vicam.c +++ b/linux/drivers/media/video/usbvideo/vicam.c @@ -540,7 +540,7 @@ set_camera_power(struct vicam_camera *cam, int state) } static int -vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg) +vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg) { void __user *user_arg = (void __user *)arg; struct vicam_camera *cam = file->private_data; @@ -780,7 +780,7 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign } static int -vicam_open(struct inode *inode, struct file *file) +vicam_open(struct file *file) { struct vicam_camera *cam = video_drvdata(file); @@ -846,7 +846,7 @@ vicam_open(struct inode *inode, struct file *file) } static int -vicam_close(struct inode *inode, struct file *file) +vicam_close(struct file *file) { struct vicam_camera *cam = file->private_data; int open_count; @@ -1093,17 +1093,13 @@ vicam_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -static const struct file_operations vicam_fops = { +static const struct v4l2_file_operations vicam_fops = { .owner = THIS_MODULE, .open = vicam_open, .release = vicam_close, .read = vicam_read, .mmap = vicam_mmap, .ioctl = vicam_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, }; static struct video_device vicam_template = { diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 48c8c4399..422ce849f 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -355,7 +355,7 @@ static void usbvision_remove_sysfs(struct video_device *vdev) * then allocates buffers needed for video processing. * */ -static int usbvision_v4l2_open(struct inode *inode, struct file *file) +static int usbvision_v4l2_open(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); int errCode = 0; @@ -432,7 +432,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) * allocated in usbvision_v4l2_open(). * */ -static int usbvision_v4l2_close(struct inode *inode, struct file *file) +static int usbvision_v4l2_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -1178,7 +1178,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) * Here comes the stuff for radio on usbvision based devices * */ -static int usbvision_radio_open(struct inode *inode, struct file *file) +static int usbvision_radio_open(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); int errCode = 0; @@ -1228,7 +1228,7 @@ out: } -static int usbvision_radio_close(struct inode *inode, struct file *file) +static int usbvision_radio_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); int errCode = 0; @@ -1266,13 +1266,13 @@ static int usbvision_radio_close(struct inode *inode, struct file *file) * Here comes the stuff for vbi on usbvision based devices * */ -static int usbvision_vbi_open(struct inode *inode, struct file *file) +static int usbvision_vbi_open(struct file *file) { /* TODO */ return -ENODEV; } -static int usbvision_vbi_close(struct inode *inode, struct file *file) +static int usbvision_vbi_close(struct file *file) { /* TODO */ return -ENODEV; @@ -1285,7 +1285,7 @@ static int usbvision_do_vbi_ioctl(struct file *file, return -ENOIOCTLCMD; } -static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, +static int usbvision_vbi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, usbvision_do_vbi_ioctl); @@ -1297,16 +1297,14 @@ static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, // // Video template -static const struct file_operations usbvision_fops = { +static const struct v4l2_file_operations usbvision_fops = { .owner = THIS_MODULE, .open = usbvision_v4l2_open, .release = usbvision_v4l2_close, .read = usbvision_v4l2_read, .mmap = usbvision_v4l2_mmap, .ioctl = video_ioctl2, - .llseek = no_llseek, /* .poll = video_poll, */ - .compat_ioctl = v4l_compat_ioctl32, }; static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { @@ -1355,13 +1353,11 @@ static struct video_device usbvision_video_template = { // Radio template -static const struct file_operations usbvision_radio_fops = { +static const struct v4l2_file_operations usbvision_radio_fops = { .owner = THIS_MODULE, .open = usbvision_radio_open, .release = usbvision_radio_close, .ioctl = video_ioctl2, - .llseek = no_llseek, - .compat_ioctl = v4l_compat_ioctl32, }; static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = { @@ -1392,13 +1388,11 @@ static struct video_device usbvision_radio_template = { }; // vbi template -static const struct file_operations usbvision_vbi_fops = { +static const struct v4l2_file_operations usbvision_vbi_fops = { .owner = THIS_MODULE, .open = usbvision_vbi_open, .release = usbvision_vbi_close, .ioctl = usbvision_vbi_ioctl, - .llseek = no_llseek, - .compat_ioctl = v4l_compat_ioctl32, }; static struct video_device usbvision_vbi_template= diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 662039b99..fd3285ec9 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -406,7 +406,7 @@ static int uvc_has_privileges(struct uvc_fh *handle) * V4L2 file operations */ -static int uvc_v4l2_open(struct inode *inode, struct file *file) +static int uvc_v4l2_open(struct file *file) { struct uvc_video_device *video; struct uvc_fh *handle; @@ -448,7 +448,7 @@ done: return ret; } -static int uvc_v4l2_release(struct inode *inode, struct file *file) +static int uvc_v4l2_release(struct file *file) { struct uvc_video_device *video = video_drvdata(file); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; @@ -1002,7 +1002,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) return ret; } -static int uvc_v4l2_ioctl(struct inode *inode, struct file *file, +static int uvc_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { if (uvc_trace_param & UVC_TRACE_IOCTL) { @@ -1103,13 +1103,11 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) return uvc_queue_poll(&video->queue, file, wait); } -struct file_operations uvc_fops = { +const struct v4l2_file_operations uvc_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, .release = uvc_v4l2_release, .ioctl = uvc_v4l2_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, .read = uvc_v4l2_read, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index a045fa40d..7936d39c9 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -754,7 +754,7 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) } /* V4L2 interface */ -extern struct file_operations uvc_fops; +extern const struct v4l2_file_operations uvc_fops; /* Video */ extern int uvc_video_init(struct uvc_video_device *video); diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index ef9ece0d3..0797793e9 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -1077,12 +1077,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) } return ret; } -#else -long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) -{ - return -ENOIOCTLCMD; -} -#endif EXPORT_SYMBOL_GPL(v4l_compat_ioctl32); +#endif MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 0b832f210..8a56e9760 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -31,6 +31,7 @@ #include #include +#include #include "compat.h" #define VIDEO_NUM_DEVICES 256 @@ -220,7 +221,7 @@ static int v4l2_ioctl(struct inode *inode, struct file *filp, return -ENOTTY; /* Allow ioctl to continue even if the device was unregistered. Things like dequeueing buffers might still be useful. */ - return vdev->fops->ioctl(inode, filp, cmd, arg); + return vdev->fops->ioctl(filp, cmd, arg); } static long v4l2_unlocked_ioctl(struct file *filp, @@ -235,20 +236,6 @@ static long v4l2_unlocked_ioctl(struct file *filp, return vdev->fops->unlocked_ioctl(filp, cmd, arg); } -#ifdef CONFIG_COMPAT -static long v4l2_compat_ioctl(struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct video_device *vdev = video_devdata(filp); - - if (!vdev->fops->compat_ioctl) - return -ENOIOCTLCMD; - /* Allow ioctl to continue even if the device was unregistered. - Things like dequeueing buffers might still be useful. */ - return vdev->fops->compat_ioctl(filp, cmd, arg); -} -#endif - static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) { struct video_device *vdev = video_devdata(filp); @@ -277,7 +264,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) /* and increase the device refcount */ video_get(vdev); mutex_unlock(&videodev_lock); - ret = vdev->fops->open(inode, filp); + ret = vdev->fops->open(filp); /* decrease the refcount in case of an error */ if (ret) video_put(vdev); @@ -288,7 +275,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) static int v4l2_release(struct inode *inode, struct file *filp) { struct video_device *vdev = video_devdata(filp); - int ret = vdev->fops->release(inode, filp); + int ret = vdev->fops->release(filp); /* decrease the refcount unconditionally since the release() return value is ignored. */ @@ -304,7 +291,7 @@ static const struct file_operations v4l2_unlocked_fops = { .mmap = v4l2_mmap, .unlocked_ioctl = v4l2_unlocked_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = v4l2_compat_ioctl, + .compat_ioctl = v4l_compat_ioctl32, #endif .release = v4l2_release, .poll = v4l2_poll, @@ -319,7 +306,7 @@ static const struct file_operations v4l2_fops = { .mmap = v4l2_mmap, .ioctl = v4l2_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = v4l2_compat_ioctl, + .compat_ioctl = v4l_compat_ioctl32, #endif .release = v4l2_release, .poll = v4l2_poll, diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 9e32a2c56..ec0db1bd2 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -1853,7 +1853,7 @@ static int __video_do_ioctl(struct file *file, return ret; } -long __video_ioctl2(struct file *file, +int video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg) { char sbuf[128]; @@ -1945,11 +1945,4 @@ out: kfree(mbuf); return err; } -EXPORT_SYMBOL(__video_ioctl2); - -int video_ioctl2(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return __video_ioctl2(file, cmd, arg); -} EXPORT_SYMBOL(video_ioctl2); diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 50f685fae..6d70541b2 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -4023,7 +4023,7 @@ out: /* File operations */ -static int vino_open(struct inode *inode, struct file *file) +static int vino_open(struct file *file) { struct vino_channel_settings *vcs = video_drvdata(file); int ret = 0; @@ -4054,7 +4054,7 @@ static int vino_open(struct inode *inode, struct file *file) return ret; } -static int vino_close(struct inode *inode, struct file *file) +static int vino_close(struct file *file) { struct vino_channel_settings *vcs = video_drvdata(file); dprintk("close():\n"); @@ -4347,7 +4347,7 @@ static int vino_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int vino_ioctl(struct inode *inode, struct file *file, +static int vino_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct vino_channel_settings *vcs = video_drvdata(file); @@ -4368,14 +4368,13 @@ static int vino_ioctl(struct inode *inode, struct file *file, /* __initdata */ static int vino_init_stage; -static const struct file_operations vino_fops = { +static const struct v4l2_file_operations vino_fops = { .owner = THIS_MODULE, .open = vino_open, .release = vino_close, .ioctl = vino_ioctl, .mmap = vino_mmap, .poll = vino_poll, - .llseek = no_llseek, }; static struct video_device v4l_device_template = { diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 692a90c35..90a6f70bb 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -1027,9 +1027,9 @@ static int vidioc_s_ctrl(struct file *file, void *priv, File operations for the device ------------------------------------------------------------------*/ -static int vivi_open(struct inode *inode, struct file *file) +static int vivi_open(struct file *file) { - int minor = iminor(inode); + int minor = video_devdata(file)->minor; struct vivi_dev *dev; struct vivi_fh *fh = NULL; int i; @@ -1130,13 +1130,13 @@ vivi_poll(struct file *file, struct poll_table_struct *wait) return videobuf_poll_stream(file, q, wait); } -static int vivi_close(struct inode *inode, struct file *file) +static int vivi_close(struct file *file) { struct vivi_fh *fh = file->private_data; struct vivi_dev *dev = fh->dev; struct vivi_dmaqueue *vidq = &dev->vidq; - int minor = iminor(inode); + int minor = video_devdata(file)->minor; vivi_stop_thread(vidq); videobuf_stop(&fh->vb_vidq); @@ -1198,16 +1198,14 @@ static int vivi_mmap(struct file *file, struct vm_area_struct *vma) return ret; } -static const struct file_operations vivi_fops = { +static const struct v4l2_file_operations vivi_fops = { .owner = THIS_MODULE, .open = vivi_open, .release = vivi_close, .read = vivi_read, .poll = vivi_poll, .ioctl = video_ioctl2, /* V4L2 ioctl handler */ - .compat_ioctl = v4l_compat_ioctl32, .mmap = vivi_mmap, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops vivi_ioctl_ops = { diff --git a/linux/drivers/media/video/w9966.c b/linux/drivers/media/video/w9966.c index 53f317dcd..7118dd724 100644 --- a/linux/drivers/media/video/w9966.c +++ b/linux/drivers/media/video/w9966.c @@ -181,19 +181,19 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data); static int w9966_i2c_rbyte(struct w9966_dev* cam); #endif -static int w9966_v4l_ioctl(struct inode *inode, struct file *file, +static int w9966_v4l_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); -static int w9966_exclusive_open(struct inode *inode, struct file *file) +static int w9966_exclusive_open(struct file *file) { struct w9966_dev *cam = video_drvdata(file); return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; } -static int w9966_exclusive_release(struct inode *inode, struct file *file) +static int w9966_exclusive_release(struct file *file) { struct w9966_dev *cam = video_drvdata(file); @@ -201,16 +201,12 @@ static int w9966_exclusive_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations w9966_fops = { +static const struct v4l2_file_operations w9966_fops = { .owner = THIS_MODULE, .open = w9966_exclusive_open, .release = w9966_exclusive_release, .ioctl = w9966_v4l_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .read = w9966_v4l_read, - .llseek = no_llseek, }; static struct video_device w9966_template = { .name = W9966_DRIVERNAME, @@ -878,7 +874,7 @@ static int w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int w9966_v4l_ioctl(struct inode *inode, struct file *file, +static int w9966_v4l_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl); diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 5763a4234..45c5f1bae 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -399,13 +399,13 @@ MODULE_PARM_DESC(specific_debug, ****************************************************************************/ /* Video4linux interface */ -static const struct file_operations w9968cf_fops; -static int w9968cf_open(struct inode*, struct file*); -static int w9968cf_release(struct inode*, struct file*); -static int w9968cf_mmap(struct file*, struct vm_area_struct*); -static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long); -static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*); -static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int, +static const struct v4l2_file_operations w9968cf_fops; +static int w9968cf_open(struct file *); +static int w9968cf_release(struct file *); +static int w9968cf_mmap(struct file *, struct vm_area_struct *); +static int w9968cf_ioctl(struct file *, unsigned, unsigned long); +static ssize_t w9968cf_read(struct file *, char __user *, size_t, loff_t *); +static int w9968cf_v4l_ioctl(struct file *, unsigned int, void __user *); /* USB-specific */ @@ -2673,7 +2673,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam) * Video4Linux interface * ****************************************************************************/ -static int w9968cf_open(struct inode* inode, struct file* filp) +static int w9968cf_open(struct file *filp) { struct w9968cf_device* cam; int err; @@ -2759,7 +2759,7 @@ deallocate_memory: } -static int w9968cf_release(struct inode* inode, struct file* filp) +static int w9968cf_release(struct file *filp) { struct w9968cf_device* cam; @@ -2897,7 +2897,7 @@ static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma) static int -w9968cf_ioctl(struct inode* inode, struct file* filp, +w9968cf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct w9968cf_device* cam; @@ -2920,15 +2920,15 @@ w9968cf_ioctl(struct inode* inode, struct file* filp, return -EIO; } - err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg); + err = w9968cf_v4l_ioctl(filp, cmd, (void __user *)arg); mutex_unlock(&cam->fileop_mutex); return err; } -static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) +static int w9968cf_v4l_ioctl(struct file *filp, + unsigned int cmd, void __user *arg) { struct w9968cf_device* cam; const char* v4l1_ioctls[] = { @@ -3467,17 +3467,13 @@ ioctl_fail: } -static const struct file_operations w9968cf_fops = { +static const struct v4l2_file_operations w9968cf_fops = { .owner = THIS_MODULE, .open = w9968cf_open, .release = w9968cf_release, .read = w9968cf_read, .ioctl = w9968cf_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .mmap = w9968cf_mmap, - .llseek = no_llseek, }; diff --git a/linux/drivers/media/video/zc0301/zc0301_core.c b/linux/drivers/media/video/zc0301/zc0301_core.c index a8c1f6730..b67c7e054 100644 --- a/linux/drivers/media/video/zc0301/zc0301_core.c +++ b/linux/drivers/media/video/zc0301/zc0301_core.c @@ -653,7 +653,7 @@ static void zc0301_release_resources(struct kref *kref) } -static int zc0301_open(struct inode* inode, struct file* filp) +static int zc0301_open(struct file *filp) { struct zc0301_device* cam; int err = 0; @@ -737,7 +737,7 @@ out: } -static int zc0301_release(struct inode* inode, struct file* filp) +static int zc0301_release(struct file *filp) { struct zc0301_device* cam; @@ -1797,8 +1797,8 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) } -static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) +static int zc0301_ioctl_v4l2(struct file *filp, + unsigned int cmd, void __user *arg) { struct zc0301_device *cam = video_drvdata(filp); @@ -1892,7 +1892,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, } -static int zc0301_ioctl(struct inode* inode, struct file* filp, +static int zc0301_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct zc0301_device *cam = video_drvdata(filp); @@ -1916,7 +1916,7 @@ static int zc0301_ioctl(struct inode* inode, struct file* filp, V4LDBG(3, "zc0301", cmd); - err = zc0301_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); + err = zc0301_ioctl_v4l2(filp, cmd, (void __user *)arg); mutex_unlock(&cam->fileop_mutex); @@ -1924,18 +1924,14 @@ static int zc0301_ioctl(struct inode* inode, struct file* filp, } -static const struct file_operations zc0301_fops = { +static const struct v4l2_file_operations zc0301_fops = { .owner = THIS_MODULE, .open = zc0301_open, .release = zc0301_release, .ioctl = zc0301_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif .read = zc0301_read, .poll = zc0301_poll, .mmap = zc0301_mmap, - .llseek = no_llseek, }; /*****************************************************************************/ diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 605195a82..d7624b203 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1262,10 +1262,9 @@ zoran_close_end_session (struct file *file) */ static int -zoran_open (struct inode *inode, - struct file *file) +zoran_open(struct file *file) { - unsigned int minor = iminor(inode); + unsigned int minor = video_devdata(file)->minor; struct zoran *zr = NULL; struct zoran_fh *fh; int i, res, first_open = 0, have_module_locks = 0; @@ -1405,8 +1404,7 @@ open_unlock_and_return: } static int -zoran_close (struct inode *inode, - struct file *file) +zoran_close(struct file *file) { struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; @@ -4257,10 +4255,9 @@ static int zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) static int -zoran_ioctl (struct inode *inode, - struct file *file, - unsigned int cmd, - unsigned long arg) +zoran_ioctl(struct file *file, + unsigned int cmd, + unsigned long arg) { return video_usercopy(file, cmd, arg, zoran_do_ioctl); } @@ -4685,15 +4682,11 @@ zoran_mmap (struct file *file, return 0; } -static const struct file_operations zoran_fops = { +static const struct v4l2_file_operations zoran_fops = { .owner = THIS_MODULE, .open = zoran_open, .release = zoran_close, .ioctl = zoran_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, .read = zoran_read, .write = zoran_write, .mmap = zoran_mmap, diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 1f43328a5..3a409c0ff 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -635,7 +635,7 @@ static int zr364xx_vidioc_streamoff(struct file *file, void *priv, /* open the camera */ -static int zr364xx_open(struct inode *inode, struct file *file) +static int zr364xx_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct zr364xx_camera *cam = video_get_drvdata(vdev); @@ -689,7 +689,7 @@ out: /* release the camera */ -static int zr364xx_release(struct inode *inode, struct file *file) +static int zr364xx_release(struct file *file) { struct video_device *vdev = video_devdata(file); struct zr364xx_camera *cam; @@ -762,14 +762,13 @@ static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) } -static const struct file_operations zr364xx_fops = { +static const struct v4l2_file_operations zr364xx_fops = { .owner = THIS_MODULE, .open = zr364xx_open, .release = zr364xx_release, .read = zr364xx_read, .mmap = zr364xx_mmap, .ioctl = video_ioctl2, - .llseek = no_llseek, }; static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { diff --git a/linux/include/media/saa7146_vv.h b/linux/include/media/saa7146_vv.h index 6bbb0d93b..fd7f4fe8c 100644 --- a/linux/include/media/saa7146_vv.h +++ b/linux/include/media/saa7146_vv.h @@ -179,7 +179,7 @@ struct saa7146_ext_vv struct saa7146_extension_ioctls *ioctls; int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg); - struct file_operations vbi_fops; + struct v4l2_file_operations vbi_fops; }; struct saa7146_use_ops { diff --git a/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h index c6cf5b1b2..baa0c21d4 100644 --- a/linux/include/media/v4l2-dev.h +++ b/linux/include/media/v4l2-dev.h @@ -25,6 +25,7 @@ #define VFL_TYPE_MAX 4 struct v4l2_ioctl_callbacks; +struct video_device; struct v4l2_device; /* Flag to mark the video_device struct as unregistered. @@ -32,6 +33,18 @@ struct v4l2_device; device access. It is set by video_unregister_device. */ #define V4L2_FL_UNREGISTERED (0) +struct v4l2_file_operations { + struct module *owner; + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); + ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); + unsigned int (*poll) (struct file *, struct poll_table_struct *); + int (*ioctl) (struct file *, unsigned int, unsigned long); + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); + int (*mmap) (struct file *, struct vm_area_struct *); + int (*open) (struct file *); + int (*release) (struct file *); +}; + /* * Newer version of video_device, handled by videodev2.c * This version moves redundant code from video device code to @@ -41,7 +54,7 @@ struct v4l2_device; struct video_device { /* device ops */ - const struct file_operations *fops; + const struct v4l2_file_operations *fops; /* sysfs */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) diff --git a/linux/include/media/v4l2-ioctl.h b/linux/include/media/v4l2-ioctl.h index fcdb58c4c..835af438e 100644 --- a/linux/include/media/v4l2-ioctl.h +++ b/linux/include/media/v4l2-ioctl.h @@ -286,27 +286,18 @@ int v4l_compat_translate_ioctl(struct file *file, #define v4l_compat_translate_ioctl(file, cmd, arg, ioctl) (-EINVAL) #endif +#ifdef CONFIG_COMPAT /* 32 Bits compatibility layer for 64 bits processors */ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg); +#endif /* Include support for obsoleted stuff */ extern int video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, v4l2_kioctl func); /* Standard handlers for V4L ioctl's */ - -/* This prototype is used on fops.unlocked_ioctl */ -extern long __video_ioctl2(struct file *file, - unsigned int cmd, unsigned long arg); - -/* This prototype is used on fops.ioctl - * Since fops.ioctl enables Kernel Big Lock, it is preferred - * to use __video_ioctl2 instead. - * It should be noticed that there's no lock code inside - * video_ioctl2(). - */ -extern int video_ioctl2(struct inode *inode, struct file *file, +extern int video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg); #endif /* _V4L2_IOCTL_H */ diff --git a/linux/include/sound/tea575x-tuner.h b/linux/include/sound/tea575x-tuner.h index 4076c6dfb..b09cf5882 100644 --- a/linux/include/sound/tea575x-tuner.h +++ b/linux/include/sound/tea575x-tuner.h @@ -50,7 +50,7 @@ struct snd_tea575x { struct snd_card *card; #endif struct video_device vd; /* video device */ - struct file_operations fops; + struct v4l2_file_operations fops; int dev_nr; /* requested device number + 1 */ int vd_registered; /* video device is registered */ int tea5759; /* 5759 chip is present */ diff --git a/linux/sound/i2c/other/tea575x-tuner.c b/linux/sound/i2c/other/tea575x-tuner.c index 2d07c8ea5..f13494a73 100644 --- a/linux/sound/i2c/other/tea575x-tuner.c +++ b/linux/sound/i2c/other/tea575x-tuner.c @@ -89,7 +89,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea) * Linux Video interface */ -static int snd_tea575x_ioctl(struct inode *inode, struct file *file, +static int snd_tea575x_ioctl(struct file *file, unsigned int cmd, unsigned long data) { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) @@ -185,7 +185,7 @@ static void snd_tea575x_release(struct video_device *vfd) { } -static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file) +static int snd_tea575x_exclusive_open(struct file *file) { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) tea575x_t *tea = video_drvdata(file); @@ -196,7 +196,7 @@ static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file) return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0; } -static int snd_tea575x_exclusive_release(struct inode *inode, struct file *file) +static int snd_tea575x_exclusive_release(struct file *file) { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) tea575x_t *tea = video_drvdata(file); -- cgit v1.2.3 From 8cf45753ff5b8f410dcb8165cf5c339436153ed8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2008 17:42:25 +0100 Subject: v4l2 doc: update v4l2-framework.txt From: Hans Verkuil Mention the new v4l2_file_operations struct. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index 38d054aa0..3b483c1e0 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -392,13 +392,16 @@ You should also set these fields: - v4l2_dev: set to the v4l2_device parent device. - name: set to something descriptive and unique. -- fops: set to the file_operations struct. +- fops: set to the v4l2_file_operations struct. - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance (highly recommended to use this and it might become compulsory in the future!), then set this to your v4l2_ioctl_ops struct. -If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to -__video_ioctl2 or .ioctl to video_ioctl2 in your file_operations struct. +If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or +.ioctl to video_ioctl2 in your v4l2_file_operations struct. + +The v4l2_file_operations struct is a subset of file_operations. The main +difference is that the inode argument is omitted since it is never used. video_device registration -- cgit v1.2.3 From db66abb56195fcfe907beec7b9a3d29278306256 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2008 19:02:16 +0100 Subject: v4l2-compat32: only build if needed From: Hans Verkuil Add CONFIG_COMPAT check in Makefile. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 1611c33b1..72f6d03d2 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -12,7 +12,10 @@ omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-subdev.o -obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-compat-ioctl32.o v4l2-int-device.o +obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o +ifeq ($(CONFIG_COMPAT),y) + obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o +endif obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o -- cgit v1.2.3 From 3e6b888d8b2f7a4ebef1b4c33acb0d253488ea4a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Dec 2008 11:04:34 +0100 Subject: v4l2-ioctl: change to long return type to match unlocked_ioctl. From: Hans Verkuil Since internal to v4l2 the ioctl prototype is the same regardless of it being called through .ioctl or .unlocked_ioctl, we need to convert it all to the long return type of unlocked_ioctl. Thanks to Jean-Francois Moine for posting an initial patch for this and thus bringing it to our attention. Priority: normal Signed-off-by: Hans Verkuil CC: Jean-Francois Moine --- linux/drivers/media/common/saa7146_fops.c | 2 +- linux/drivers/media/common/saa7146_video.c | 5 +- linux/drivers/media/dvb/ttpci/av7110_v4l.c | 2 +- linux/drivers/media/dvb/ttpci/budget-av.c | 2 +- linux/drivers/media/video/arv.c | 4 +- linux/drivers/media/video/bw-qcam.c | 4 +- linux/drivers/media/video/c-qcam.c | 4 +- linux/drivers/media/video/cpia.c | 4 +- linux/drivers/media/video/cpia2/cpia2_v4l.c | 6 +- linux/drivers/media/video/cx18/cx18-ioctl.c | 6 +- linux/drivers/media/video/cx18/cx18-ioctl.h | 2 +- linux/drivers/media/video/et61x251/et61x251_core.c | 6 +- linux/drivers/media/video/hexium_gemini.c | 2 +- linux/drivers/media/video/hexium_orion.c | 2 +- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 2 +- linux/drivers/media/video/meye.c | 2 +- linux/drivers/media/video/msp3400-driver.c | 2 +- linux/drivers/media/video/mxb.c | 2 +- linux/drivers/media/video/ov511.c | 4 +- linux/drivers/media/video/pms.c | 4 +- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 16 +- linux/drivers/media/video/pwc/pwc-ctrl.c | 4 +- linux/drivers/media/video/pwc/pwc-if.c | 6 +- linux/drivers/media/video/pwc/pwc-v4l.c | 2 +- linux/drivers/media/video/pwc/pwc.h | 4 +- linux/drivers/media/video/saa5246a.c | 6 +- linux/drivers/media/video/saa5249.c | 6 +- linux/drivers/media/video/se401.c | 4 +- linux/drivers/media/video/sn9c102/sn9c102_core.c | 4 +- linux/drivers/media/video/stradis.c | 2 +- linux/drivers/media/video/stv680.c | 4 +- linux/drivers/media/video/tda9840.c | 2 +- linux/drivers/media/video/tea6415c.c | 2 +- linux/drivers/media/video/tea6420.c | 2 +- linux/drivers/media/video/tuner-core.c | 2 +- linux/drivers/media/video/usbvideo/usbvideo.c | 6 +- linux/drivers/media/video/usbvideo/vicam.c | 4 +- .../media/video/usbvision/usbvision-video.c | 4 +- linux/drivers/media/video/uvc/uvc_v4l2.c | 6 +- linux/drivers/media/video/v4l1-compat.c | 164 +++++++++++---------- linux/drivers/media/video/v4l2-compat-ioctl32.c | 10 +- linux/drivers/media/video/v4l2-ioctl.c | 14 +- linux/drivers/media/video/vino.c | 6 +- linux/drivers/media/video/w9966.c | 6 +- linux/drivers/media/video/w9968cf.c | 10 +- linux/drivers/media/video/zc0301/zc0301_core.c | 4 +- linux/drivers/media/video/zoran/zoran_driver.c | 4 +- linux/include/media/saa7146_vv.h | 4 +- linux/include/media/v4l2-dev.h | 2 +- linux/include/media/v4l2-device.h | 2 +- linux/include/media/v4l2-ioctl.h | 10 +- linux/include/media/v4l2-subdev.h | 2 +- linux/sound/i2c/other/tea575x-tuner.c | 2 +- 53 files changed, 198 insertions(+), 195 deletions(-) diff --git a/linux/drivers/media/common/saa7146_fops.c b/linux/drivers/media/common/saa7146_fops.c index b0e86eebb..b1ee5e3d9 100644 --- a/linux/drivers/media/common/saa7146_fops.c +++ b/linux/drivers/media/common/saa7146_fops.c @@ -309,7 +309,7 @@ static int fops_release(struct file *file) return 0; } -static int fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { /* DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg)); diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index 12717058e..416a37f1b 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -835,13 +835,14 @@ static int video_end(struct saa7146_fh *fh, struct file *file) * copying is done already, arg is a kernel pointer. */ -int saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) +long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; - int err = 0, result = 0, ee = 0; + long err = 0; + int result = 0, ee = 0; struct saa7146_use_ops *ops; struct videobuf_queue *q; diff --git a/linux/drivers/media/dvb/ttpci/av7110_v4l.c b/linux/drivers/media/dvb/ttpci/av7110_v4l.c index 315ba6fa0..c5b9c7056 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c @@ -316,7 +316,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh) return 0; } -static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static long av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct av7110 *av7110 = (struct av7110*) dev->ext_priv; diff --git a/linux/drivers/media/dvb/ttpci/budget-av.c b/linux/drivers/media/dvb/ttpci/budget-av.c index f996cef79..4182121d7 100644 --- a/linux/drivers/media/dvb/ttpci/budget-av.c +++ b/linux/drivers/media/dvb/ttpci/budget-av.c @@ -1493,7 +1493,7 @@ static struct saa7146_extension_ioctls ioctls[] = { {0, 0} }; -static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static long av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct budget_av *budget_av = (struct budget_av *) dev->ext_priv; diff --git a/linux/drivers/media/video/arv.c b/linux/drivers/media/video/arv.c index cc97a35a8..6d84626e1 100644 --- a/linux/drivers/media/video/arv.c +++ b/linux/drivers/media/video/arv.c @@ -397,7 +397,7 @@ out_up: return ret; } -static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long ar_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); struct ar_device *ar = video_get_drvdata(dev); @@ -540,7 +540,7 @@ static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int ar_ioctl(struct file *file, unsigned int cmd, +static long ar_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, ar_do_ioctl); diff --git a/linux/drivers/media/video/bw-qcam.c b/linux/drivers/media/video/bw-qcam.c index 12d50acbf..3702baad6 100644 --- a/linux/drivers/media/video/bw-qcam.c +++ b/linux/drivers/media/video/bw-qcam.c @@ -707,7 +707,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l * Video4linux interfacing */ -static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); struct qcam_device *qcam=(struct qcam_device *)dev; @@ -864,7 +864,7 @@ static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int qcam_ioctl(struct file *file, +static long qcam_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, qcam_do_ioctl); diff --git a/linux/drivers/media/video/c-qcam.c b/linux/drivers/media/video/c-qcam.c index 6e785c3c1..abb873fc6 100644 --- a/linux/drivers/media/video/c-qcam.c +++ b/linux/drivers/media/video/c-qcam.c @@ -501,7 +501,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le * Video4linux interfacing */ -static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); struct qcam_device *qcam=(struct qcam_device *)dev; @@ -666,7 +666,7 @@ static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int qcam_ioctl(struct file *file, +static long qcam_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, qcam_do_ioctl); diff --git a/linux/drivers/media/video/cpia.c b/linux/drivers/media/video/cpia.c index f1b993972..9baa70fc9 100644 --- a/linux/drivers/media/video/cpia.c +++ b/linux/drivers/media/video/cpia.c @@ -3334,7 +3334,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf, return cam->decompressed_frame.count; } -static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = file->private_data; struct cam_data *cam = video_get_drvdata(dev); @@ -3721,7 +3721,7 @@ static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg) return retval; } -static int cpia_ioctl(struct file *file, +static long cpia_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, cpia_do_ioctl); diff --git a/linux/drivers/media/video/cpia2/cpia2_v4l.c b/linux/drivers/media/video/cpia2/cpia2_v4l.c index 91870cc9c..9c25894fd 100644 --- a/linux/drivers/media/video/cpia2/cpia2_v4l.c +++ b/linux/drivers/media/video/cpia2/cpia2_v4l.c @@ -1572,10 +1572,10 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file) * cpia2_ioctl * *****************************************************************************/ -static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct camera_data *cam = video_drvdata(file); - int retval = 0; + long retval = 0; if (!cam) return -ENOTTY; @@ -1841,7 +1841,7 @@ static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) return retval; } -static int cpia2_ioctl(struct file *file, +static long cpia2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, cpia2_do_ioctl); diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 6cde2a7fa..4529f26b0 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -860,7 +860,7 @@ static int cx18_log_status(struct file *file, void *fh) return 0; } -static int cx18_default(struct file *file, void *fh, int cmd, void *arg) +static long cx18_default(struct file *file, void *fh, int cmd, void *arg) { struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; @@ -888,13 +888,13 @@ static int cx18_default(struct file *file, void *fh, int cmd, void *arg) return 0; } -int cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, +long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct video_device *vfd = video_devdata(filp); struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data; struct cx18 *cx = id->cx; - int res; + long res; mutex_lock(&cx->serialize_lock); diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.h b/linux/drivers/media/video/cx18/cx18-ioctl.h index 50b8d6056..e2ca0d152 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.h +++ b/linux/drivers/media/video/cx18/cx18-ioctl.h @@ -29,5 +29,5 @@ void cx18_set_funcs(struct video_device *vdev); int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std); int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); int cx18_s_input(struct file *file, void *fh, unsigned int inp); -int cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, +long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/linux/drivers/media/video/et61x251/et61x251_core.c b/linux/drivers/media/video/et61x251/et61x251_core.c index 706f2e630..bf88a1387 100644 --- a/linux/drivers/media/video/et61x251/et61x251_core.c +++ b/linux/drivers/media/video/et61x251/et61x251_core.c @@ -2396,7 +2396,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) } -static int et61x251_ioctl_v4l2(struct file *filp, +static long et61x251_ioctl_v4l2(struct file *filp, unsigned int cmd, void __user *arg) { struct et61x251_device *cam = video_drvdata(filp); @@ -2491,11 +2491,11 @@ static int et61x251_ioctl_v4l2(struct file *filp, } -static int et61x251_ioctl(struct file *filp, +static long et61x251_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct et61x251_device *cam = video_drvdata(filp); - int err = 0; + long err = 0; if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; diff --git a/linux/drivers/media/video/hexium_gemini.c b/linux/drivers/media/video/hexium_gemini.c index 185a862c0..043a3080b 100644 --- a/linux/drivers/media/video/hexium_gemini.c +++ b/linux/drivers/media/video/hexium_gemini.c @@ -307,7 +307,7 @@ static int hexium_detach(struct saa7146_dev *dev) return 0; } -static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct hexium *hexium = (struct hexium *) dev->ext_priv; diff --git a/linux/drivers/media/video/hexium_orion.c b/linux/drivers/media/video/hexium_orion.c index 53db5fabc..847518f78 100644 --- a/linux/drivers/media/video/hexium_orion.c +++ b/linux/drivers/media/video/hexium_orion.c @@ -371,7 +371,7 @@ static int hexium_detach(struct saa7146_dev *dev) return 0; } -static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct hexium *hexium = (struct hexium *) dev->ext_priv; diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index a6cd02460..1f6ca93b9 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1725,7 +1725,7 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) return 0; } -static int ivtv_default(struct file *file, void *fh, int cmd, void *arg) +static long ivtv_default(struct file *file, void *fh, int cmd, void *arg) { struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c index 649faa796..323aa378b 100644 --- a/linux/drivers/media/video/meye.c +++ b/linux/drivers/media/video/meye.c @@ -1582,7 +1582,7 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) return 0; } -static int vidioc_default(struct file *file, void *fh, int cmd, void *arg) +static long vidioc_default(struct file *file, void *fh, int cmd, void *arg) { switch (cmd) { case MEYEIOC_G_PARAMS: diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index 9d2c98b82..d59f7a537 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -488,7 +488,7 @@ static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) } #ifdef CONFIG_VIDEO_ALLOW_V4L1 -static int msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +static long msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct msp_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 8252ad94c..974d9bcbd 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -490,7 +490,7 @@ static int mxb_detach(struct saa7146_dev *dev) return 0; } -static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static long mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; diff --git a/linux/drivers/media/video/ov511.c b/linux/drivers/media/video/ov511.c index 03ab40832..12d109eaa 100644 --- a/linux/drivers/media/video/ov511.c +++ b/linux/drivers/media/video/ov511.c @@ -4014,7 +4014,7 @@ ov51x_v4l1_close(struct file *file) } /* Do not call this function directly! */ -static int +static long ov51x_v4l1_ioctl_internal(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = file->private_data; @@ -4453,7 +4453,7 @@ redo: return 0; } -static int +static long ov51x_v4l1_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { diff --git a/linux/drivers/media/video/pms.c b/linux/drivers/media/video/pms.c index da5de81c2..ca6404605 100644 --- a/linux/drivers/media/video/pms.c +++ b/linux/drivers/media/video/pms.c @@ -681,7 +681,7 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int * Video4linux interfacing */ -static int pms_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long pms_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); struct pms_device *pd=(struct pms_device *)dev; @@ -863,7 +863,7 @@ static int pms_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int pms_ioctl(struct file *file, +static long pms_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, pms_do_ioctl); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index d1a6a9c1b..36ce7ebf9 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -169,13 +169,13 @@ static const char *get_v4l_name(int v4l_type) * This is part of Video 4 Linux API. The procedure handles ioctl() calls. * */ -static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_v4l2 *vp = fh->vhead; struct pvr2_v4l2_dev *dev_info = fh->dev_info; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int ret = -EINVAL; + long ret = -EINVAL; if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd); @@ -872,20 +872,20 @@ static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (ret < 0) { if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { pvr2_trace(PVR2_TRACE_V4LIOCTL, - "pvr2_v4l2_do_ioctl failure, ret=%d",ret); + "pvr2_v4l2_do_ioctl failure, ret=%ld", ret); } else { if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { pvr2_trace(PVR2_TRACE_V4LIOCTL, - "pvr2_v4l2_do_ioctl failure, ret=%d" - " command was:",ret); + "pvr2_v4l2_do_ioctl failure, ret=%ld" + " command was:", ret); v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); } } } else { pvr2_trace(PVR2_TRACE_V4LIOCTL, - "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)", - ret,ret); + "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)", + ret, ret); } return ret; } @@ -949,7 +949,7 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) } -static int pvr2_v4l2_ioctl(struct file *file, +static long pvr2_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { diff --git a/linux/drivers/media/video/pwc/pwc-ctrl.c b/linux/drivers/media/video/pwc/pwc-ctrl.c index c66530210..f9fbe02e0 100644 --- a/linux/drivers/media/video/pwc/pwc-ctrl.c +++ b/linux/drivers/media/video/pwc/pwc-ctrl.c @@ -1266,9 +1266,9 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) /* copy local variable to arg */ #define ARG_OUT(ARG_name) /* nothing */ -int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) +long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { - int ret = 0; + long ret = 0; switch(cmd) { case VIDIOCPWCRUSER: diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index cce3ceda1..63c8ff8df 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -147,7 +147,7 @@ static int pwc_video_close(struct file *file); static ssize_t pwc_video_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); static unsigned int pwc_video_poll(struct file *file, poll_table *wait); -static int pwc_video_ioctl(struct file *file, +static long pwc_video_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg); static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); @@ -1399,12 +1399,12 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) return 0; } -static int pwc_video_ioctl(struct file *file, +static long pwc_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct video_device *vdev = file->private_data; struct pwc_device *pdev; - int r = -ENODEV; + long r = -ENODEV; if (!vdev) goto out; diff --git a/linux/drivers/media/video/pwc/pwc-v4l.c b/linux/drivers/media/video/pwc/pwc-v4l.c index d7c147328..bc0a46429 100644 --- a/linux/drivers/media/video/pwc/pwc-v4l.c +++ b/linux/drivers/media/video/pwc/pwc-v4l.c @@ -337,7 +337,7 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f) } -int pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) +long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); struct pwc_device *pdev; diff --git a/linux/drivers/media/video/pwc/pwc.h b/linux/drivers/media/video/pwc/pwc.h index ade796037..a76971ead 100644 --- a/linux/drivers/media/video/pwc/pwc.h +++ b/linux/drivers/media/video/pwc/pwc.h @@ -338,10 +338,10 @@ extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise); extern int pwc_camera_power(struct pwc_device *pdev, int power); /* Private ioctl()s; see pwc-ioctl.h */ -extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); +extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); /** Functions in pwc-v4l.c */ -extern int pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg); +extern long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg); /** pwc-uncompress.c */ /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */ diff --git a/linux/drivers/media/video/saa5246a.c b/linux/drivers/media/video/saa5246a.c index 78ae8f46e..cb8a92e5f 100644 --- a/linux/drivers/media/video/saa5246a.c +++ b/linux/drivers/media/video/saa5246a.c @@ -805,7 +805,7 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t, * * Returns 0 if successful */ -static int do_saa5246a_ioctl(struct file *file, unsigned int cmd, void *arg) +static long do_saa5246a_ioctl(struct file *file, unsigned int cmd, void *arg) { struct saa5246a_device *t = video_drvdata(file); @@ -945,11 +945,11 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) /* * Handle the locking */ -static int saa5246a_ioctl(struct file *file, +static long saa5246a_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct saa5246a_device *t = video_drvdata(file); - int err; + long err; cmd = vtx_fix_command(cmd); mutex_lock(&t->lock); diff --git a/linux/drivers/media/video/saa5249.c b/linux/drivers/media/video/saa5249.c index d91fd838d..9102c6cea 100644 --- a/linux/drivers/media/video/saa5249.c +++ b/linux/drivers/media/video/saa5249.c @@ -191,7 +191,7 @@ static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) * Standard character-device-driver functions */ -static int do_saa5249_ioctl(struct file *file, unsigned int cmd, void *arg) +static long do_saa5249_ioctl(struct file *file, unsigned int cmd, void *arg) { static int virtual_mode = false; struct saa5249_device *t = video_drvdata(file); @@ -480,11 +480,11 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) * Handle the locking */ -static int saa5249_ioctl(struct file *file, +static long saa5249_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct saa5249_device *t = video_drvdata(file); - int err; + long err; cmd = vtx_fix_command(cmd); mutex_lock(&t->lock); diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c index 3ca9f31fb..cca1cb0c4 100644 --- a/linux/drivers/media/video/se401.c +++ b/linux/drivers/media/video/se401.c @@ -983,7 +983,7 @@ static int se401_close(struct file *file) return 0; } -static int se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = file->private_data; struct usb_se401 *se401 = (struct usb_se401 *)vdev; @@ -1146,7 +1146,7 @@ static int se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int se401_ioctl(struct file *file, +static long se401_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, se401_do_ioctl); diff --git a/linux/drivers/media/video/sn9c102/sn9c102_core.c b/linux/drivers/media/video/sn9c102/sn9c102_core.c index 1421a644f..63432ccd2 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_core.c +++ b/linux/drivers/media/video/sn9c102/sn9c102_core.c @@ -3096,7 +3096,7 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg) } -static int sn9c102_ioctl_v4l2(struct file *filp, +static long sn9c102_ioctl_v4l2(struct file *filp, unsigned int cmd, void __user *arg) { struct sn9c102_device *cam = video_drvdata(filp); @@ -3200,7 +3200,7 @@ static int sn9c102_ioctl_v4l2(struct file *filp, } -static int sn9c102_ioctl(struct file *filp, +static long sn9c102_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct sn9c102_device *cam = video_drvdata(filp); diff --git a/linux/drivers/media/video/stradis.c b/linux/drivers/media/video/stradis.c index 755c6b517..33001b426 100644 --- a/linux/drivers/media/video/stradis.c +++ b/linux/drivers/media/video/stradis.c @@ -1280,7 +1280,7 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr) clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y); } -static int saa_ioctl(struct file *file, +static long saa_ioctl(struct file *file, unsigned int cmd, unsigned long argl) { struct saa7146 *saa = file->private_data; diff --git a/linux/drivers/media/video/stv680.c b/linux/drivers/media/video/stv680.c index 715c823e1..a2d7ec732 100644 --- a/linux/drivers/media/video/stv680.c +++ b/linux/drivers/media/video/stv680.c @@ -1137,7 +1137,7 @@ static int stv_close(struct file *file) return 0; } -static int stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = file->private_data; struct usb_stv *stv680 = video_get_drvdata(vdev); @@ -1304,7 +1304,7 @@ static int stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int stv680_ioctl(struct file *file, +static long stv680_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, stv680_do_ioctl); diff --git a/linux/drivers/media/video/tda9840.c b/linux/drivers/media/video/tda9840.c index 7b749e4bb..62e257161 100644 --- a/linux/drivers/media/video/tda9840.c +++ b/linux/drivers/media/video/tda9840.c @@ -138,7 +138,7 @@ static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) return 0; } -static int tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static long tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) { int byte; diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index 21900def4..0f589842c 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -123,7 +123,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o) return ret; } -static int tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static long tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) { if (cmd == TEA6415C_SWITCH) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index aee419402..b5f8342e0 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -91,7 +91,7 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) return 0; } -static int tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static long tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) { if (cmd == TEA6420_SWITCH) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 343ab2d8b..0188d87ea 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -810,7 +810,7 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) } #ifdef CONFIG_VIDEO_ALLOW_V4L1 -static int tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +static long tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/usbvideo/usbvideo.c b/linux/drivers/media/video/usbvideo/usbvideo.c index 6d66c95cb..dc6ffbbf8 100644 --- a/linux/drivers/media/video/usbvideo/usbvideo.c +++ b/linux/drivers/media/video/usbvideo/usbvideo.c @@ -41,7 +41,7 @@ module_param(video_nr, int, 0); static void usbvideo_Disconnect(struct usb_interface *intf); static void usbvideo_CameraRelease(struct uvd *uvd); -static int usbvideo_v4l_ioctl(struct file *file, +static long usbvideo_v4l_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); static int usbvideo_v4l_open(struct file *file); @@ -1277,7 +1277,7 @@ static int usbvideo_v4l_close(struct file *file) * History: * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings. */ -static int usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct uvd *uvd = file->private_data; @@ -1497,7 +1497,7 @@ static int usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int usbvideo_v4l_ioctl(struct file *file, +static long usbvideo_v4l_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl); diff --git a/linux/drivers/media/video/usbvideo/vicam.c b/linux/drivers/media/video/usbvideo/vicam.c index 76c7eeaec..1c02f38a7 100644 --- a/linux/drivers/media/video/usbvideo/vicam.c +++ b/linux/drivers/media/video/usbvideo/vicam.c @@ -539,12 +539,12 @@ set_camera_power(struct vicam_camera *cam, int state) return 0; } -static int +static long vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg) { void __user *user_arg = (void __user *)arg; struct vicam_camera *cam = file->private_data; - int retval = 0; + long retval = 0; if (!cam) return -ENODEV; diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 422ce849f..1c9c2188a 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1278,14 +1278,14 @@ static int usbvision_vbi_close(struct file *file) return -ENODEV; } -static int usbvision_do_vbi_ioctl(struct file *file, +static long usbvision_do_vbi_ioctl(struct file *file, unsigned int cmd, void *arg) { /* TODO */ return -ENOIOCTLCMD; } -static int usbvision_vbi_ioctl(struct file *file, +static long usbvision_vbi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, usbvision_do_vbi_ioctl); diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index fd3285ec9..2f958379d 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -478,12 +478,12 @@ static int uvc_v4l2_release(struct file *file) return 0; } -static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); struct uvc_video_device *video = video_get_drvdata(vdev); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; - int ret = 0; + long ret = 0; switch (cmd) { /* Query capabilities */ @@ -1002,7 +1002,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) return ret; } -static int uvc_v4l2_ioctl(struct file *file, +static long uvc_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { if (uvc_trace_param & UVC_TRACE_IOCTL) { diff --git a/linux/drivers/media/video/v4l1-compat.c b/linux/drivers/media/video/v4l1-compat.c index ff1d3eb68..14b559b16 100644 --- a/linux/drivers/media/video/v4l1-compat.c +++ b/linux/drivers/media/video/v4l1-compat.c @@ -268,12 +268,12 @@ done: /* ----------------------------------------------------------------- */ -static noinline int v4l1_compat_get_capabilities( +static noinline long v4l1_compat_get_capabilities( struct video_capability *cap, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_framebuffer fbuf; struct v4l2_capability *cap2; @@ -287,13 +287,13 @@ static noinline int v4l1_compat_get_capabilities( err = drv(file, VIDIOC_QUERYCAP, cap2); if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err); + dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %ld\n", err); goto done; } if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { err = drv(file, VIDIOC_G_FBUF, &fbuf); if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err); + dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %ld\n", err); memset(&fbuf, 0, sizeof(fbuf)); } err = 0; @@ -325,12 +325,12 @@ done: return err; } -static noinline int v4l1_compat_get_frame_buffer( +static noinline long v4l1_compat_get_frame_buffer( struct video_buffer *buffer, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_framebuffer fbuf; memset(buffer, 0, sizeof(*buffer)); @@ -338,7 +338,7 @@ static noinline int v4l1_compat_get_frame_buffer( err = drv(file, VIDIOC_G_FBUF, &fbuf); if (err < 0) { - dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err); + dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %ld\n", err); goto done; } buffer->base = fbuf.base; @@ -379,12 +379,12 @@ done: return err; } -static noinline int v4l1_compat_set_frame_buffer( +static noinline long v4l1_compat_set_frame_buffer( struct video_buffer *buffer, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_framebuffer fbuf; memset(&fbuf, 0, sizeof(fbuf)); @@ -411,16 +411,16 @@ static noinline int v4l1_compat_set_frame_buffer( fbuf.fmt.bytesperline = buffer->bytesperline; err = drv(file, VIDIOC_S_FBUF, &fbuf); if (err < 0) - dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err); + dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %ld\n", err); return err; } -static noinline int v4l1_compat_get_win_cap_dimensions( +static noinline long v4l1_compat_get_win_cap_dimensions( struct video_window *win, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_format *fmt; fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); @@ -433,7 +433,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions( fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) - dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err); + dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %ld\n", err); if (err == 0) { win->x = fmt->fmt.win.w.left; win->y = fmt->fmt.win.w.top; @@ -448,7 +448,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions( fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) { - dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err); + dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %ld\n", err); goto done; } win->x = 0; @@ -463,12 +463,12 @@ done: return err; } -static noinline int v4l1_compat_set_win_cap_dimensions( +static noinline long v4l1_compat_set_win_cap_dimensions( struct video_window *win, struct file *file, v4l2_kioctl drv) { - int err, err1, err2; + long err, err1, err2; struct v4l2_format *fmt; fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); @@ -480,7 +480,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions( drv(file, VIDIOC_STREAMOFF, &fmt->type); err1 = drv(file, VIDIOC_G_FMT, fmt); if (err1 < 0) - dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1); + dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %ld\n", err1); if (err1 == 0) { fmt->fmt.pix.width = win->width; fmt->fmt.pix.height = win->height; @@ -488,7 +488,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions( fmt->fmt.pix.bytesperline = 0; err = drv(file, VIDIOC_S_FMT, fmt); if (err < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n", + dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %ld\n", err); win->width = fmt->fmt.pix.width; win->height = fmt->fmt.pix.height; @@ -505,7 +505,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions( fmt->fmt.win.clipcount = win->clipcount; err2 = drv(file, VIDIOC_S_FMT, fmt); if (err2 < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2); + dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %ld\n", err2); if (err1 != 0 && err2 != 0) err = err1; @@ -515,12 +515,12 @@ static noinline int v4l1_compat_set_win_cap_dimensions( return err; } -static noinline int v4l1_compat_turn_preview_on_off( +static noinline long v4l1_compat_turn_preview_on_off( int *on, struct file *file, v4l2_kioctl drv) { - int err; + long err; enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (0 == *on) { @@ -531,16 +531,16 @@ static noinline int v4l1_compat_turn_preview_on_off( } err = drv(file, VIDIOC_OVERLAY, on); if (err < 0) - dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); + dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %ld\n", err); return err; } -static noinline int v4l1_compat_get_input_info( +static noinline long v4l1_compat_get_input_info( struct video_channel *chan, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_input input2; v4l2_std_id sid; @@ -549,7 +549,7 @@ static noinline int v4l1_compat_get_input_info( err = drv(file, VIDIOC_ENUMINPUT, &input2); if (err < 0) { dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " - "channel=%d err=%d\n", chan->channel, err); + "channel=%d err=%ld\n", chan->channel, err); goto done; } chan->channel = input2.index; @@ -570,7 +570,7 @@ static noinline int v4l1_compat_get_input_info( chan->norm = 0; err = drv(file, VIDIOC_G_STD, &sid); if (err < 0) - dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err); + dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %ld\n", err); if (err == 0) { if (sid & V4L2_STD_PAL) chan->norm = VIDEO_MODE_PAL; @@ -583,17 +583,17 @@ done: return err; } -static noinline int v4l1_compat_set_input( +static noinline long v4l1_compat_set_input( struct video_channel *chan, struct file *file, v4l2_kioctl drv) { - int err; + long err; v4l2_std_id sid = 0; err = drv(file, VIDIOC_S_INPUT, &chan->channel); if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err); + dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %ld\n", err); switch (chan->norm) { case VIDEO_MODE_PAL: sid = V4L2_STD_PAL; @@ -608,17 +608,17 @@ static noinline int v4l1_compat_set_input( if (0 != sid) { err = drv(file, VIDIOC_S_STD, &sid); if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err); + dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %ld\n", err); } return err; } -static noinline int v4l1_compat_get_picture( +static noinline long v4l1_compat_get_picture( struct video_picture *pict, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_format *fmt; fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); @@ -641,7 +641,7 @@ static noinline int v4l1_compat_get_picture( fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) { - dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err); + dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %ld\n", err); goto done; } @@ -655,12 +655,12 @@ done: return err; } -static noinline int v4l1_compat_set_picture( +static noinline long v4l1_compat_set_picture( struct video_picture *pict, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_framebuffer fbuf; int mem_err = 0, ovl_err = 0; struct v4l2_format *fmt; @@ -695,7 +695,7 @@ static noinline int v4l1_compat_set_picture( support memory capture. Trying to set the memory capture parameters would be pointless. */ if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err); + dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %ld\n", err); mem_err = -1000; /* didn't even try */ } else if (fmt->fmt.pix.pixelformat != palette_to_pixelformat(pict->palette)) { @@ -712,7 +712,7 @@ static noinline int v4l1_compat_set_picture( support overlay. Trying to set the overlay parameters would be quite pointless. */ if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err); + dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %ld\n", err); ovl_err = -1000; /* didn't even try */ } else if (fbuf.fmt.pixelformat != palette_to_pixelformat(pict->palette)) { @@ -737,12 +737,13 @@ static noinline int v4l1_compat_set_picture( return err; } -static noinline int v4l1_compat_get_tuner( +static noinline long v4l1_compat_get_tuner( struct video_tuner *tun, struct file *file, v4l2_kioctl drv) { - int err, i; + long err; + int i; struct v4l2_tuner tun2; struct v4l2_standard std2; v4l2_std_id sid; @@ -750,7 +751,7 @@ static noinline int v4l1_compat_get_tuner( memset(&tun2, 0, sizeof(tun2)); err = drv(file, VIDIOC_G_TUNER, &tun2); if (err < 0) { - dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err); + dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %ld\n", err); goto done; } memcpy(tun->name, tun2.name, @@ -776,7 +777,7 @@ static noinline int v4l1_compat_get_tuner( err = drv(file, VIDIOC_G_STD, &sid); if (err < 0) - dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err); + dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %ld\n", err); if (err == 0) { if (sid & V4L2_STD_PAL) tun->mode = VIDEO_MODE_PAL; @@ -795,12 +796,12 @@ done: return err; } -static noinline int v4l1_compat_select_tuner( +static noinline long v4l1_compat_select_tuner( struct video_tuner *tun, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_tuner t;/*84 bytes on x86_64*/ memset(&t, 0, sizeof(t)); @@ -808,34 +809,34 @@ static noinline int v4l1_compat_select_tuner( err = drv(file, VIDIOC_S_INPUT, &t); if (err < 0) - dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err); + dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %ld\n", err); return err; } -static noinline int v4l1_compat_get_frequency( +static noinline long v4l1_compat_get_frequency( unsigned long *freq, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_frequency freq2; memset(&freq2, 0, sizeof(freq2)); freq2.tuner = 0; err = drv(file, VIDIOC_G_FREQUENCY, &freq2); if (err < 0) - dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err); + dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %ld\n", err); if (0 == err) *freq = freq2.frequency; return err; } -static noinline int v4l1_compat_set_frequency( +static noinline long v4l1_compat_set_frequency( unsigned long *freq, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_frequency freq2; memset(&freq2, 0, sizeof(freq2)); @@ -843,16 +844,17 @@ static noinline int v4l1_compat_set_frequency( freq2.frequency = *freq; err = drv(file, VIDIOC_S_FREQUENCY, &freq2); if (err < 0) - dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err); + dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %ld\n", err); return err; } -static noinline int v4l1_compat_get_audio( +static noinline long v4l1_compat_get_audio( struct video_audio *aud, struct file *file, v4l2_kioctl drv) { - int err, i; + long err; + int i; struct v4l2_queryctrl qctrl2; struct v4l2_audio aud2; struct v4l2_tuner tun2; @@ -860,7 +862,7 @@ static noinline int v4l1_compat_get_audio( err = drv(file, VIDIOC_G_AUDIO, &aud2); if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err); + dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %ld\n", err); goto done; } memcpy(aud->name, aud2.name, @@ -904,7 +906,7 @@ static noinline int v4l1_compat_get_audio( memset(&tun2, 0, sizeof(tun2)); err = drv(file, VIDIOC_G_TUNER, &tun2); if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err); + dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %ld\n", err); err = 0; goto done; } @@ -919,12 +921,12 @@ done: return err; } -static noinline int v4l1_compat_set_audio( +static noinline long v4l1_compat_set_audio( struct video_audio *aud, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_audio aud2; struct v4l2_tuner tun2; @@ -934,7 +936,7 @@ static noinline int v4l1_compat_set_audio( aud2.index = aud->audio; err = drv(file, VIDIOC_S_AUDIO, &aud2); if (err < 0) { - dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err); + dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %ld\n", err); goto done; } @@ -951,7 +953,7 @@ static noinline int v4l1_compat_set_audio( err = drv(file, VIDIOC_G_TUNER, &tun2); if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err); + dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %ld\n", err); if (err == 0) { switch (aud->mode) { default: @@ -968,19 +970,19 @@ static noinline int v4l1_compat_set_audio( } err = drv(file, VIDIOC_S_TUNER, &tun2); if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err); + dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %ld\n", err); } err = 0; done: return err; } -static noinline int v4l1_compat_capture_frame( +static noinline long v4l1_compat_capture_frame( struct video_mmap *mm, struct file *file, v4l2_kioctl drv) { - int err; + long err; enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; struct v4l2_buffer buf; struct v4l2_format *fmt; @@ -995,7 +997,7 @@ static noinline int v4l1_compat_capture_frame( fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err); + dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %ld\n", err); goto done; } if (mm->width != fmt->fmt.pix.width || @@ -1011,7 +1013,7 @@ static noinline int v4l1_compat_capture_frame( fmt->fmt.pix.bytesperline = 0; err = drv(file, VIDIOC_S_FMT, fmt); if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err); + dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %ld\n", err); goto done; } } @@ -1019,28 +1021,28 @@ static noinline int v4l1_compat_capture_frame( buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err); + dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %ld\n", err); goto done; } err = drv(file, VIDIOC_QBUF, &buf); if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err); + dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %ld\n", err); goto done; } err = drv(file, VIDIOC_STREAMON, &captype); if (err < 0) - dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err); + dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %ld\n", err); done: kfree(fmt); return err; } -static noinline int v4l1_compat_sync( +static noinline long v4l1_compat_sync( int *i, struct file *file, v4l2_kioctl drv) { - int err; + long err; enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; struct v4l2_buffer buf; struct poll_wqueues *pwq; @@ -1051,7 +1053,7 @@ static noinline int v4l1_compat_sync( err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) { /* No such buffer */ - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); + dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err); goto done; } if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) { @@ -1063,7 +1065,7 @@ static noinline int v4l1_compat_sync( /* make sure capture actually runs so we don't block forever */ err = drv(file, VIDIOC_STREAMON, &captype); if (err < 0) { - dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err); + dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %ld\n", err); goto done; } @@ -1077,7 +1079,7 @@ static noinline int v4l1_compat_sync( break; err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); + dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err); } kfree(pwq); if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */ @@ -1085,18 +1087,18 @@ static noinline int v4l1_compat_sync( do { err = drv(file, VIDIOC_DQBUF, &buf); if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err); + dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %ld\n", err); } while (err == 0 && buf.index != *i); done: return err; } -static noinline int v4l1_compat_get_vbi_format( +static noinline long v4l1_compat_get_vbi_format( struct vbi_format *fmt, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_format *fmt2; fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); @@ -1108,7 +1110,7 @@ static noinline int v4l1_compat_get_vbi_format( err = drv(file, VIDIOC_G_FMT, fmt2); if (err < 0) { - dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); + dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %ld\n", err); goto done; } if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { @@ -1129,12 +1131,12 @@ done: return err; } -static noinline int v4l1_compat_set_vbi_format( +static noinline long v4l1_compat_set_vbi_format( struct vbi_format *fmt, struct file *file, v4l2_kioctl drv) { - int err; + long err; struct v4l2_format *fmt2 = NULL; if (VIDEO_PALETTE_RAW != fmt->sample_format) { @@ -1158,7 +1160,7 @@ static noinline int v4l1_compat_set_vbi_format( fmt2->fmt.vbi.flags = fmt->flags; err = drv(file, VIDIOC_TRY_FMT, fmt2); if (err < 0) { - dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err); + dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %ld\n", err); goto done; } @@ -1175,7 +1177,7 @@ static noinline int v4l1_compat_set_vbi_format( } err = drv(file, VIDIOC_S_FMT, fmt2); if (err < 0) - dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err); + dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %ld\n", err); done: kfree(fmt2); return err; @@ -1184,13 +1186,13 @@ done: /* * This function is exported. */ -int +long v4l_compat_translate_ioctl(struct file *file, int cmd, void *arg, v4l2_kioctl drv) { - int err; + long err; switch (cmd) { case VIDIOCGCAP: /* capability */ diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index 0797793e9..a20417fb1 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -223,9 +223,9 @@ static int get_microcode32(struct video_code *kp, struct video_code32 __user *up #endif -static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int ret = -ENOIOCTLCMD; + long ret = -ENOIOCTLCMD; if (file->f_op->unlocked_ioctl) ret = file->f_op->unlocked_ioctl(file, cmd, arg); @@ -710,7 +710,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32) #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32) -static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { union { #ifdef CONFIG_VIDEO_V4L1_COMPAT @@ -731,7 +731,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg } karg; void __user *up = compat_ptr(arg); int compatible_arg = 1; - int err = 0; + long err = 0; /* First, convert the command. */ switch (cmd) { @@ -944,7 +944,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) { - int ret = -ENOIOCTLCMD; + long ret = -ENOIOCTLCMD; if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl) return ret; diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index ec0db1bd2..c1d46bbd0 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -393,14 +393,14 @@ video_fix_command(unsigned int cmd) /* * Obsolete usercopy function - Should be removed soon */ -int +long video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, v4l2_kioctl func) { char sbuf[128]; void *mbuf = NULL; void *parg = NULL; - int err = -EINVAL; + long err = -EINVAL; int is_ext_ctrl; size_t ctrls_size = 0; void __user *user_ptr = NULL; @@ -624,13 +624,13 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) return -EINVAL; } -static int __video_do_ioctl(struct file *file, +static long __video_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vfd = video_devdata(file); const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; void *fh = file->private_data; - int ret = -EINVAL; + long ret = -EINVAL; if ((vfd->debug & V4L2_DEBUG_IOCTL) && !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { @@ -1846,20 +1846,20 @@ static int __video_do_ioctl(struct file *file, if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { if (ret < 0) { v4l_print_ioctl(vfd->name, cmd); - printk(KERN_CONT " error %d\n", ret); + printk(KERN_CONT " error %ld\n", ret); } } return ret; } -int video_ioctl2(struct file *file, +long video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg) { char sbuf[128]; void *mbuf = NULL; void *parg = NULL; - int err = -EINVAL; + long err = -EINVAL; int is_ext_ctrl; size_t ctrls_size = 0; void __user *user_ptr = NULL; diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 6d70541b2..349ef053f 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -4241,7 +4241,7 @@ error: return ret; } -static int vino_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long vino_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct vino_channel_settings *vcs = video_drvdata(file); @@ -4347,11 +4347,11 @@ static int vino_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int vino_ioctl(struct file *file, +static long vino_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct vino_channel_settings *vcs = video_drvdata(file); - int ret; + long ret; if (mutex_lock_interruptible(&vcs->mutex)) return -EINTR; diff --git a/linux/drivers/media/video/w9966.c b/linux/drivers/media/video/w9966.c index 7118dd724..b8ede9e3f 100644 --- a/linux/drivers/media/video/w9966.c +++ b/linux/drivers/media/video/w9966.c @@ -181,7 +181,7 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data); static int w9966_i2c_rbyte(struct w9966_dev* cam); #endif -static int w9966_v4l_ioctl(struct file *file, +static long w9966_v4l_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); @@ -724,7 +724,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data) * Video4linux interfacing */ -static int w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct w9966_dev *cam = video_drvdata(file); @@ -874,7 +874,7 @@ static int w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } -static int w9966_v4l_ioctl(struct file *file, +static long w9966_v4l_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl); diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 45c5f1bae..55fb4b585 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -403,9 +403,9 @@ static const struct v4l2_file_operations w9968cf_fops; static int w9968cf_open(struct file *); static int w9968cf_release(struct file *); static int w9968cf_mmap(struct file *, struct vm_area_struct *); -static int w9968cf_ioctl(struct file *, unsigned, unsigned long); +static long w9968cf_ioctl(struct file *, unsigned, unsigned long); static ssize_t w9968cf_read(struct file *, char __user *, size_t, loff_t *); -static int w9968cf_v4l_ioctl(struct file *, unsigned int, +static long w9968cf_v4l_ioctl(struct file *, unsigned int, void __user *); /* USB-specific */ @@ -2896,12 +2896,12 @@ static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma) } -static int +static long w9968cf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct w9968cf_device* cam; - int err; + long err; cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); @@ -2927,7 +2927,7 @@ w9968cf_ioctl(struct file *filp, } -static int w9968cf_v4l_ioctl(struct file *filp, +static long w9968cf_v4l_ioctl(struct file *filp, unsigned int cmd, void __user *arg) { struct w9968cf_device* cam; diff --git a/linux/drivers/media/video/zc0301/zc0301_core.c b/linux/drivers/media/video/zc0301/zc0301_core.c index b67c7e054..b6a3ac815 100644 --- a/linux/drivers/media/video/zc0301/zc0301_core.c +++ b/linux/drivers/media/video/zc0301/zc0301_core.c @@ -1797,7 +1797,7 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) } -static int zc0301_ioctl_v4l2(struct file *filp, +static long zc0301_ioctl_v4l2(struct file *filp, unsigned int cmd, void __user *arg) { struct zc0301_device *cam = video_drvdata(filp); @@ -1892,7 +1892,7 @@ static int zc0301_ioctl_v4l2(struct file *filp, } -static int zc0301_ioctl(struct file *filp, +static long zc0301_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct zc0301_device *cam = video_drvdata(filp); diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index d7624b203..dffa2e96f 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2003,7 +2003,7 @@ zoran_set_input (struct zoran *zr, * ioctl routine */ -static int zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; @@ -4254,7 +4254,7 @@ static int zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) } -static int +static long zoran_ioctl(struct file *file, unsigned int cmd, unsigned long arg) diff --git a/linux/include/media/saa7146_vv.h b/linux/include/media/saa7146_vv.h index fd7f4fe8c..c8d0b23fd 100644 --- a/linux/include/media/saa7146_vv.h +++ b/linux/include/media/saa7146_vv.h @@ -177,7 +177,7 @@ struct saa7146_ext_vv int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *); struct saa7146_extension_ioctls *ioctls; - int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg); + long (*ioctl)(struct saa7146_fh *, unsigned int cmd, void *arg); struct v4l2_file_operations vbi_fops; }; @@ -216,7 +216,7 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); extern struct saa7146_use_ops saa7146_video_uops; int saa7146_start_preview(struct saa7146_fh *fh); int saa7146_stop_preview(struct saa7146_fh *fh); -int saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg); +long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg); /* from saa7146_vbi.c */ extern struct saa7146_use_ops saa7146_vbi_uops; diff --git a/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h index baa0c21d4..96b4ea2d9 100644 --- a/linux/include/media/v4l2-dev.h +++ b/linux/include/media/v4l2-dev.h @@ -38,7 +38,7 @@ struct v4l2_file_operations { ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); unsigned int (*poll) (struct file *, struct poll_table_struct *); - int (*ioctl) (struct file *, unsigned int, unsigned long); + long (*ioctl) (struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct file *); diff --git a/linux/include/media/v4l2-device.h b/linux/include/media/v4l2-device.h index 97b283a04..9bf4ccc93 100644 --- a/linux/include/media/v4l2-device.h +++ b/linux/include/media/v4l2-device.h @@ -80,7 +80,7 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); #define __v4l2_device_call_subdevs_until_err(dev, cond, o, f, args...) \ ({ \ struct v4l2_subdev *sd; \ - int err = 0; \ + long err = 0; \ \ list_for_each_entry(sd, &(dev)->subdevs, list) { \ if ((cond) && sd->ops->o && sd->ops->o->f) \ diff --git a/linux/include/media/v4l2-ioctl.h b/linux/include/media/v4l2-ioctl.h index 835af438e..172c39678 100644 --- a/linux/include/media/v4l2-ioctl.h +++ b/linux/include/media/v4l2-ioctl.h @@ -239,7 +239,7 @@ struct v4l2_ioctl_ops { struct v4l2_frmivalenum *fival); /* For other private ioctls */ - int (*vidioc_default) (struct file *file, void *fh, + long (*vidioc_default) (struct file *file, void *fh, int cmd, void *arg); }; @@ -277,10 +277,10 @@ extern const char *v4l2_field_names[]; extern const char *v4l2_type_names[]; /* Compatibility layer interface -- v4l1-compat module */ -typedef int (*v4l2_kioctl)(struct file *file, +typedef long (*v4l2_kioctl)(struct file *file, unsigned int cmd, void *arg); #ifdef CONFIG_VIDEO_V4L1_COMPAT -int v4l_compat_translate_ioctl(struct file *file, +long v4l_compat_translate_ioctl(struct file *file, int cmd, void *arg, v4l2_kioctl driver_ioctl); #else #define v4l_compat_translate_ioctl(file, cmd, arg, ioctl) (-EINVAL) @@ -293,11 +293,11 @@ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, #endif /* Include support for obsoleted stuff */ -extern int video_usercopy(struct file *file, unsigned int cmd, +extern long video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, v4l2_kioctl func); /* Standard handlers for V4L ioctl's */ -extern int video_ioctl2(struct file *file, +extern long video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg); #endif /* _V4L2_IOCTL_H */ diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h index ceef016bb..251734431 100644 --- a/linux/include/media/v4l2-subdev.h +++ b/linux/include/media/v4l2-subdev.h @@ -79,7 +79,7 @@ struct v4l2_subdev_core_ops { int (*g_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl); int (*s_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl); int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm); - int (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); + long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); #ifdef CONFIG_VIDEO_ADV_DEBUG int (*g_register)(struct v4l2_subdev *sd, struct v4l2_register *reg); int (*s_register)(struct v4l2_subdev *sd, struct v4l2_register *reg); diff --git a/linux/sound/i2c/other/tea575x-tuner.c b/linux/sound/i2c/other/tea575x-tuner.c index f13494a73..db47945e9 100644 --- a/linux/sound/i2c/other/tea575x-tuner.c +++ b/linux/sound/i2c/other/tea575x-tuner.c @@ -89,7 +89,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea) * Linux Video interface */ -static int snd_tea575x_ioctl(struct file *file, +static long snd_tea575x_ioctl(struct file *file, unsigned int cmd, unsigned long data) { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) -- cgit v1.2.3 From 11aa6827bc8e1035b00c3e957e46b1fd9de17a85 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Dec 2008 10:42:40 +0100 Subject: v4l: rename v4l_compat_ioctl32 to v4l2_compat_ioctl32 From: Hans Verkuil This rename prevents conflicts with the older compat_ioctl32 module. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-compat-ioctl32.c | 4 ++-- linux/drivers/media/video/v4l2-dev.c | 4 ++-- linux/include/media/v4l2-ioctl.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index a20417fb1..dedd0dea3 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -942,7 +942,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar return err; } -long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) +long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) { long ret = -ENOIOCTLCMD; @@ -1077,7 +1077,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) } return ret; } -EXPORT_SYMBOL_GPL(v4l_compat_ioctl32); +EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); #endif MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 8a56e9760..9e34e9ec2 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -291,7 +291,7 @@ static const struct file_operations v4l2_unlocked_fops = { .mmap = v4l2_mmap, .unlocked_ioctl = v4l2_unlocked_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, + .compat_ioctl = v4l2_compat_ioctl32, #endif .release = v4l2_release, .poll = v4l2_poll, @@ -306,7 +306,7 @@ static const struct file_operations v4l2_fops = { .mmap = v4l2_mmap, .ioctl = v4l2_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, + .compat_ioctl = v4l2_compat_ioctl32, #endif .release = v4l2_release, .poll = v4l2_poll, diff --git a/linux/include/media/v4l2-ioctl.h b/linux/include/media/v4l2-ioctl.h index 172c39678..bf0e723a9 100644 --- a/linux/include/media/v4l2-ioctl.h +++ b/linux/include/media/v4l2-ioctl.h @@ -288,7 +288,7 @@ long v4l_compat_translate_ioctl(struct file *file, #ifdef CONFIG_COMPAT /* 32 Bits compatibility layer for 64 bits processors */ -extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, +extern long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg); #endif -- cgit v1.2.3 From 033f7befdeeb65b662a90b0685f24ea62dfcbbd5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Dec 2008 11:07:53 +0100 Subject: gp8psk: fix incorrect return code (EINVAL instead of -EINVAL) From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/dvb-usb/gp8psk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk.c b/linux/drivers/media/dvb/dvb-usb/gp8psk.c index c1da962cc..3dd684386 100644 --- a/linux/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.c @@ -187,7 +187,7 @@ int gp8psk_bcm4500_reload(struct dvb_usb_device *d) /* load BCM4500 firmware */ if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) if (gp8psk_load_bcm4500fw(d)) - return EINVAL; + return -EINVAL; return 0; } -- cgit v1.2.3 From 1b466c7ec5d6b66905c47c49fd3cbc59569e7b4e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Dec 2008 11:14:19 +0100 Subject: v4l2: debugging API changed to match against driver name instead of ID. From: Hans Verkuil Since the i2c driver ID will be removed in the near future we have to modify the v4l2 debugging API to use the driver name instead of driver ID. Note that this API is not used in applications other than v4l2-dbg.cpp as it is for debugging and testing only. Should anyone use the old VIDIOC_G_CHIP_IDENT, then this will be logged with a warning that it is deprecated and will be removed in 2.6.30. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 2 +- linux/drivers/media/video/bt8xx/bttv-driver.c | 9 +- linux/drivers/media/video/cafe_ccic.c | 7 +- linux/drivers/media/video/cs5345.c | 13 +- linux/drivers/media/video/cs53l32a.c | 2 +- linux/drivers/media/video/cx18/cx18-i2c.c | 28 +--- linux/drivers/media/video/cx18/cx18-i2c.h | 1 - linux/drivers/media/video/cx18/cx18-ioctl.c | 41 ++--- linux/drivers/media/video/cx23885/cx23885-video.c | 8 +- linux/drivers/media/video/cx25840/cx25840-core.c | 13 +- linux/drivers/media/video/cx88/cx88-video.c | 13 +- linux/drivers/media/video/em28xx/em28xx-video.c | 28 ++-- linux/drivers/media/video/ivtv/ivtv-driver.c | 7 +- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 21 +-- linux/drivers/media/video/m52790.c | 13 +- linux/drivers/media/video/msp3400-driver.c | 2 +- linux/drivers/media/video/mt9m001.c | 19 +-- linux/drivers/media/video/mt9m111.c | 19 +-- linux/drivers/media/video/mt9t031.c | 18 +-- linux/drivers/media/video/mt9v022.c | 19 +-- linux/drivers/media/video/ov7670.c | 2 +- linux/drivers/media/video/ov772x.c | 7 +- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 11 +- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h | 4 +- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 6 +- linux/drivers/media/video/saa7115.c | 13 +- linux/drivers/media/video/saa7127.c | 13 +- linux/drivers/media/video/saa7134/saa6752hs.c | 2 +- .../drivers/media/video/saa7134/saa7134-empress.c | 14 +- linux/drivers/media/video/saa7134/saa7134-video.c | 9 +- linux/drivers/media/video/saa717x.c | 9 +- linux/drivers/media/video/soc_camera.c | 6 +- linux/drivers/media/video/tvaudio.c | 2 +- linux/drivers/media/video/tvp5150.c | 13 +- linux/drivers/media/video/tw9910.c | 6 +- linux/drivers/media/video/upd64031a.c | 13 +- linux/drivers/media/video/upd64083.c | 13 +- .../media/video/usbvision/usbvision-video.c | 9 +- linux/drivers/media/video/v4l2-common.c | 29 ++-- linux/drivers/media/video/v4l2-compat-ioctl32.c | 3 +- linux/drivers/media/video/v4l2-ioctl.c | 15 +- linux/drivers/media/video/v4l2-subdev.c | 2 +- linux/drivers/media/video/vp27smpx.c | 2 +- linux/drivers/media/video/wm8739.c | 2 +- linux/drivers/media/video/wm8775.c | 2 +- linux/include/linux/videodev2.h | 51 ++++-- linux/include/media/soc_camera.h | 6 +- linux/include/media/v4l2-chip-ident.h | 4 +- linux/include/media/v4l2-common.h | 6 +- linux/include/media/v4l2-int-device.h | 2 +- linux/include/media/v4l2-ioctl.h | 6 +- linux/include/media/v4l2-subdev.h | 6 +- v4l2-apps/test/ioctl-test.c | 8 +- v4l2-apps/util/Makefile | 11 +- v4l2-apps/util/cx18-ctl.c | 12 +- v4l2-apps/util/ivtv-ctl.c | 12 +- v4l2-apps/util/v4l2-compliance.cpp | 36 +++-- v4l2-apps/util/v4l2-dbg.cpp | 177 ++++++++------------- 58 files changed, 397 insertions(+), 430 deletions(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index 3b483c1e0..ff124374e 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -184,7 +184,7 @@ may be NULL if the subdev driver does not support anything from that category. It looks like this: struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip); + int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); int (*log_status)(struct v4l2_subdev *sd); int (*init)(struct v4l2_subdev *sd, u32 val); ... diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 4994afb1e..690e09b91 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -2067,7 +2067,7 @@ static int bttv_log_status(struct file *file, void *f) #ifdef CONFIG_VIDEO_ADV_DEBUG static int bttv_g_register(struct file *file, void *f, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct bttv_fh *fh = f; struct bttv *btv = fh->btv; @@ -2075,18 +2075,19 @@ static int bttv_g_register(struct file *file, void *f, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* bt848 has a 12-bit register space */ reg->reg &= 0xfff; reg->val = btread(reg->reg); + reg->size = 1; return 0; } static int bttv_s_register(struct file *file, void *f, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct bttv_fh *fh = f; struct bttv *btv = fh->btv; @@ -2094,7 +2095,7 @@ static int bttv_s_register(struct file *file, void *f, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* bt848 has a 12-bit register space */ diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 48ecd5d35..bb8959386 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -866,7 +866,7 @@ static int __cafe_cam_reset(struct cafe_camera *cam) */ static int cafe_cam_init(struct cafe_camera *cam) { - struct v4l2_chip_ident chip = { V4L2_CHIP_MATCH_I2C_ADDR, 0, 0, 0 }; + struct v4l2_dbg_chip_ident chip; int ret; mutex_lock(&cam->s_mutex); @@ -876,8 +876,9 @@ static int cafe_cam_init(struct cafe_camera *cam) ret = __cafe_cam_reset(cam); if (ret) goto out; - chip.match_chip = cam->sensor->addr; - ret = __cafe_cam_cmd(cam, VIDIOC_G_CHIP_IDENT, &chip); + chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; + chip.match.addr = cam->sensor->addr; + ret = __cafe_cam_cmd(cam, VIDIOC_DBG_G_CHIP_IDENT, &chip); if (ret) goto out; cam->sensor_type = chip.ident; diff --git a/linux/drivers/media/video/cs5345.c b/linux/drivers/media/video/cs5345.c index 1af0f53dd..9d19970ce 100644 --- a/linux/drivers/media/video/cs5345.c +++ b/linux/drivers/media/video/cs5345.c @@ -101,25 +101,24 @@ static int cs5345_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + reg->size = 1; reg->val = cs5345_read(sd, reg->reg & 0x1f); return 0; } -static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -128,7 +127,7 @@ static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) } #endif -static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c index 0620c4af4..842a8e4ed 100644 --- a/linux/drivers/media/video/cs53l32a.c +++ b/linux/drivers/media/video/cs53l32a.c @@ -103,7 +103,7 @@ static int cs53l32a_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index c0a79ecd4..efae2301a 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -268,7 +268,7 @@ int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg) return retval; } } - if (cmd != VIDIOC_G_CHIP_IDENT) + if (cmd != VIDIOC_DBG_G_CHIP_IDENT) CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n", addr, cmd); return -ENODEV; @@ -294,17 +294,6 @@ static int cx18_i2c_id_addr(struct cx18 *cx, u32 id) return retval; } -/* Find the i2c device name matching the DRIVERID */ -static const char *cx18_i2c_id_name(u32 id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) - if (hw_driverids[i] == id) - return hw_devicenames[i]; - return "unknown device"; -} - /* Find the i2c device name matching the CX18_HW_ flag */ static const char *cx18_i2c_hw_name(u32 hw) { @@ -352,21 +341,6 @@ int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg) return cx18_call_i2c_client(cx, addr, cmd, arg); } -/* Calls i2c device based on I2C driver ID. */ -int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg) -{ - int addr; - - addr = cx18_i2c_id_addr(cx, id); - if (addr < 0) { - if (cmd != VIDIOC_G_CHIP_IDENT) - CX18_ERR("i2c ID 0x%08x (%s) not found for cmd 0x%x!\n", - id, cx18_i2c_id_name(id), cmd); - return addr; - } - return cx18_call_i2c_client(cx, addr, cmd, arg); -} - /* broadcast cmd for all I2C clients and for the gpio subsystem */ void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg) { diff --git a/linux/drivers/media/video/cx18/cx18-i2c.h b/linux/drivers/media/video/cx18/cx18-i2c.h index 113c3f9a2..486973901 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.h +++ b/linux/drivers/media/video/cx18/cx18-i2c.h @@ -23,7 +23,6 @@ int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw); int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg); -int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg); int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg); void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg); int cx18_i2c_register(struct cx18 *cx, unsigned idx); diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 4529f26b0..84d6381aa 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -326,30 +326,24 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, } static int cx18_g_chip_ident(struct file *file, void *fh, - struct v4l2_chip_ident *chip) + struct v4l2_dbg_chip_ident *chip) { struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - if (chip->match_type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(chip->match_type, chip->match_chip)) - chip->ident = V4L2_IDENT_CX23418; + if (v4l2_chip_match_host(&chip->match)) { + chip->ident = V4L2_IDENT_CX23418; return 0; } - if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) - return cx18_i2c_id(cx, chip->match_chip, VIDIOC_G_CHIP_IDENT, - chip); - if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR) - return cx18_call_i2c_client(cx, chip->match_chip, - VIDIOC_G_CHIP_IDENT, chip); - return -EINVAL; + cx18_call_i2c_clients(cx, VIDIOC_DBG_G_CHIP_IDENT, chip); + return 0; } #ifdef CONFIG_VIDEO_ADV_DEBUG static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) { - struct v4l2_register *regs = arg; + struct v4l2_dbg_register *regs = arg; unsigned long flags; if (!capable(CAP_SYS_ADMIN)) @@ -358,6 +352,7 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) return -EINVAL; spin_lock_irqsave(&cx18_cards_lock, flags); + regs->size = 4; if (cmd == VIDIOC_DBG_G_REGISTER) regs->val = cx18_read_enc(cx, regs->reg); else @@ -367,31 +362,25 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) } static int cx18_g_register(struct file *file, void *fh, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; - if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (v4l2_chip_match_host(®->match)) return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg); - if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) - return cx18_i2c_id(cx, reg->match_chip, VIDIOC_DBG_G_REGISTER, - reg); - return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_G_REGISTER, - reg); + cx18_call_i2c_clients(cx, VIDIOC_DBG_G_REGISTER, reg); + return 0; } static int cx18_s_register(struct file *file, void *fh, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; - if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (v4l2_chip_match_host(®->match)) return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg); - if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) - return cx18_i2c_id(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER, - reg); - return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER, - reg); + cx18_call_i2c_clients(cx, VIDIOC_DBG_S_REGISTER, reg); + return 0; } #endif diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index 26f8b8efa..838b3ac5a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -1415,11 +1415,11 @@ static int vidioc_s_frequency(struct file *file, void *priv, #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register(struct file *file, void *fh, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg); @@ -1428,11 +1428,11 @@ static int vidioc_g_register(struct file *file, void *fh, } static int vidioc_s_register(struct file *file, void *fh, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg); diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 52a2a5799..9bac0e67a 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -1139,25 +1139,24 @@ static int cx25840_init(struct v4l2_subdev *sd, u32 val) } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + reg->size = 1; reg->val = cx25840_read(client, reg->reg & 0x0fff); return 0; } -static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1381,7 +1380,7 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val) return 0; } -static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 0f551f845..a95bcb0ea 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1713,25 +1713,26 @@ static int vidioc_s_frequency (struct file *file, void *priv, #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register (struct file *file, void *fh, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* cx2388x has a 24-bit register space */ - reg->val = cx_read(reg->reg&0xffffff); + reg->val = cx_read(reg->reg & 0xffffff); + reg->size = 4; return 0; } static int vidioc_s_register (struct file *file, void *fh, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; - cx_write(reg->reg&0xffffff, reg->val); + cx_write(reg->reg & 0xffffff, reg->val); return 0; } #endif diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index dd3f49140..eb3a87e0a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1164,7 +1164,7 @@ static int em28xx_reg_len(int reg) } static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_chip_ident *chip) + struct v4l2_dbg_chip_ident *chip) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; @@ -1172,20 +1172,20 @@ static int vidioc_g_chip_ident(struct file *file, void *priv, chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - em28xx_i2c_call_clients(dev, VIDIOC_G_CHIP_IDENT, chip); + em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); return 0; } static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int ret; - switch (reg->match_type) { + switch (reg->match.type) { case V4L2_CHIP_MATCH_AC97: mutex_lock(&dev->lock); ret = em28xx_read_ac97(dev, reg->reg); @@ -1194,6 +1194,7 @@ static int vidioc_g_register(struct file *file, void *priv, return ret; reg->val = ret; + reg->size = 1; return 0; case V4L2_CHIP_MATCH_I2C_DRIVER: em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_REGISTER, reg); @@ -1202,12 +1203,13 @@ static int vidioc_g_register(struct file *file, void *priv, /* Not supported yet */ return -EINVAL; default: - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; } /* Match host */ - if (em28xx_reg_len(reg->reg) == 1) { + reg->size = em28xx_reg_len(reg->reg); + if (reg->size == 1) { mutex_lock(&dev->lock); ret = em28xx_read_reg(dev, reg->reg); mutex_unlock(&dev->lock); @@ -1217,7 +1219,7 @@ static int vidioc_g_register(struct file *file, void *priv, reg->val = ret; } else { - __le64 val = 0; + __le16 val = 0; mutex_lock(&dev->lock); ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, reg->reg, (char *)&val, 2); @@ -1225,21 +1227,21 @@ static int vidioc_g_register(struct file *file, void *priv, if (ret < 0) return ret; - reg->val = le64_to_cpu(val); + reg->val = le16_to_cpu(val); } return 0; } static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - __le64 buf; + __le16 buf; int rc; - switch (reg->match_type) { + switch (reg->match.type) { case V4L2_CHIP_MATCH_AC97: mutex_lock(&dev->lock); rc = em28xx_write_ac97(dev, reg->reg, reg->val); @@ -1253,12 +1255,12 @@ static int vidioc_s_register(struct file *file, void *priv, /* Not supported yet */ return -EINVAL; default: - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; } /* Match host */ - buf = cpu_to_le64(reg->val); + buf = cpu_to_le16(reg->val); mutex_lock(&dev->lock); rc = em28xx_write_regs(dev, reg->reg, (char *)&buf, diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index b29625ca2..b712c29e7 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -906,18 +906,19 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) } if (hw & IVTV_HW_SAA711X) { - struct v4l2_chip_ident v = { V4L2_CHIP_MATCH_I2C_DRIVER, I2C_DRIVERID_SAA711X }; + struct v4l2_dbg_chip_ident v; /* determine the exact saa711x model */ itv->hw_flags &= ~IVTV_HW_SAA711X; + v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER; + strlcpy(v.match.name, "saa7115", sizeof(v.match.name)); ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v); if (v.ident == V4L2_IDENT_SAA7114) { itv->hw_flags |= IVTV_HW_SAA7114; /* VBI is not yet supported by the saa7114 driver. */ itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE); - } - else { + } else { itv->hw_flags |= IVTV_HW_SAA7115; } itv->vbi.raw_decoder_line_size = 1443; diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 1f6ca93b9..f6b3ef6e6 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -674,19 +674,19 @@ static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_f return ret; } -static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident *chip) +static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip) { struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - if (chip->match_type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(chip->match_type, chip->match_chip)) + if (chip->match.type == V4L2_CHIP_MATCH_HOST) { + if (v4l2_chip_match_host(&chip->match)) chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; return 0; } - if (chip->match_type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && + chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; /* TODO: is this correct? */ return ivtv_call_all_err(itv, core, g_chip_ident, chip); @@ -695,7 +695,7 @@ static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident #ifdef CONFIG_VIDEO_ADV_DEBUG static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) { - struct v4l2_register *regs = arg; + struct v4l2_dbg_register *regs = arg; volatile u8 __iomem *reg_start; if (!capable(CAP_SYS_ADMIN)) @@ -710,6 +710,7 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) else return -EINVAL; + regs->size = 4; if (cmd == VIDIOC_DBG_G_REGISTER) regs->val = readl(regs->reg + reg_start); else @@ -717,11 +718,11 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) return 0; } -static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *reg) +static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; - if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (v4l2_chip_match_host(®->match)) return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg); /* TODO: subdev errors should not be ignored, this should become a subdev helper function. */ @@ -729,11 +730,11 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *re return 0; } -static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg) +static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; - if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (v4l2_chip_match_host(®->match)) return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg); /* TODO: subdev errors should not be ignored, this should become a subdev helper function. */ diff --git a/linux/drivers/media/video/m52790.c b/linux/drivers/media/video/m52790.c index 1976451e0..af179cf4b 100644 --- a/linux/drivers/media/video/m52790.c +++ b/linux/drivers/media/video/m52790.c @@ -86,29 +86,28 @@ static int m52790_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct m52790_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (reg->reg != 0) return -EINVAL; + reg->size = 1; reg->val = state->input | state->output; return 0; } -static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct m52790_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -121,7 +120,7 @@ static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) } #endif -static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index d59f7a537..053f168bf 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -738,7 +738,7 @@ static int msp_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return 0; } -static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct msp_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index dd1435d41..3d8e6ed8d 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -343,14 +343,14 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, } static int mt9m001_get_chip_id(struct soc_camera_device *icd, - struct v4l2_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match_chip != mt9m001->client->addr) + if (id->match.addr != mt9m001->client->addr) return -ENODEV; id->ident = mt9m001->model; @@ -361,16 +361,17 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9m001_get_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match_chip != mt9m001->client->addr) + if (reg->match.addr != mt9m001->client->addr) return -ENODEV; + reg->size = 2; reg->val = reg_read(icd, reg->reg); if (reg->val > 0xffff) @@ -380,14 +381,14 @@ static int mt9m001_get_register(struct soc_camera_device *icd, } static int mt9m001_set_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match_chip != mt9m001->client->addr) + if (reg->match.addr != mt9m001->client->addr) return -ENODEV; if (reg_write(icd, reg->reg, reg->val) < 0) diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 39f2e83cf..cdf3f38e2 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -514,14 +514,14 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd, } static int mt9m111_get_chip_id(struct soc_camera_device *icd, - struct v4l2_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match_chip != mt9m111->client->addr) + if (id->match.addr != mt9m111->client->addr) return -ENODEV; id->ident = mt9m111->model; @@ -532,18 +532,19 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9m111_get_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { int val; struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; - if (reg->match_chip != mt9m111->client->addr) + if (reg->match.addr != mt9m111->client->addr) return -ENODEV; val = mt9m111_reg_read(icd, reg->reg); + reg->size = 2; reg->val = (u64)val; if (reg->val > 0xffff) @@ -553,14 +554,14 @@ static int mt9m111_get_register(struct soc_camera_device *icd, } static int mt9m111_set_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; - if (reg->match_chip != mt9m111->client->addr) + if (reg->match.addr != mt9m111->client->addr) return -ENODEV; if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0) diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 1a9d53966..349d8e365 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -326,14 +326,14 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, } static int mt9t031_get_chip_id(struct soc_camera_device *icd, - struct v4l2_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match_chip != mt9t031->client->addr) + if (id->match.addr != mt9t031->client->addr) return -ENODEV; id->ident = mt9t031->model; @@ -344,14 +344,14 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9t031_get_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match_chip != mt9t031->client->addr) + if (reg->match.addr != mt9t031->client->addr) return -ENODEV; reg->val = reg_read(icd, reg->reg); @@ -363,14 +363,14 @@ static int mt9t031_get_register(struct soc_camera_device *icd, } static int mt9t031_set_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match_chip != mt9t031->client->addr) + if (reg->match.addr != mt9t031->client->addr) return -ENODEV; if (reg_write(icd, reg->reg, reg->val) < 0) diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index e2579559d..9601884ca 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -422,14 +422,14 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, } static int mt9v022_get_chip_id(struct soc_camera_device *icd, - struct v4l2_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match_chip != mt9v022->client->addr) + if (id->match.addr != mt9v022->client->addr) return -ENODEV; id->ident = mt9v022->model; @@ -440,16 +440,17 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9v022_get_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match_chip != mt9v022->client->addr) + if (reg->match.addr != mt9v022->client->addr) return -ENODEV; + reg->size = 2; reg->val = reg_read(icd, reg->reg); if (reg->val > 0xffff) @@ -459,14 +460,14 @@ static int mt9v022_get_register(struct soc_camera_device *icd, } static int mt9v022_set_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match_chip != mt9v022->client->addr) + if (reg->match.addr != mt9v022->client->addr) return -ENODEV; if (reg_write(icd, reg->reg, reg->val) < 0) diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c index 9cf1aa2bc..ef9d7c022 100644 --- a/linux/drivers/media/video/ov7670.c +++ b/linux/drivers/media/video/ov7670.c @@ -1354,7 +1354,7 @@ static int ov7670_command(struct i2c_client *client, unsigned int cmd, void *arg) { switch (cmd) { - case VIDIOC_G_CHIP_IDENT: + case VIDIOC_DBG_G_CHIP_IDENT: return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0); case VIDIOC_INT_RESET: diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 932444623..ce389cacf 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -724,7 +724,7 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) } static int ov772x_get_chip_id(struct soc_camera_device *icd, - struct v4l2_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); @@ -736,11 +736,12 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov772x_get_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); int ret; + reg->size = 1; if (reg->reg > 0xff) return -EINVAL; @@ -754,7 +755,7 @@ static int ov772x_get_register(struct soc_camera_device *icd, } static int ov772x_set_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 447fcede8..21fdc66b4 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4867,26 +4867,25 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - u32 match_type, u32 match_chip, u64 reg_id, - int setFl,u64 *val_ptr) + struct v4l2_dbg_match *match, u64 reg_id, + int setFl, u64 *val_ptr) { #ifdef CONFIG_VIDEO_ADV_DEBUG struct pvr2_i2c_client *cp; - struct v4l2_register req; + struct v4l2_dbg_register req; int stat = 0; int okFl = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - req.match_type = match_type; - req.match_chip = match_chip; + req.match = *match; req.reg = reg_id; if (setFl) req.val = *val_ptr; mutex_lock(&hdw->i2c_list_lock); do { list_for_each_entry(cp, &hdw->i2c_clients, list) { if (!v4l2_chip_match_i2c_client( cp->client, - req.match_type, req.match_chip)) { + &req.match)) { continue; } stat = pvr2_i2c_client_cmd( diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 29fb0729d..732546fa3 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -248,8 +248,8 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, setFl - true to set the register, false to read it val_ptr - storage location for source / result. */ int pvr2_hdw_register_access(struct pvr2_hdw *, - u32 match_type, u32 match_chip,u64 reg_id, - int setFl,u64 *val_ptr); + struct v4l2_dbg_match *match, u64 reg_id, + int setFl, u64 *val_ptr); /* The following entry points are all lower level things you normally don't want to worry about. */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 36ce7ebf9..7340f4815 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -852,11 +852,11 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_DBG_G_REGISTER: { u64 val; - struct v4l2_register *req = (struct v4l2_register *)arg; + struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg; if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; ret = pvr2_hdw_register_access( - hdw,req->match_type,req->match_chip,req->reg, - cmd == VIDIOC_DBG_S_REGISTER,&val); + hdw, &req->match, req->reg, + cmd == VIDIOC_DBG_S_REGISTER, &val); if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; break; } diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index e9edd4d37..40b0196e6 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1372,25 +1372,24 @@ static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_dat } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; reg->val = saa711x_read(sd, reg->reg & 0xff); + reg->size = 1; return 0; } -static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1399,7 +1398,7 @@ static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) } #endif -static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct saa711x_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c index 5414b027f..79c947ca0 100644 --- a/linux/drivers/media/video/saa7127.c +++ b/linux/drivers/media/video/saa7127.c @@ -629,25 +629,24 @@ static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_v } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; reg->val = saa7127_read(sd, reg->reg & 0xff); + reg->size = 1; return 0; } -static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -656,7 +655,7 @@ static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) } #endif -static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct saa7127_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index 8ccca4d56..f2d4aea16 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -839,7 +839,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) h->standard = *((v4l2_std_id *) arg); break; - case VIDIOC_G_CHIP_IDENT: + case VIDIOC_DBG_G_CHIP_IDENT: return v4l2_chip_ident_i2c_client(client, arg, h->chip, h->revision); diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index 37235c4d0..6955db2fe 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -405,7 +405,7 @@ static int empress_querymenu(struct file *file, void *priv, } static int empress_g_chip_ident(struct file *file, void *fh, - struct v4l2_chip_ident *chip) + struct v4l2_dbg_chip_ident *chip) { struct saa7134_dev *dev = file->private_data; @@ -413,12 +413,12 @@ static int empress_g_chip_ident(struct file *file, void *fh, chip->revision = 0; if (dev->mpeg_i2c_client == NULL) return -EINVAL; - if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match_chip == I2C_DRIVERID_SAA6752HS) - return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); - if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR && - chip->match_chip == dev->mpeg_i2c_client->addr) - return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); + if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER && + !strcmp(chip->match.name, "saa6752hs")) + return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR && + chip->match.addr == dev->mpeg_i2c_client->addr) + return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); return -EINVAL; } diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 1fcf2693d..37dec30a4 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -2254,24 +2254,25 @@ static int saa7134_g_parm(struct file *file, void *fh, #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register (struct file *file, void *priv, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; reg->val = saa_readb(reg->reg); + reg->size = 1; return 0; } static int vidioc_s_register (struct file *file, void *priv, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; saa_writeb(reg->reg&0xffffff, reg->val); return 0; diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c index 2d667e66a..65bcf6dad 100644 --- a/linux/drivers/media/video/saa717x.c +++ b/linux/drivers/media/video/saa717x.c @@ -1177,25 +1177,26 @@ static int saa717x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; reg->val = saa717x_read(sd, reg->reg); + reg->size = 1; return 0; } -static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); u16 addr = reg->reg & 0xffff; u8 val = reg->val & 0xff; - if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4909b74db..356b77e10 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -700,7 +700,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, } static int soc_camera_g_chip_ident(struct file *file, void *fh, - struct v4l2_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; @@ -713,7 +713,7 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh, #ifdef CONFIG_VIDEO_ADV_DEBUG static int soc_camera_g_register(struct file *file, void *fh, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; @@ -725,7 +725,7 @@ static int soc_camera_g_register(struct file *file, void *fh, } static int soc_camera_s_register(struct file *file, void *fh, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 492da4d8e..3ca242af5 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -1770,7 +1770,7 @@ static int tvaudio_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fr return 0; } -static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index 404df4aa2..f968e8941 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -1030,7 +1030,7 @@ static int tvp5150_decode_vbi_line(struct v4l2_subdev *sd, #endif static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_chip_ident *chip) + struct v4l2_dbg_chip_ident *chip) { int rev; struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -1044,25 +1044,24 @@ static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_ADV_DEBUG -static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; reg->val = tvp5150_read(sd, reg->reg & 0xff); + reg->size = 1; return 0; } -static int tvp5150_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int tvp5150_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index d5cdc4be1..52c0357fa 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -575,7 +575,7 @@ static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) } static int tw9910_get_chip_id(struct soc_camera_device *icd, - struct v4l2_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { id->ident = V4L2_IDENT_TW9910; id->revision = 0; @@ -606,7 +606,7 @@ static int tw9910_enum_input(struct soc_camera_device *icd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int tw9910_get_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); int ret; @@ -627,7 +627,7 @@ static int tw9910_get_register(struct soc_camera_device *icd, } static int tw9910_set_register(struct soc_camera_device *icd, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c index df5f4b0c8..eb1dfe312 100644 --- a/linux/drivers/media/video/upd64031a.c +++ b/linux/drivers/media/video/upd64031a.c @@ -153,7 +153,7 @@ static int upd64031a_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing return upd64031a_s_frequency(sd, NULL); } -static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -168,25 +168,24 @@ static int upd64031a_log_status(struct v4l2_subdev *sd) } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; reg->val = upd64031a_read(sd, reg->reg & 0xff); + reg->size = 1; return 0; } -static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c index fe71b038b..7bc2f2fa6 100644 --- a/linux/drivers/media/video/upd64083.c +++ b/linux/drivers/media/video/upd64083.c @@ -126,25 +126,24 @@ static int upd64083_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; reg->val = upd64083_read(sd, reg->reg & 0xff); + reg->size = 1; return 0; } -static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) +static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, - reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -153,7 +152,7 @@ static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg } #endif -static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 1c9c2188a..71be57774 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -477,12 +477,12 @@ static int usbvision_v4l2_close(struct file *file) */ #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register (struct file *file, void *priv, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct usb_usbvision *usbvision = video_drvdata(file); int errCode; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* NT100x has a 8-bit register space */ errCode = usbvision_read_reg(usbvision, reg->reg&0xff); @@ -492,16 +492,17 @@ static int vidioc_g_register (struct file *file, void *priv, return errCode; } reg->val = errCode; + reg->size = 1; return 0; } static int vidioc_s_register (struct file *file, void *priv, - struct v4l2_register *reg) + struct v4l2_dbg_register *reg) { struct usb_usbvision *usbvision = video_drvdata(file); int errCode; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* NT100x has a 8-bit register space */ errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 02eb97fa4..27af4d97a 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -798,11 +798,11 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) } EXPORT_SYMBOL(v4l2_ctrl_next); -int v4l2_chip_match_host(u32 match_type, u32 match_chip) +int v4l2_chip_match_host(const struct v4l2_dbg_match *match) { - switch (match_type) { + switch (match->type) { case V4L2_CHIP_MATCH_HOST: - return match_chip == 0; + return match->addr == 0; default: return 0; } @@ -810,23 +810,34 @@ int v4l2_chip_match_host(u32 match_type, u32 match_chip) EXPORT_SYMBOL(v4l2_chip_match_host); #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) -int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip) +int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match) { - switch (match_type) { + int len; + + if (c == NULL || match == NULL) + return 0; + + switch (match->type) { case V4L2_CHIP_MATCH_I2C_DRIVER: - return (c != NULL && c->driver != NULL && c->driver->id == match_chip); + if (c->driver == NULL || c->driver->driver.name == NULL) + return 0; + len = strlen(c->driver->driver.name); + /* legacy drivers have a ' suffix, don't try to match that */ + if (len && c->driver->driver.name[len - 1] == '\'') + len--; + return len && !strncmp(c->driver->driver.name, match->name, len); case V4L2_CHIP_MATCH_I2C_ADDR: - return (c != NULL && c->addr == match_chip); + return c->addr == match->addr; default: return 0; } } EXPORT_SYMBOL(v4l2_chip_match_i2c_client); -int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip, +int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip, u32 ident, u32 revision) { - if (!v4l2_chip_match_i2c_client(c, chip->match_type, chip->match_chip)) + if (!v4l2_chip_match_i2c_client(c, &chip->match)) return 0; if (chip->ident == V4L2_IDENT_NONE) { chip->ident = ident; diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index dedd0dea3..05a356776 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -1051,7 +1051,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_TRY_ENCODER_CMD: case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: - case VIDIOC_G_CHIP_IDENT: + case VIDIOC_DBG_G_CHIP_IDENT: + case VIDIOC_G_CHIP_IDENT_OLD: case VIDIOC_S_HW_FREQ_SEEK: ret = do_video_ioctl(file, cmd, arg); break; diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index c1d46bbd0..165bc9005 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -267,7 +267,7 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", - [_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT", + [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT", [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK", #endif }; @@ -1721,7 +1721,7 @@ static long __video_do_ioctl(struct file *file, #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: { - struct v4l2_register *p = arg; + struct v4l2_dbg_register *p = arg; if (!capable(CAP_SYS_ADMIN)) ret = -EPERM; @@ -1731,7 +1731,7 @@ static long __video_do_ioctl(struct file *file, } case VIDIOC_DBG_S_REGISTER: { - struct v4l2_register *p = arg; + struct v4l2_dbg_register *p = arg; if (!capable(CAP_SYS_ADMIN)) ret = -EPERM; @@ -1740,9 +1740,9 @@ static long __video_do_ioctl(struct file *file, break; } #endif - case VIDIOC_G_CHIP_IDENT: + case VIDIOC_DBG_G_CHIP_IDENT: { - struct v4l2_chip_ident *p = arg; + struct v4l2_dbg_chip_ident *p = arg; if (!ops->vidioc_g_chip_ident) break; @@ -1751,6 +1751,11 @@ static long __video_do_ioctl(struct file *file, dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); break; } + case VIDIOC_G_CHIP_IDENT_OLD: + printk(KERN_ERR "VIDIOC_G_CHIP_IDENT has been deprecated and will disappear in 2.6.30.\n"); + printk(KERN_ERR "It is a debugging ioctl and must not be used in applications!\n"); + return -EINVAL; + case VIDIOC_S_HW_FREQ_SEEK: { struct v4l2_hw_freq_seek *p = arg; diff --git a/linux/drivers/media/video/v4l2-subdev.c b/linux/drivers/media/video/v4l2-subdev.c index e3612f29d..fbe9cc0d4 100644 --- a/linux/drivers/media/video/v4l2-subdev.c +++ b/linux/drivers/media/video/v4l2-subdev.c @@ -37,7 +37,7 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, core, queryctrl, arg); case VIDIOC_LOG_STATUS: return v4l2_subdev_call(sd, core, log_status); - case VIDIOC_G_CHIP_IDENT: + case VIDIOC_DBG_G_CHIP_IDENT: return v4l2_subdev_call(sd, core, g_chip_ident, arg); case VIDIOC_INT_S_STANDBY: return v4l2_subdev_call(sd, core, s_standby, arg ? (*(u32 *)arg) : 0); diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c index cd9df6a1c..b3b3ee61d 100644 --- a/linux/drivers/media/video/vp27smpx.c +++ b/linux/drivers/media/video/vp27smpx.c @@ -119,7 +119,7 @@ static int vp27smpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } -static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/wm8739.c b/linux/drivers/media/video/wm8739.c index ea311672c..ac81c6442 100644 --- a/linux/drivers/media/video/wm8739.c +++ b/linux/drivers/media/video/wm8739.c @@ -239,7 +239,7 @@ static int wm8739_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return -EINVAL; } -static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/drivers/media/video/wm8775.c b/linux/drivers/media/video/wm8775.c index 526926635..3140c1313 100644 --- a/linux/drivers/media/video/wm8775.c +++ b/linux/drivers/media/video/wm8775.c @@ -131,7 +131,7 @@ static int wm8775_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) +static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 0aae06946..b0c501074 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -1370,25 +1370,41 @@ struct v4l2_streamparm { /* * A D V A N C E D D E B U G G I N G * - * NOTE: EXPERIMENTAL API + * NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS! + * FOR DEBUGGING, TESTING AND INTERNAL USE ONLY! */ /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ #define V4L2_CHIP_MATCH_HOST 0 /* Match against chip ID on host (0 for the host) */ -#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver ID */ +#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver name */ #define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ #define V4L2_CHIP_MATCH_AC97 3 /* Match against anciliary AC97 chip */ -struct v4l2_register { - __u32 match_type; /* Match type */ - __u32 match_chip; /* Match this chip, meaning determined by match_type */ +struct v4l2_dbg_match { + __u32 type; /* Match type */ + union { /* Match this chip, meaning determined by type */ + __u32 addr; + char name[32]; + }; +} __attribute__ ((packed)); + +struct v4l2_dbg_register { + struct v4l2_dbg_match match; + __u32 size; /* register size in bytes */ __u64 reg; __u64 val; -}; +} __attribute__ ((packed)); + +/* VIDIOC_DBG_G_CHIP_IDENT */ +struct v4l2_dbg_chip_ident { + struct v4l2_dbg_match match; + __u32 ident; /* chip identifier as specified in */ + __u32 revision; /* chip revision, chip specific */ +} __attribute__ ((packed)); -/* VIDIOC_G_CHIP_IDENT */ -struct v4l2_chip_ident { +/* VIDIOC_G_CHIP_IDENT_OLD: Deprecated, do not use */ +struct v4l2_chip_ident_old { __u32 match_type; /* Match type */ __u32 match_chip; /* Match this chip, meaning determined by match_type */ __u32 ident; /* chip identifier as specified in */ @@ -1460,13 +1476,22 @@ struct v4l2_chip_ident { #define VIDIOC_G_ENC_INDEX _IOR('V', 76, struct v4l2_enc_idx) #define VIDIOC_ENCODER_CMD _IOWR('V', 77, struct v4l2_encoder_cmd) #define VIDIOC_TRY_ENCODER_CMD _IOWR('V', 78, struct v4l2_encoder_cmd) +#endif -/* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ -#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_register) -#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_register) - -#define VIDIOC_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_chip_ident) +#if 1 /*KEEP*/ +/* Experimental, meant for debugging, testing and internal use. + Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. + You must be root to use these ioctls. Never use these in applications! */ +#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) +#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) + +/* Experimental, meant for debugging, testing and internal use. + Never use this ioctl in applications! */ +#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident) +/* This is deprecated and will go away in 2.6.30 */ +#define VIDIOC_G_CHIP_IDENT_OLD _IOWR('V', 81, struct v4l2_chip_ident_old) #endif + #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 425b6a98c..7440d9250 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -164,12 +164,12 @@ struct soc_camera_ops { unsigned long (*query_bus_param)(struct soc_camera_device *); int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*get_chip_id)(struct soc_camera_device *, - struct v4l2_chip_ident *); + struct v4l2_dbg_chip_ident *); int (*set_std)(struct soc_camera_device *, v4l2_std_id *); int (*enum_input)(struct soc_camera_device *, struct v4l2_input *); #ifdef CONFIG_VIDEO_ADV_DEBUG - int (*get_register)(struct soc_camera_device *, struct v4l2_register *); - int (*set_register)(struct soc_camera_device *, struct v4l2_register *); + int (*get_register)(struct soc_camera_device *, struct v4l2_dbg_register *); + int (*set_register)(struct soc_camera_device *, struct v4l2_dbg_register *); #endif int (*get_control)(struct soc_camera_device *, struct v4l2_control *); int (*set_control)(struct soc_camera_device *, struct v4l2_control *); diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index 43dbb659f..9aaf652b2 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -2,7 +2,7 @@ v4l2 chip identifiers header This header provides a list of chip identifiers that can be returned - through the VIDIOC_G_CHIP_IDENT ioctl. + through the VIDIOC_DBG_G_CHIP_IDENT ioctl. Copyright (C) 2007 Hans Verkuil @@ -24,7 +24,7 @@ #ifndef V4L2_CHIP_IDENT_H_ #define V4L2_CHIP_IDENT_H_ -/* VIDIOC_G_CHIP_IDENT: identifies the actual chip installed on the board */ +/* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */ enum { /* general idents: reserved range 0-49 */ V4L2_IDENT_NONE = 0, /* No chip matched */ diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h index f99c866d8..95e74f187 100644 --- a/linux/include/media/v4l2-common.h +++ b/linux/include/media/v4l2-common.h @@ -114,10 +114,10 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* Register/chip ident helper function */ struct i2c_client; /* forward reference */ -int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 id_type, u32 chip_id); -int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip, +int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match); +int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip, u32 ident, u32 revision); -int v4l2_chip_match_host(u32 id_type, u32 chip_id); +int v4l2_chip_match_host(const struct v4l2_dbg_match *match); /* ------------------------------------------------------------------------- */ diff --git a/linux/include/media/v4l2-int-device.h b/linux/include/media/v4l2-int-device.h index ecda3c725..fbf585561 100644 --- a/linux/include/media/v4l2-int-device.h +++ b/linux/include/media/v4l2-int-device.h @@ -219,7 +219,7 @@ enum v4l2_int_ioctl_num { vidioc_int_reset_num, /* VIDIOC_INT_INIT */ vidioc_int_init_num, - /* VIDIOC_INT_G_CHIP_IDENT */ + /* VIDIOC_DBG_G_CHIP_IDENT */ vidioc_int_g_chip_ident_num, /* diff --git a/linux/include/media/v4l2-ioctl.h b/linux/include/media/v4l2-ioctl.h index bf0e723a9..b01c04486 100644 --- a/linux/include/media/v4l2-ioctl.h +++ b/linux/include/media/v4l2-ioctl.h @@ -225,12 +225,12 @@ struct v4l2_ioctl_ops { /* Debugging ioctls */ #ifdef CONFIG_VIDEO_ADV_DEBUG int (*vidioc_g_register) (struct file *file, void *fh, - struct v4l2_register *reg); + struct v4l2_dbg_register *reg); int (*vidioc_s_register) (struct file *file, void *fh, - struct v4l2_register *reg); + struct v4l2_dbg_register *reg); #endif int (*vidioc_g_chip_ident) (struct file *file, void *fh, - struct v4l2_chip_ident *chip); + struct v4l2_dbg_chip_ident *chip); int (*vidioc_enum_framesizes) (struct file *file, void *fh, struct v4l2_frmsizeenum *fsize); diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h index 251734431..37b09e56e 100644 --- a/linux/include/media/v4l2-subdev.h +++ b/linux/include/media/v4l2-subdev.h @@ -69,7 +69,7 @@ struct tuner_setup; not yet implemented) since ops provide proper type-checking. */ struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip); + int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); int (*log_status)(struct v4l2_subdev *sd); int (*init)(struct v4l2_subdev *sd, u32 val); int (*s_standby)(struct v4l2_subdev *sd, u32 standby); @@ -81,8 +81,8 @@ struct v4l2_subdev_core_ops { int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm); long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); #ifdef CONFIG_VIDEO_ADV_DEBUG - int (*g_register)(struct v4l2_subdev *sd, struct v4l2_register *reg); - int (*s_register)(struct v4l2_subdev *sd, struct v4l2_register *reg); + int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg); + int (*s_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg); #endif }; diff --git a/v4l2-apps/test/ioctl-test.c b/v4l2-apps/test/ioctl-test.c index 37a0e2374..f9ac1cad5 100644 --- a/v4l2-apps/test/ioctl-test.c +++ b/v4l2-apps/test/ioctl-test.c @@ -88,8 +88,9 @@ union v4l_parms { struct v4l2_frmivalenum p_v4l2_frmivalenum; struct v4l2_enc_idx p_v4l2_enc_idx; struct v4l2_encoder_cmd p_v4l2_encoder_cmd; - struct v4l2_register p_v4l2_register; - struct v4l2_chip_ident p_v4l2_chip_ident; + struct v4l2_dbg_register p_v4l2_dbg_register; + struct v4l2_dbg_chip_ident p_v4l2_dbg_chip_ident; + struct v4l2_chip_ident_old p_v4l2_chip_ident_old; struct v4l2_hw_freq_seek p_v4l2_hw_freq_seek; }; @@ -195,7 +196,8 @@ static const struct { ioc(VIDIOC_TRY_ENCODER_CMD), /* struct v4l2_encoder_cmd */ ioc(VIDIOC_DBG_S_REGISTER), /* struct v4l2_register */ ioc(VIDIOC_DBG_G_REGISTER), /* struct v4l2_register */ - ioc(VIDIOC_G_CHIP_IDENT), /* struct v4l2_chip_ident */ + ioc(VIDIOC_DBG_G_CHIP_IDENT), /* struct v4l2_dbg_chip_ident */ + ioc(VIDIOC_G_CHIP_IDENT_OLD), /* struct v4l2_chip_ident_old */ ioc(VIDIOC_S_HW_FREQ_SEEK), /* struct v4l2_hw_freq_seek */ #ifdef __OLD_VIDIOC_ ioc(VIDIOC_OVERLAY_OLD), /* int */ diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile index 0a28e7da9..b80de190b 100644 --- a/v4l2-apps/util/Makefile +++ b/v4l2-apps/util/Makefile @@ -18,18 +18,18 @@ endif all: $(binaries) qv4l2 keytable clean:: - rm -f $(binaries) v4l2-driverids.cpp v4l2-chipids.cpp + rm -f $(binaries) v4l2-chipids.cpp -if [ -f qv4l2/Makefile ]; then make -C qv4l2 $@; fi -rm -f qv4l2/qv4l2 qv4l2/Makefile make -C xc3028-firmware $@ - rm -f v4l2-driverids.cpp v4l2-chipids.cpp + rm -f v4l2-chipids.cpp rm -rf keycodes parse.h keytable qv4l2: -if [ ! -f qv4l2/Makefile ]; then (cd qv4l2; qmake); fi $(MAKE) -C qv4l2 -v4l2-dbg: v4l2-dbg.o v4l2-driverids.o v4l2-chipids.o +v4l2-dbg: v4l2-dbg.o v4l2-chipids.o $(CXX) $^ -o $@ v4l2-dbg.o: v4l2-dbg.h v4l2-dbg-bttv.h v4l2-dbg-em28xx.h v4l2-dbg-saa7134.h @@ -59,11 +59,6 @@ keytables: keytable: keytable.c parse.h keytables -v4l2-driverids.cpp: ../include/linux/i2c-id.h - @echo "struct driverid { const char *name; unsigned id; } driverids[] = {" >$@ - @grep I2C_DRIVERID_ $^ | sed -e 's/.*I2C_DRIVERID_\([0-9A-Z_]*\)[^0-9]*\([0-9]*\).*/{ "\1", \2 },/' | tr A-Z a-z >>$@ - @echo "{ 0, 0 }};" >>$@ - v4l2-chipids.cpp: ../include/media/v4l2-chip-ident.h @echo "struct chipid { const char *name; unsigned id; } chipids[] = {" >$@ @grep V4L2_IDENT_ $^ | sed -e 's/.*V4L2_IDENT_\([0-9A-Z_]*\)[^=]*=[^0-9]*\([0-9]*\).*/{ "\1", \2 },/' | tr A-Z a-z >>$@ diff --git a/v4l2-apps/util/cx18-ctl.c b/v4l2-apps/util/cx18-ctl.c index 4081f3aef..3d8ff385d 100644 --- a/v4l2-apps/util/cx18-ctl.c +++ b/v4l2-apps/util/cx18-ctl.c @@ -419,10 +419,10 @@ int main(int argc, char **argv) doioctl(fd, VIDIOC_INT_S_AUDIO_ROUTING, &route, "VIDIOC_INT_S_AUDIO_ROUTING"); if (options[OptSetGPIO]) { - struct v4l2_register reg; + struct v4l2_dbg_register reg; - reg.match_type = V4L2_CHIP_MATCH_HOST; - reg.match_chip = 0; + reg.match.type = V4L2_CHIP_MATCH_HOST; + reg.match.addr = 0; reg.reg = CX18_REG_GPIO_DIR1; reg.val = (unsigned)((gpio_dir & 0xffff) << 16); if (gpio_set_dir && doioctl(fd, VIDIOC_DBG_S_REGISTER, ®, @@ -446,10 +446,10 @@ int main(int argc, char **argv) } if (options[OptListGPIO]) { - struct v4l2_register reg; + struct v4l2_dbg_register reg; - reg.match_type = V4L2_CHIP_MATCH_HOST; - reg.match_chip = 0; + reg.match.type = V4L2_CHIP_MATCH_HOST; + reg.match.addr = 0; reg.reg = CX18_REG_GPIO_IN; if (ioctl(fd, VIDIOC_DBG_G_REGISTER, ®) == 0) printf("GPIO in: 0x%04llx\n", reg.val); diff --git a/v4l2-apps/util/ivtv-ctl.c b/v4l2-apps/util/ivtv-ctl.c index af84164e3..a05dcbba2 100644 --- a/v4l2-apps/util/ivtv-ctl.c +++ b/v4l2-apps/util/ivtv-ctl.c @@ -564,10 +564,10 @@ int main(int argc, char **argv) } if (options[OptSetGPIO]) { - struct v4l2_register reg; + struct v4l2_dbg_register reg; - reg.match_type = V4L2_CHIP_MATCH_HOST; - reg.match_chip = 0; + reg.match.type = V4L2_CHIP_MATCH_HOST; + reg.match.addr = 0; reg.reg = IVTV_REG_GPIO_DIR_OFFSET; reg.val = gpio_dir; if (gpio_set_dir && doioctl(fd, VIDIOC_DBG_S_REGISTER, ®, @@ -581,10 +581,10 @@ int main(int argc, char **argv) } if (options[OptListGPIO]) { - struct v4l2_register reg; + struct v4l2_dbg_register reg; - reg.match_type = V4L2_CHIP_MATCH_HOST; - reg.match_chip = 0; + reg.match.type = V4L2_CHIP_MATCH_HOST; + reg.match.addr = 0; reg.reg = IVTV_REG_GPIO_IN_OFFSET; if (ioctl(fd, VIDIOC_DBG_G_REGISTER, ®) == 0) printf("GPIO in: 0x%04llx\n", reg.val); diff --git a/v4l2-apps/util/v4l2-compliance.cpp b/v4l2-apps/util/v4l2-compliance.cpp index 2fe5292fe..3780f982e 100644 --- a/v4l2-apps/util/v4l2-compliance.cpp +++ b/v4l2-apps/util/v4l2-compliance.cpp @@ -910,23 +910,25 @@ static int testCap(int fd) static int testChipIdent(int fd) { - struct v4l2_chip_ident chip; + struct v4l2_dbg_chip_ident chip; int ret; - chip.match_type = V4L2_CHIP_MATCH_HOST; - chip.match_chip = 0; - ret = doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip, "VIDIOC_G_CHIP_IDENT"); + memset(&chip, 0, sizeof(chip)); + chip.match.type = V4L2_CHIP_MATCH_HOST; + chip.match.addr = 0; + ret = doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip, "VIDIOC_DBG_G_CHIP_IDENT"); // Must return either 0 (OK) or EINVAL (not supported) if (ret == 0) { - struct v4l2_chip_ident orig; + struct v4l2_dbg_chip_ident orig; + memset(&orig, 0, sizeof(orig)); // set invalid match_type - chip.match_type = V4L2_CHIP_MATCH_I2C_ADDR + 1; - chip.match_chip = 0xdeadbeef; + chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR + 1; + chip.match.addr = 0xdeadbeef; chip.ident = 0xdeadbeef; chip.revision = 0xdeadbeef; orig = chip; - ret = doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip, "VIDIOC_G_CHIP_IDENT"); + ret = doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip, "VIDIOC_DBG_G_CHIP_IDENT"); if (ret != EINVAL) { if (verbose) printf("Invalid match_type accepted\n"); @@ -944,13 +946,13 @@ static int testChipIdent(int fd) static int testRegister(int fd) { - struct v4l2_register reg; - struct v4l2_chip_ident chip; + struct v4l2_dbg_register reg; + struct v4l2_dbg_chip_ident chip; int ret; int uid = getuid(); - reg.match_type = V4L2_CHIP_MATCH_HOST; - reg.match_chip = 0; + reg.match.type = V4L2_CHIP_MATCH_HOST; + reg.match.addr = 0; reg.reg = 0; ret = doioctl(fd, VIDIOC_DBG_G_REGISTER, ®, "VIDIOC_DBG_G_REGISTER"); if (ret == EINVAL) @@ -963,10 +965,10 @@ static int testRegister(int fd) printf("Not allowed to call VIDIOC_DBG_G_REGISTER even though we are root\n"); return -1; } - chip.match_type = V4L2_CHIP_MATCH_HOST; - chip.match_chip = 0; - if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip, "VIDIOC_G_CHIP_IDENT")) { - printf("Must support VIDIOC_G_CHIP_IDENT\n"); + chip.match.type = V4L2_CHIP_MATCH_HOST; + chip.match.addr = 0; + if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip, "VIDIOC_DBG_G_CHIP_IDENT")) { + printf("Must support VIDIOC_DBG_G_CHIP_IDENT\n"); return -1; } if (uid) { @@ -1111,7 +1113,7 @@ int main(int argc, char **argv) printf("Debug ioctls:\n"); if (test[TestChipIdent]) - printf("\ttest VIDIOC_G_CHIP_IDENT: %s\n", ok(testChipIdent(fd))); + printf("\ttest VIDIOC_DBG_G_CHIP_IDENT: %s\n", ok(testChipIdent(fd))); if (test[TestRegister]) printf("\ttest VIDIOC_DBG_G/S_REGISTER: %s\n", ok(testRegister(fd))); if (test[TestLogStatus]) diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index 577c8585e..b38d18cf0 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -103,13 +103,6 @@ static const struct board_list boards[] = { }, }; -struct driverid { - const char *name; - unsigned id; -}; - -extern struct driverid driverids[]; - struct chipid { const char *name; unsigned id; @@ -138,7 +131,6 @@ enum Option { OptLogStatus = 128, OptVerbose, - OptListDriverIDs, OptListSymbols, OptLast = 256 }; @@ -159,7 +151,6 @@ static struct option long_options[] = { {"info", no_argument, 0, OptGetDriverInfo}, {"verbose", no_argument, 0, OptVerbose}, {"log-status", no_argument, 0, OptLogStatus}, - {"list-driverids", no_argument, 0, OptListDriverIDs}, {"list-symbols", no_argument, 0, OptListSymbols}, {"wide", required_argument, 0, OptSetStride}, {0, 0, 0, 0} @@ -175,7 +166,7 @@ static void usage(void) " --verbose Turn on verbose ioctl error reporting\n" " -c, --chip= The chip identifier to use with other commands\n" " It can be one of:\n" - " I2C driver ID (see --list-driverids)\n" + " I2C driver name\n" " I2C 7-bit address\n" " AC97: for ac97 anciliary mixer\n" " host: host chip number \n" @@ -188,25 +179,16 @@ static void usage(void) " Set the register with the commandline arguments\n" " The register will autoincrement [VIDIOC_DBG_S_REGISTER]\n" " -S, --scan-chip-idents\n" - " Scan the available host and i2c chips [VIDIOC_G_CHIP_IDENT]\n" + " Scan the available host and i2c chips [VIDIOC_DBG_G_CHIP_IDENT]\n" " -i, --get-chip-ident\n" - " Get the chip identifier [VIDIOC_G_CHIP_IDENT]\n" + " Get the chip identifier [VIDIOC_DBG_G_CHIP_IDENT]\n" " -w, --wide=\n" " Sets step between two registers\n" " --list-symbols List the symbolic register names you can use, if any\n" - " --log-status Log the board status in the kernel log [VIDIOC_LOG_STATUS]\n" - " --list-driverids List the known I2C driver IDs for use with the i2cdrv type\n"); + " --log-status Log the board status in the kernel log [VIDIOC_LOG_STATUS]\n"); exit(0); } -static unsigned parse_chip(const std::string &s) -{ - for (int i = 0; driverids[i].name; i++) - if (!strcasecmp(s.c_str(), driverids[i].name)) - return driverids[i].id; - return 0; -} - static std::string cap2s(unsigned cap) { std::string s; @@ -244,7 +226,7 @@ static std::string cap2s(unsigned cap) return s; } -static void print_regs(int fd, struct v4l2_register *reg, unsigned long min, unsigned long max, int stride) +static void print_regs(int fd, struct v4l2_dbg_register *reg, unsigned long min, unsigned long max, int stride) { unsigned long mask = stride > 1 ? 0x1f : 0x0f; unsigned long i; @@ -278,7 +260,7 @@ static void print_regs(int fd, struct v4l2_register *reg, unsigned long min, uns printf("\n"); } -static void print_chip(struct v4l2_chip_ident *chip) +static void print_chip(struct v4l2_dbg_chip_ident *chip) { const char *name = NULL; @@ -403,9 +385,9 @@ int main(int argc, char **argv) int ch; const char *device = "/dev/video0"; /* -d device */ struct v4l2_capability vcap; /* list_cap */ - struct v4l2_register set_reg; - struct v4l2_register get_reg; - struct v4l2_chip_ident chip_id; + struct v4l2_dbg_register set_reg; + struct v4l2_dbg_register get_reg; + struct v4l2_dbg_chip_ident chip_id; const struct board_list *curr_bd = NULL; char short_options[26 * 2 * 2 + 1]; int idx = 0; @@ -413,10 +395,11 @@ int main(int argc, char **argv) std::string reg_set_arg; unsigned long long reg_min = 0, reg_max = 0; std::vector get_regs; - int match_type = V4L2_CHIP_MATCH_HOST; - int match_chip = 0; char driver[255]; + struct v4l2_dbg_match match; + match.type = V4L2_CHIP_MATCH_HOST; + match.addr = 0; memset(&set_reg, 0, sizeof(set_reg)); memset(&get_reg, 0, sizeof(get_reg)); memset(&chip_id, 0, sizeof(chip_id)); @@ -460,26 +443,23 @@ int main(int argc, char **argv) case OptChip: if (isdigit(optarg[0])) { - match_type = V4L2_CHIP_MATCH_I2C_ADDR; - match_chip = strtoul(optarg, NULL, 0); + match.type = V4L2_CHIP_MATCH_I2C_ADDR; + match.addr = strtoul(optarg, NULL, 0); break; } if (!memcmp(optarg, "host", 4)) { - match_type = V4L2_CHIP_MATCH_HOST; - match_chip = strtoul(optarg + 4, NULL, 0); + match.type = V4L2_CHIP_MATCH_HOST; + match.addr = strtoul(optarg + 4, NULL, 0); break; } if (!strcasecmp(optarg, "ac97")) { - match_type = V4L2_CHIP_MATCH_AC97; + match.type = V4L2_CHIP_MATCH_AC97; + match.addr = 0; break; } - match_type = V4L2_CHIP_MATCH_I2C_DRIVER; - strcpy(driver, optarg); - match_chip = parse_chip(optarg); - if (!match_chip) { - fprintf(stderr, "unknown driver ID %s\n", optarg); - exit(-1); - } + match.type = V4L2_CHIP_MATCH_I2C_DRIVER; + strncpy(match.name, optarg, sizeof(match.name)); + match.name[sizeof(match.name) - 1] = '\0'; break; case OptSetRegister: @@ -558,16 +538,16 @@ int main(int argc, char **argv) printf("%s", cap2s(vcap.capabilities).c_str()); } - if (match_type == V4L2_CHIP_MATCH_AC97) { + if (match.type == V4L2_CHIP_MATCH_AC97) { curr_bd = &boards[AC97_BOARD]; - } else if (match_type == V4L2_CHIP_MATCH_HOST) { + } else if (match.type == V4L2_CHIP_MATCH_HOST) { for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) { if (!strcasecmp((char *)vcap.driver, boards[board].name)) { curr_bd = &boards[board]; break; } } - } else if (match_type == V4L2_CHIP_MATCH_I2C_DRIVER) { + } else if (match.type == V4L2_CHIP_MATCH_I2C_DRIVER) { for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) { if (!strcasecmp(driver, boards[board].name)) { curr_bd = &boards[board]; @@ -579,8 +559,7 @@ int main(int argc, char **argv) /* Set options */ if (options[OptSetRegister]) { - set_reg.match_type = match_type; - set_reg.match_chip = match_chip; + set_reg.match = match; if (optind >= argc) usage(); set_reg.reg = parse_reg(curr_bd, reg_set_arg); @@ -607,28 +586,27 @@ int main(int argc, char **argv) } if (options[OptGetChipIdent]) { - chip_id.match_type = match_type; - chip_id.match_chip = match_chip; - if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0) + chip_id.match = match; + if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0) print_chip(&chip_id); } if (options[OptScanChipIdents]) { int i; - chip_id.match_type = V4L2_CHIP_MATCH_HOST; - chip_id.match_chip = 0; + chip_id.match.type = V4L2_CHIP_MATCH_HOST; + chip_id.match.addr = 0; - while (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0 && chip_id.ident) { - printf("host%d: ", chip_id.match_chip); + while (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0 && chip_id.ident) { + printf("host%d: ", chip_id.match.addr); print_chip(&chip_id); - chip_id.match_chip++; + chip_id.match.addr++; } - chip_id.match_type = V4L2_CHIP_MATCH_I2C_ADDR; + chip_id.match.type = V4L2_CHIP_MATCH_I2C_ADDR; for (i = 0; i < 128; i++) { - chip_id.match_chip = i; - if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0 && chip_id.ident) { + chip_id.match.addr = i; + if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0 && chip_id.ident) { printf("i2c 0x%02x: ", i); print_chip(&chip_id); } @@ -638,8 +616,7 @@ int main(int argc, char **argv) if (options[OptGetRegister]) { int stride = 1; - get_reg.match_type = match_type; - get_reg.match_chip = match_chip; + get_reg.match = match; printf("ioctl: VIDIOC_DBG_G_REGISTER\n"); for (std::vector::iterator iter = get_regs.begin(); @@ -665,16 +642,14 @@ int main(int argc, char **argv) } if (options[OptListRegisters]) { + std::string name; int stride = 1; - get_reg.match_type = match_type; - get_reg.match_chip = match_chip; - + get_reg.match = match; if (forcedstride) { stride = forcedstride; - } else { - if (get_reg.match_type == V4L2_CHIP_MATCH_HOST) - stride = 4; + } else if (get_reg.match.type == V4L2_CHIP_MATCH_HOST) { + stride = 4; } printf("ioctl: VIDIOC_DBG_G_REGISTER\n"); @@ -726,57 +701,47 @@ int main(int argc, char **argv) goto list_done; } - /* try to match the i2c chip */ - switch (get_reg.match_chip) { - case I2C_DRIVERID_SAA711X: - print_regs(fd, &get_reg, 0, 0xff, stride); + /* try to figure out which chip it is */ + chip_id.match = match; + if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") != 0) { + chip_id.ident = V4L2_IDENT_NONE; + } + switch (chip_id.ident) { + case V4L2_IDENT_CX23415: + case V4L2_IDENT_CX23416: + name = "cx23416"; + break; + case V4L2_IDENT_CX23418: + name = "cx23418"; break; - case I2C_DRIVERID_SAA717X: + default: + if (get_reg.match.type == V4L2_CHIP_MATCH_I2C_DRIVER) + name = get_reg.match.name; + break; + } + + if (name == "saa7115") { + print_regs(fd, &get_reg, 0, 0xff, stride); + } else if (name == "saa717x") { // FIXME: use correct reg regions print_regs(fd, &get_reg, 0, 0xff, stride); - break; - case I2C_DRIVERID_SAA7127: + } else if (name == "saa7127") { print_regs(fd, &get_reg, 0, 0x7f, stride); - break; - case I2C_DRIVERID_CX25840: + } else if (name == "cx25840") { print_regs(fd, &get_reg, 0, 2, stride); print_regs(fd, &get_reg, 0x100, 0x15f, stride); print_regs(fd, &get_reg, 0x200, 0x23f, stride); print_regs(fd, &get_reg, 0x400, 0x4bf, stride); print_regs(fd, &get_reg, 0x800, 0x9af, stride); - break; - case I2C_DRIVERID_CS5345: + } else if (name == "cs5345") { print_regs(fd, &get_reg, 1, 0x10, stride); - break; - case 0: - /* host chip, handle later */ - break; - default: - /* unknown i2c chip, dump 0-0xff by default */ - print_regs(fd, &get_reg, 0, 0xff, stride); - break; - } - if (get_reg.match_chip != 0) { - /* found i2c chip, we're done */ - goto list_done; - } - /* try to figure out which host chip it is */ - if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") != 0) { - chip_id.ident = V4L2_IDENT_NONE; - } - - switch (chip_id.ident) { - case V4L2_IDENT_CX23415: - case V4L2_IDENT_CX23416: + } else if (name == "cx23416") { print_regs(fd, &get_reg, 0x02000000, 0x020000ff, stride); - break; - case V4L2_IDENT_CX23418: + } else if (name == "cx23418") { print_regs(fd, &get_reg, 0x02c40000, 0x02c409c7, stride); - break; - default: - /* By default print range 0-0xff */ + } else { + /* unknown chip, dump 0-0xff by default */ print_regs(fd, &get_reg, 0, 0xff, stride); - break; } } list_done: @@ -808,12 +773,6 @@ list_done: } } - if (options[OptListDriverIDs]) { - printf("Known I2C driver IDs:\n"); - for (int i = 0; driverids[i].name; i++) - printf("%s\n", driverids[i].name); - } - if (options[OptListSymbols]) { if (curr_bd == NULL) { printf("No symbols found for driver %s\n", vcap.driver); -- cgit v1.2.3 From b50e38700408ec0bb073fc56ade123a1305842b6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Dec 2008 15:58:55 +0100 Subject: v4l2-dbg: fix --list-symbols From: Hans Verkuil --list-symbols didn't work for i2c drivers anymore. Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/util/v4l2-dbg.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index b38d18cf0..f427d4442 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -395,7 +395,6 @@ int main(int argc, char **argv) std::string reg_set_arg; unsigned long long reg_min = 0, reg_max = 0; std::vector get_regs; - char driver[255]; struct v4l2_dbg_match match; match.type = V4L2_CHIP_MATCH_HOST; @@ -549,7 +548,7 @@ int main(int argc, char **argv) } } else if (match.type == V4L2_CHIP_MATCH_I2C_DRIVER) { for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) { - if (!strcasecmp(driver, boards[board].name)) { + if (!strcasecmp(match.name, boards[board].name)) { curr_bd = &boards[board]; break; } @@ -778,7 +777,7 @@ list_done: printf("No symbols found for driver %s\n", vcap.driver); } else { - printf("Symbols for driver %s:\n", vcap.driver); + printf("Symbols for driver %s:\n", curr_bd->name); for (int i = 0; i < curr_bd->regs_size; i++) printf("0x%08x: %s\n", curr_bd->regs[i].reg, curr_bd->regs[i].name); for (int i = 0; i < curr_bd->alt_regs_size; i++) -- cgit v1.2.3 From 34f7174184f8336672613230fb12421a8ab2d187 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 00:49:22 +0000 Subject: use USB API functions rather than constants From: Julia Lawall This set of patches introduces calls to the following set of functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_is_isoc_in(epd) usb_endpoint_is_isoc_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) In some cases, introducing one of these functions is not possible, and it just replaces an explicit integer value by one of the following constants: USB_ENDPOINT_XFER_BULK USB_ENDPOINT_XFER_CONTROL USB_ENDPOINT_XFER_INT USB_ENDPOINT_XFER_ISOC An extract of the semantic patch that makes these changes is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r1@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bmAttributes & \(USB_ENDPOINT_XFERTYPE_MASK\|3\)) == - \(USB_ENDPOINT_XFER_CONTROL\|0\)) + usb_endpoint_xfer_control(epd) @r5@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bEndpointAddress & \(USB_ENDPOINT_DIR_MASK\|0x80\)) == - \(USB_DIR_IN\|0x80\)) + usb_endpoint_dir_in(epd) // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 8 ++++---- linux/drivers/media/video/stk-webcam.c | 7 ++----- linux/drivers/media/video/usbvideo/ibmcam.c | 4 ++-- linux/drivers/media/video/usbvideo/konicawc.c | 4 ++-- linux/drivers/media/video/usbvideo/quickcam_messenger.c | 7 ++----- linux/drivers/media/video/usbvideo/ultracam.c | 4 ++-- linux/drivers/media/video/usbvideo/vicam.c | 3 +-- linux/drivers/media/video/usbvision/usbvision-video.c | 5 ++--- 8 files changed, 17 insertions(+), 25 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 211305c18..c5dd7a96c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2064,8 +2064,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, endpoint = &interface->cur_altsetting->endpoint[0].desc; /* check if the device has the iso in endpoint at the correct place */ - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC && + if (usb_endpoint_xfer_isoc(endpoint) + && (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) { /* It's a newer em2874/em2875 device */ isoc_pipe = 0; @@ -2073,11 +2073,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, int check_interface = 1; isoc_pipe = 1; endpoint = &interface->cur_altsetting->endpoint[1].desc; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + if (usb_endpoint_type(endpoint) != USB_ENDPOINT_XFER_ISOC) check_interface = 0; - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) + if (usb_endpoint_dir_out(endpoint)) check_interface = 0; if (!check_interface) { diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index bfd0ddb63..62c66cc93 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1397,12 +1397,9 @@ static int stk_camera_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[i].desc; if (!dev->isoc_ep - && ((endpoint->bEndpointAddress - & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) - && ((endpoint->bmAttributes - & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) { + && usb_endpoint_is_isoc_in(endpoint)) { /* we found an isoc in endpoint */ - dev->isoc_ep = (endpoint->bEndpointAddress & 0xF); + dev->isoc_ep = usb_endpoint_num(endpoint); break; } } diff --git a/linux/drivers/media/video/usbvideo/ibmcam.c b/linux/drivers/media/video/usbvideo/ibmcam.c index 1119bcf58..8b1a10fe1 100644 --- a/linux/drivers/media/video/usbvideo/ibmcam.c +++ b/linux/drivers/media/video/usbvideo/ibmcam.c @@ -3779,11 +3779,11 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * err("Alternate settings have different endpoint addresses!"); return -ENODEV; } - if ((endpoint->bmAttributes & 0x03) != 0x01) { + if (usb_endpoint_type(endpoint) != USB_ENDPOINT_XFER_ISOC) { err("Interface %d. has non-ISO endpoint!", ifnum); return -ENODEV; } - if ((endpoint->bEndpointAddress & 0x80) == 0) { + if (usb_endpoint_dir_out(endpoint)) { err("Interface %d. has ISO OUT endpoint!", ifnum); return -ENODEV; } diff --git a/linux/drivers/media/video/usbvideo/konicawc.c b/linux/drivers/media/video/usbvideo/konicawc.c index 73abbb3f4..cf20643a0 100644 --- a/linux/drivers/media/video/usbvideo/konicawc.c +++ b/linux/drivers/media/video/usbvideo/konicawc.c @@ -836,12 +836,12 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id err("Alternate settings have different endpoint addresses!"); return -ENODEV; } - if ((endpoint->bmAttributes & 0x03) != 0x01) { + if (usb_endpoint_type(endpoint) != USB_ENDPOINT_XFER_ISOC) { err("Interface %d. has non-ISO endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; } - if ((endpoint->bEndpointAddress & 0x80) == 0) { + if (usb_endpoint_dir_out(endpoint)) { err("Interface %d. has ISO OUT endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; diff --git a/linux/drivers/media/video/usbvideo/quickcam_messenger.c b/linux/drivers/media/video/usbvideo/quickcam_messenger.c index 9602ba0bd..f129bea11 100644 --- a/linux/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/linux/drivers/media/video/usbvideo/quickcam_messenger.c @@ -972,8 +972,7 @@ static int qcm_probe(struct usb_interface *intf, for (j=0; j < interface->desc.bNumEndpoints; j++) { endpoint = &interface->endpoint[j].desc; - if ((endpoint->bEndpointAddress & - USB_ENDPOINT_DIR_MASK) != USB_DIR_IN) + if (usb_endpoint_dir_out(endpoint)) continue; /* not input then not good */ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); @@ -982,9 +981,7 @@ static int qcm_probe(struct usb_interface *intf, continue; /* 0 pkt size is not what we want */ } - if ((endpoint->bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC) { + if (usb_endpoint_xfer_isoc(endpoint)) { video_ep = endpoint->bEndpointAddress; /* break out of the search */ goto good_videoep; diff --git a/linux/drivers/media/video/usbvideo/ultracam.c b/linux/drivers/media/video/usbvideo/ultracam.c index d29e6a81b..b0c9495e8 100644 --- a/linux/drivers/media/video/usbvideo/ultracam.c +++ b/linux/drivers/media/video/usbvideo/ultracam.c @@ -556,12 +556,12 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id err("Alternate settings have different endpoint addresses!"); return -ENODEV; } - if ((endpoint->bmAttributes & 0x03) != 0x01) { + if (usb_endpoint_type(endpoint) != USB_ENDPOINT_XFER_ISOC) { err("Interface %d. has non-ISO endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; } - if ((endpoint->bEndpointAddress & 0x80) == 0) { + if (usb_endpoint_dir_out(endpoint)) { err("Interface %d. has ISO OUT endpoint!", interface->desc.bInterfaceNumber); return -ENODEV; diff --git a/linux/drivers/media/video/usbvideo/vicam.c b/linux/drivers/media/video/usbvideo/vicam.c index 77032eaa7..a49f7f488 100644 --- a/linux/drivers/media/video/usbvideo/vicam.c +++ b/linux/drivers/media/video/usbvideo/vicam.c @@ -1154,8 +1154,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints)); endpoint = &interface->endpoint[0].desc; - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x02)) { + if (usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ bulkEndpoint = endpoint->bEndpointAddress; } else { diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 48c8c4399..85661b184 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1679,7 +1679,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, interface = &dev->actconfig->interface[ifnum]->altsetting[0]; } endpoint = &interface->endpoint[1].desc; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + if (usb_endpoint_type(endpoint) != USB_ENDPOINT_XFER_ISOC) { err("%s: interface %d. has non-ISO endpoint!", __func__, ifnum); @@ -1687,8 +1687,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, __func__, endpoint->bmAttributes); return -ENODEV; } - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == - USB_DIR_OUT) { + if (usb_endpoint_dir_out(endpoint)) { err("%s: interface %d. has ISO OUT endpoint!", __func__, ifnum); return -ENODEV; -- cgit v1.2.3 From b0ab681e920adac28d099cb1ec192d2ada2c160f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 08:47:03 -0200 Subject: Add compat support for usb_endpoint_type() From: Mauro Carvalho Chehab While here, make sure that config-compat.h is rebuild if the script change. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l/Makefile | 2 +- v4l/compat.h | 13 +++++++++---- v4l/scripts/make_config_compat.pl | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/v4l/Makefile b/v4l/Makefile index 2aa856974..f96873227 100644 --- a/v4l/Makefile +++ b/v4l/Makefile @@ -256,7 +256,7 @@ links:: oss: ln -sf . oss -config-compat.h:: $(obj)/.version .myconfig +config-compat.h:: $(obj)/.version .myconfig scripts/make_config_compat.pl perl scripts/make_config_compat.pl $(SRCDIR) $(obj)/.myconfig $(obj)/config-compat.h kernel-links makelinks:: diff --git a/v4l/compat.h b/v4l/compat.h index 22281f6f9..200c21458 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -339,14 +339,19 @@ usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) -#ifdef NEED_NETDEV_PRIV -#define netdev_priv(dev) ((dev)->priv) -#endif - /* * uninitialized_var() macro */ #define uninitialized_var(x) x = x #endif +#ifdef NEED_NETDEV_PRIV +#define netdev_priv(dev) ((dev)->priv) +#endif + +#ifdef NEED_USB_ENDPOINT_TYPE +#define usb_endpoint_type(ep) \ + ((ep)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) +#endif + #endif diff --git a/v4l/scripts/make_config_compat.pl b/v4l/scripts/make_config_compat.pl index 8fb7a9441..dc6653b0d 100755 --- a/v4l/scripts/make_config_compat.pl +++ b/v4l/scripts/make_config_compat.pl @@ -216,6 +216,25 @@ sub check_net_dev() close INNET; } +sub check_usb_endpoint_type() +{ + my $file = "$kdir/include/linux/usb.h"; + my $need_compat = 1; + + open INNET, "<$file" or die "File not found: $file"; + while () { + if (m/usb_endpoint_type/) { + $need_compat = 0; + last; + } + } + + if ($need_compat) { + $out.= "\n#define NEED_USB_ENDPOINT_TYPE 1\n"; + } + close INNET; +} + sub check_other_dependencies() { check_spin_lock(); @@ -229,6 +248,7 @@ sub check_other_dependencies() check_pcm_lock(); check_algo_control(); check_net_dev(); + check_usb_endpoint_type(); } # Do the basic rules -- cgit v1.2.3 From d2240c64f5eac6aef7490e451eeeaddddd4f3457 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 22:40:00 +0300 Subject: cx24116 - build fix From: Cyrill Gorcunov Add missed MODULE check to eliminate inapropriate declaration being choosed which causes a build error. Signed-off-by: Cyrill Gorcunov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/cx24116.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/frontends/cx24116.h b/linux/drivers/media/dvb/frontends/cx24116.h index 4cb3ddd6c..b1b76b47a 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.h +++ b/linux/drivers/media/dvb/frontends/cx24116.h @@ -37,7 +37,8 @@ struct cx24116_config { u8 mpg_clk_pos_pol:0x02; }; -#if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE) +#if defined(CONFIG_DVB_CX24116) || \ + (defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE)) extern struct dvb_frontend *cx24116_attach( const struct cx24116_config *config, struct i2c_adapter *i2c); -- cgit v1.2.3 From 1ca1203a1eab7dc3951e569975bbbccc76aeb8fe Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 30 Dec 2008 21:58:17 +0100 Subject: v4l: fix compile errors for older kernels From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/frontends/af9013.c | 1 + linux/drivers/media/video/mt9t031.c | 8 ++++ linux/drivers/media/video/tw9910.c | 8 ++++ v4l/compat.h | 61 +++++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/af9013.c b/linux/drivers/media/dvb/frontends/af9013.c index b2b50fb4c..937715a96 100644 --- a/linux/drivers/media/dvb/frontends/af9013.c +++ b/linux/drivers/media/dvb/frontends/af9013.c @@ -33,6 +33,7 @@ #include "dvb_frontend.h" #include "af9013_priv.h" #include "af9013.h" +#include "compat.h" int af9013_debug; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 349d8e365..dd5bd9dd0 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -632,8 +632,12 @@ static void mt9t031_video_remove(struct soc_camera_device *icd) soc_camera_video_stop(icd); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) +static int mt9t031_probe(struct i2c_client *client) +#else static int mt9t031_probe(struct i2c_client *client, const struct i2c_device_id *did) +#endif { struct mt9t031 *mt9t031; struct soc_camera_device *icd; @@ -703,19 +707,23 @@ static int mt9t031_remove(struct i2c_client *client) return 0; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id mt9t031_id[] = { { "mt9t031", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, mt9t031_id); +#endif static struct i2c_driver mt9t031_i2c_driver = { .driver = { .name = "mt9t031", }, .probe = mt9t031_probe, .remove = mt9t031_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = mt9t031_id, +#endif }; static int __init mt9t031_mod_init(void) diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 52c0357fa..c670b23a1 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -837,8 +837,12 @@ static struct soc_camera_ops tw9910_ops = { * i2c_driver function */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) +static int tw9910_probe(struct i2c_client *client) +#else static int tw9910_probe(struct i2c_client *client, const struct i2c_device_id *did) +#endif { struct tw9910_priv *priv; @@ -915,19 +919,23 @@ static int tw9910_remove(struct i2c_client *client) return 0; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id tw9910_id[] = { { "tw9910", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, tw9910_id); +#endif static struct i2c_driver tw9910_i2c_driver = { .driver = { .name = "tw9910", }, .probe = tw9910_probe, .remove = tw9910_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tw9910_id, +#endif }; /* diff --git a/v4l/compat.h b/v4l/compat.h index 200c21458..c2b805cec 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -280,8 +280,8 @@ static inline int dummy_algo_control(struct i2c_adapter *adapter, #define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC 0x4102 #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) #ifdef __LINUX_USB_H +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) /* * usb_endpoint_* functions * @@ -328,10 +328,67 @@ usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) { return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd); } + +static inline int usb_endpoint_dir_out( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); +} + +static inline int usb_endpoint_is_bulk_in( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); +} + +static inline int usb_endpoint_is_bulk_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); +} + +static inline int usb_endpoint_is_int_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); +} + +static inline int usb_endpoint_is_isoc_in( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); +} + +static inline int usb_endpoint_is_isoc_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); +} #endif /* RHEL_HAS_USB_ENDPOINT */ -#endif /* __LINUX_USB_H */ #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21) +static inline int usb_endpoint_xfer_control( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) +static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) +{ + return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; +} + +static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) +{ + return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; +} +#endif +#endif /* __LINUX_USB_H */ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* * Linked list API -- cgit v1.2.3 From 811d39fde60ebeaa0bb102736149c5ddecb94535 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 19:48:14 -0200 Subject: Fix compilation against RHEL kernel From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l/compat.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/v4l/compat.h b/v4l/compat.h index c2b805cec..3b04c91f6 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -368,12 +368,14 @@ static inline int usb_endpoint_is_isoc_out( #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21) +#ifndef RHEL_HAS_USB_ENDPOINT static inline int usb_endpoint_xfer_control( const struct usb_endpoint_descriptor *epd) { return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL); } +#endif /* RHEL_HAS_USB_ENDPOINT */ #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) @@ -381,7 +383,9 @@ static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) { return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; } +#endif +#ifdef NEED_USB_ENDPOINT_TYPE static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) { return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; @@ -406,9 +410,5 @@ static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) #define netdev_priv(dev) ((dev)->priv) #endif -#ifdef NEED_USB_ENDPOINT_TYPE -#define usb_endpoint_type(ep) \ - ((ep)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) -#endif #endif -- cgit v1.2.3 From be469f334286914f2d78ec4ea51b8083b4542e1b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Nov 2008 01:03:18 +0000 Subject: cx23885: unsigned cx23417_mailbox cannot be negative From: roel kluin Unsigned cx23417_mailbox cannot be negative Signed-off-by: Roel Kluin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx23885/cx23885-417.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index 1aa8a9ca3..52f6824ff 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -1027,12 +1027,13 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev) printk(KERN_ERR "%s() f/w load failed\n", __func__); return retval; } - dev->cx23417_mailbox = cx23885_find_mailbox(dev); - if (dev->cx23417_mailbox < 0) { + retval = cx23885_find_mailbox(dev); + if (retval < 0) { printk(KERN_ERR "%s() mailbox < 0, error\n", __func__); return -1; } + dev->cx23417_mailbox = retval; retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); if (retval < 0) { printk(KERN_ERR -- cgit v1.2.3 From c372b355046aaa6f7f18919b3ebf2944b92df84c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Nov 2008 15:00:18 +0000 Subject: ttusb-budget: make it depend on PCI From: Mike Frysinger Since dvb-ttusb-budget.c relies on pci_alloc_consistent and pci_free_consistent, make it depend on PCI in Kconfig. Signed-off-by: Mike Frysinger Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/ttusb-budget/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/ttusb-budget/Kconfig b/linux/drivers/media/dvb/ttusb-budget/Kconfig index f546bccdb..2663ae39b 100644 --- a/linux/drivers/media/dvb/ttusb-budget/Kconfig +++ b/linux/drivers/media/dvb/ttusb-budget/Kconfig @@ -1,6 +1,6 @@ config DVB_TTUSB_BUDGET tristate "Technotrend/Hauppauge Nova-USB devices" - depends on DVB_CORE && USB && I2C + depends on DVB_CORE && USB && I2C && PCI select DVB_CX22700 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_VES1820 if !DVB_FE_CUSTOMISE -- cgit v1.2.3 From 446536a00d50da5b7cb82f62560e7c63ef295557 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Nov 2008 15:04:28 +0000 Subject: ttusb-dec: make it depend on PCI From: Mike Frysinger Since ttusb_dec.c relies on pci_alloc_consistent and pci_free_consistent, make it depend on PCI in Kconfig. Signed-off-by: Mike Frysinger Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/ttusb-dec/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/ttusb-dec/Kconfig b/linux/drivers/media/dvb/ttusb-dec/Kconfig index d5f48a310..290254ab0 100644 --- a/linux/drivers/media/dvb/ttusb-dec/Kconfig +++ b/linux/drivers/media/dvb/ttusb-dec/Kconfig @@ -1,6 +1,6 @@ config DVB_TTUSB_DEC tristate "Technotrend/Hauppauge USB DEC devices" - depends on DVB_CORE && USB && INPUT + depends on DVB_CORE && USB && INPUT && PCI select CRC32 help Support for external USB adapters designed by Technotrend and -- cgit v1.2.3 From 7dddcd8c1610cacae33a0ee67971d597c4bdaffb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 24 Nov 2008 09:45:57 -0200 Subject: em28xx-alsa: implement another locking schema From: Mauro Carvalho Chehab Instead of using a spinlock, it is better to call the proper pcm stream locking schema. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-audio.c | 37 ++++++++++++++++--------- v4l/scripts/gentree.pl | 1 + v4l/scripts/make_config_compat.pl | 20 +++++++++++++ 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index b86b0870d..7bdbbf717 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -80,7 +80,9 @@ static void em28xx_audio_isocirq(struct urb *urb) struct em28xx *dev = urb->context; int i; unsigned int oldptr; +#ifdef NO_PCM_LOCK unsigned long flags; +#endif int period_elapsed = 0; int status; unsigned char *cp; @@ -106,9 +108,26 @@ static void em28xx_audio_isocirq(struct urb *urb) if (!length) continue; +#ifdef NO_PCM_LOCK spin_lock_irqsave(&dev->adev->slock, flags); - +#endif oldptr = dev->adev->hwptr_done_capture; + if (oldptr + length >= runtime->buffer_size) { + unsigned int cnt = + runtime->buffer_size - oldptr; + memcpy(runtime->dma_area + oldptr * stride, cp, + cnt * stride); + memcpy(runtime->dma_area, cp + cnt * stride, + length * stride - cnt * stride); + } else { + memcpy(runtime->dma_area + oldptr * stride, cp, + length * stride); + } + +#ifndef NO_PCM_LOCK + snd_pcm_stream_lock(substream); +#endif + dev->adev->hwptr_done_capture += length; if (dev->adev->hwptr_done_capture >= runtime->buffer_size) @@ -123,19 +142,11 @@ static void em28xx_audio_isocirq(struct urb *urb) period_elapsed = 1; } +#ifdef NO_PCM_LOCK spin_unlock_irqrestore(&dev->adev->slock, flags); - - if (oldptr + length >= runtime->buffer_size) { - unsigned int cnt = - runtime->buffer_size - oldptr; - memcpy(runtime->dma_area + oldptr * stride, cp, - cnt * stride); - memcpy(runtime->dma_area, cp + cnt * stride, - length * stride - cnt * stride); - } else { - memcpy(runtime->dma_area + oldptr * stride, cp, - length * stride); - } +#else + snd_pcm_stream_unlock(substream); +#endif } if (period_elapsed) snd_pcm_period_elapsed(substream); diff --git a/v4l/scripts/gentree.pl b/v4l/scripts/gentree.pl index fccaedff4..d84608aa1 100755 --- a/v4l/scripts/gentree.pl +++ b/v4l/scripts/gentree.pl @@ -73,6 +73,7 @@ my %defs = ( 'BUZ_USE_HIMEM' => 1, 'NEED_SOUND_DRIVER_H' => 0, 'TTUSB_KERNEL' => 1, + 'NO_PCM_LOCK' => 0, ); ################################################################# diff --git a/v4l/scripts/make_config_compat.pl b/v4l/scripts/make_config_compat.pl index fdbc5eaba..3aac7e3b3 100755 --- a/v4l/scripts/make_config_compat.pl +++ b/v4l/scripts/make_config_compat.pl @@ -159,6 +159,25 @@ sub check_proc_create() close INNET; } +sub check_pcm_lock() +{ + my $file = "$kdir/include/sound/pcm.h"; + my $need_compat = 1; + + open INNET, "<$file" or die "File not found: $file"; + while () { + if (m/pcm_stream_lock/) { + $need_compat = 0; + last; + } + } + + if ($need_compat) { + $out.= "\n#define NO_PCM_LOCK 1\n"; + } + close INNET; +} + sub check_other_dependencies() { check_spin_lock(); @@ -169,6 +188,7 @@ sub check_other_dependencies() check_is_singular(); check_clamp(); check_proc_create(); + check_pcm_lock(); } # Do the basic rules -- cgit v1.2.3 From a7992964c85bcd6fd2140245b904c9a54bc93238 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 24 Nov 2008 10:51:20 -0200 Subject: em28xx: fix oops audio From: Douglas Schilling Landgraf Replaced usb_kill_usb for usb_unlink_usb (wait until urb to fully stop require USB core to put the calling process to sleep). Oops: http://www.kerneloops.org/raw.php?rawid=71799&msgid= Priority: high Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index 7bdbbf717..c62455202 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -63,7 +63,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) dprintk("Stopping isoc\n"); for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - usb_kill_urb(dev->adev->urb[i]); + usb_unlink_urb(dev->adev->urb[i]); usb_free_urb(dev->adev->urb[i]); dev->adev->urb[i] = NULL; } -- cgit v1.2.3 From e01ddb9b92a5b1f69f1a5a88bdb1ffb7bb984ef5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 07:03:31 -0200 Subject: em28xx: cleanup XCLK register usage From: Devin Heitmueller Convert over to setting the XCLK register usage with the new em28xx_write_reg() function. Thanks to Ray Lu from Empia for providing the em2860/2880 datasheet. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 57 ++++++++++++++++++------- linux/drivers/media/video/em28xx/em28xx-reg.h | 18 ++++++++ 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 9177ea54b..9ba6eadb5 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1401,7 +1401,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2882_BOARD_PINNACLE_HYBRID_PRO: case EM2883_BOARD_KWORLD_HYBRID_A316: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1415,7 +1417,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2882_BOARD_TERRATEC_HYBRID_XS: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1437,7 +1441,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2880_BOARD_KWORLD_DVB_310U: case EM2870_BOARD_KWORLD_350U: case EM2881_BOARD_DNT_DA2_HYBRID: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1456,7 +1462,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2880_BOARD_MSI_DIGIVOX_AD: case EM2880_BOARD_MSI_DIGIVOX_AD_II: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1471,11 +1479,14 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2750_BOARD_UNKNOWN: case EM2750_BOARD_DLCW_130: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x0a", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_FREQUENCY_48MHZ); break; case EM2861_BOARD_PLEXTOR_PX_TV100U: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1486,7 +1497,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2861_BOARD_KWORLD_PVRTV_300U: case EM2880_BOARD_KWORLD_DVB_305U: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1498,7 +1511,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2870_BOARD_KWORLD_355U: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1509,7 +1524,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2870_BOARD_COMPRO_VIDEOMATE: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1530,7 +1547,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2870_BOARD_TERRATEC_XS_MT2060: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1558,12 +1577,17 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_regs(dev, 0x08, "\xfe", 1); mdelay(70); /* switch em2880 rc protocol */ - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x22", 1); + /* djh - I have serious doubts this is right... */ + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_10MHZ); /* should be added ir_codes here */ break; case EM2820_BOARD_GADMEI_UTV310: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1572,8 +1596,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2860_BOARD_GADMEI_UTV330: - /* Turn on IR */ - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); @@ -1581,7 +1606,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2820_BOARD_MSI_VOX_USB_2: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 98e95054e..45d588c3a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -51,6 +51,24 @@ #define EM28XX_R0E_AUDIOSRC 0x0e #define EM28XX_R0F_XCLK 0x0f +/* em28xx XCLK Register (0x0f) */ +#define EM28XX_XCLK_AUDIO_UNMUTE 0x80 /* otherwise audio muted */ +#define EM28XX_XCLK_I2S_MSB_TIMING 0x40 /* otherwise standard timing */ +#define EM28XX_XCLK_IR_RC5_MODE 0x20 /* otherwise NEC mode */ +#define EM28XX_XCLK_IR_NEC_CHK_PARITY 0x10 +#define EM28XX_XCLK_FREQUENCY_30MHZ 0x00 /* Freq. select (bits [3-0]) */ +#define EM28XX_XCLK_FREQUENCY_15MHZ 0x01 +#define EM28XX_XCLK_FREQUENCY_10MHZ 0x02 +#define EM28XX_XCLK_FREQUENCY_7_5MHZ 0x03 +#define EM28XX_XCLK_FREQUENCY_6MHZ 0x04 +#define EM28XX_XCLK_FREQUENCY_5MHZ 0x05 +#define EM28XX_XCLK_FREQUENCY_4_3MHZ 0x06 +#define EM28XX_XCLK_FREQUENCY_12MHZ 0x07 +#define EM28XX_XCLK_FREQUENCY_20MHZ 0x08 +#define EM28XX_XCLK_FREQUENCY_20MHZ_2 0x09 +#define EM28XX_XCLK_FREQUENCY_48MHZ 0x0a +#define EM28XX_XCLK_FREQUENCY_24MHZ 0x0b + #define EM28XX_R10_VINMODE 0x10 #define EM28XX_R11_VINCTRL 0x11 #define EM28XX_R12_VINENABLE 0x12 /* */ -- cgit v1.2.3 From 88682d2d8d89ab9c29ec079a2e849724e3b4b77d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 07:04:02 -0200 Subject: em28xx: Cleanup GPIO/GPO setup code From: Devin Heitmueller Cleanup the calls to set the GPIOs and GPOs for various devices, replacing the register number with the #define from em28xx-reg.h and converting over to using em28xx_write_reg() Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 9ba6eadb5..7a304d8fe 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1492,7 +1492,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ); /* FIXME guess */ /* Turn on analog audio output */ - em28xx_write_regs_req(dev, 0x00, 0x08, "\xfd", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; case EM2861_BOARD_KWORLD_PVRTV_300U: @@ -1504,9 +1504,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); msleep(10); - em28xx_write_regs(dev, 0x08, "\x6d", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d); msleep(10); - em28xx_write_regs(dev, 0x08, "\x7d", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d); msleep(10); break; @@ -1532,17 +1532,17 @@ void em28xx_pre_card_setup(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ); /* TODO: someone can do some cleanup here... not everything's needed */ - em28xx_write_regs(dev, 0x04, "\x00", 1); + em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); msleep(10); - em28xx_write_regs(dev, 0x04, "\x01", 1); + em28xx_write_reg(dev, EM2880_R04_GPO, 0x01); msleep(10); - em28xx_write_regs(dev, 0x08, "\xfd", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); mdelay(70); - em28xx_write_regs(dev, 0x08, "\xfc", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); mdelay(70); - em28xx_write_regs(dev, 0x08, "\xdc", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xdc); mdelay(70); - em28xx_write_regs(dev, 0x08, "\xfc", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); mdelay(70); break; @@ -1555,11 +1555,11 @@ void em28xx_pre_card_setup(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ); /* this device needs some gpio writes to get the DVB-T demod work */ - em28xx_write_regs(dev, 0x08, "\xfe", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); mdelay(70); - em28xx_write_regs(dev, 0x08, "\xde", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); mdelay(70); - dev->em28xx_write_regs(dev, 0x08, "\xfe", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); mdelay(70); break; @@ -1570,11 +1570,11 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* this device needs some gpio writes to get the DVB-T demod work */ - em28xx_write_regs(dev, 0x08, "\xfe", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); mdelay(70); - em28xx_write_regs(dev, 0x08, "\xde", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); mdelay(70); - em28xx_write_regs(dev, 0x08, "\xfe", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); mdelay(70); /* switch em2880 rc protocol */ /* djh - I have serious doubts this is right... */ @@ -1592,7 +1592,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); /* Turn on analog audio output */ - em28xx_write_regs_req(dev, 0x00, 0x08, "\xfd", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; case EM2860_BOARD_GADMEI_UTV330: @@ -1613,7 +1613,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ); /* enables audio for that device */ - em28xx_write_regs_req(dev, 0x00, 0x08, "\xfd", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; case EM2874_BOARD_PINNACLE_PCTV_80E: @@ -1866,7 +1866,7 @@ void em28xx_card_setup(struct em28xx *dev) } case EM2820_BOARD_KWORLD_PVRTV2800RF: /* GPIO enables sound on KWORLD PVR TV 2800RF */ - em28xx_write_regs_req(dev, 0x00, 0x08, "\xf9", 1); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9); break; case EM2820_BOARD_UNKNOWN: case EM2800_BOARD_UNKNOWN: -- cgit v1.2.3 From d5ea5fe48b325b90b09a2f386e1ca6a7bd773db4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 07:58:55 -0200 Subject: cx18 now compiles only with kernels 2.6.22 and upper From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l/versions.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l/versions.txt b/v4l/versions.txt index 3ef9af5d8..c09b5d69a 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -20,6 +20,8 @@ USB_STKWEBCAM DVB_DRX397XD # Assumes struct input_dev has a dev field DVB_DM1105 +# Need cancel_work_sync +VIDEO_CX18 [2.6.20] #This driver requires HID_REQ_GET_REPORT -- cgit v1.2.3 From c8686bdb02ff7ea276b796993fee13626e52ccea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 08:05:06 -0200 Subject: em28xx: Properly handles XCLK and I2C speed From: Mauro Carvalho Chehab The previous patches removed XCLK and I2C magic. Now, we finally know what those registers do. Also, only a very few cards need different setups for those. Instead of keeping the setups for those values inside the per-device hack magic switch, move the uncommon values to the board-specific struct, and have a common setup for all other boards. So, almost 100 lines of hacking magic were removed. A co-lateral effect of this patch is that it also fixes a bug at em28xx-core, where xclk were set, without taking any care about not overriding a previous xclk setup. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 158 +++++------------------- linux/drivers/media/video/em28xx/em28xx-core.c | 8 +- linux/drivers/media/video/em28xx/em28xx.h | 6 +- 3 files changed, 39 insertions(+), 133 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 7a304d8fe..f6815ae85 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -56,6 +56,7 @@ struct em28xx_board em28xx_boards[] = { [EM2750_BOARD_UNKNOWN] = { .name = "Unknown EM2750/EM2751 webcam grabber", .vchannels = 1, + .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -79,15 +80,15 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_UNKNOWN] = { - .name = "Unknown EM2750/28xx video grabber", - .is_em2800 = 0, - .tuner_type = TUNER_ABSENT, + .name = "Unknown EM2750/28xx video grabber", + .tuner_type = TUNER_ABSENT, }, [EM2750_BOARD_DLCW_130] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ .name = "Huaqi DLCW-130", .valid = EM28XX_BOARD_NOT_VALIDATED, .vchannels = 1, + .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -515,6 +516,10 @@ struct em28xx_board em28xx_boards[] = { .name = "Pinnacle PCTV DVB-T", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_ABSENT, /* MT2060 */ + + /* djh - I have serious doubts this is right... */ + .xclk = EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_10MHZ, }, [EM2870_BOARD_COMPRO_VIDEOMATE] = { .name = "Compro, VideoMate U3", @@ -548,7 +553,7 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, .mts_firmware = 1, - .has_dvb = 1, + .has_dvb = 1, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -590,7 +595,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_XC2028, .mts_firmware = 1, - .has_12mhz_i2s = 1, .has_dvb = 1, .ir_codes = ir_codes_hauppauge_new, .decoder = EM28XX_TVP5150, @@ -613,7 +617,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_XC2028, .mts_firmware = 1, - .has_12mhz_i2s = 1, .has_dvb = 1, .ir_codes = ir_codes_pinnacle_pctv_hd, .decoder = EM28XX_TVP5150, @@ -636,7 +639,6 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .tuner_type = TUNER_XC2028, .mts_firmware = 1, - .has_12mhz_i2s = 1, .has_dvb = 1, .ir_codes = ir_codes_ati_tv_wonder_hd_600, .decoder = EM28XX_TVP5150, @@ -1092,9 +1094,12 @@ struct em28xx_board em28xx_boards[] = { .name = "Pinnacle PCTV HD Mini", .vchannels = 0, .tuner_type = TUNER_ABSENT, - .has_dvb = 1, - .ir_codes = ir_codes_pinnacle_pctv_hd, + .has_dvb = 1, + .ir_codes = ir_codes_pinnacle_pctv_hd, .decoder = EM28XX_NODECODER, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM2874_I2C_SECONDARY_BUS_SELECT | + EM28XX_I2C_FREQ_400_KHZ, #ifdef DJH_DEBUG .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -1331,7 +1336,8 @@ static void em28xx_set_model(struct em28xx *dev) dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; dev->decoder = em28xx_boards[dev->model].decoder; dev->video_inputs = em28xx_boards[dev->model].vchannels; - dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; + dev->xclk = em28xx_boards[dev->model].xclk; + dev->i2c_speed = em28xx_boards[dev->model].i2c_speed; dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; dev->has_dvb = em28xx_boards[dev->model].has_dvb; dev->has_snapshot_button = em28xx_boards[dev->model].has_snapshot_button; @@ -1390,6 +1396,21 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_set_model(dev); + /* Those are the default values for the majority of boards + Use those values if not specified otherwise at boards entry + */ + if (!dev->xclk) + dev->xclk = EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ; + + if (!dev->i2c_speed) + dev->i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_100_KHZ; + + em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->xclk & 0x7f); + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->i2c_speed); + msleep(50); + /* request some modules */ switch (dev->model) { case EM2880_BOARD_TERRATEC_PRODIGY_XS: @@ -1401,14 +1422,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2882_BOARD_PINNACLE_HYBRID_PRO: case EM2883_BOARD_KWORLD_HYBRID_A316: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - msleep(50); - /* Sets GPO/GPIO sequences for this device */ dev->analog_gpio = hauppauge_wintv_hvr_900_analog; dev->digital_gpio = hauppauge_wintv_hvr_900_digital; @@ -1417,16 +1430,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2882_BOARD_TERRATEC_HYBRID_XS: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - msleep(50); - - /* should be added ir_codes here */ - /* Sets GPO/GPIO sequences for this device */ dev->analog_gpio = hauppauge_wintv_hvr_900_analog; dev->digital_gpio = hauppauge_wintv_hvr_900_digital; @@ -1441,14 +1444,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2880_BOARD_KWORLD_DVB_310U: case EM2870_BOARD_KWORLD_350U: case EM2881_BOARD_DNT_DA2_HYBRID: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - msleep(50); - /* NOTE: EM2881_DNT_DA2_HYBRID spend 140 msleep for digital and analog commands. If this commands doesn't work, add this timer. */ @@ -1462,14 +1457,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2880_BOARD_MSI_DIGIVOX_AD: case EM2880_BOARD_MSI_DIGIVOX_AD_II: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - msleep(50); - /* Sets GPO/GPIO sequences for this device */ dev->analog_gpio = em2880_msi_digivox_ad_analog; dev->digital_gpio = em2880_msi_digivox_ad_digital; @@ -1477,19 +1464,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) dev->tun_digital_gpio = default_callback; break; - case EM2750_BOARD_UNKNOWN: - case EM2750_BOARD_DLCW_130: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_FREQUENCY_48MHZ); - break; - case EM2861_BOARD_PLEXTOR_PX_TV100U: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); /* FIXME guess */ /* Turn on analog audio output */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); @@ -1497,13 +1472,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) case EM2861_BOARD_KWORLD_PVRTV_300U: case EM2880_BOARD_KWORLD_DVB_305U: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - msleep(10); em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d); msleep(10); em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d); @@ -1511,25 +1479,11 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2870_BOARD_KWORLD_355U: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - msleep(50); - /* Sets GPO/GPIO sequences for this device */ dev->digital_gpio = em2870_kworld_355u_digital; break; case EM2870_BOARD_COMPRO_VIDEOMATE: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); /* TODO: someone can do some cleanup here... not everything's needed */ em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); @@ -1547,12 +1501,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2870_BOARD_TERRATEC_XS_MT2060: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); /* this device needs some gpio writes to get the DVB-T demod work */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); @@ -1564,10 +1512,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2870_BOARD_PINNACLE_PCTV_DVB: - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - /* this device needs some gpio writes to get the DVB-T demod work */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); @@ -1576,53 +1520,15 @@ void em28xx_pre_card_setup(struct em28xx *dev) mdelay(70); em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); mdelay(70); - /* switch em2880 rc protocol */ - /* djh - I have serious doubts this is right... */ - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_10MHZ); - /* should be added ir_codes here */ break; case EM2820_BOARD_GADMEI_UTV310: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - /* Turn on analog audio output */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - break; - - case EM2860_BOARD_GADMEI_UTV330: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - /* should be added ir_codes here */ - break; - case EM2820_BOARD_MSI_VOX_USB_2: - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ); - /* enables audio for that device */ + /* enables audio for that devices */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; case EM2874_BOARD_PINNACLE_PCTV_80E: - /* Set 400 KHz clock and select secondary i2c bus */ - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, - EM28XX_I2C_CLK_WAIT_ENABLE | - EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_FREQ_400_KHZ); - dev->digital_gpio = em2874_pinnacle_80e_digital; break; } diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index eb8515895..64503c04a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -399,7 +399,7 @@ struct em28xx_vol_table outputs[] = { int em28xx_audio_analog_set(struct em28xx *dev) { int ret, i; - u8 xclk = 0x07; + u8 xclk; if (!dev->audio_mode.has_audio) return 0; @@ -417,13 +417,11 @@ int em28xx_audio_analog_set(struct em28xx *dev) } } - if (dev->has_12mhz_i2s) - xclk |= 0x20; - + xclk = dev->xclk & 0x7f; if (!dev->mute) xclk |= 0x80; - ret = em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, xclk, 0xa7); + ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk); if (ret < 0) return ret; msleep(10); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 151668c60..c6f7870b7 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -339,12 +339,13 @@ struct em28xx_board { unsigned int is_em2800:1; unsigned int has_msp34xx:1; unsigned int mts_firmware:1; - unsigned int has_12mhz_i2s:1; unsigned int max_range_640_480:1; unsigned int has_dvb:1; unsigned int has_snapshot_button:1; unsigned int valid:1; + unsigned char xclk, i2c_speed; + enum em28xx_decoder decoder; struct em28xx_input input[MAX_EM28XX_INPUT]; @@ -431,12 +432,13 @@ struct em28xx { unsigned int stream_on:1; /* Locks streams */ unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; - unsigned int has_12mhz_i2s:1; unsigned int max_range_640_480:1; unsigned int has_dvb:1; unsigned int has_snapshot_button:1; unsigned int valid:1; /* report for validated boards */ + unsigned char xclk, i2c_speed; + struct em28xx_IR *ir; /* Some older em28xx chips needs a waiting time after writing */ -- cgit v1.2.3 From aadce2c5e2229edf817d779c20b5bcf74e12ac1a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 24 Nov 2008 13:53:22 +0100 Subject: em28xx: fix compile warning From: Hans Verkuil Label fail_unreg is no longer used. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/em28xx/em28xx-video.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 5da519bfa..634b82f4b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2205,8 +2205,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return 0; -fail_unreg: - em28xx_release_resources(dev); fail_reg_devices: mutex_unlock(&dev->lock); return retval; -- cgit v1.2.3 From 6941ff312bc3df2578143871566980c02dade212 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 24 Nov 2008 13:56:06 +0100 Subject: qv4l2: fix compile warnings. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/util/qv4l2/qv4l2.cpp | 8 ++++---- v4l2-apps/util/qv4l2/qv4l2.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/v4l2-apps/util/qv4l2/qv4l2.cpp b/v4l2-apps/util/qv4l2/qv4l2.cpp index eb1506531..d144723d9 100644 --- a/v4l2-apps/util/qv4l2/qv4l2.cpp +++ b/v4l2-apps/util/qv4l2/qv4l2.cpp @@ -136,13 +136,13 @@ void ApplicationWindow::selectdev(int index) setDevice(videoDevice->text(index)); } -void ApplicationWindow::add_dirVideoDevice(char *dirname) +void ApplicationWindow::add_dirVideoDevice(const char *dirname) { DIR *dir; struct dirent *entry; - char *vid = "video"; - char *rad = "radio"; - char *vbi = "vbi"; + const char *vid = "video"; + const char *rad = "radio"; + const char *vbi = "vbi"; char name[512], *p; dir = opendir(dirname); diff --git a/v4l2-apps/util/qv4l2/qv4l2.h b/v4l2-apps/util/qv4l2/qv4l2.h index 805c5d612..5421a867d 100644 --- a/v4l2-apps/util/qv4l2/qv4l2.h +++ b/v4l2-apps/util/qv4l2/qv4l2.h @@ -66,7 +66,7 @@ private slots: void about(); private: - void add_dirVideoDevice(char *dirname); + void add_dirVideoDevice(const char *dirname); void addTabs(); void finishGrid(QWidget *vbox, QGrid *grid, unsigned ctrl_class, bool odd); void addCtrl(QGrid *grid, const struct v4l2_queryctrl &qctrl); -- cgit v1.2.3 From 564d21054d1f61d9448a93b3fa8a254a29713d26 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 09:07:00 -0200 Subject: fix boards for kernels with algo_control From: Mauro Carvalho Chehab changeset 4ecae6da8244 removed algo_control from i2c drivers. However, on older kernels, a dummy function to implement algo_control is required, otherwise, an OOPS is generated. This patch adds a backport for all i2c drivers that defines an i2c_algorithm, except for cafe_ccic, since OLPC hardware only works for kernels newer than 2.6.19. Some of the backported drivers would need also extra changes to work with older kernels, as specified on v4l/versions.txt. Yet, I decided to add the backport for those drivers also, since the lack of algo_control doesn't generate any compilation error, but it is enough to break the driver. So, better to all for all boards than to allow compiling a kernel backported that just generates OOPS. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/saa7146_i2c.c | 3 +++ linux/drivers/media/dvb/b2c2/flexcop-i2c.c | 3 +++ linux/drivers/media/dvb/dm1105/dm1105.c | 3 +++ linux/drivers/media/dvb/dvb-usb/af9005.c | 3 +++ linux/drivers/media/dvb/dvb-usb/af9015.c | 3 +++ linux/drivers/media/dvb/dvb-usb/anysee.c | 3 +++ linux/drivers/media/dvb/dvb-usb/au6610.c | 3 +++ linux/drivers/media/dvb/dvb-usb/cxusb.c | 3 +++ linux/drivers/media/dvb/dvb-usb/dib0700_core.c | 3 +++ linux/drivers/media/dvb/dvb-usb/dibusb-common.c | 3 +++ linux/drivers/media/dvb/dvb-usb/digitv.c | 3 +++ linux/drivers/media/dvb/dvb-usb/dtv5100.c | 3 +++ linux/drivers/media/dvb/dvb-usb/dw2102.c | 12 ++++++++++++ linux/drivers/media/dvb/dvb-usb/gl861.c | 3 +++ linux/drivers/media/dvb/dvb-usb/m920x.c | 3 +++ linux/drivers/media/dvb/dvb-usb/opera1.c | 3 +++ linux/drivers/media/dvb/dvb-usb/ttusb2.c | 3 +++ linux/drivers/media/dvb/frontends/cx24123.c | 4 ++++ linux/drivers/media/dvb/frontends/dibx000_common.c | 4 ++++ linux/drivers/media/dvb/frontends/s5h1420.c | 4 ++++ .../media/dvb/ttusb-budget/dvb-ttusb-budget.c | 3 +++ linux/drivers/media/video/au0828/au0828-i2c.c | 3 +++ linux/drivers/media/video/bt8xx/bttv-i2c.c | 3 +++ linux/drivers/media/video/cx23885/cx23885-i2c.c | 3 +++ linux/drivers/media/video/em28xx/em28xx-i2c.c | 3 +++ linux/drivers/media/video/ivtv/ivtv-i2c.c | 3 +++ linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 3 +++ linux/drivers/media/video/saa7134/saa7134-i2c.c | 3 +++ linux/drivers/media/video/usbvision/usbvision-i2c.c | 3 +++ linux/drivers/media/video/w9968cf.c | 3 +++ v4l/compat.h | 12 ++++++++++++ v4l/scripts/gentree.pl | 1 + v4l/scripts/make_config_compat.pl | 20 ++++++++++++++++++++ 33 files changed, 135 insertions(+) diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index ae20d2729..255b14551 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -406,6 +406,9 @@ static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, in static struct i2c_algorithm saa7146_algo = { .master_xfer = saa7146_i2c_xfer, .functionality = saa7146_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate) diff --git a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c index 43a112ec6..05635c453 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -205,6 +205,9 @@ static u32 flexcop_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm flexcop_algo = { .master_xfer = flexcop_master_xfer, .functionality = flexcop_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; int flexcop_i2c_init(struct flexcop_device *fc) diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c index 100a7f661..d7034e6a1 100644 --- a/linux/drivers/media/dvb/dm1105/dm1105.c +++ b/linux/drivers/media/dvb/dm1105/dm1105.c @@ -330,6 +330,9 @@ static u32 functionality(struct i2c_adapter *adap) static struct i2c_algorithm dm1105_algo = { .master_xfer = dm1105_i2c_xfer, .functionality = functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed) diff --git a/linux/drivers/media/dvb/dvb-usb/af9005.c b/linux/drivers/media/dvb/dvb-usb/af9005.c index ca5a0a4d2..fdf592625 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9005.c +++ b/linux/drivers/media/dvb/dvb-usb/af9005.c @@ -500,6 +500,9 @@ static u32 af9005_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm af9005_i2c_algo = { .master_xfer = af9005_i2c_xfer, .functionality = af9005_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf, diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index e6e534e04..f0b57c739 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -318,6 +318,9 @@ static u32 af9015_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm af9015_i2c_algo = { .master_xfer = af9015_i2c_xfer, .functionality = af9015_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) diff --git a/linux/drivers/media/dvb/dvb-usb/anysee.c b/linux/drivers/media/dvb/dvb-usb/anysee.c index cd2edbcaa..90a04266a 100644 --- a/linux/drivers/media/dvb/dvb-usb/anysee.c +++ b/linux/drivers/media/dvb/dvb-usb/anysee.c @@ -199,6 +199,9 @@ static u32 anysee_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm anysee_i2c_algo = { .master_xfer = anysee_master_xfer, .functionality = anysee_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static int anysee_mt352_demod_init(struct dvb_frontend *fe) diff --git a/linux/drivers/media/dvb/dvb-usb/au6610.c b/linux/drivers/media/dvb/dvb-usb/au6610.c index eb34cc389..b2400d693 100644 --- a/linux/drivers/media/dvb/dvb-usb/au6610.c +++ b/linux/drivers/media/dvb/dvb-usb/au6610.c @@ -119,6 +119,9 @@ static u32 au6610_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm au6610_i2c_algo = { .master_xfer = au6610_i2c_xfer, .functionality = au6610_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* Callbacks for DVB USB */ diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c index 406d7fba3..f467cad8a 100644 --- a/linux/drivers/media/dvb/dvb-usb/cxusb.c +++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c @@ -213,6 +213,9 @@ static u32 cxusb_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm cxusb_i2c_algo = { .master_xfer = cxusb_i2c_xfer, .functionality = cxusb_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff) diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c index 2fbb7049a..807bff0e1 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -252,6 +252,9 @@ static u32 dib0700_i2c_func(struct i2c_adapter *adapter) struct i2c_algorithm dib0700_i2c_algo = { .master_xfer = dib0700_i2c_xfer, .functionality = dib0700_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c index 8ee6cd4da..d774879df 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -155,6 +155,9 @@ static u32 dibusb_i2c_func(struct i2c_adapter *adapter) struct i2c_algorithm dibusb_i2c_algo = { .master_xfer = dibusb_i2c_xfer, .functionality = dibusb_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; EXPORT_SYMBOL(dibusb_i2c_algo); diff --git a/linux/drivers/media/dvb/dvb-usb/digitv.c b/linux/drivers/media/dvb/dvb-usb/digitv.c index b545cf3ea..3a560dcdd 100644 --- a/linux/drivers/media/dvb/dvb-usb/digitv.c +++ b/linux/drivers/media/dvb/dvb-usb/digitv.c @@ -83,6 +83,9 @@ static u32 digitv_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm digitv_i2c_algo = { .master_xfer = digitv_i2c_xfer, .functionality = digitv_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* Callbacks for DVB USB */ diff --git a/linux/drivers/media/dvb/dvb-usb/dtv5100.c b/linux/drivers/media/dvb/dvb-usb/dtv5100.c index 078ce92ca..e07a805f6 100644 --- a/linux/drivers/media/dvb/dvb-usb/dtv5100.c +++ b/linux/drivers/media/dvb/dvb-usb/dtv5100.c @@ -104,6 +104,9 @@ static u32 dtv5100_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm dtv5100_i2c_algo = { .master_xfer = dtv5100_i2c_xfer, .functionality = dtv5100_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* Callbacks for DVB USB */ diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c index bc5e47a2b..9b32c9c0a 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.c +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c @@ -368,21 +368,33 @@ static u32 dw210x_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm dw2102_i2c_algo = { .master_xfer = dw2102_i2c_transfer, .functionality = dw210x_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static struct i2c_algorithm dw2102_serit_i2c_algo = { .master_xfer = dw2102_serit_i2c_transfer, .functionality = dw210x_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static struct i2c_algorithm dw2102_earda_i2c_algo = { .master_xfer = dw2102_earda_i2c_transfer, .functionality = dw210x_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static struct i2c_algorithm dw2104_i2c_algo = { .master_xfer = dw2104_i2c_transfer, .functionality = dw210x_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) diff --git a/linux/drivers/media/dvb/dvb-usb/gl861.c b/linux/drivers/media/dvb/dvb-usb/gl861.c index 6f596ed41..41bec1b58 100644 --- a/linux/drivers/media/dvb/dvb-usb/gl861.c +++ b/linux/drivers/media/dvb/dvb-usb/gl861.c @@ -91,6 +91,9 @@ static u32 gl861_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm gl861_i2c_algo = { .master_xfer = gl861_i2c_xfer, .functionality = gl861_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* Callbacks for DVB USB */ diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 54626a0db..51c1c8dba 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -256,6 +256,9 @@ static u32 m920x_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm m920x_i2c_algo = { .master_xfer = m920x_i2c_xfer, .functionality = m920x_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* pid filter */ diff --git a/linux/drivers/media/dvb/dvb-usb/opera1.c b/linux/drivers/media/dvb/dvb-usb/opera1.c index cba064615..d45ceb83b 100644 --- a/linux/drivers/media/dvb/dvb-usb/opera1.c +++ b/linux/drivers/media/dvb/dvb-usb/opera1.c @@ -167,6 +167,9 @@ static u32 opera1_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm opera1_i2c_algo = { .master_xfer = opera1_i2c_xfer, .functionality = opera1_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static int opera1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) diff --git a/linux/drivers/media/dvb/dvb-usb/ttusb2.c b/linux/drivers/media/dvb/dvb-usb/ttusb2.c index e79a26473..849c59478 100644 --- a/linux/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/linux/drivers/media/dvb/dvb-usb/ttusb2.c @@ -124,6 +124,9 @@ static u32 ttusb2_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm ttusb2_i2c_algo = { .master_xfer = ttusb2_i2c_xfer, .functionality = ttusb2_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* Callbacks for DVB USB */ diff --git a/linux/drivers/media/dvb/frontends/cx24123.c b/linux/drivers/media/dvb/frontends/cx24123.c index fb559369e..c9cfc8393 100644 --- a/linux/drivers/media/dvb/frontends/cx24123.c +++ b/linux/drivers/media/dvb/frontends/cx24123.c @@ -29,6 +29,7 @@ #include "dvb_frontend.h" #include "cx24123.h" +#include "compat.h" #define XTAL 10111000 @@ -1065,6 +1066,9 @@ static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter) static struct i2c_algorithm cx24123_tuner_i2c_algo = { .master_xfer = cx24123_tuner_i2c_tuner_xfer, .functionality = cx24123_tuner_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; struct i2c_adapter * diff --git a/linux/drivers/media/dvb/frontends/dibx000_common.c b/linux/drivers/media/dvb/frontends/dibx000_common.c index a8e3a950c..6f1f41ae3 100644 --- a/linux/drivers/media/dvb/frontends/dibx000_common.c +++ b/linux/drivers/media/dvb/frontends/dibx000_common.c @@ -1,6 +1,7 @@ #include #include "dibx000_common.h" +#include "compat.h" static int debug; module_param(debug, int, 0644); @@ -107,6 +108,9 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { .master_xfer = dibx000_i2c_gated_tuner_xfer, .functionality = dibx000_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating) diff --git a/linux/drivers/media/dvb/frontends/s5h1420.c b/linux/drivers/media/dvb/frontends/s5h1420.c index 46d55e393..f357f8233 100644 --- a/linux/drivers/media/dvb/frontends/s5h1420.c +++ b/linux/drivers/media/dvb/frontends/s5h1420.c @@ -37,6 +37,7 @@ #include "dvb_frontend.h" #include "s5h1420.h" #include "s5h1420_priv.h" +#include "compat.h" #define TONE_FREQ 22000 @@ -904,6 +905,9 @@ static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c static struct i2c_algorithm s5h1420_tuner_i2c_algo = { .master_xfer = s5h1420_tuner_i2c_tuner_xfer, .functionality = s5h1420_tuner_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe) diff --git a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 8775b78af..086b9987f 100644 --- a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1657,6 +1657,9 @@ static void frontend_init(struct ttusb* ttusb) static struct i2c_algorithm ttusb_dec_algo = { .master_xfer = master_xfer, .functionality = functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id) diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index 03b797b9b..d8cef6ccc 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -301,6 +301,9 @@ static u32 au0828_functionality(struct i2c_adapter *adap) static struct i2c_algorithm au0828_i2c_algo_template = { .master_xfer = i2c_xfer, .functionality = au0828_functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* ----------------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index bcd2cd240..558572589 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -260,6 +260,9 @@ static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int static const struct i2c_algorithm bttv_algo = { .master_xfer = bttv_i2c_xfer, .functionality = functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* ----------------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index ced5648d8..2210b47d2 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -353,6 +353,9 @@ static u32 cx23885_functionality(struct i2c_adapter *adap) static struct i2c_algorithm cx23885_i2c_algo_template = { .master_xfer = i2c_xfer, .functionality = cx23885_functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* ----------------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index ec3e3b157..4e6fa575d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -521,6 +521,9 @@ static int attach_inform(struct i2c_client *client) static struct i2c_algorithm em28xx_algo = { .master_xfer = em28xx_i2c_xfer, .functionality = functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static struct i2c_adapter em28xx_adap_template = { diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index c251ddb2f..fa18eae17 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -550,6 +550,9 @@ static u32 ivtv_functionality(struct i2c_adapter *adap) static struct i2c_algorithm ivtv_algo = { .master_xfer = ivtv_xfer, .functionality = ivtv_functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; /* template for our-bit banger */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index edce8fc34..877c8f7b1 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -1013,6 +1013,9 @@ static int pvr2_i2c_detach_inform(struct i2c_client *client) static struct i2c_algorithm pvr2_i2c_algo_template = { .master_xfer = pvr2_i2c_xfer, .functionality = pvr2_i2c_functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static struct i2c_adapter pvr2_i2c_adap_template = { diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index df97ac987..3f7d4eb80 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -358,6 +358,9 @@ static int attach_inform(struct i2c_client *client) static struct i2c_algorithm saa7134_algo = { .master_xfer = saa7134_i2c_xfer, .functionality = functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static struct i2c_adapter saa7134_adap_template = { diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.c b/linux/drivers/media/video/usbvision/usbvision-i2c.c index 888051b80..58f65e03a 100644 --- a/linux/drivers/media/video/usbvision/usbvision-i2c.c +++ b/linux/drivers/media/video/usbvision/usbvision-i2c.c @@ -198,6 +198,9 @@ static struct i2c_algorithm usbvision_algo = { .master_xfer = usbvision_i2c_xfer, .smbus_xfer = NULL, .functionality = functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index ab3c054c4..5763a4234 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -1557,6 +1557,9 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam) static struct i2c_algorithm algo = { .smbus_xfer = w9968cf_i2c_smbus_xfer, .functionality = w9968cf_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static struct i2c_adapter adap = { diff --git a/v4l/compat.h b/v4l/compat.h index 1d042d96c..ad2d9df22 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -27,6 +27,10 @@ #include #endif +#ifdef NEED_ALGO_CONTROL +#include +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) #define set_freezable() #define cancel_delayed_work_sync cancel_rearming_delayed_work @@ -231,6 +235,14 @@ static inline int list_is_singular(const struct list_head *head) ( x ) ) ) #endif +#ifdef NEED_ALGO_CONTROL +static inline int dummy_algo_control(struct i2c_adapter *adapter, + unsigned int cmd, unsigned long arg) +{ + return 0; +} +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) #define div64_u64(a,b) div64_64(a,b) diff --git a/v4l/scripts/gentree.pl b/v4l/scripts/gentree.pl index d84608aa1..1968bb334 100755 --- a/v4l/scripts/gentree.pl +++ b/v4l/scripts/gentree.pl @@ -74,6 +74,7 @@ my %defs = ( 'NEED_SOUND_DRIVER_H' => 0, 'TTUSB_KERNEL' => 1, 'NO_PCM_LOCK' => 0, + 'NEED_ALGO_CONTROL' => 0, ); ################################################################# diff --git a/v4l/scripts/make_config_compat.pl b/v4l/scripts/make_config_compat.pl index 3aac7e3b3..3a8bdd81e 100755 --- a/v4l/scripts/make_config_compat.pl +++ b/v4l/scripts/make_config_compat.pl @@ -178,6 +178,25 @@ sub check_pcm_lock() close INNET; } +sub check_algo_control() +{ + my $file = "$kdir/include/linux/i2c.h"; + my $need_compat = 0; + + open INNET, "<$file" or die "File not found: $file"; + while () { + if (m/algo_control/) { + $need_compat = 1; + last; + } + } + + if ($need_compat) { + $out.= "\n#define NEED_ALGO_CONTROL 1\n"; + } + close INNET; +} + sub check_other_dependencies() { check_spin_lock(); @@ -189,6 +208,7 @@ sub check_other_dependencies() check_clamp(); check_proc_create(); check_pcm_lock(); + check_algo_control(); } # Do the basic rules -- cgit v1.2.3 From 7a8e65e6272706e69c47c96e865ec1170c1e1564 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 10:10:25 -0200 Subject: em28xx: card description cleanups From: Mauro Carvalho Chehab Remove unused em28xx_board.vchannels and em28xx.video_channels. Also, .is_em2800 = 0 is not needed, as all data is zeroed by kernel loader. The table also included a notice that svideo weren't test on Hauppauge USB2. Remove this notice, since this input also works properly. Also, it does some whitespace cleanups. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 181 ++++++++---------------- linux/drivers/media/video/em28xx/em28xx.h | 2 - 2 files changed, 59 insertions(+), 124 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index f6815ae85..42f9fb6a5 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -55,7 +55,6 @@ struct em28xx_hash_table { struct em28xx_board em28xx_boards[] = { [EM2750_BOARD_UNKNOWN] = { .name = "Unknown EM2750/EM2751 webcam grabber", - .vchannels = 1, .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, .input = { { .type = EM28XX_VMUX_COMPOSITE1, @@ -66,10 +65,9 @@ struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_UNKNOWN] = { .name = "Unknown EM2800 video grabber", .is_em2800 = 1, - .vchannels = 2, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -87,7 +85,6 @@ struct em28xx_board em28xx_boards[] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ .name = "Huaqi DLCW-130", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 1, .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, .input = { { .type = EM28XX_VMUX_COMPOSITE1, @@ -97,12 +94,10 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_KWORLD_PVRTV2800RF] = { .name = "Kworld PVR TV 2800 RF", - .is_em2800 = 0, - .vchannels = 2, .tuner_type = TUNER_TEMIC_PAL, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -114,11 +109,10 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_TERRATEC_CINERGY_250] = { .name = "Terratec Cinergy 250 USB", - .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, @@ -134,11 +128,10 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_PINNACLE_USB_2] = { .name = "Pinnacle PCTV USB 2", - .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, @@ -154,15 +147,13 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = { .name = "Hauppauge WinTV USB 2", - .vchannels = 3, .tuner_type = TUNER_PHILIPS_FM1236_MK3, .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE| TDA9887_PORT2_ACTIVE, .decoder = EM28XX_TVP5150, .has_msp34xx = 1, - /*FIXME: S-Video not tested */ - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = MSP_INPUT_DEFAULT, @@ -176,12 +167,10 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_DLINK_USB_TV] = { .name = "D-Link DUB-T210 TV Tuner", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, - .is_em2800 = 0, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, @@ -198,7 +187,6 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_HERCULES_SMART_TV_USB2] = { .name = "Hercules Smart TV USB 2.0", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, @@ -219,12 +207,10 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_PINNACLE_USB_2_FM1216ME] = { .name = "Pinnacle PCTV USB 2 (Philips FM1216ME)", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, - .is_em2800 = 0, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, @@ -241,11 +227,10 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_GADMEI_UTV310] = { .name = "Gadmei UTV310", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_TNF_5335MF, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, @@ -262,11 +247,10 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE] = { .name = "Leadtek Winfast USB II Deluxe", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7114, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = 2, .amux = EM28XX_AMUX_VIDEO, @@ -283,9 +267,8 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_PINNACLE_DVC_100] = { .name = "Pinnacle Dazzle DVC 100", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -296,10 +279,9 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { - .name = "Videology 20K14XUSB USB2.0", + .name = "Videology 20K14XUSB USB2.0", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 1, - .input = { { + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, @@ -308,12 +290,10 @@ struct em28xx_board em28xx_boards[] = { [EM2821_BOARD_PROLINK_PLAYTV_USB2] = { .name = "SIIG AVTuner-PVR/Prolink PlayTV USB 2.0", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, - .is_em2800 = 0, .tuner_type = TUNER_LG_PAL_NEW_TAPC, /* unknown? */ .tda9887_conf = TDA9887_PRESENT, /* unknown? */ .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, @@ -330,14 +310,12 @@ struct em28xx_board em28xx_boards[] = { [EM2821_BOARD_SUPERCOMP_USB_2] = { .name = "Supercomp USB 2.0 TV", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, - .is_em2800 = 0, .tuner_type = TUNER_PHILIPS_FM1236_MK3, .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, @@ -352,11 +330,10 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2821_BOARD_USBGEAR_VD204] = { - .name = "Usbgear VD204v9", + .name = "Usbgear VD204v9", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 2, - .decoder = EM28XX_SAA7113, - .input = { { + .decoder = EM28XX_SAA7113, + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -368,21 +345,19 @@ struct em28xx_board em28xx_boards[] = { }, [EM2860_BOARD_NETGMBH_CAM] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ - .name = "NetGMBH Cam", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 1, - .input = { { + .name = "NetGMBH Cam", + .valid = EM28XX_BOARD_NOT_VALIDATED, + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, }, [EM2860_BOARD_TYPHOON_DVD_MAKER] = { - .name = "Typhoon DVD Maker", + .name = "Typhoon DVD Maker", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 2, - .decoder = EM28XX_SAA7113, - .input = { { + .decoder = EM28XX_SAA7113, + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -395,11 +370,10 @@ struct em28xx_board em28xx_boards[] = { [EM2860_BOARD_GADMEI_UTV330] = { .name = "Gadmei UTV330", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_TNF_5335MF, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, @@ -416,10 +390,9 @@ struct em28xx_board em28xx_boards[] = { [EM2860_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Cinergy A Hybrid XS", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -436,10 +409,9 @@ struct em28xx_board em28xx_boards[] = { [EM2861_BOARD_KWORLD_PVRTV_300U] = { .name = "KWorld PVRTV 300U", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -455,8 +427,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = { .name = "Yakumo MovieMixer", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 1, + .valid = EM28XX_BOARD_NOT_VALIDATED, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -475,11 +446,10 @@ struct em28xx_board em28xx_boards[] = { [EM2861_BOARD_PLEXTOR_PX_TV100U] = { .name = "Plextor ConvertX PX-TV100U", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_TNF_5335MF, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -516,7 +486,6 @@ struct em28xx_board em28xx_boards[] = { .name = "Pinnacle PCTV DVB-T", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_ABSENT, /* MT2060 */ - /* djh - I have serious doubts this is right... */ .xclk = EM28XX_XCLK_IR_RC5_MODE | EM28XX_XCLK_FREQUENCY_10MHZ, @@ -529,11 +498,10 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = { .name = "Terratec Hybrid XS Secam", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .has_msp34xx = 1, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -549,13 +517,12 @@ struct em28xx_board em28xx_boards[] = { }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { .name = "Hauppauge WinTV HVR 900", - .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_dvb = 1, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -571,12 +538,11 @@ struct em28xx_board em28xx_boards[] = { }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = { .name = "Hauppauge WinTV HVR 900 (R2)", - .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, .mts_firmware = 1, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -592,7 +558,6 @@ struct em28xx_board em28xx_boards[] = { }, [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = { .name = "Hauppauge WinTV HVR 950", - .vchannels = 3, .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_dvb = 1, @@ -614,7 +579,6 @@ struct em28xx_board em28xx_boards[] = { }, [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = { .name = "Pinnacle PCTV HD Pro Stick", - .vchannels = 3, .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_dvb = 1, @@ -636,7 +600,6 @@ struct em28xx_board em28xx_boards[] = { }, [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = { .name = "AMD ATI TV Wonder HD 600", - .vchannels = 3, .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_dvb = 1, @@ -657,10 +620,9 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2880_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Hybrid XS", - .vchannels = 3, - .tuner_type = TUNER_XC2028, - .decoder = EM28XX_TVP5150, + .name = "Terratec Hybrid XS", + .tuner_type = TUNER_XC2028, + .decoder = EM28XX_TVP5150, .has_dvb = 1, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -681,10 +643,9 @@ struct em28xx_board em28xx_boards[] = { maybe we'll need it lateron */ [EM2880_BOARD_TERRATEC_PRODIGY_XS] = { .name = "Terratec Prodigy XS", - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -700,13 +661,11 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_MSI_VOX_USB_2] = { .name = "MSI VOX USB 2.0", - .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, .max_range_640_480 = 1, - .decoder = EM28XX_SAA7114, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -725,11 +684,10 @@ struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_TERRATEC_CINERGY_200] = { .name = "Terratec Cinergy 200 USB", .is_em2800 = 1, - .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, @@ -746,9 +704,8 @@ struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_GRABBEEX_USB2800] = { .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", .is_em2800 = 1, - .vchannels = 2, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -761,11 +718,10 @@ struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { .name = "Leadtek Winfast USB II", .is_em2800 = 1, - .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, @@ -782,11 +738,10 @@ struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_KWORLD_USB2800] = { .name = "Kworld USB2800", .is_em2800 = 1, - .vchannels = 3, .tuner_type = TUNER_PHILIPS_FCV1236D, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, @@ -802,10 +757,9 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_PINNACLE_DVC_90] = { .name = "Pinnacle Dazzle DVC 90/DVC 100", - .vchannels = 3, .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -818,11 +772,10 @@ struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_VGEAR_POCKETTV] = { .name = "V-Gear PocketTV", .is_em2800 = 1, - .vchannels = 3, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, @@ -838,11 +791,10 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { .name = "Pixelview Prolink PlayTV USB 2.0", - .vchannels = 3, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, .decoder = EM28XX_SAA7113, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, @@ -859,13 +811,12 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA] = { - .name = "PointNix Intra-Oral Camera", + .name = "PointNix Intra-Oral Camera", .has_snapshot_button = 1, - .vchannels = 1, - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA7113, - .input = { { + .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_SAA7113, + .input = { { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, .amux = EM28XX_AMUX_VIDEO, @@ -874,10 +825,9 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_MSI_DIGIVOX_AD] = { .name = "MSI DigiVox A/D", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -894,10 +844,9 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_MSI_DIGIVOX_AD_II] = { .name = "MSI DigiVox A/D II", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -914,10 +863,9 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_KWORLD_DVB_305U] = { .name = "KWorld DVB-T 305U", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -933,12 +881,11 @@ struct em28xx_board em28xx_boards[] = { }, [EM2880_BOARD_KWORLD_DVB_310U] = { .name = "KWorld DVB-T 310U", - .vchannels = 3, .tuner_type = TUNER_XC2028, .has_dvb = 1, .mts_firmware = 1, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -955,10 +902,9 @@ struct em28xx_board em28xx_boards[] = { [EM2881_BOARD_DNT_DA2_HYBRID] = { .name = "DNT DA2 Hybrid", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -975,10 +921,9 @@ struct em28xx_board em28xx_boards[] = { [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { .name = "Pinnacle Hybrid Pro", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -995,11 +940,10 @@ struct em28xx_board em28xx_boards[] = { [EM2882_BOARD_PINNACLE_HYBRID_PRO] = { .name = "Pinnacle Hybrid Pro (2)", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .mts_firmware = 1, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -1016,10 +960,9 @@ struct em28xx_board em28xx_boards[] = { [EM2882_BOARD_KWORLD_VS_DVBT] = { .name = "Kworld VS-DVB-T 323UR", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -1036,10 +979,9 @@ struct em28xx_board em28xx_boards[] = { [EM2882_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Hybrid XS (em2882)", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -1056,11 +998,9 @@ struct em28xx_board em28xx_boards[] = { [EM2883_BOARD_KWORLD_HYBRID_A316] = { .name = "Kworld PlusTV HD Hybrid 330", .valid = EM28XX_BOARD_NOT_VALIDATED, - .vchannels = 3, - .is_em2800 = 0, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, @@ -1076,11 +1016,10 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { .name = "Compro VideoMate ForYou/Stereo", - .vchannels = 2, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -1092,7 +1031,6 @@ struct em28xx_board em28xx_boards[] = { }, [EM2874_BOARD_PINNACLE_PCTV_80E] = { .name = "Pinnacle PCTV HD Mini", - .vchannels = 0, .tuner_type = TUNER_ABSENT, .has_dvb = 1, .ir_codes = ir_codes_pinnacle_pctv_hd, @@ -1101,7 +1039,7 @@ struct em28xx_board em28xx_boards[] = { EM2874_I2C_SECONDARY_BUS_SELECT | EM28XX_I2C_FREQ_400_KHZ, #ifdef DJH_DEBUG - .input = { { + .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -1335,7 +1273,6 @@ static void em28xx_set_model(struct em28xx *dev) dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx; dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; dev->decoder = em28xx_boards[dev->model].decoder; - dev->video_inputs = em28xx_boards[dev->model].vchannels; dev->xclk = em28xx_boards[dev->model].xclk; dev->i2c_speed = em28xx_boards[dev->model].i2c_speed; dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index c6f7870b7..f9270f681 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -329,7 +329,6 @@ struct em28xx_reg_seq { struct em28xx_board { char *name; - int vchannels; int tuner_type; int tuner_addr; @@ -450,7 +449,6 @@ struct em28xx { /* GPIO sequences for tuner callbacks */ struct em28xx_reg_seq *tun_analog_gpio, *tun_digital_gpio; - int video_inputs; /* number of video inputs */ struct list_head devlist; u32 i2s_speed; /* I2S speed for audio digital stream */ -- cgit v1.2.3 From 648862d26603ff7d30334417fda9c5d8bfa0871a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 10:39:50 -0200 Subject: Remove duplicated fields on em28xx_board and em28xx structs From: Mauro Carvalho Chehab Several fields are duplicated on both structs. Let's just copy em28xx_board instead. A later cleanup could just copy the fields that are changed, in order to keep em28xx_board const. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 44 ++++++++++--------------- linux/drivers/media/video/em28xx/em28xx-core.c | 8 ++--- linux/drivers/media/video/em28xx/em28xx-dvb.c | 4 +-- linux/drivers/media/video/em28xx/em28xx-i2c.c | 6 ++-- linux/drivers/media/video/em28xx/em28xx-input.c | 4 +-- linux/drivers/media/video/em28xx/em28xx-video.c | 18 +++++----- linux/drivers/media/video/em28xx/em28xx.h | 21 ++++-------- 7 files changed, 43 insertions(+), 62 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 42f9fb6a5..9363aa721 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1267,19 +1267,9 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg) } EXPORT_SYMBOL_GPL(em28xx_tuner_callback); -static void em28xx_set_model(struct em28xx *dev) +static void inline em28xx_set_model(struct em28xx *dev) { - dev->is_em2800 = em28xx_boards[dev->model].is_em2800; - dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx; - dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; - dev->decoder = em28xx_boards[dev->model].decoder; - dev->xclk = em28xx_boards[dev->model].xclk; - dev->i2c_speed = em28xx_boards[dev->model].i2c_speed; - dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; - dev->has_dvb = em28xx_boards[dev->model].has_dvb; - dev->has_snapshot_button = em28xx_boards[dev->model].has_snapshot_button; - dev->ir_codes = em28xx_boards[dev->model].ir_codes; - dev->valid = em28xx_boards[dev->model].valid; + memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board)); } /* Since em28xx_pre_card_setup() requires a proper dev->model, @@ -1336,16 +1326,16 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* Those are the default values for the majority of boards Use those values if not specified otherwise at boards entry */ - if (!dev->xclk) - dev->xclk = EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ; + if (!dev->board.xclk) + dev->board.xclk = EM28XX_XCLK_IR_RC5_MODE | + EM28XX_XCLK_FREQUENCY_12MHZ; - if (!dev->i2c_speed) - dev->i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ; + if (!dev->board.i2c_speed) + dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_100_KHZ; - em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->xclk & 0x7f); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->i2c_speed); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); msleep(50); /* request some modules */ @@ -1699,7 +1689,7 @@ void em28xx_card_setup(struct em28xx *dev) if (tv.audio_processor == V4L2_IDENT_MSPX4XX) { dev->i2s_speed = 2048000; - dev->has_msp34xx = 1; + dev->board.has_msp34xx = 1; } #ifdef CONFIG_MODULES if (tv.has_ir) @@ -1732,10 +1722,10 @@ void em28xx_card_setup(struct em28xx *dev) break; } - if (dev->has_snapshot_button) + if (dev->board.has_snapshot_button) em28xx_register_snapshot_button(dev); - if (dev->valid == EM28XX_BOARD_NOT_VALIDATED) { + if (dev->board.valid == EM28XX_BOARD_NOT_VALIDATED) { em28xx_errdev("\n\n"); em28xx_errdev("The support for this board weren't " "valid yet.\n"); @@ -1750,13 +1740,13 @@ void em28xx_card_setup(struct em28xx *dev) #ifdef CONFIG_MODULES /* request some modules */ - if (dev->has_msp34xx) + if (dev->board.has_msp34xx) request_module("msp3400"); - if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) + if (dev->board.decoder == EM28XX_SAA7113 || dev->board.decoder == EM28XX_SAA7114) request_module("saa7115"); - if (dev->decoder == EM28XX_TVP5150) + if (dev->board.decoder == EM28XX_TVP5150) request_module("tvp5150"); - if (dev->tuner_type != TUNER_ABSENT) + if (dev->board.tuner_type != TUNER_ABSENT) request_module("tuner"); #endif diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 64503c04a..339913c0d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -349,7 +349,7 @@ static int em28xx_set_audio_source(struct em28xx *dev) int ret; u8 input; - if (dev->is_em2800) { + if (dev->board.is_em2800) { if (dev->ctl_ainput == EM28XX_AMUX_VIDEO) input = EM2800_AUDIO_SRC_TUNER; else @@ -360,7 +360,7 @@ static int em28xx_set_audio_source(struct em28xx *dev) return ret; } - if (dev->has_msp34xx) + if (dev->board.has_msp34xx) input = EM28XX_AUDIO_SRC_TUNER; else { switch (dev->ctl_ainput) { @@ -417,7 +417,7 @@ int em28xx_audio_analog_set(struct em28xx *dev) } } - xclk = dev->xclk & 0x7f; + xclk = dev->board.xclk & 0x7f; if (!dev->mute) xclk |= 0x80; @@ -658,7 +658,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) { u8 mode; /* the em2800 scaler only supports scaling down to 50% */ - if (dev->is_em2800) + if (dev->board.is_em2800) mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); else { u8 buf[2]; diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 714d35c51..6e6509c7a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -394,7 +394,7 @@ static int dvb_init(struct em28xx *dev) int result = 0; struct em28xx_dvb *dvb; - if (!dev->has_dvb) { + if (!dev->board.has_dvb) { /* This device does not support the extension */ return 0; } @@ -480,7 +480,7 @@ out_free: static int dvb_fini(struct em28xx *dev) { - if (!dev->has_dvb) { + if (!dev->board.has_dvb) { /* This device does not support the extension */ return 0; } diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 4e6fa575d..adc5ab20f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -250,7 +250,7 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); if (!msgs[i].len) { /* no len: check only for device presence */ - if (dev->is_em2800) + if (dev->board.is_em2800) rc = em2800_i2c_check_for_device(dev, addr); else rc = em28xx_i2c_check_for_device(dev, addr); @@ -261,7 +261,7 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, } else if (msgs[i].flags & I2C_M_RD) { /* read bytes */ - if (dev->is_em2800) + if (dev->board.is_em2800) rc = em2800_i2c_recv_bytes(dev, addr, msgs[i].buf, msgs[i].len); @@ -279,7 +279,7 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } - if (dev->is_em2800) + if (dev->board.is_em2800) rc = em2800_i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len); diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index 29900920d..d6ef5c461 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -345,7 +345,7 @@ int em28xx_ir_init(struct em28xx *dev) u8 ir_config; int err = -ENOMEM; - if (dev->ir_codes == NULL) { + if (dev->board.ir_codes == NULL) { /* No remote control support */ return 0; } @@ -384,7 +384,7 @@ int em28xx_ir_init(struct em28xx *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->ir_codes); + ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->board.ir_codes); input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_USB; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 634b82f4b..a54e904f1 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -521,7 +521,7 @@ static int em28xx_config(struct em28xx *dev) int retval; /* Sets I2C speed to 100 KHz */ - if (!dev->is_em2800) { + if (!dev->board.is_em2800) { retval = em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); if (retval < 0) { em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n", @@ -578,7 +578,7 @@ static void video_mux(struct em28xx *dev, int index) em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); - if (dev->has_msp34xx) { + if (dev->board.has_msp34xx) { if (dev->i2s_speed) { em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); @@ -752,7 +752,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&dev->lock); - if (dev->is_em2800) { + if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ if (height % (maxh / 2)) height = maxh; @@ -1009,7 +1009,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, qc->id = id; - if (!dev->has_msp34xx) { + if (!dev->board.has_msp34xx) { for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { if (qc->id && qc->id == em28xx_qctrl[i].id) { memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc)); @@ -1039,7 +1039,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - if (!dev->has_msp34xx) + if (!dev->board.has_msp34xx) rc = em28xx_get_ctrl(dev, ctrl); else rc = -EINVAL; @@ -1067,7 +1067,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, mutex_lock(&dev->lock); - if (dev->has_msp34xx) + if (dev->board.has_msp34xx) em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl); else { rc = 1; @@ -2103,7 +2103,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; dev->em28xx_write_regs_req = em28xx_write_regs_req; dev->em28xx_read_reg_req = em28xx_read_reg_req; - dev->is_em2800 = em28xx_boards[dev->model].is_em2800; + dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; em28xx_pre_card_setup(dev); @@ -2163,7 +2163,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, video_set_drvdata(dev->vbi_dev, dev); #endif - if (dev->has_msp34xx) { + if (dev->board.has_msp34xx) { /* Send a reset to other chips via gpio */ errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); if (errCode < 0) { @@ -2227,7 +2227,7 @@ static void request_module_async(struct work_struct *work) else if (dev->has_alsa_audio) request_module("em28xx-alsa"); - if (dev->has_dvb) + if (dev->board.has_dvb) request_module("em28xx-dvb"); } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index f9270f681..c75216145 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -329,6 +329,7 @@ struct em28xx_reg_seq { struct em28xx_board { char *name; + int vchannels; int tuner_type; int tuner_addr; @@ -425,18 +426,12 @@ struct em28xx { int model; /* index in the device_data struct */ int devno; /* marks the number of this device */ enum em28xx_chip_id chip_id; - unsigned int is_em2800:1; - unsigned int has_msp34xx:1; - unsigned int has_tda9887:1; + + struct em28xx_board board; + unsigned int stream_on:1; /* Locks streams */ unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; - unsigned int max_range_640_480:1; - unsigned int has_dvb:1; - unsigned int has_snapshot_button:1; - unsigned int valid:1; /* report for validated boards */ - - unsigned char xclk, i2c_speed; struct em28xx_IR *ir; @@ -453,7 +448,6 @@ struct em28xx { u32 i2s_speed; /* I2S speed for audio digital stream */ - enum em28xx_decoder decoder; struct em28xx_audio_mode audio_mode; int tuner_type; /* type of the tuner */ @@ -536,9 +530,6 @@ struct em28xx { /* Caches GPO and GPIO registers */ unsigned char reg_gpo, reg_gpio; - /* Infrared remote control support */ - IR_KEYTAB_TYPE *ir_codes; - /* Snapshot button */ char snapshot_button_path[30]; /* path of the input dev */ struct input_dev *sbutton_input_dev; @@ -712,7 +703,7 @@ static inline int em28xx_gamma_set(struct em28xx *dev, s32 val) /*FIXME: maxw should be dependent of alt mode */ static inline unsigned int norm_maxw(struct em28xx *dev) { - if (dev->max_range_640_480) + if (dev->board.max_range_640_480) return 640; else return 720; @@ -720,7 +711,7 @@ static inline unsigned int norm_maxw(struct em28xx *dev) static inline unsigned int norm_maxh(struct em28xx *dev) { - if (dev->max_range_640_480) + if (dev->board.max_range_640_480) return 480; else return (dev->norm & V4L2_STD_625_50) ? 576 : 480; -- cgit v1.2.3 From efb46542b7fee04e74f27680711a75dfda1861e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 10:43:29 -0200 Subject: em28xx: cleanup: saa7115 module auto-detects saa711x type From: Mauro Carvalho Chehab Since saa7115 has saa711x chip auto-detection, there's no need on differenciating it at cards table. Just use the generic name for all boards that use a philips saa711x decoder. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 50 ++++++++++++------------- linux/drivers/media/video/em28xx/em28xx.h | 3 +- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 9363aa721..43a768b5f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -66,7 +66,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Unknown EM2800 video grabber", .is_em2800 = 1, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -96,7 +96,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Kworld PVR TV 2800 RF", .tuner_type = TUNER_TEMIC_PAL, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -111,7 +111,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Cinergy 250 USB", .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -130,7 +130,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Pinnacle PCTV USB 2", .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -169,7 +169,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -189,7 +189,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -209,7 +209,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -229,7 +229,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_TNF_5335MF, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE1, @@ -249,7 +249,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7114, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = 2, @@ -267,7 +267,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_PINNACLE_DVC_100] = { .name = "Pinnacle Dazzle DVC 100", .valid = EM28XX_BOARD_NOT_VALIDATED, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -292,7 +292,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_LG_PAL_NEW_TAPC, /* unknown? */ .tda9887_conf = TDA9887_PRESENT, /* unknown? */ - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -314,7 +314,7 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -332,7 +332,7 @@ struct em28xx_board em28xx_boards[] = { [EM2821_BOARD_USBGEAR_VD204] = { .name = "Usbgear VD204v9", .valid = EM28XX_BOARD_NOT_VALIDATED, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -356,7 +356,7 @@ struct em28xx_board em28xx_boards[] = { [EM2860_BOARD_TYPHOON_DVD_MAKER] = { .name = "Typhoon DVD Maker", .valid = EM28XX_BOARD_NOT_VALIDATED, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -372,7 +372,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_TNF_5335MF, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -666,7 +666,7 @@ struct em28xx_board em28xx_boards[] = { TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, .max_range_640_480 = 1, - .decoder = EM28XX_SAA7114, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE4, @@ -686,7 +686,7 @@ struct em28xx_board em28xx_boards[] = { .is_em2800 = 1, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -704,7 +704,7 @@ struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_GRABBEEX_USB2800] = { .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", .is_em2800 = 1, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -720,7 +720,7 @@ struct em28xx_board em28xx_boards[] = { .is_em2800 = 1, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -740,7 +740,7 @@ struct em28xx_board em28xx_boards[] = { .is_em2800 = 1, .tuner_type = TUNER_PHILIPS_FCV1236D, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -758,7 +758,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_PINNACLE_DVC_90] = { .name = "Pinnacle Dazzle DVC 90/DVC 100", .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -774,7 +774,7 @@ struct em28xx_board em28xx_boards[] = { .is_em2800 = 1, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -793,7 +793,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Pixelview Prolink PlayTV USB 2.0", .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, @@ -815,7 +815,7 @@ struct em28xx_board em28xx_boards[] = { .has_snapshot_button = 1, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA7113, + .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, @@ -1742,7 +1742,7 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->board.has_msp34xx) request_module("msp3400"); - if (dev->board.decoder == EM28XX_SAA7113 || dev->board.decoder == EM28XX_SAA7114) + if (dev->board.decoder == EM28XX_SAA711X) request_module("saa7115"); if (dev->board.decoder == EM28XX_TVP5150) request_module("tvp5150"); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index c75216145..895a5a68f 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -317,8 +317,7 @@ struct em28xx_input { enum em28xx_decoder { EM28XX_NODECODER, EM28XX_TVP5150, - EM28XX_SAA7113, - EM28XX_SAA7114 + EM28XX_SAA711X, }; struct em28xx_reg_seq { -- cgit v1.2.3 From 83f9b196743f52d7b3e0566287bf173fac764bd5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 11:06:21 -0200 Subject: em28xx: improve debug messages From: Mauro Carvalho Chehab Now, the first message states board names. Also, removed printing the alternate settings by default. I2C messages are now clearer. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 11 +++++---- linux/drivers/media/video/em28xx/em28xx-i2c.c | 32 +++++++++++++------------ linux/drivers/media/video/em28xx/em28xx-video.c | 6 ++--- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 43a768b5f..137ed3399 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1279,6 +1279,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) { int rc; + em28xx_set_model(dev); + + em28xx_info("Found %s\n", dev->board.name); + /* Set the default GPO/GPIO for legacy devices */ dev->reg_gpo_num = EM2880_R04_GPO; dev->reg_gpio_num = EM28XX_R08_GPIO; @@ -1289,7 +1293,8 @@ void em28xx_pre_card_setup(struct em28xx *dev) rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); if (rc > 0) { dev->chip_id = rc; - switch (rc) { + + switch (dev->chip_id) { case CHIP_ID_EM2750: em28xx_info("chip ID is em2750\n"); break; @@ -1312,7 +1317,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) dev->wait_after_write = 0; break; default: - em28xx_info("em28xx chip ID = %d\n", rc); + em28xx_info("em28xx chip ID = %d\n", dev->chip_id); } } @@ -1321,8 +1326,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) if (rc >= 0) dev->reg_gpo = rc; - em28xx_set_model(dev); - /* Those are the default values for the majority of boards Use those values if not specified otherwise at boards entry */ diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index adc5ab20f..7084728eb 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -388,47 +388,49 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) if (em_eeprom->id == 0x9567eb1a) dev->hash = em28xx_hash_mem(eedata, len, 32); - printk(KERN_INFO "EEPROM ID= 0x%08x, hash = 0x%08lx\n", - em_eeprom->id, dev->hash); - printk(KERN_INFO "Vendor/Product ID= %04x:%04x\n", em_eeprom->vendor_ID, - em_eeprom->product_ID); + printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n", + dev->name, em_eeprom->id, dev->hash); + + printk(KERN_INFO "%s: EEPROM info:\n", dev->name); switch (em_eeprom->chip_conf >> 4 & 0x3) { case 0: - printk(KERN_INFO "No audio on board.\n"); + printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name); break; case 1: - printk(KERN_INFO "AC97 audio (5 sample rates)\n"); + printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n", + dev->name); break; case 2: - printk(KERN_INFO "I2S audio, sample rate=32k\n"); + printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", dev->name); break; case 3: - printk(KERN_INFO "I2S audio, 3 sample rates\n"); + printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", dev->name); break; } if (em_eeprom->chip_conf & 1 << 3) - printk(KERN_INFO "USB Remote wakeup capable\n"); + printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name); if (em_eeprom->chip_conf & 1 << 2) - printk(KERN_INFO "USB Self power capable\n"); + printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name); switch (em_eeprom->chip_conf & 0x3) { case 0: - printk(KERN_INFO "500mA max power\n"); + printk(KERN_INFO "%s:\t500mA max power\n", dev->name); break; case 1: - printk(KERN_INFO "400mA max power\n"); + printk(KERN_INFO "%s:\t400mA max power\n", dev->name); break; case 2: - printk(KERN_INFO "300mA max power\n"); + printk(KERN_INFO "%s:\t300mA max power\n", dev->name); break; case 3: - printk(KERN_INFO "200mA max power\n"); + printk(KERN_INFO "%s:\t200mA max power\n", dev->name); break; } - printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", + printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", + dev->name, em_eeprom->string_idx_table, em_eeprom->string1, em_eeprom->string2, diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index a54e904f1..12f7fa0a3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2354,7 +2354,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, uif = udev->actconfig->interface[0]; dev->num_alt = uif->num_altsetting; - em28xx_info("Alternate settings: %i\n", dev->num_alt); + em28xx_videodbg("Alternate settings: %i\n", dev->num_alt); /* dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */ dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); @@ -2370,7 +2370,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, wMaxPacketSize); dev->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - em28xx_info("Alternate setting %i, max size= %i\n", i, + em28xx_videodbg("Alternate setting %i, max size= %i\n", i, dev->alt_max_pkt_size[i]); } @@ -2386,8 +2386,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, return retval; } - em28xx_info("Found %s\n", em28xx_boards[dev->model].name); - /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); -- cgit v1.2.3 From 1f3f7671e12715041b3b002db1403ce4da682fda Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 14:10:14 -0200 Subject: em28xx: cleanup: We need just one tuner callback From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 29 ++++++------------------- linux/drivers/media/video/em28xx/em28xx.h | 2 +- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 137ed3399..f400f80f0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1211,15 +1211,6 @@ static struct em28xx_reg_seq default_callback[] = { { -1, -1, -1, -1}, }; -/* Callback for EM2882 TERRATEC HYBRID XS */ -static struct em28xx_reg_seq em2882_terratec_hybrid_xs_digital[] = { - {EM28XX_R08_GPIO, 0x2e, 0xff, 6}, - {EM28XX_R08_GPIO, 0x3e, ~EM_GPIO_4, 6}, - {EM2880_R04_GPO, 0x04, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 10}, - { -1, -1, -1, -1}, -}; - /* Pinnacle PCTV HD Mini (80e) GPIOs 0-5: not used 6: demod reset, active low @@ -1258,10 +1249,7 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg) if (command != XC2028_TUNER_RESET) return 0; - if (dev->mode == EM28XX_ANALOG_MODE) - rc = em28xx_gpio_set(dev, dev->tun_analog_gpio); - else - rc = em28xx_gpio_set(dev, dev->tun_digital_gpio); + rc = em28xx_gpio_set(dev, dev->tuner_gpio); return rc; } @@ -1355,16 +1343,12 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* Sets GPO/GPIO sequences for this device */ dev->analog_gpio = hauppauge_wintv_hvr_900_analog; dev->digital_gpio = hauppauge_wintv_hvr_900_digital; - dev->tun_analog_gpio = default_callback; - dev->tun_digital_gpio = default_callback; break; case EM2882_BOARD_TERRATEC_HYBRID_XS: /* Sets GPO/GPIO sequences for this device */ dev->analog_gpio = hauppauge_wintv_hvr_900_analog; dev->digital_gpio = hauppauge_wintv_hvr_900_digital; - dev->tun_analog_gpio = default_callback; - dev->tun_digital_gpio = em2882_terratec_hybrid_xs_digital; break; case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: @@ -1381,8 +1365,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* Sets GPO/GPIO sequences for this device */ dev->analog_gpio = default_analog; dev->digital_gpio = default_digital; - dev->tun_analog_gpio = default_callback; - dev->tun_digital_gpio = default_callback; break; case EM2880_BOARD_MSI_DIGIVOX_AD: @@ -1390,8 +1372,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* Sets GPO/GPIO sequences for this device */ dev->analog_gpio = em2880_msi_digivox_ad_analog; dev->digital_gpio = em2880_msi_digivox_ad_digital; - dev->tun_analog_gpio = default_callback; - dev->tun_digital_gpio = default_callback; break; case EM2861_BOARD_PLEXTOR_PX_TV100U: @@ -1463,7 +1443,11 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; } - em28xx_gpio_set(dev, dev->tun_analog_gpio); + /* Sets the default callback. Used only for certain tuners */ + if (!dev->tuner_gpio) + dev->tuner_gpio = default_callback; + + em28xx_gpio_set(dev, dev->tuner_gpio); em28xx_set_mode(dev, EM28XX_ANALOG_MODE); /* Unlock device */ @@ -1757,3 +1741,4 @@ void em28xx_card_setup(struct em28xx *dev) em28xx_ir_init(dev); } + diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 895a5a68f..bea105250 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -441,7 +441,7 @@ struct em28xx { struct em28xx_reg_seq *analog_gpio, *digital_gpio; /* GPIO sequences for tuner callbacks */ - struct em28xx_reg_seq *tun_analog_gpio, *tun_digital_gpio; + struct em28xx_reg_seq *tuner_gpio; struct list_head devlist; -- cgit v1.2.3 From c851fa22bef3a441b457845c01a4d83a748dcd8d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Nov 2008 10:58:48 -0200 Subject: em28xx: Improve register log format Change log format to look more like URB transactions. In fact, setup and IN/OUT transactions are merged. This helps to debug the driver. From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-core.c | 60 ++++++++++++++------------ 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 339913c0d..f70cffb4a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -66,7 +66,8 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, char *buf, int len) { - int ret, byte; + int ret; + int pipe = usb_rcvctrlpipe(dev->udev, 0); if (dev->state & DEV_DISCONNECTED) return -ENODEV; @@ -74,10 +75,18 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, if (len > URB_MAX_CTRL_SIZE) return -EINVAL; - em28xx_regdbg("req=%02x, reg=%02x ", req, reg); + if (reg_debug) { + printk( KERN_DEBUG "(pipe 0x%08x): " + "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", + pipe, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + req, 0, 0, + reg & 0xff, reg >> 8, + len & 0xff, len >> 8); + } mutex_lock(&dev->ctrl_urb_lock); - ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, + ret = usb_control_msg(dev->udev, pipe, req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, dev->urb_buf, len, HZ); if (ret < 0) { @@ -93,7 +102,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, mutex_unlock(&dev->ctrl_urb_lock); if (reg_debug) { - printk("%02x values: ", ret); + int byte; + + printk("<<<"); for (byte = 0; byte < len; byte++) printk(" %02x", (unsigned char)buf[byte]); printk("\n"); @@ -108,28 +119,12 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, */ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) { - u8 val; int ret; + u8 val; - if (dev->state & DEV_DISCONNECTED) - return(-ENODEV); - - em28xx_regdbg("req=%02x, reg=%02x:", req, reg); - - mutex_lock(&dev->ctrl_urb_lock); - ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, dev->urb_buf, 1, HZ); - val = dev->urb_buf[0]; - mutex_unlock(&dev->ctrl_urb_lock); - - if (ret < 0) { - printk(" failed!\n"); + ret = em28xx_read_reg_req_len(dev, req, reg, &val, 1); + if (ret < 0) return ret; - } - - if (reg_debug) - printk("%02x\n", (unsigned char) val); return val; } @@ -147,6 +142,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int len) { int ret; + int pipe = usb_sndctrlpipe(dev->udev, 0); if (dev->state & DEV_DISCONNECTED) return -ENODEV; @@ -154,17 +150,25 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) return -EINVAL; - em28xx_regdbg("req=%02x reg=%02x:", req, reg); if (reg_debug) { - int i; - for (i = 0; i < len; ++i) - printk(" %02x", (unsigned char)buf[i]); + int byte; + + printk( KERN_DEBUG "(pipe 0x%08x): " + "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", + pipe, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + req, 0, 0, + reg & 0xff, reg >> 8, + len & 0xff, len >> 8); + + for (byte = 0; byte < len; byte++) + printk(" %02x", (unsigned char)buf[byte]); printk("\n"); } mutex_lock(&dev->ctrl_urb_lock); memcpy(dev->urb_buf, buf, len); - ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, + ret = usb_control_msg(dev->udev, pipe, req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, dev->urb_buf, len, HZ); mutex_unlock(&dev->ctrl_urb_lock); -- cgit v1.2.3 From 0be93bb183e34c9271b6cc20c1da18fa8beaa07c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Nov 2008 12:30:47 -0200 Subject: Add a parser for em28xx register debug log From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/parse_em28xx.pl | 278 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100755 v4l2-apps/util/parse_em28xx.pl diff --git a/v4l2-apps/util/parse_em28xx.pl b/v4l2-apps/util/parse_em28xx.pl new file mode 100755 index 000000000..d1bbb0f0d --- /dev/null +++ b/v4l2-apps/util/parse_em28xx.pl @@ -0,0 +1,278 @@ +#!/usr/bin/perl + +# Copyright (C) 2008 Mauro Carvalho Chehab +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# This small script parses register dumps generated by em28xx driver +# with debug options enabled, generating a source code with the results +# of the dump. +# +# To use it, you may modprobe em28xx with reg_debug=1, and do: +# dmesg | ./parse_em28xx.pl +# +# Also, there are other utilities that produce similar outputs, and it +# is not hard to parse some USB analyzers log into the expected format. +# +# It will parse anything (including this file) with a format similar to: +# +# 40 00 00 00 48 00 01 00 >>> 00 +# 40 00 00 00 12 00 01 00 >>> 37 +# 40 00 00 00 08 00 01 00 >>> 3d +# 40 00 00 00 08 00 01 00 >>> 2d +# 40 00 00 00 08 00 01 00 >>> 3d +# 40 00 00 00 48 00 01 00 >>> 00 +# 40 00 00 00 12 00 01 00 >>> 37 +# 40 00 00 00 08 00 01 00 >>> 3d +# 40 00 00 00 08 00 01 00 >>> 2d +# 40 00 00 00 08 00 01 00 >>> 3d +# c0 00 00 00 43 00 01 00 <<< 00 +# 40 00 00 00 42 00 01 00 >>> fc +# c0 00 00 00 40 00 02 00 <<< ff ff +# c0 00 00 00 43 00 01 00 <<< 00 +# 40 00 00 00 42 00 01 00 >>> fe +# c0 00 00 00 40 00 02 00 <<< ff ff +# c0 00 00 00 43 00 01 00 <<< 00 +# 40 00 00 00 42 00 01 00 >>> 80 +# c0 00 00 00 40 00 02 00 <<< 90 6a +# +# Producing a much easier to understand series of C function calls: +# +# em28xx_write_reg(dev, 0x48, 0x00); +# em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); +# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x3d); +# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x2d); +# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x3d); +# em28xx_write_reg(dev, 0x48, 0x00); +# em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); +# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x3d); +# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x2d); +# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x3d); +# em28xx_read_ac97(dev, AC97_VENDOR_ID1); /* read 0x0xffff */ +# em28xx_read_ac97(dev, AC97_VENDOR_ID2); /* read 0x0xffff */ +# em28xx_read_ac97(dev, AC97_RESET); /* read 0x0x6a90 */ +# +# This way, it is easier to understand what the em28xx driver is doing. +# +# Known limitations: +# - Currently, the tool only parses em28xx, ac97 and em202 registers. +# - It is limited to read/write operations with 1 or 2 bytes of +# arguments; +# - Not all registers are documented; +# - It doesn't parse em2800-only registers; +# - em28xx currently doesn't implement em28xx_read_reg16() or +# em28xx_write_reg16(). However, this tool uses those two "functions" +# meaning to read or write 2 consecutive bytes, ordering arguments +# in big-endian notation. +# + +use strict; + +my %reg_map = ( + "0x00" => "EM28XX_R00_CHIPCFG", + "0x04" => "EM2880_R04_GPO", + "0x08" => "EM28XX_R08_GPIO", + "0x06" => "EM28XX_R06_I2C_CLK", + "0x0a" => "EM28XX_R0A_CHIPID", + "0x0c" => "EM28XX_R0C_USBSUSP", + "0x0e" => "EM28XX_R0E_AUDIOSRC", + "0x0f" => "EM28XX_R0F_XCLK", + "0x20" => "EM28XX_XCLK_IR_RC5_MODE", + "0x10" => "EM28XX_R10_VINMODE", + "0x11" => "EM28XX_R11_VINCTRL", + "0x12" => "EM28XX_R12_VINENABLE", + "0x14" => "EM28XX_R14_GAMMA", + "0x15" => "EM28XX_R15_RGAIN", + "0x16" => "EM28XX_R16_GGAIN", + "0x17" => "EM28XX_R17_BGAIN", + "0x18" => "EM28XX_R18_ROFFSET", + "0x19" => "EM28XX_R19_GOFFSET", + "0x1a" => "EM28XX_R1A_BOFFSET", + "0x1b" => "EM28XX_R1B_OFLOW", + "0x1c" => "EM28XX_R1C_HSTART", + "0x1d" => "EM28XX_R1D_VSTART", + "0x1e" => "EM28XX_R1E_CWIDTH", + "0x1f" => "EM28XX_R1F_CHEIGHT", + "0x20" => "EM28XX_R20_YGAIN", + "0x21" => "EM28XX_R21_YOFFSET", + "0x22" => "EM28XX_R22_UVGAIN", + "0x23" => "EM28XX_R23_UOFFSET", + "0x24" => "EM28XX_R24_VOFFSET", + "0x25" => "EM28XX_R25_SHARPNESS", + "0x26" => "EM28XX_R26_COMPR", + "0x27" => "EM28XX_R27_OUTFMT", + "0x28" => "EM28XX_R28_XMIN", + "0x29" => "EM28XX_R29_XMAX", + "0x2a" => "EM28XX_R2A_YMIN", + "0x2b" => "EM28XX_R2B_YMAX", + "0x30" => "EM28XX_R30_HSCALELOW", + "0x31" => "EM28XX_R31_HSCALEHIGH", + "0x32" => "EM28XX_R32_VSCALELOW", + "0x33" => "EM28XX_R33_VSCALEHIGH", + "0x40" => "EM28XX_R40_AC97LSB", + "0x41" => "EM28XX_R41_AC97MSB", + "0x42" => "EM28XX_R42_AC97ADDR", + "0x43" => "EM28XX_R43_AC97BUSY", + "0x45" => "EM28XX_R45_IR", + "0x50" => "EM2874_R50_IR_CONFIG", + "0x51" => "EM2874_R51_IR", + "0x5f" => "EM2874_R5F_TS_ENABLE", + "0x80" => "EM2874_R80_GPIO", +); + +my %ac97_map = ( + "0x00" => "AC97_RESET", + "0x02" => "AC97_MASTER_VOL", + "0x04" => "AC97_LINE_LEVEL_VOL", + "0x06" => "AC97_MASTER_MONO_VOL", + "0x0a" => "AC97_PC_BEEP_VOL", + "0x0c" => "AC97_PHONE_VOL", + "0x0e" => "AC97_MIC_VOL", + "0x10" => "AC97_LINEIN_VOL", + "0x12" => "AC97_CD_VOL", + "0x14" => "AC97_VIDEO_VOL", + "0x16" => "AC97_AUX_VOL", + "0x18" => "AC97_PCM_OUT_VOL", + "0x1a" => "AC97_RECORD_SELECT", + "0x1c" => "AC97_RECORD_GAIN", + "0x20" => "AC97_GENERAL_PURPOSE", + "0x22" => "AC97_3D_CTRL", + "0x24" => "AC97_AUD_INT_AND_PAG", + "0x26" => "AC97_POWER_DOWN_CTRL", + "0x28" => "AC97_EXT_AUD_ID", + "0x2a" => "AC97_EXT_AUD_CTRL", + "0x2c" => "AC97_PCM_OUT_FRONT_SRATE", + "0x2e" => "AC97_PCM_OUT_SURR_SRATE", + "0x30" => "AC97_PCM_OUT_LFE_SRATE", + "0x32" => "AC97_PCM_IN_SRATE", + "0x36" => "AC97_LFE_MASTER_VOL", + "0x38" => "AC97_SURR_MASTER_VOL", + "0x3a" => "AC97_SPDIF_OUT_CTRL", + "0x7c" => "AC97_VENDOR_ID1", + "0x7e" => "AC97_VENDOR_ID2", + + # em202 specific AC97 registers + + "0x3e" => "EM202_EXT_MODEM_CTRL", + "0x4c" => "EM202_GPIO_CONF", + "0x4e" => "EM202_GPIO_POLARITY", + "0x50" => "EM202_GPIO_STICKY", + "0x52" => "EM202_GPIO_MASK", + "0x54" => "EM202_GPIO_STATUS", + "0x6a" => "EM202_SPDIF_OUT_SEL", + "0x72" => "EM202_ANTIPOP", + "0x74" => "EM202_EAPD_GPIO_ACCESS", +); + +my ($r40, $r42, $r43, $dir); + +sub output_ac97() +{ + if (hex($r42) < 0x80) { + if ($dir < 0) { + return; + } + $r42 = $ac97_map{$r42} if defined($ac97_map{$r42}); + printf "em28xx_write_ac97(dev, %s, %s);\n",$r42, $r40; + $r43 = 0; + + return; + } + + if ($dir > 0) { + return; + } + $r42 = sprintf("0x%02x", hex($r42) - 0x80); + $r42 = $ac97_map{$r42} if defined($ac97_map{$r42}); + printf "em28xx_read_ac97(dev, %s);\t/* read 0x%s */\n",$r42, $r40; + $r43 = 0; +} + +while (<>) { + tr/A-F/a-f/; + if (m/c0 00 00 00 ([0-9a-f].) 00 01 00\s+[\<]+\s+([0-9a-f].)/) { + if ($1 eq "43" && $2 eq "00") { + $r43 = 1; + $r40 = -1; + $r42 = -1; + $dir = 0; + next; + } + + my $reg = "0x$1"; + $reg = $reg_map{$reg} if defined($reg_map{$reg}); + + printf "em28xx_read_reg(dev, %s);\t\t/* read 0x%s */\n", + $reg, $2; + next; + } + if (m/40 00 00 00 ([0-9a-f].) 00 01 00\s+[\>]+\s+([0-9a-f].)/) { + if ($r43 == 1) { + if ($1 eq "42") { + $r42 = "0x$2"; + if ($r40 >= 0) { + output_ac97(); + next; + } + next; + } + $r43 = 0; + } + + my $reg = "0x$1"; + $reg = $reg_map{$reg} if defined($reg_map{$reg}); + + printf "em28xx_write_reg(dev, %s, 0x%s);\n", + $reg, $2; + next; + } + if (m/c0 00 00 00 ([0-9a-f].) 00 02 00\s+[\<]+\s+([0-9a-f].) ([0-9a-f].)/) { + if ($r43 == 1) { + if ($1 eq "40") { + $r40 = "0x$3$2"; + $dir = -1; + + if ($r42 >= 0) { + output_ac97(); + next; + } + next; + } + $r43 = 0; + } + my $reg = "0x$1"; + $reg = $reg_map{$reg} if defined($reg_map{$reg}); + + printf "em28xx_read_reg16(dev, %s);\t\t/*read 0x%s%s */\n", + $reg, $3, $2; + next; + } + if (m/40 00 00 00 ([0-9a-f].) 00 02 00\s+[\>]+\s+([0-9a-f].) ([0-9a-f].)/) { + if ($r43 == 1) { + if ($1 eq "40") { + $r40 = "0x$3$2"; + $dir = 1; + + if ($r42 >= 0) { + output_ac97(); + next; + } + next; + } + $r43 = 0; + } + my $reg = "0x$1"; + $reg = $reg_map{$reg} if defined($reg_map{$reg}); + + printf "em28xx_write_reg16(dev, %s,0x%s%s);\n", + $reg, $3, $2; + next; + } +} -- cgit v1.2.3 From a6965c34bf836e6d9c5d3888bd7e01105ef32306 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Nov 2008 17:28:42 -0200 Subject: em28xx: replace some magic by register descriptions where known From: Mauro Carvalho Chehab Replaces all occurrences of em28xx_write_regs_req() and em28xx_write_reg() used to setup register names by em28xx_write_reg(). Also, documents the register names that are known. This patch were generated by this small perl script: my %reg_map = ( # Register table - the same as defined on parse_em28xx.pl script ); while (<>) { if (m/(.*)em28xx_write_regs_req\(dev\,\s*0x00\,\s*(.*)\,\s*\"\\x(..)\",\s*1\)\;(.*)/) { my $reg = $2; my $val = $3; $val =~ tr/A-f/a-f/; $reg = $reg_map{$reg} if defined($reg_map{$reg}); printf "$1em28xx_write_reg(dev, %s, 0x%s);$4\n", $reg, $val; } elsif (m/(.*)em28xx_write_regs\(dev\,\s*(.*)\,\s*\"\\x(..)\",\s*1\)\;(.*)/) { my $reg = $2; my $val = $3; $val =~ tr/A-f/a-f/; $reg = $reg_map{$reg} if defined($reg_map{$reg}); printf "$1em28xx_write_reg(dev, %s, 0x%s);$4\n", $reg, $val; } else { print $_; } } Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-core.c | 48 ++++++++++++------------- linux/drivers/media/video/em28xx/em28xx-video.c | 12 +++---- linux/drivers/media/video/em28xx/em28xx.h | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index f70cffb4a..d63e5b997 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -558,20 +558,20 @@ EXPORT_SYMBOL_GPL(em28xx_audio_setup); int em28xx_colorlevels_set_default(struct em28xx *dev) { - em28xx_write_regs(dev, EM28XX_R20_YGAIN, "\x10", 1); /* contrast */ - em28xx_write_regs(dev, EM28XX_R21_YOFFSET, "\x00", 1); /* brightness */ - em28xx_write_regs(dev, EM28XX_R22_UVGAIN, "\x10", 1); /* saturation */ - em28xx_write_regs(dev, EM28XX_R23_UOFFSET, "\x00", 1); - em28xx_write_regs(dev, EM28XX_R24_VOFFSET, "\x00", 1); - em28xx_write_regs(dev, EM28XX_R25_SHARPNESS, "\x00", 1); - - em28xx_write_regs(dev, EM28XX_R14_GAMMA, "\x20", 1); - em28xx_write_regs(dev, EM28XX_R15_RGAIN, "\x20", 1); - em28xx_write_regs(dev, EM28XX_R16_GGAIN, "\x20", 1); - em28xx_write_regs(dev, EM28XX_R17_BGAIN, "\x20", 1); - em28xx_write_regs(dev, EM28XX_R18_ROFFSET, "\x00", 1); - em28xx_write_regs(dev, EM28XX_R19_GOFFSET, "\x00", 1); - return em28xx_write_regs(dev, EM28XX_R1A_BOFFSET, "\x00", 1); + em28xx_write_reg(dev, EM28XX_R20_YGAIN, 0x10); /* contrast */ + em28xx_write_reg(dev, EM28XX_R21_YOFFSET, 0x00); /* brightness */ + em28xx_write_reg(dev, EM28XX_R22_UVGAIN, 0x10); /* saturation */ + em28xx_write_reg(dev, EM28XX_R23_UOFFSET, 0x00); + em28xx_write_reg(dev, EM28XX_R24_VOFFSET, 0x00); + em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, 0x00); + + em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20); + em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20); + em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20); + em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20); + em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00); + em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00); + return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00); } int em28xx_capture_start(struct em28xx *dev, int start) @@ -604,17 +604,17 @@ int em28xx_capture_start(struct em28xx *dev, int start) if (!start) { /* disable video capture */ - rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x27", 1); + rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27); return rc; } /* enable video capture */ - rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + rc = em28xx_write_reg(dev, 0x48, 0x00); if (dev->mode == EM28XX_ANALOG_MODE) - rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x67", 1); + rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); else - rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x37", 1); + rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); msleep(6); @@ -623,9 +623,9 @@ int em28xx_capture_start(struct em28xx *dev, int start) int em28xx_outfmt_set_yuv422(struct em28xx *dev) { - em28xx_write_regs(dev, EM28XX_R27_OUTFMT, "\x34", 1); - em28xx_write_regs(dev, EM28XX_R10_VINMODE, "\x10", 1); - return em28xx_write_regs(dev, EM28XX_R11_VINCTRL, "\x11", 1); + em28xx_write_reg(dev, EM28XX_R27_OUTFMT, 0x34); + em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); } static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, @@ -741,11 +741,11 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio) if (!gpio) return rc; - dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); + em28xx_write_reg(dev, 0x48, 0x00); if (dev->mode == EM28XX_ANALOG_MODE) - dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); + em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); else - dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1); + em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); msleep(6); /* Send GPIO reset sequences specified at board entry */ diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 12f7fa0a3..bc3a59a57 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -522,7 +522,7 @@ static int em28xx_config(struct em28xx *dev) /* Sets I2C speed to 100 KHz */ if (!dev->board.is_em2800) { - retval = em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); + retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); if (retval < 0) { em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n", __func__, retval); @@ -533,9 +533,9 @@ static int em28xx_config(struct em28xx *dev) #if 1 /* enable vbi capturing */ -/* em28xx_write_regs_req(dev, 0x00, 0x0e, "\xC0", 1); audio register */ -/* em28xx_write_regs_req(dev, 0x00, 0x0f, "\x80", 1); clk register */ - em28xx_write_regs_req(dev, 0x00, 0x11, "\x51", 1); +/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ +/* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */ + em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); #endif dev->mute = 1; /* maybe not the right place... */ @@ -2165,7 +2165,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (dev->board.has_msp34xx) { /* Send a reset to other chips via gpio */ - errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); + errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); if (errCode < 0) { em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n", __func__, errCode); @@ -2173,7 +2173,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } msleep(3); - errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); + errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); if (errCode < 0) { em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n", __func__, errCode); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index bea105250..81acbd1a2 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -630,7 +630,7 @@ int em28xx_ir_fini(struct em28xx *dev); static inline int em28xx_compression_disable(struct em28xx *dev) { /* side effect of disabling scaler and mixer */ - return em28xx_write_regs(dev, EM28XX_R26_COMPR, "\x00", 1); + return em28xx_write_reg(dev, EM28XX_R26_COMPR, 0x00); } static inline int em28xx_contrast_get(struct em28xx *dev) -- cgit v1.2.3 From ee3056da58ea512f08850e2023e371a89f93fd5b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 25 Nov 2008 14:16:13 -0200 Subject: em28xx: move gpio tables to the top of em28xx-cards From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 141 ++++++++++++------------ 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index f400f80f0..aae578e21 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -52,6 +52,78 @@ struct em28xx_hash_table { unsigned int tuner; }; +/* + * Reset sequences for analog/digital modes + */ + +/* Reset for the most [analog] boards */ +static struct em28xx_reg_seq default_analog[] = { + {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + { -1, -1, -1, -1}, +}; + +/* Reset for the most [digital] boards */ +static struct em28xx_reg_seq default_digital[] = { + {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + { -1, -1, -1, -1}, +}; + +/* Board Hauppauge WinTV HVR 900 analog */ +static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { + {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, + {0x05, 0xff, 0x10, 10}, + { -1, -1, -1, -1}, +}; + +/* Board Hauppauge WinTV HVR 900 digital */ +static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { + {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, + {EM2880_R04_GPO, 0x04, 0x0f, 10}, + {EM2880_R04_GPO, 0x0c, 0x0f, 10}, + { -1, -1, -1, -1}, +}; + +/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ +static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { + {EM28XX_R08_GPIO, 0x69, ~EM_GPIO_4, 10}, + { -1, -1, -1, -1}, +}; + +/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ +static struct em28xx_reg_seq em2880_msi_digivox_ad_digital[] = { + {EM28XX_R08_GPIO, 0x6a, ~EM_GPIO_4, 10}, + { -1, -1, -1, -1}, +}; + +/* Board - EM2870 Kworld 355u + Analog - No input analog */ +static struct em28xx_reg_seq em2870_kworld_355u_digital[] = { + {EM2880_R04_GPO, 0x01, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +/* Callback for the most boards */ +static struct em28xx_reg_seq default_callback[] = { + {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, + {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, + {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, + { -1, -1, -1, -1}, +}; + +/* Pinnacle PCTV HD Mini (80e) GPIOs + 0-5: not used + 6: demod reset, active low + 7: LED on, active high */ +static struct em28xx_reg_seq em2874_pinnacle_80e_digital[] = { + {EM28XX_R06_I2C_CLK, 0x45, 0xff, 10}, /*400 KHz*/ + {EM2874_R80_GPIO, 0x80, 0xff, 100},/*Demod reset*/ + {EM2874_R80_GPIO, 0xc0, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +/* + * Board definitions + */ struct em28xx_board em28xx_boards[] = { [EM2750_BOARD_UNKNOWN] = { .name = "Unknown EM2750/EM2751 webcam grabber", @@ -1153,75 +1225,6 @@ struct usb_device_id em28xx_id_table [] = { }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); -/* - * Reset sequences for analog/digital modes - */ - -/* Reset for the most [analog] boards */ -static struct em28xx_reg_seq default_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Reset for the most [digital] boards */ -static struct em28xx_reg_seq default_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Board Hauppauge WinTV HVR 900 analog */ -static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { - {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, - {0x05, 0xff, 0x10, 10}, - { -1, -1, -1, -1}, -}; - -/* Board Hauppauge WinTV HVR 900 digital */ -static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x04, 0x0f, 10}, - {EM2880_R04_GPO, 0x0c, 0x0f, 10}, - { -1, -1, -1, -1}, -}; - -/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ -static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { - {EM28XX_R08_GPIO, 0x69, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ -static struct em28xx_reg_seq em2880_msi_digivox_ad_digital[] = { - {EM28XX_R08_GPIO, 0x6a, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Board - EM2870 Kworld 355u - Analog - No input analog */ -static struct em28xx_reg_seq em2870_kworld_355u_digital[] = { - {EM2880_R04_GPO, 0x01, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -/* Callback for the most boards */ -static struct em28xx_reg_seq default_callback[] = { - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Pinnacle PCTV HD Mini (80e) GPIOs - 0-5: not used - 6: demod reset, active low - 7: LED on, active high */ -static struct em28xx_reg_seq em2874_pinnacle_80e_digital[] = { - {EM28XX_R06_I2C_CLK, 0x45, 0xff, 10}, /*400 KHz*/ - {EM2874_R80_GPIO, 0x80, 0xff, 100},/*Demod reset*/ - {EM2874_R80_GPIO, 0xc0, 0xff, 10}, - { -1, -1, -1, -1}, -}; - /* * EEPROM hash table for devices with generic USB IDs */ -- cgit v1.2.3 From 93b293e2a697005bb0eca0f5a792f02f97d61e4f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Nov 2008 08:42:26 -0200 Subject: em28xx: move gpio lines into board table description From: Mauro Carvalho Chehab Instead of a large, ugly switch specifying the gpio tables for each device, let's move it into the boards struct. This also helps to see what boards have already the gpio's for DVB. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 175 ++++++++++++++++-------- linux/drivers/media/video/em28xx/em28xx.h | 15 +- 2 files changed, 127 insertions(+), 63 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index aae578e21..64f097446 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -90,17 +90,21 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { }; /* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ +#if 0 /* Still missing the dvb setup */ static struct em28xx_reg_seq em2880_msi_digivox_ad_digital[] = { {EM28XX_R08_GPIO, 0x6a, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; +#endif /* Board - EM2870 Kworld 355u Analog - No input analog */ +#if 0 /* Still missing the dvb setup */ static struct em28xx_reg_seq em2870_kworld_355u_digital[] = { {EM2880_R04_GPO, 0x01, 0xff, 10}, { -1, -1, -1, -1}, }; +#endif /* Callback for the most boards */ static struct em28xx_reg_seq default_callback[] = { @@ -464,18 +468,25 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2861_BOARD_KWORLD_PVRTV_300U] = { @@ -539,6 +550,10 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Cinergy T XS", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = default_digital, +#endif }, [EM2870_BOARD_TERRATEC_XS_MT2060] = { .name = "Terratec Cinergy T XS (MT2060)", @@ -549,10 +564,18 @@ struct em28xx_board em28xx_boards[] = { .name = "Kworld 350 U DVB-T", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = default_digital, +#endif }, [EM2870_BOARD_KWORLD_355U] = { .name = "Kworld 355 U DVB-T", .valid = EM28XX_BOARD_NOT_VALIDATED, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = em2870_kworld_355u_digital, +#endif }, [EM2870_BOARD_PINNACLE_PCTV_DVB] = { .name = "Pinnacle PCTV DVB-T", @@ -573,18 +596,25 @@ struct em28xx_board em28xx_boards[] = { .has_msp34xx = 1, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = default_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = default_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, } }, }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { @@ -593,19 +623,23 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = { @@ -614,18 +648,25 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .mts_firmware = 1, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = 3, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = { @@ -633,20 +674,24 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, .ir_codes = ir_codes_hauppauge_new, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = { @@ -654,20 +699,24 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, .ir_codes = ir_codes_pinnacle_pctv_hd, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = { @@ -675,20 +724,24 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .mts_firmware = 1, .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, .ir_codes = ir_codes_ati_tv_wonder_hd_600, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2880_BOARD_TERRATEC_HYBRID_XS] = { @@ -696,18 +749,22 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, .has_dvb = 1, + .dvb_gpio = default_analog, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = default_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, } }, }, /* maybe there's a reason behind it why Terratec sells the Hybrid XS @@ -717,18 +774,25 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Prodigy XS", .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2820_BOARD_MSI_VOX_USB_2] = { @@ -899,18 +963,25 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = em2880_msi_digivox_ad_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = em2880_msi_digivox_ad_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = em2880_msi_digivox_ad_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = em2880_msi_digivox_ad_analog, } }, }, [EM2880_BOARD_MSI_DIGIVOX_AD_II] = { @@ -918,18 +989,25 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = em2880_msi_digivox_ad_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = em2880_msi_digivox_ad_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = em2880_msi_digivox_ad_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = em2880_msi_digivox_ad_analog, } }, }, [EM2880_BOARD_KWORLD_DVB_305U] = { @@ -955,20 +1033,24 @@ struct em28xx_board em28xx_boards[] = { .name = "KWorld DVB-T 310U", .tuner_type = TUNER_XC2028, .has_dvb = 1, + .dvb_gpio = default_digital, .mts_firmware = 1, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = default_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, }, { /* S-video has not been tested yet */ .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, } }, }, [EM2881_BOARD_DNT_DA2_HYBRID] = { @@ -976,18 +1058,25 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = default_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = default_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, } }, }, [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { @@ -995,18 +1084,25 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = default_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = default_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, } }, }, [EM2882_BOARD_PINNACLE_HYBRID_PRO] = { @@ -1015,18 +1111,25 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .mts_firmware = 1, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2882_BOARD_KWORLD_VS_DVBT] = { @@ -1053,18 +1156,25 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2883_BOARD_KWORLD_HYBRID_A316] = { @@ -1072,18 +1182,25 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .decoder = EM28XX_TVP5150, +#if 0 /* FIXME: add an entry at em28xx-dvb */ + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +#endif .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = hauppauge_wintv_hvr_900_analog, } }, }, [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { @@ -1105,6 +1222,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Pinnacle PCTV HD Mini", .tuner_type = TUNER_ABSENT, .has_dvb = 1, + .dvb_gpio = em2874_pinnacle_80e_digital, .ir_codes = ir_codes_pinnacle_pctv_hd, .decoder = EM28XX_NODECODER, .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | @@ -1334,55 +1452,11 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* request some modules */ switch (dev->model) { - case EM2880_BOARD_TERRATEC_PRODIGY_XS: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: - case EM2860_BOARD_TERRATEC_HYBRID_XS: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: - case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: - case EM2882_BOARD_PINNACLE_HYBRID_PRO: - case EM2883_BOARD_KWORLD_HYBRID_A316: - case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: - /* Sets GPO/GPIO sequences for this device */ - dev->analog_gpio = hauppauge_wintv_hvr_900_analog; - dev->digital_gpio = hauppauge_wintv_hvr_900_digital; - break; - - case EM2882_BOARD_TERRATEC_HYBRID_XS: - /* Sets GPO/GPIO sequences for this device */ - dev->analog_gpio = hauppauge_wintv_hvr_900_analog; - dev->digital_gpio = hauppauge_wintv_hvr_900_digital; - break; - - case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: - case EM2880_BOARD_TERRATEC_HYBRID_XS: - case EM2870_BOARD_TERRATEC_XS: - case EM2881_BOARD_PINNACLE_HYBRID_PRO: - case EM2880_BOARD_KWORLD_DVB_310U: - case EM2870_BOARD_KWORLD_350U: - case EM2881_BOARD_DNT_DA2_HYBRID: - /* NOTE: EM2881_DNT_DA2_HYBRID spend 140 msleep for digital - and analog commands. If this commands doesn't work, - add this timer. */ - - /* Sets GPO/GPIO sequences for this device */ - dev->analog_gpio = default_analog; - dev->digital_gpio = default_digital; - break; - - case EM2880_BOARD_MSI_DIGIVOX_AD: - case EM2880_BOARD_MSI_DIGIVOX_AD_II: - /* Sets GPO/GPIO sequences for this device */ - dev->analog_gpio = em2880_msi_digivox_ad_analog; - dev->digital_gpio = em2880_msi_digivox_ad_digital; - break; - case EM2861_BOARD_PLEXTOR_PX_TV100U: /* FIXME guess */ /* Turn on analog audio output */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; - case EM2861_BOARD_KWORLD_PVRTV_300U: case EM2880_BOARD_KWORLD_DVB_305U: em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d); @@ -1390,12 +1464,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d); msleep(10); break; - - case EM2870_BOARD_KWORLD_355U: - /* Sets GPO/GPIO sequences for this device */ - dev->digital_gpio = em2870_kworld_355u_digital; - break; - case EM2870_BOARD_COMPRO_VIDEOMATE: /* TODO: someone can do some cleanup here... not everything's needed */ @@ -1412,7 +1480,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); mdelay(70); break; - case EM2870_BOARD_TERRATEC_XS_MT2060: /* this device needs some gpio writes to get the DVB-T demod work */ @@ -1423,7 +1490,6 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); mdelay(70); break; - case EM2870_BOARD_PINNACLE_PCTV_DVB: /* this device needs some gpio writes to get the DVB-T demod work */ @@ -1434,16 +1500,11 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); mdelay(70); break; - case EM2820_BOARD_GADMEI_UTV310: case EM2820_BOARD_MSI_VOX_USB_2: /* enables audio for that devices */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; - - case EM2874_BOARD_PINNACLE_PCTV_80E: - dev->digital_gpio = em2874_pinnacle_80e_digital; - break; } /* Sets the default callback. Used only for certain tuners */ diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 81acbd1a2..1171578a8 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -305,11 +305,18 @@ enum em28xx_aout { EM28XX_AOUT_SURR = 1 << 4, }; +struct em28xx_reg_seq { + int reg; + unsigned char val, mask; + int sleep; +}; + struct em28xx_input { enum enum28xx_itype type; unsigned int vmux; enum em28xx_amux amux; enum em28xx_aout aout; + struct em28xx_reg_seq *gpio; }; #define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) @@ -320,12 +327,6 @@ enum em28xx_decoder { EM28XX_SAA711X, }; -struct em28xx_reg_seq { - int reg; - unsigned char val, mask; - int sleep; -}; - struct em28xx_board { char *name; int vchannels; @@ -335,6 +336,8 @@ struct em28xx_board { /* i2c flags */ unsigned int tda9887_conf; + struct em28xx_reg_seq *dvb_gpio; + unsigned int is_em2800:1; unsigned int has_msp34xx:1; unsigned int mts_firmware:1; -- cgit v1.2.3 From 227c9555066cd0e4d06443c59239eb4f6f8ae25d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Nov 2008 08:44:00 -0200 Subject: em28xx: replace magic numbers for mux aliases From: Mauro Carvalho Chehab Instead of using magic vmux/amux, let's use an alias where possible. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 64f097446..33000a5fd 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -328,15 +328,15 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, - .vmux = 2, + .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, } }, }, @@ -660,7 +660,7 @@ struct em28xx_board em28xx_boards[] = { }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, - .amux = 3, + .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, }, { .type = EM28XX_VMUX_SVIDEO, -- cgit v1.2.3 From 698f109d2265f635cf7216c68a836d0a11a5ac8a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Nov 2008 08:46:59 -0200 Subject: em28xx: fix tuner absent entries From: Mauro Carvalho Chehab Before this patch, several devices without tuner were kept the value 0 for tuner_type. However, this means TUNER_TEMIC_PAL. Replace those entries for the proper TUNER_ABSENT value. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 33000a5fd..24d7e8892 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -132,6 +132,7 @@ struct em28xx_board em28xx_boards[] = { [EM2750_BOARD_UNKNOWN] = { .name = "Unknown EM2750/EM2751 webcam grabber", .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, + .tuner_type = TUNER_ABSENT, /* This is a webcam */ .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -143,6 +144,7 @@ struct em28xx_board em28xx_boards[] = { .is_em2800 = 1, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA711X, + .tuner_type = TUNER_ABSENT, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -162,6 +164,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Huaqi DLCW-130", .valid = EM28XX_BOARD_NOT_VALIDATED, .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, + .tuner_type = TUNER_ABSENT, /* This is a webcam */ .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -342,8 +345,8 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_PINNACLE_DVC_100] = { .name = "Pinnacle Dazzle DVC 100", - .valid = EM28XX_BOARD_NOT_VALIDATED, .decoder = EM28XX_SAA711X, + .tuner_type = TUNER_ABSENT, /* Capture only device */ .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -357,6 +360,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { .name = "Videology 20K14XUSB USB2.0", .valid = EM28XX_BOARD_NOT_VALIDATED, + .tuner_type = TUNER_ABSENT, /* This is a webcam */ .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -408,6 +412,7 @@ struct em28xx_board em28xx_boards[] = { [EM2821_BOARD_USBGEAR_VD204] = { .name = "Usbgear VD204v9", .valid = EM28XX_BOARD_NOT_VALIDATED, + .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, @@ -423,6 +428,7 @@ struct em28xx_board em28xx_boards[] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ .name = "NetGMBH Cam", .valid = EM28XX_BOARD_NOT_VALIDATED, + .tuner_type = TUNER_ABSENT, /* This is a webcam */ .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -431,8 +437,8 @@ struct em28xx_board em28xx_boards[] = { }, [EM2860_BOARD_TYPHOON_DVD_MAKER] = { .name = "Typhoon DVD Maker", - .valid = EM28XX_BOARD_NOT_VALIDATED, .decoder = EM28XX_SAA711X, + .tuner_type = TUNER_ABSENT, /* Capture only device */ .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -510,7 +516,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = { .name = "Yakumo MovieMixer", - .valid = EM28XX_BOARD_NOT_VALIDATED, + .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -546,6 +552,9 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + + /* Those boards with em2870 are DVB Only*/ + [EM2870_BOARD_TERRATEC_XS] = { .name = "Terratec Cinergy T XS", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -590,6 +599,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_ABSENT, /* MT2060 */ }, + [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = { .name = "Terratec Hybrid XS Secam", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -841,6 +851,7 @@ struct em28xx_board em28xx_boards[] = { .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", .is_em2800 = 1, .decoder = EM28XX_SAA711X, + .tuner_type = TUNER_ABSENT, /* capture only board */ .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, @@ -893,7 +904,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2820_BOARD_PINNACLE_DVC_90] = { .name = "Pinnacle Dazzle DVC 90/DVC 100", - .tuner_type = TUNER_ABSENT, + .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_COMPOSITE1, @@ -1218,6 +1229,9 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + + /* em2874 tuners are DVB only */ + [EM2874_BOARD_PINNACLE_PCTV_80E] = { .name = "Pinnacle PCTV HD Mini", .tuner_type = TUNER_ABSENT, -- cgit v1.2.3 From a1e782e39b16be26c0d2a5a18f29cc85251d2cb1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Nov 2008 10:00:00 -0200 Subject: em28xx: fix gpio settings From: Mauro Carvalho Chehab A previous changeset moved gpio from em28xx struct into em28xx_board. However, the driver were not updated to properly honor those gpio's. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-core.c | 4 ++-- linux/drivers/media/video/em28xx/em28xx.h | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index d63e5b997..729120807 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -784,9 +784,9 @@ int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode) dev->mode = set_mode; if (dev->mode == EM28XX_DIGITAL_MODE) - return em28xx_gpio_set(dev, dev->digital_gpio); + return em28xx_gpio_set(dev, dev->board.dvb_gpio); else - return em28xx_gpio_set(dev, dev->analog_gpio); + return em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio); } EXPORT_SYMBOL_GPL(em28xx_set_mode); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 1171578a8..62921982f 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -440,9 +440,6 @@ struct em28xx { /* Some older em28xx chips needs a waiting time after writing */ unsigned int wait_after_write; - /* GPIO sequences for analog and digital mode */ - struct em28xx_reg_seq *analog_gpio, *digital_gpio; - /* GPIO sequences for tuner callbacks */ struct em28xx_reg_seq *tuner_gpio; -- cgit v1.2.3 From 3a1f2e4b150aba36c07a25ec58986cf12469ba94 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Nov 2008 10:10:40 -0200 Subject: em28xx: Add support for suspend the device when not used From: Mauro Carvalho Chehab Several chips may be turned off when the device is not used, like audio, video and dvb demods. This patch adds a gpio callback at the core structs to allow turning off such devices. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- linux/drivers/media/video/em28xx/em28xx-core.c | 23 ++++++++++++++--------- linux/drivers/media/video/em28xx/em28xx-dvb.c | 8 ++++---- linux/drivers/media/video/em28xx/em28xx-video.c | 2 +- linux/drivers/media/video/em28xx/em28xx.h | 3 ++- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 24d7e8892..cf3bb3c1b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1529,7 +1529,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_set_mode(dev, EM28XX_ANALOG_MODE); /* Unlock device */ - em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); + em28xx_set_mode(dev, EM28XX_SUSPEND); } static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 729120807..f62b05eae 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -741,12 +741,14 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio) if (!gpio) return rc; - em28xx_write_reg(dev, 0x48, 0x00); - if (dev->mode == EM28XX_ANALOG_MODE) - em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); - else - em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); - msleep(6); + if (dev->mode != EM28XX_SUSPEND) { + em28xx_write_reg(dev, 0x48, 0x00); + if (dev->mode == EM28XX_ANALOG_MODE) + em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); + else + em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); + msleep(6); + } /* Send GPIO reset sequences specified at board entry */ while (gpio->sleep >= 0) { @@ -771,14 +773,17 @@ int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode) if (dev->mode == set_mode) return 0; - if (set_mode == EM28XX_MODE_UNDEFINED) { + if (set_mode == EM28XX_SUSPEND) { dev->mode = set_mode; - return 0; + + /* FIXME: add suspend support for ac97 */ + + return em28xx_gpio_set(dev, dev->board.suspend_gpio); } #if 0 /* Resource is locked */ - if (dev->mode != EM28XX_MODE_UNDEFINED) + if (dev->mode != EM28XX_SUSPEND) return -EINVAL; #endif dev->mode = set_mode; diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 6e6509c7a..a06659f28 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -162,7 +162,7 @@ static int stop_streaming(struct em28xx_dvb *dvb) em28xx_uninit_isoc(dev); - em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); + em28xx_set_mode(dev, EM28XX_SUSPEND); return 0; } @@ -216,7 +216,7 @@ static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) if (acquire) return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); else - return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); + return em28xx_set_mode(dev, EM28XX_SUSPEND); } /* ------------------------------------------------------------------ */ @@ -467,12 +467,12 @@ static int dvb_init(struct em28xx *dev) if (result < 0) goto out_free; - em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); + em28xx_set_mode(dev, EM28XX_SUSPEND); printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); return 0; out_free: - em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); + em28xx_set_mode(dev, EM28XX_SUSPEND); kfree(dvb); dev->dvb = NULL; return result; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index bc3a59a57..676240bb1 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1760,7 +1760,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) /* do this before setting alternate! */ em28xx_uninit_isoc(dev); - em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); + em28xx_set_mode(dev, EM28XX_SUSPEND); /* set alternate 0 */ dev->alt = 0; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 62921982f..be13c5d2b 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -161,7 +161,7 @@ #define EM2800_I2C_WRITE_TIMEOUT 20 enum em28xx_mode { - EM28XX_MODE_UNDEFINED, + EM28XX_SUSPEND, EM28XX_ANALOG_MODE, EM28XX_DIGITAL_MODE, }; @@ -337,6 +337,7 @@ struct em28xx_board { unsigned int tda9887_conf; struct em28xx_reg_seq *dvb_gpio; + struct em28xx_reg_seq *suspend_gpio; unsigned int is_em2800:1; unsigned int has_msp34xx:1; -- cgit v1.2.3 From ed2bce4cb08784c495e2a63775256ea4e2a75300 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Nov 2008 10:21:55 -0200 Subject: em28xx: move tuner gpio's to the cards struct From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 33 +++++++++++++++++++------ linux/drivers/media/video/em28xx/em28xx.h | 5 ++-- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index cf3bb3c1b..fe14ecc05 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -107,7 +107,7 @@ static struct em28xx_reg_seq em2870_kworld_355u_digital[] = { #endif /* Callback for the most boards */ -static struct em28xx_reg_seq default_callback[] = { +static struct em28xx_reg_seq default_tuner_gpio[] = { {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, @@ -473,7 +473,9 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Cinergy A Hybrid XS", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, + #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, @@ -499,6 +501,7 @@ struct em28xx_board em28xx_boards[] = { .name = "KWorld PVRTV 300U", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -559,6 +562,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Cinergy T XS", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, .dvb_gpio = default_digital, @@ -573,6 +577,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Kworld 350 U DVB-T", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, .dvb_gpio = default_digital, @@ -605,6 +610,7 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .has_msp34xx = 1, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -631,6 +637,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Hauppauge WinTV HVR 900", .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, @@ -656,6 +663,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Hauppauge WinTV HVR 900 (R2)", .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ @@ -682,6 +690,7 @@ struct em28xx_board em28xx_boards[] = { [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = { .name = "Hauppauge WinTV HVR 950", .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, @@ -707,6 +716,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = { .name = "Pinnacle PCTV HD Pro Stick", .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, @@ -732,6 +742,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = { .name = "AMD ATI TV Wonder HD 600", .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, @@ -757,6 +768,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Hybrid XS", .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .has_dvb = 1, .dvb_gpio = default_analog, @@ -783,6 +795,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_TERRATEC_PRODIGY_XS] = { .name = "Terratec Prodigy XS", .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -973,6 +986,7 @@ struct em28xx_board em28xx_boards[] = { .name = "MSI DigiVox A/D", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -999,6 +1013,7 @@ struct em28xx_board em28xx_boards[] = { .name = "MSI DigiVox A/D II", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -1025,6 +1040,7 @@ struct em28xx_board em28xx_boards[] = { .name = "KWorld DVB-T 305U", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -1043,6 +1059,7 @@ struct em28xx_board em28xx_boards[] = { [EM2880_BOARD_KWORLD_DVB_310U] = { .name = "KWorld DVB-T 310U", .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .has_dvb = 1, .dvb_gpio = default_digital, .mts_firmware = 1, @@ -1068,6 +1085,7 @@ struct em28xx_board em28xx_boards[] = { .name = "DNT DA2 Hybrid", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -1094,6 +1112,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Pinnacle Hybrid Pro", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -1120,6 +1139,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Pinnacle Hybrid Pro (2)", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ @@ -1147,6 +1167,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Kworld VS-DVB-T 323UR", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -1166,6 +1187,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Hybrid XS (em2882)", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -1192,6 +1214,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Kworld PlusTV HD Hybrid 330", .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -1384,7 +1407,7 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg) if (command != XC2028_TUNER_RESET) return 0; - rc = em28xx_gpio_set(dev, dev->tuner_gpio); + rc = em28xx_gpio_set(dev, dev->board.tuner_gpio); return rc; } @@ -1521,11 +1544,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) break; } - /* Sets the default callback. Used only for certain tuners */ - if (!dev->tuner_gpio) - dev->tuner_gpio = default_callback; - - em28xx_gpio_set(dev, dev->tuner_gpio); + em28xx_gpio_set(dev, dev->board.tuner_gpio); em28xx_set_mode(dev, EM28XX_ANALOG_MODE); /* Unlock device */ diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index be13c5d2b..667cb70cf 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -336,8 +336,10 @@ struct em28xx_board { /* i2c flags */ unsigned int tda9887_conf; + /* GPIO sequences */ struct em28xx_reg_seq *dvb_gpio; struct em28xx_reg_seq *suspend_gpio; + struct em28xx_reg_seq *tuner_gpio; unsigned int is_em2800:1; unsigned int has_msp34xx:1; @@ -441,9 +443,6 @@ struct em28xx { /* Some older em28xx chips needs a waiting time after writing */ unsigned int wait_after_write; - /* GPIO sequences for tuner callbacks */ - struct em28xx_reg_seq *tuner_gpio; - struct list_head devlist; u32 i2s_speed; /* I2S speed for audio digital stream */ -- cgit v1.2.3 From 1396809fc70840b729f6bdc9ef62e6bcb60825c7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Nov 2008 15:32:17 -0200 Subject: em28xx: improve probe messages From: Mauro Carvalho Chehab Prints usb speed used by em28xx interface. While there, fixes USB ID's endiannes. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 42 ++++++++++++++++++------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 676240bb1..23507ac4e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2258,6 +2258,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, struct em28xx *dev = NULL; int retval = -ENODEV; int i, nr, ifnum, isoc_pipe; + char *speed; udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; @@ -2268,11 +2269,12 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* Don't register audio interfaces */ if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n", - udev->descriptor.idVendor, - udev->descriptor.idProduct, - ifnum, - interface->altsetting[0].desc.bInterfaceClass); + em28xx_err(DRIVER_NAME " audio device (%04x:%04x): " + "interface %i, class %i\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + ifnum, + interface->altsetting[0].desc.bInterfaceClass); em28xx_devused &= ~(1<descriptor.idVendor, - udev->descriptor.idProduct, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), ifnum, interface->altsetting[0].desc.bInterfaceClass); @@ -2312,14 +2314,30 @@ static int em28xx_usb_probe(struct usb_interface *interface, em28xx_devused &= ~(1<speed) { + case USB_SPEED_LOW: + speed = "1.5"; + break; + case USB_SPEED_UNKNOWN: + case USB_SPEED_FULL: + speed = "12"; + break; + case USB_SPEED_HIGH: + speed = "480"; + break; + default: + speed = "unknown"; } - em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n", - udev->descriptor.idVendor, - udev->descriptor.idProduct, - ifnum, - interface->altsetting[0].desc.bInterfaceClass); + printk(DRIVER_NAME ": New video device @ %s Mbps " + "(%04x:%04x, interface %d, class %d)\n", + speed, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + ifnum, + interface->altsetting->desc.bInterfaceNumber); if (nr >= EM28XX_MAXBOARDS) { printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", -- cgit v1.2.3 From fd418b6a655b77600b58eca51b4e373e03bf6e26 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Nov 2008 00:46:43 -0200 Subject: em28xx: improve board description messages Print manufacturer/product info from USB device and also card entry. From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 3 ++- linux/drivers/media/video/em28xx/em28xx-video.c | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index fe14ecc05..d38b3ba72 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1427,7 +1427,8 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_set_model(dev); - em28xx_info("Found %s\n", dev->board.name); + em28xx_info("Identified as %s (card=%d)\n", + dev->board.name, dev->model); /* Set the default GPO/GPIO for legacy devices */ dev->reg_gpo_num = EM2880_R04_GPO; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 23507ac4e..00d49c45f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2259,6 +2259,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, int retval = -ENODEV; int i, nr, ifnum, isoc_pipe; char *speed; + char descr[255] = ""; udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; @@ -2331,8 +2332,20 @@ static int em28xx_usb_probe(struct usb_interface *interface, speed = "unknown"; } - printk(DRIVER_NAME ": New video device @ %s Mbps " + if (udev->manufacturer) + strlcpy(descr, udev->manufacturer, sizeof(descr)); + + if (udev->product) { + if (*descr) + strlcat(descr, " ", sizeof(descr)); + strlcat(descr, udev->product, sizeof(descr)); + } + if (*descr) + strlcat(descr, " ", sizeof(descr)); + + printk(DRIVER_NAME ": New device %s@ %s Mbps " "(%04x:%04x, interface %d, class %d)\n", + descr, speed, le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct), -- cgit v1.2.3 From 81755eaa892b63b3357fca8123471febe60b9f66 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Dec 2008 15:32:11 -0200 Subject: backport commit 72e9622c2a2eb73d82c716504cc93d22cd3cfd8e From: Mauro Carvalho Chehab Author: Guennadi Liakhovetski Date: Tue Nov 25 18:57:08 2008 +0100 [ARM] pxa/pcm990: use negative number for an invalid GPIO in camera data 0 is a valid GPIO number, use a negative number to specify, that this camera doesn't have a GPIO for bus-width switching. kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/arch/arm/mach-pxa/pcm990-baseboard.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/arch/arm/mach-pxa/pcm990-baseboard.c b/linux/arch/arm/mach-pxa/pcm990-baseboard.c index e8eb8cbc3..da25913c4 100644 --- a/linux/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/linux/arch/arm/mach-pxa/pcm990-baseboard.c @@ -403,6 +403,7 @@ static struct soc_camera_link iclink[] = { .gpio = NR_BUILTIN_GPIO + 1, }, { .bus_id = 0, /* Must match with the camera ID above */ + .gpio = -ENXIO, } }; -- cgit v1.2.3 From bda2ee9b43936b9a74544ce71e9b398f42ef2572 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Wed, 3 Dec 2008 19:26:15 +0100 Subject: Add USB ID for the Sil4701 radio from DealExtreme. Signed-off-by: Mark Lord Cc: Tobias Lorenz Cc: Greg KH Signed-off-by: Andrew Morton Code beautifications and documentation added. Signed-off-by: Tobias Lorenz --- linux/Documentation/video4linux/si470x.txt | 1 + linux/drivers/media/radio/radio-si470x.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/linux/Documentation/video4linux/si470x.txt b/linux/Documentation/video4linux/si470x.txt index 11c5fd22a..49679e6aa 100644 --- a/linux/Documentation/video4linux/si470x.txt +++ b/linux/Documentation/video4linux/si470x.txt @@ -41,6 +41,7 @@ chips are known to work: - 10c4:818a: Silicon Labs USB FM Radio Reference Design - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) +- 10c5:819a: DealExtreme USB Radio Software diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 5d6237b6d..67b56868b 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -96,6 +96,8 @@ * 2008-10-20 Alexey Klimov * - add support for KWorld USB FM Radio FM700 * - blacklisted KWorld radio in hid-core.c and hid-ids.h + * 2008-12-03 Mark Lord + * - add support for DealExtreme USB Radio * * ToDo: * - add firmware download/update support @@ -139,6 +141,8 @@ static struct usb_device_id si470x_usb_driver_id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, + /* DealExtreme USB Radio */ + { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) }, /* Terminating entry */ { } }; -- cgit v1.2.3 From d149837768a0043157da6e1e09a30cb52c314e48 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Dec 2008 06:50:09 +0000 Subject: Fix I2C bridge error in zl10353 From: Dmitri Belimov Fix I2C bridge error in zl10353 if no tunner attached to internal I2C bus of zl10353 chip. When set enable bridge from internal I2C bus to the main I2C bus (saa7134) the main I2C bus stopped very hardly. No any communication. In our next board we solder additional resistors to internal I2C bus. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/zl10353.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index 2e449a457..be5d7ef7c 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -598,8 +598,15 @@ static int zl10353_init(struct dvb_frontend *fe) static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) { + struct zl10353_state *state = fe->demodulator_priv; u8 val = 0x0a; + if (state->config.no_tuner) { + /* No tuner attached to the internal I2C bus */ + /* If set enable I2C bridge, the main I2C bus stopped hardly */ + return 0; + } + if (enable) val |= 0x10; -- cgit v1.2.3 From e52868f76809af37db6fa0a922d73a73fe47fc12 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Dec 2008 06:51:38 +0000 Subject: Change configuration of the Beholder H6 card From: Dmitri Belimov Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 54be8314f..d81888103 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4501,6 +4501,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, .vmux = 3, @@ -4519,8 +4520,6 @@ struct saa7134_board saa7134_boards[] = { .name = name_radio, .amux = LINE2, }, - /* no DVB support for now */ - /* .mpeg = SAA7134_MPEG_DVB, */ }, [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = { .name = "Asus Tiger 3in1", @@ -6128,6 +6127,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_M6: case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: + case SAA7134_BOARD_BEHOLD_H6: dev->has_remote = SAA7134_REMOTE_I2C; break; case SAA7134_BOARD_AVERMEDIA_A169_B: -- cgit v1.2.3 From 5e175b73ce763bcf08352450b452f43928285236 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Dec 2008 06:53:03 +0000 Subject: Add the Beholder H6 card to DVB-T part of sources. From: Dmitri Belimov Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-dvb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index 704442f55..d4c9de9fd 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -49,6 +49,8 @@ #include "lnbp21.h" #include "tuner-simple.h" +#include "zl10353.h" + MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -854,6 +856,12 @@ static struct tda1004x_config ads_tech_duo_config = { .request_firmware = philips_tda1004x_request_firmware }; +static struct zl10353_config behold_h6_config = { + .demod_address = 0x1e>>1, + .no_tuner = 1, + .parallel_ts = 1, +}; + /* ================================================================== * tda10086 based DVB-S cards, helper functions */ @@ -1361,6 +1369,16 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_0) < 0) goto dettach_frontend; break; + case SAA7134_BOARD_BEHOLD_H6: + dev->dvb.frontend = dvb_attach(zl10353_attach, + &behold_h6_config, + &dev->i2c_adap); + if (dev->dvb.frontend) { + dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &dev->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3); + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; -- cgit v1.2.3 From 07310480aa20dd3b3ba3bc0c5cd96a0cab6e63a5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 20:10:09 -0200 Subject: saa7134: fix a merge conflict on Behold H6 board From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-dvb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index d4c9de9fd..0bbb97b1b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -1370,11 +1370,11 @@ static int dvb_init(struct saa7134_dev *dev) goto dettach_frontend; break; case SAA7134_BOARD_BEHOLD_H6: - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &behold_h6_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3); } -- cgit v1.2.3 From e09f8540a83dea53bc34089f07eca7a62e3c440d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Dec 2008 20:27:09 -0200 Subject: Add TEA5764 radio driver From: Fabio Belavenuto Add support for radio driver TEA5764 from NXP. This chip is connected in pxa I2C bus in EZX phones from Motorola, the chip is used in phone model A1200. This driver is for OpenEZX project (www.openezx.org) Tested with A1200 phone, openezx kernel and fm-tools Signed-off-by: Fabio Belavenuto [mchehab@redhat.com: Fixed CodingStyle and solved some merge conflicts] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/Kconfig | 19 + linux/drivers/media/radio/Makefile | 1 + linux/drivers/media/radio/radio-tea5764.c | 638 ++++++++++++++++++++++++++++++ 3 files changed, 658 insertions(+) create mode 100644 linux/drivers/media/radio/radio-tea5764.c diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig index 5189c4eb4..3315cac87 100644 --- a/linux/drivers/media/radio/Kconfig +++ b/linux/drivers/media/radio/Kconfig @@ -387,4 +387,23 @@ config USB_MR800 To compile this driver as a module, choose M here: the module will be called radio-mr800. +config RADIO_TEA5764 + tristate "TEA5764 I2C FM radio support" + depends on I2C && VIDEO_V4L2 + ---help--- + Say Y here if you want to use the TEA5764 FM chip found in + EZX phones. This FM chip is present in EZX phones from Motorola, + connected to internal pxa I2C bus. + + To compile this driver as a module, choose M here: the + module will be called radio-tea5764. + +config RADIO_TEA5764_XTAL + bool "TEA5764 crystal reference" + depends on RADIO_TEA5764=y + default y + help + Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N + here if TEA5764 reference frequency is connected in FREQIN. + endif # RADIO_ADAPTERS diff --git a/linux/drivers/media/radio/Makefile b/linux/drivers/media/radio/Makefile index 240ec63cd..0f2b35b3e 100644 --- a/linux/drivers/media/radio/Makefile +++ b/linux/drivers/media/radio/Makefile @@ -19,5 +19,6 @@ obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_SI470X) += radio-si470x.o obj-$(CONFIG_USB_MR800) += radio-mr800.o +obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o EXTRA_CFLAGS += -Isound diff --git a/linux/drivers/media/radio/radio-tea5764.c b/linux/drivers/media/radio/radio-tea5764.c new file mode 100644 index 000000000..328fa50ca --- /dev/null +++ b/linux/drivers/media/radio/radio-tea5764.c @@ -0,0 +1,638 @@ +/* + * driver/media/radio/radio-tea5764.c + * + * Driver for TEA5764 radio chip for linux 2.6. + * This driver is for TEA5764 chip from NXP, used in EZX phones from Motorola. + * The I2C protocol is used for communicate with chip. + * + * Based in radio-tea5761.c Copyright (C) 2005 Nokia Corporation + * + * Copyright (c) 2008 Fabio Belavenuto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * History: + * 2008-12-06 Fabio Belavenuto + * initial code + * + * TODO: + * add platform_data support for IRQs platform dependencies + * add RDS support + */ +#include +#include +#include /* Initdata */ +#include /* kernel radio structs */ +#include /* I2C */ +#include +#include +#include /* for KERNEL_VERSION MACRO */ + +#define DRIVER_VERSION "v0.01" +#define RADIO_VERSION KERNEL_VERSION(0, 0, 1) + +#define DRIVER_AUTHOR "Fabio Belavenuto " +#define DRIVER_DESC "A driver for the TEA5764 radio chip for EZX Phones." + +#define PINFO(format, ...)\ + printk(KERN_INFO KBUILD_MODNAME ": "\ + DRIVER_VERSION ": " format "\n", ## __VA_ARGS__) +#define PWARN(format, ...)\ + printk(KERN_WARNING KBUILD_MODNAME ": "\ + DRIVER_VERSION ": " format "\n", ## __VA_ARGS__) +#if 1 +# define PDEBUG(format, ...)\ + printk(KERN_DEBUG KBUILD_MODNAME ": "\ + DRIVER_VERSION ": " format "\n", ## __VA_ARGS__) +#else +# define PDEBUG(format, ...) +#endif + +/* Frequency limits in MHz -- these are European values. For Japanese +devices, that would be 76000 and 91000. */ +#define FREQ_MIN 87500 +#define FREQ_MAX 108000 +#define FREQ_MUL 16 + +/* TEA5764 registers */ +#define TEA5764_MANID 0x002b +#define TEA5764_CHIPID 0x5764 + +#define TEA5764_INTREG_BLMSK 0x0001 +#define TEA5764_INTREG_FRRMSK 0x0002 +#define TEA5764_INTREG_LEVMSK 0x0008 +#define TEA5764_INTREG_IFMSK 0x0010 +#define TEA5764_INTREG_BLMFLAG 0x0100 +#define TEA5764_INTREG_FRRFLAG 0x0200 +#define TEA5764_INTREG_LEVFLAG 0x0800 +#define TEA5764_INTREG_IFFLAG 0x1000 + +#define TEA5764_FRQSET_SUD 0x8000 +#define TEA5764_FRQSET_SM 0x4000 + +#define TEA5764_TNCTRL_PUPD1 0x8000 +#define TEA5764_TNCTRL_PUPD0 0x4000 +#define TEA5764_TNCTRL_BLIM 0x2000 +#define TEA5764_TNCTRL_SWPM 0x1000 +#define TEA5764_TNCTRL_IFCTC 0x0800 +#define TEA5764_TNCTRL_AFM 0x0400 +#define TEA5764_TNCTRL_SMUTE 0x0200 +#define TEA5764_TNCTRL_SNC 0x0100 +#define TEA5764_TNCTRL_MU 0x0080 +#define TEA5764_TNCTRL_SSL1 0x0040 +#define TEA5764_TNCTRL_SSL0 0x0020 +#define TEA5764_TNCTRL_HLSI 0x0010 +#define TEA5764_TNCTRL_MST 0x0008 +#define TEA5764_TNCTRL_SWP 0x0004 +#define TEA5764_TNCTRL_DTC 0x0002 +#define TEA5764_TNCTRL_AHLSI 0x0001 + +#define TEA5764_TUNCHK_LEVEL(x) (((x) & 0x00F0) >> 4) +#define TEA5764_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9) +#define TEA5764_TUNCHK_TUNTO 0x0100 +#define TEA5764_TUNCHK_LD 0x0008 +#define TEA5764_TUNCHK_STEREO 0x0004 + +#define TEA5764_TESTREG_TRIGFR 0x0800 + +struct tea5764_regs { + u16 intreg; /* INTFLAG & INTMSK */ + u16 frqset; /* FRQSETMSB & FRQSETLSB */ + u16 tnctrl; /* TNCTRL1 & TNCTRL2 */ + u16 frqchk; /* FRQCHKMSB & FRQCHKLSB */ + u16 tunchk; /* IFCHK & LEVCHK */ + u16 testreg; /* TESTBITS & TESTMODE */ + u16 rdsstat; /* RDSSTAT1 & RDSSTAT2 */ + u16 rdslb; /* RDSLBMSB & RDSLBLSB */ + u16 rdspb; /* RDSPBMSB & RDSPBLSB */ + u16 rdsbc; /* RDSBBC & RDSGBC */ + u16 rdsctrl; /* RDSCTRL1 & RDSCTRL2 */ + u16 rdsbbl; /* PAUSEDET & RDSBBL */ + u16 manid; /* MANID1 & MANID2 */ + u16 chipid; /* CHIPID1 & CHIPID2 */ +} __attribute__ ((packed)); + +struct tea5764_write_regs { + u8 intreg; /* INTMSK */ + u16 frqset; /* FRQSETMSB & FRQSETLSB */ + u16 tnctrl; /* TNCTRL1 & TNCTRL2 */ + u16 testreg; /* TESTBITS & TESTMODE */ + u16 rdsctrl; /* RDSCTRL1 & RDSCTRL2 */ + u16 rdsbbl; /* PAUSEDET & RDSBBL */ +} __attribute__ ((packed)); + +#ifndef RADIO_TEA5764_XTAL +#define RADIO_TEA5764_XTAL 1 +#endif + +static int radio_nr = -1; +static int use_xtal = RADIO_TEA5764_XTAL; + +struct tea5764_device { + struct i2c_client *i2c_client; + struct video_device *videodev; + struct tea5764_regs regs; + struct mutex mutex; + int users; +}; + +/* I2C code related */ +int tea5764_i2c_read(struct tea5764_device *radio) +{ + int i; + u16 *p = (u16 *) &radio->regs; + + struct i2c_msg msgs[1] = { + { radio->i2c_client->addr, I2C_M_RD, sizeof(radio->regs), + (void *)&radio->regs }, + }; + if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1) + return -EIO; + for (i = 0; i < sizeof(struct tea5764_regs) / sizeof(u16); i++) + p[i] = __be16_to_cpu(p[i]); + + return 0; +} + +int tea5764_i2c_write(struct tea5764_device *radio) +{ + struct tea5764_write_regs wr; + struct tea5764_regs *r = &radio->regs; + struct i2c_msg msgs[1] = { + { radio->i2c_client->addr, 0, sizeof(wr), (void *) &wr }, + }; + wr.intreg = r->intreg & 0xff; + wr.frqset = __cpu_to_be16(r->frqset); + wr.tnctrl = __cpu_to_be16(r->tnctrl); + wr.testreg = __cpu_to_be16(r->testreg); + wr.rdsctrl = __cpu_to_be16(r->rdsctrl); + wr.rdsbbl = __cpu_to_be16(r->rdsbbl); + if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1) + return -EIO; + return 0; +} + +/* V4L2 code related */ +static struct v4l2_queryctrl radio_qctrl[] = { + { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + } +}; + +static void tea5764_power_up(struct tea5764_device *radio) +{ + struct tea5764_regs *r = &radio->regs; + + if (!(r->tnctrl & TEA5764_TNCTRL_PUPD0)) { + r->tnctrl &= ~(TEA5764_TNCTRL_AFM | TEA5764_TNCTRL_MU | + TEA5764_TNCTRL_HLSI); + if (!use_xtal) + r->testreg |= TEA5764_TESTREG_TRIGFR; + else + r->testreg &= ~TEA5764_TESTREG_TRIGFR; + + r->tnctrl |= TEA5764_TNCTRL_PUPD0; + tea5764_i2c_write(radio); + } +} + +static void tea5764_power_down(struct tea5764_device *radio) +{ + struct tea5764_regs *r = &radio->regs; + + if (r->tnctrl & TEA5764_TNCTRL_PUPD0) { + r->tnctrl &= ~TEA5764_TNCTRL_PUPD0; + tea5764_i2c_write(radio); + } +} + +static void tea5764_set_freq(struct tea5764_device *radio, int freq) +{ + struct tea5764_regs *r = &radio->regs; + + /* formula: (freq [+ or -] 225000) / 8192 */ + if (r->tnctrl & TEA5764_TNCTRL_HLSI) + r->frqset = (freq + 225000) / 8192; + else + r->frqset = (freq - 225000) / 8192; +} + +static int tea5764_get_freq(struct tea5764_device *radio) +{ + struct tea5764_regs *r = &radio->regs; + + if (r->tnctrl & TEA5764_TNCTRL_HLSI) + return (r->frqchk * 8192) - 225000; + else + return (r->frqchk * 8192) + 225000; +} + +/* tune an frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ +static void tea5764_tune(struct tea5764_device *radio, int freq) +{ + tea5764_set_freq(radio, freq); + if (tea5764_i2c_write(radio)) + PWARN("Could not set frequency!"); +} + +static void tea5764_set_audout_mode(struct tea5764_device *radio, int audmode) +{ + struct tea5764_regs *r = &radio->regs; + int tnctrl = r->tnctrl; + + if (audmode == V4L2_TUNER_MODE_MONO) + r->tnctrl |= TEA5764_TNCTRL_MST; + else + r->tnctrl &= ~TEA5764_TNCTRL_MST; + if (tnctrl != r->tnctrl) + tea5764_i2c_write(radio); +} + +static int tea5764_get_audout_mode(struct tea5764_device *radio) +{ + struct tea5764_regs *r = &radio->regs; + + if (r->tnctrl & TEA5764_TNCTRL_MST) + return V4L2_TUNER_MODE_MONO; + else + return V4L2_TUNER_MODE_STEREO; +} + +static void tea5764_mute(struct tea5764_device *radio, int on) +{ + struct tea5764_regs *r = &radio->regs; + int tnctrl = r->tnctrl; + + if (on) + r->tnctrl |= TEA5764_TNCTRL_MU; + else + r->tnctrl &= ~TEA5764_TNCTRL_MU; + if (tnctrl != r->tnctrl) + tea5764_i2c_write(radio); +} + +static int tea5764_is_muted(struct tea5764_device *radio) +{ + return radio->regs.tnctrl & TEA5764_TNCTRL_MU; +} + +/* V4L2 vidioc */ +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + struct tea5764_device *radio = video_drvdata(file); + struct video_device *dev = radio->videodev; + + strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); + strlcpy(v->card, dev->name, sizeof(v->card)); + snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev->dev.bus_id); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + return 0; +} + +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + struct tea5764_device *radio = video_drvdata(file); + struct tea5764_regs *r = &radio->regs; + + if (v->index > 0) + return -EINVAL; + + memset(v, 0, sizeof(v)); + strcpy(v->name, "FM"); + v->type = V4L2_TUNER_RADIO; + tea5764_i2c_read(radio); + v->rangelow = FREQ_MIN * FREQ_MUL; + v->rangehigh = FREQ_MAX * FREQ_MUL; + v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + if (r->tunchk & TEA5764_TUNCHK_STEREO) + v->rxsubchans = V4L2_TUNER_SUB_STEREO; + v->audmode = tea5764_get_audout_mode(radio); + v->signal = TEA5764_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf; + v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk); + + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + struct tea5764_device *radio = video_drvdata(file); + + if (v->index > 0) + return -EINVAL; + + tea5764_set_audout_mode(radio, v->audmode); + return 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct tea5764_device *radio = video_drvdata(file); + + if (f->tuner != 0) + return -EINVAL; + if (f->frequency == 0) { + /* We special case this as a power down control. */ + tea5764_power_down(radio); + } + if (f->frequency < (FREQ_MIN * FREQ_MUL)) + return -EINVAL; + if (f->frequency > (FREQ_MAX * FREQ_MUL)) + return -EINVAL; + tea5764_power_up(radio); + tea5764_tune(radio, (f->frequency * 125) / 2); + return 0; +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct tea5764_device *radio = video_drvdata(file); + struct tea5764_regs *r = &radio->regs; + + tea5764_i2c_read(radio); + memset(f, 0, sizeof(f)); + f->type = V4L2_TUNER_RADIO; + if (r->tnctrl & TEA5764_TNCTRL_PUPD0) + f->frequency = (tea5764_get_freq(radio) * 2) / 125; + else + f->frequency = 0; + + return 0; +} + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { + if (qc->id && qc->id == radio_qctrl[i].id) { + memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); + return 0; + } + } + return -EINVAL; +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct tea5764_device *radio = video_drvdata(file); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + tea5764_i2c_read(radio); + ctrl->value = tea5764_is_muted(radio) ? 1 : 0; + return 0; + } + return -EINVAL; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct tea5764_device *radio = video_drvdata(file); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + tea5764_mute(radio, ctrl->value); + return 0; + } + return -EINVAL; +} + +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + return 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index > 1) + return -EINVAL; + + strcpy(a->name, "Radio"); + a->capability = V4L2_AUDCAP_STEREO; + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index != 0) + return -EINVAL; + + return 0; +} + +static int tea5764_open(struct file *file) +{ + /* Currently we support only one device */ + int minor = video_devdata(file)->minor; + struct tea5764_device *radio = video_drvdata(file); + + if (radio->videodev->minor != minor) + return -ENODEV; + + mutex_lock(&radio->mutex); + /* Only exclusive access */ + if (radio->users) { + mutex_unlock(&radio->mutex); + return -EBUSY; + } + radio->users++; + mutex_unlock(&radio->mutex); + file->private_data = radio; + return 0; +} + +static int tea5764_close(struct file *file) +{ + struct tea5764_device *radio = video_drvdata(file); + + if (!radio) + return -ENODEV; + mutex_lock(&radio->mutex); + radio->users--; + mutex_unlock(&radio->mutex); + return 0; +} + +/* File system interface */ +static const struct v4l2_file_operations tea5764_fops = { + .owner = THIS_MODULE, + .open = tea5764_open, + .release = tea5764_close, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops tea5764_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, +}; + +/* V4L2 interface */ +static struct video_device tea5764_radio_template = { + .name = "TEA5764 FM-Radio", + .fops = &tea5764_fops, + .ioctl_ops = &tea5764_ioctl_ops, + .release = video_device_release, +}; + +/* I2C probe: check if the device exists and register with v4l if it is */ +static int __devinit tea5764_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tea5764_device *radio; + struct tea5764_regs *r; + int ret; + + PDEBUG("probe"); + radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL); + if (!radio) + return -ENOMEM; + + mutex_init(&radio->mutex); + radio->i2c_client = client; + ret = tea5764_i2c_read(radio); + if (ret) + goto errfr; + r = &radio->regs; + PDEBUG("chipid = %04X, manid = %04X", r->chipid, r->manid); + if (r->chipid != TEA5764_CHIPID || + (r->manid & 0x0fff) != TEA5764_MANID) { + PWARN("This chip is not a TEA5764!"); + ret = -EINVAL; + goto errfr; + } + + radio->videodev = video_device_alloc(); + if (!(radio->videodev)) { + ret = -ENOMEM; + goto errfr; + } + memcpy(radio->videodev, &tea5764_radio_template, + sizeof(tea5764_radio_template)); + + i2c_set_clientdata(client, radio); + video_set_drvdata(radio->videodev, radio); + + ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); + if (ret < 0) { + PWARN("Could not register video device!"); + goto errrel; + } + + /* initialize and power off the chip */ + tea5764_i2c_read(radio); + tea5764_set_audout_mode(radio, V4L2_TUNER_MODE_STEREO); + tea5764_mute(radio, 1); + tea5764_power_down(radio); + + PINFO("registered."); + return 0; +errrel: + video_device_release(radio->videodev); +errfr: + kfree(radio); + return ret; +} + +static int __devexit tea5764_i2c_remove(struct i2c_client *client) +{ + struct tea5764_device *radio = i2c_get_clientdata(client); + + PDEBUG("remove"); + if (radio) { + tea5764_power_down(radio); + video_unregister_device(radio->videodev); + kfree(radio); + } + return 0; +} + +/* I2C subsystem interface */ +static const struct i2c_device_id tea5764_id[] = { + { "radio-tea5764", 0 }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(i2c, tea5764_id); + +static struct i2c_driver tea5764_i2c_driver = { + .driver = { + .name = "radio-tea5764", + .owner = THIS_MODULE, + }, + .probe = tea5764_i2c_probe, + .remove = __devexit_p(tea5764_i2c_remove), + .id_table = tea5764_id, +}; + +/* init the driver */ +static int __init tea5764_init(void) +{ + int ret = i2c_add_driver(&tea5764_i2c_driver); + + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": " + DRIVER_DESC "\n"); + return ret; +} + +/* cleanup the driver */ +static void __exit tea5764_exit(void) +{ + i2c_del_driver(&tea5764_i2c_driver); +} + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +module_param(use_xtal, int, 1); +MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board"); +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(radio_nr, "video4linux device number to use"); + +module_init(tea5764_init); +module_exit(tea5764_exit); -- cgit v1.2.3 From 03ce7280ba34fec261331d18e5bb61bb467bf1e9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 00:26:09 -0200 Subject: This patch adds support for Avermedia AVer TV GO 007 FM Plus (M15C) 1461:f31d From: Pham Thanh Nam Signed-off-by: Pham Thanh Nam Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.saa7134 | 1 + linux/drivers/media/video/saa7134/saa7134-cards.c | 40 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-input.c | 1 + linux/drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 43 insertions(+) diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index 335aef4dc..b8d470596 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -152,3 +152,4 @@ 151 -> ADS Tech Instant HDTV [1421:0380] 152 -> Asus Tiger Rev:1.00 [1043:4857] 153 -> Kworld Plus TV Analog Lite PCI [17de:7128] +154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d] diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index d81888103..44052f28d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4681,6 +4681,38 @@ struct saa7134_board saa7134_boards[] = { .amux = 2, }, }, + [SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = { + .name = "Avermedia AVerTV GO 007 FM Plus", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x00300003, + /* .gpiomask = 0x8c240003, */ + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x01, + }, { + .name = name_svideo, + .vmux = 6, + .amux = LINE1, + .gpio = 0x02, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x00300001, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x01, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5778,6 +5810,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = PCI_ANY_ID, .driver_data = SAA7134_BOARD_UNKNOWN, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf31d, + .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS, + + }, { /* --- end of list --- */ } }; @@ -6028,6 +6067,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_GENIUS_TVGO_A11MCE: case SAA7134_BOARD_REAL_ANGEL_220: case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: + case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 272490b92..3c55ca44a 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -449,6 +449,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_507: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: case SAA7134_BOARD_AVERMEDIA_M102: + case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: ir_codes = ir_codes_avermedia; mask_keycode = 0x0007C8; mask_keydown = 0x000010; diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 3bb599673..bb973d363 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -277,6 +277,7 @@ struct saa7134_format { #define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151 #define SAA7134_BOARD_ASUSTeK_TIGER 152 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153 +#define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From ec36a3c6efe4d753c0d6a336aeba24765f9c6979 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 01:45:35 -0200 Subject: parse_em28xx.pl: Add a limited capability of parsing i2c commands From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/parse_em28xx.pl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/util/parse_em28xx.pl b/v4l2-apps/util/parse_em28xx.pl index d1bbb0f0d..3f5cda6da 100755 --- a/v4l2-apps/util/parse_em28xx.pl +++ b/v4l2-apps/util/parse_em28xx.pl @@ -62,7 +62,7 @@ # This way, it is easier to understand what the em28xx driver is doing. # # Known limitations: -# - Currently, the tool only parses em28xx, ac97 and em202 registers. +# - Currently, the tool only parses em28xx, i2c, ac97 and em202 registers. # - It is limited to read/write operations with 1 or 2 bytes of # arguments; # - Not all registers are documented; @@ -275,4 +275,11 @@ while (<>) { $reg, $3, $2; next; } + + if (m/40 02 00 00 ([0-9a-f].) 00 ([0-9a-f].) 00\s+[\>]+\s+([0-9a-f ]+)/) { + printf "i2c_master_send(0x$1>>1, { $3 }, 0x$2);\n"; + } + if (m/c0 02 00 00 ([0-9a-f].) 00 ([0-9a-f].) 00\s+[\>]+\s+([0-9a-f ]+)/) { + printf "i2c_master_recv(0x$1>>1, &buf, 0x$2); /* $3 */\n"; + } } -- cgit v1.2.3 From b52a93c3b6a911753c9c0f42d77798cf66fe594a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 07:37:50 -0200 Subject: em28xx: update chip id for em2710 From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 65dcb91bd..24e39c568 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -160,7 +160,7 @@ /* FIXME: Need to be populated with the other chip ID's */ enum em28xx_chip_id { - CHIP_ID_EM2820 = 18, + CHIP_ID_EM2820 = 18, /* Also used by em2710 */ CHIP_ID_EM2840 = 20, CHIP_ID_EM2750 = 33, CHIP_ID_EM2860 = 34, -- cgit v1.2.3 From e9532d047a5c76bc75c708047e55716efb8bfca5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 07:57:19 -0200 Subject: saa7134: fix autodetection for AVer TV GO 007 FM Plus From: Pham Thanh Nam This patch fixes autodetection for Avermedia AVerTV GO 007 FM Plus (M15C) (PCI ID 1461:f31d). Priority: normal Signed-off-by: Pham Thanh Nam Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 44052f28d..12893f09b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -5771,6 +5771,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x17de, .subdevice = 0x7128, .driver_data = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf31d, + .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS, + }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -5810,13 +5817,6 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = PCI_ANY_ID, .driver_data = SAA7134_BOARD_UNKNOWN, },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf31d, - .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS, - - }, { /* --- end of list --- */ } }; -- cgit v1.2.3 From 055a77bbdc33877df3b1a9d9d8aa49230923a450 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 10:34:18 -0200 Subject: tuner-simple: Fix tuner type set message From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-simple.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c index 0d9fc1bb2..e65c170c8 100644 --- a/linux/drivers/media/common/tuners/tuner-simple.c +++ b/linux/drivers/media/common/tuners/tuner-simple.c @@ -1095,7 +1095,12 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); - tuner_info("type set to %d (%s)\n", type, priv->tun->name); + if (type != priv->type) + tuner_warn("couldn't set type to %d. Using %d (%s) instead\n", + type, priv->type, priv->tun->name); + else + tuner_info("type set to %d (%s)\n", + priv->type, priv->tun->name); if ((debug) || ((atv_input[priv->nr] > 0) || (dtv_input[priv->nr] > 0))) { -- cgit v1.2.3 From 2599228213e390de405066ffb1ada35041a11559 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 10:37:33 -0200 Subject: em28xx: allocate adev together with struct em28xx dev From: Mauro Carvalho Chehab Some devices require different setups on struct_audio. Due to that, we may need to change some fields at dev.adev during device probe. So, this patch moves the dynamic memory allocation of adev at em28xx-alsa to the dynamic allocation of struct em28xx dev that happens during device probe. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-audio.c | 95 +++++++++++-------------- linux/drivers/media/video/em28xx/em28xx.h | 2 +- 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index c62455202..34c494d68 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -63,9 +63,9 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) dprintk("Stopping isoc\n"); for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - usb_unlink_urb(dev->adev->urb[i]); - usb_free_urb(dev->adev->urb[i]); - dev->adev->urb[i] = NULL; + usb_unlink_urb(dev->adev.urb[i]); + usb_free_urb(dev->adev.urb[i]); + dev->adev.urb[i] = NULL; } return 0; @@ -94,8 +94,8 @@ static void em28xx_audio_isocirq(struct urb *urb) struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; #endif - if (dev->adev->capture_pcm_substream) { - substream = dev->adev->capture_pcm_substream; + if (dev->adev.capture_pcm_substream) { + substream = dev->adev.capture_pcm_substream; runtime = substream->runtime; stride = runtime->frame_bits >> 3; @@ -109,9 +109,9 @@ static void em28xx_audio_isocirq(struct urb *urb) continue; #ifdef NO_PCM_LOCK - spin_lock_irqsave(&dev->adev->slock, flags); + spin_lock_irqsave(&dev->adev.slock, flags); #endif - oldptr = dev->adev->hwptr_done_capture; + oldptr = dev->adev.hwptr_done_capture; if (oldptr + length >= runtime->buffer_size) { unsigned int cnt = runtime->buffer_size - oldptr; @@ -128,22 +128,22 @@ static void em28xx_audio_isocirq(struct urb *urb) snd_pcm_stream_lock(substream); #endif - dev->adev->hwptr_done_capture += length; - if (dev->adev->hwptr_done_capture >= + dev->adev.hwptr_done_capture += length; + if (dev->adev.hwptr_done_capture >= runtime->buffer_size) - dev->adev->hwptr_done_capture -= + dev->adev.hwptr_done_capture -= runtime->buffer_size; - dev->adev->capture_transfer_done += length; - if (dev->adev->capture_transfer_done >= + dev->adev.capture_transfer_done += length; + if (dev->adev.capture_transfer_done >= runtime->period_size) { - dev->adev->capture_transfer_done -= + dev->adev.capture_transfer_done -= runtime->period_size; period_elapsed = 1; } #ifdef NO_PCM_LOCK - spin_unlock_irqrestore(&dev->adev->slock, flags); + spin_unlock_irqrestore(&dev->adev.slock, flags); #else snd_pcm_stream_unlock(substream); #endif @@ -153,7 +153,7 @@ static void em28xx_audio_isocirq(struct urb *urb) } urb->status = 0; - if (dev->adev->shutdown) + if (dev->adev.shutdown) return; status = usb_submit_urb(urb, GFP_ATOMIC); @@ -176,17 +176,17 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) struct urb *urb; int j, k; - dev->adev->transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); - if (!dev->adev->transfer_buffer[i]) + dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); + if (!dev->adev.transfer_buffer[i]) return -ENOMEM; - memset(dev->adev->transfer_buffer[i], 0x80, sb_size); + memset(dev->adev.transfer_buffer[i], 0x80, sb_size); urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); if (!urb) { em28xx_errdev("usb_alloc_urb failed!\n"); for (j = 0; j < i; j++) { - usb_free_urb(dev->adev->urb[j]); - kfree(dev->adev->transfer_buffer[j]); + usb_free_urb(dev->adev.urb[j]); + kfree(dev->adev.transfer_buffer[j]); } return -ENOMEM; } @@ -195,7 +195,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) urb->context = dev; urb->pipe = usb_rcvisocpipe(dev->udev, 0x83); urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = dev->adev->transfer_buffer[i]; + urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->interval = 1; urb->complete = em28xx_audio_isocirq; urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS; @@ -207,11 +207,11 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) urb->iso_frame_desc[j].length = EM28XX_AUDIO_MAX_PACKET_SIZE; } - dev->adev->urb[i] = urb; + dev->adev.urb[i] = urb; } for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - errCode = usb_submit_urb(dev->adev->urb[i], GFP_ATOMIC); + errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); if (errCode) { em28xx_isoc_audio_deinit(dev); @@ -224,16 +224,16 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) { - dprintk("%s transfer\n", (dev->adev->capture_stream == STREAM_ON)? + dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ? "stop" : "start"); switch (cmd) { case EM28XX_CAPTURE_STREAM_EN: - if (dev->adev->capture_stream == STREAM_OFF && arg == 1) { - dev->adev->capture_stream = STREAM_ON; + if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { + dev->adev.capture_stream = STREAM_ON; em28xx_init_audio_isoc(dev); - } else if (dev->adev->capture_stream == STREAM_ON && arg == 0) { - dev->adev->capture_stream = STREAM_OFF; + } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { + dev->adev.capture_stream = STREAM_OFF; em28xx_isoc_audio_deinit(dev); } else { printk(KERN_ERR "An underrun very likely occurred. " @@ -332,17 +332,17 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) goto err; runtime->hw = snd_em28xx_hw_capture; - if (dev->alt == 0 && dev->adev->users == 0) { + if (dev->alt == 0 && dev->adev.users == 0) { int errCode; dev->alt = 7; errCode = usb_set_interface(dev->udev, 0, 7); dprintk("changing alternate number to 7\n"); } - dev->adev->users++; + dev->adev.users++; snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - dev->adev->capture_pcm_substream = substream; + dev->adev.capture_pcm_substream = substream; runtime->private_data = dev; return 0; @@ -358,7 +358,7 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) #endif { struct em28xx *dev = snd_pcm_substream_chip(substream); - dev->adev->users--; + dev->adev.users--; dprintk("closing device\n"); @@ -367,10 +367,10 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) em28xx_audio_analog_set(dev); mutex_unlock(&dev->lock); - if (dev->adev->users == 0 && dev->adev->shutdown == 1) { - dprintk("audio users: %d\n", dev->adev->users); + if (dev->adev.users == 0 && dev->adev.shutdown == 1) { + dprintk("audio users: %d\n", dev->adev.users); dprintk("disabling audio stream!\n"); - dev->adev->shutdown = 0; + dev->adev.shutdown = 0; dprintk("released lock\n"); em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); } @@ -412,7 +412,7 @@ static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) dprintk("Stop capture, if needed\n"); - if (dev->adev->capture_stream == STREAM_ON) + if (dev->adev.capture_stream == STREAM_ON) em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); return 0; @@ -443,7 +443,7 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1); return 0; case SNDRV_PCM_TRIGGER_STOP: - dev->adev->shutdown = 1; + dev->adev.shutdown = 1; return 0; default: return -EINVAL; @@ -462,7 +462,7 @@ static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream snd_pcm_uframes_t hwptr_done; dev = snd_pcm_substream_chip(substream); - hwptr_done = dev->adev->hwptr_done_capture; + hwptr_done = dev->adev.hwptr_done_capture; return hwptr_done; } @@ -498,7 +498,7 @@ static struct snd_pcm_ops snd_em28xx_pcm_capture = { static int em28xx_audio_init(struct em28xx *dev) { - struct em28xx_audio *adev; + struct em28xx_audio *adev = &dev->adev; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) snd_pcm_t *pcm; snd_card_t *card; @@ -521,16 +521,9 @@ static int em28xx_audio_init(struct em28xx *dev) printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " "Rechberger\n"); - adev = kzalloc(sizeof(*adev), GFP_KERNEL); - if (!adev) { - printk(KERN_ERR "em28xx-audio.c: out of memory\n"); - return -1; - } card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0); - if (card == NULL) { - kfree(adev); + if (card == NULL) return -ENOMEM; - } spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); @@ -554,7 +547,6 @@ static int em28xx_audio_init(struct em28xx *dev) } adev->sndcard = card; adev->udev = dev->udev; - dev->adev = adev; return 0; } @@ -571,10 +563,9 @@ static int em28xx_audio_fini(struct em28xx *dev) return 0; } - if (dev->adev) { - snd_card_free(dev->adev->sndcard); - kfree(dev->adev); - dev->adev = NULL; + if (dev->adev.sndcard) { + snd_card_free(dev->adev.sndcard); + dev->adev.sndcard = NULL; } return 0; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 1b3b75880..06fe92efc 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -482,7 +482,7 @@ struct em28xx { unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */ - struct em28xx_audio *adev; + struct em28xx_audio adev; /* states */ enum em28xx_dev_state state; -- cgit v1.2.3 From 29272bc7c66212bd5506a59d6b3ba429f5bdd01e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 15:11:23 -0200 Subject: Add missing S2 caps flag to S2API From: Klaus Schmidinger The attached patch adds a capability flag that allows an application to determine whether a particular device can handle "second generation modulation" transponders. This is necessary in order for applications to be able to decide which device to use for a given channel in a multi device environment, where DVB-S and DVB-S2 devices are mixed. It is assumed that a device capable of handling "second generation modulation" can implicitly handle "first generation modulation". The flag is not named anything with DVBS2 in order to allow its use with future DVBT2 devices as well (should they ever come). Signed-off by: Klaus Schmidinger Acked-By: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- linux/include/linux/dvb/frontend.h | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/include/linux/dvb/frontend.h b/linux/include/linux/dvb/frontend.h index b9feafa53..df9b58a19 100644 --- a/linux/include/linux/dvb/frontend.h +++ b/linux/include/linux/dvb/frontend.h @@ -63,6 +63,7 @@ typedef enum fe_caps { FE_CAN_8VSB = 0x200000, FE_CAN_16VSB = 0x400000, FE_HAS_EXTENDED_CAPS = 0x800000, // We need more bitspace for newer APIs, indicate this. + FE_CAN_2G_MODULATION = 0x10000000, // frontend supports "2nd generation modulation" (DVB-S2) FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending) FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output -- cgit v1.2.3 From b772fd296f5ed8df91b2f54f2309740b72a6f4ca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 15:13:56 -0200 Subject: Add FE_CAN_2G_MODULATION flag to frontends that support DVB-S2 From: Klaus Schmidinger Report to userspace that cx24116 and stv0899 drivers support DVB-S2. Signed-off by: Klaus Schmidinger Acked-By: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/cx24116.c | 1 + linux/drivers/media/dvb/frontends/stb0899_drv.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c index 6413c2c90..e2e7ff280 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.c +++ b/linux/drivers/media/dvb/frontends/cx24116.c @@ -1480,6 +1480,7 @@ static struct dvb_frontend_ops cx24116_ops = { FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_2G_MODULATION | FE_CAN_QPSK | FE_CAN_RECOVER }, diff --git a/linux/drivers/media/dvb/frontends/stb0899_drv.c b/linux/drivers/media/dvb/frontends/stb0899_drv.c index 63c547f31..079bb529b 100644 --- a/linux/drivers/media/dvb/frontends/stb0899_drv.c +++ b/linux/drivers/media/dvb/frontends/stb0899_drv.c @@ -1913,6 +1913,7 @@ static struct dvb_frontend_ops stb0899_ops = { .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | + FE_CAN_2G_MODULATION | FE_CAN_QPSK }, -- cgit v1.2.3 From 70e0ec035b78cab8338a5b20518bfc1d1307b7ad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Dec 2008 15:26:57 -0200 Subject: dvb frontend: stop using non-C99 compliant comments From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/include/linux/dvb/frontend.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/linux/include/linux/dvb/frontend.h b/linux/include/linux/dvb/frontend.h index df9b58a19..61a86e720 100644 --- a/linux/include/linux/dvb/frontend.h +++ b/linux/include/linux/dvb/frontend.h @@ -62,11 +62,11 @@ typedef enum fe_caps { FE_CAN_HIERARCHY_AUTO = 0x100000, FE_CAN_8VSB = 0x200000, FE_CAN_16VSB = 0x400000, - FE_HAS_EXTENDED_CAPS = 0x800000, // We need more bitspace for newer APIs, indicate this. - FE_CAN_2G_MODULATION = 0x10000000, // frontend supports "2nd generation modulation" (DVB-S2) - FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending) - FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically - FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output + FE_HAS_EXTENDED_CAPS = 0x800000, /* We need more bitspace for newer APIs, indicate this. */ + FE_CAN_2G_MODULATION = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */ + FE_NEEDS_BENDING = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */ + FE_CAN_RECOVER = 0x40000000, /* frontend can recover from a cable unplug automatically */ + FE_CAN_MUTE_TS = 0x80000000 /* frontend can stop spurious TS data output */ } fe_caps_t; @@ -122,15 +122,15 @@ typedef enum fe_sec_mini_cmd { typedef enum fe_status { - FE_HAS_SIGNAL = 0x01, /* found something above the noise level */ - FE_HAS_CARRIER = 0x02, /* found a DVB signal */ - FE_HAS_VITERBI = 0x04, /* FEC is stable */ - FE_HAS_SYNC = 0x08, /* found sync bytes */ - FE_HAS_LOCK = 0x10, /* everything's working... */ - FE_TIMEDOUT = 0x20, /* no lock within the last ~2 seconds */ - FE_REINIT = 0x40 /* frontend was reinitialized, */ -} fe_status_t; /* application is recommended to reset */ - /* DiSEqC, tone and parameters */ + FE_HAS_SIGNAL = 0x01, /* found something above the noise level */ + FE_HAS_CARRIER = 0x02, /* found a DVB signal */ + FE_HAS_VITERBI = 0x04, /* FEC is stable */ + FE_HAS_SYNC = 0x08, /* found sync bytes */ + FE_HAS_LOCK = 0x10, /* everything's working... */ + FE_TIMEDOUT = 0x20, /* no lock within the last ~2 seconds */ + FE_REINIT = 0x40 /* frontend was reinitialized, */ +} fe_status_t; /* application is recommended to reset */ + /* DiSEqC, tone and parameters */ typedef enum fe_spectral_inversion { INVERSION_OFF, -- cgit v1.2.3