From 8d64827172ae680d34d0611a1e865b546e6a5f08 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 23 Sep 2009 04:59:24 -0300 Subject: [PATCH 001/345] V4L/DVB (13040): V4L2: Add a v4l2-subdev (soc-camera) driver for OmniVision OV9640 sensor Signed-off-by: Marek Vasut Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 6 + drivers/media/video/Makefile | 1 + drivers/media/video/ov9640.c | 801 ++++++++++++++++++++++++++++++++ drivers/media/video/ov9640.h | 209 +++++++++ include/media/v4l2-chip-ident.h | 1 + 5 files changed, 1018 insertions(+) create mode 100644 drivers/media/video/ov9640.c create mode 100644 drivers/media/video/ov9640.h diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index e6186b338a12..c318676f2d29 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -865,6 +865,12 @@ config SOC_CAMERA_OV772X help This is a ov772x camera driver +config SOC_CAMERA_OV9640 + tristate "ov9640 camera support" + depends on SOC_CAMERA && I2C + help + This is a ov9640 camera driver + config MX1_VIDEO bool diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index e541932a789b..e706ceecef84 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -77,6 +77,7 @@ 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_OV9640) += ov9640.o obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o # And now the v4l2 drivers: diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c new file mode 100644 index 000000000000..c81ae2192887 --- /dev/null +++ b/drivers/media/video/ov9640.c @@ -0,0 +1,801 @@ +/* + * OmniVision OV96xx Camera Driver + * + * Copyright (C) 2009 Marek Vasut + * + * Based on ov772x camera driver: + * + * Copyright (C) 2008 Renesas Solutions Corp. + * Kuninori Morimoto + * + * Based on ov7670 and soc_camera_platform driver, + * + * 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 "ov9640.h" + +/* default register setup */ +static const struct ov9640_reg ov9640_regs_dflt[] = { + { OV9640_COM5, OV9640_COM5_SYSCLK | OV9640_COM5_LONGEXP }, + { OV9640_COM6, OV9640_COM6_OPT_BLC | OV9640_COM6_ADBLC_BIAS | + OV9640_COM6_FMT_RST | OV9640_COM6_ADBLC_OPTEN }, + { OV9640_PSHFT, OV9640_PSHFT_VAL(0x01) }, + { OV9640_ACOM, OV9640_ACOM_2X_ANALOG | OV9640_ACOM_RSVD }, + { OV9640_TSLB, OV9640_TSLB_YUYV_UYVY }, + { OV9640_COM16, OV9640_COM16_RB_AVG }, + + /* Gamma curve P */ + { 0x6c, 0x40 }, { 0x6d, 0x30 }, { 0x6e, 0x4b }, { 0x6f, 0x60 }, + { 0x70, 0x70 }, { 0x71, 0x70 }, { 0x72, 0x70 }, { 0x73, 0x70 }, + { 0x74, 0x60 }, { 0x75, 0x60 }, { 0x76, 0x50 }, { 0x77, 0x48 }, + { 0x78, 0x3a }, { 0x79, 0x2e }, { 0x7a, 0x28 }, { 0x7b, 0x22 }, + + /* Gamma curve T */ + { 0x7c, 0x04 }, { 0x7d, 0x07 }, { 0x7e, 0x10 }, { 0x7f, 0x28 }, + { 0x80, 0x36 }, { 0x81, 0x44 }, { 0x82, 0x52 }, { 0x83, 0x60 }, + { 0x84, 0x6c }, { 0x85, 0x78 }, { 0x86, 0x8c }, { 0x87, 0x9e }, + { 0x88, 0xbb }, { 0x89, 0xd2 }, { 0x8a, 0xe6 }, +}; + +/* Configurations + * NOTE: for YUV, alter the following registers: + * COM12 |= OV9640_COM12_YUV_AVG + * + * for RGB, alter the following registers: + * COM7 |= OV9640_COM7_RGB + * COM13 |= OV9640_COM13_RGB_AVG + * COM15 |= proper RGB color encoding mode + */ +static const struct ov9640_reg ov9640_regs_qqcif[] = { + { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x0f) }, + { OV9640_COM1, OV9640_COM1_QQFMT | OV9640_COM1_HREF_2SKIP }, + { OV9640_COM4, OV9640_COM4_QQ_VP | OV9640_COM4_RSVD }, + { OV9640_COM7, OV9640_COM7_QCIF }, + { OV9640_COM12, OV9640_COM12_RSVD }, + { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, + { OV9640_COM15, OV9640_COM15_OR_10F0 }, +}; + +static const struct ov9640_reg ov9640_regs_qqvga[] = { + { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x07) }, + { OV9640_COM1, OV9640_COM1_QQFMT | OV9640_COM1_HREF_2SKIP }, + { OV9640_COM4, OV9640_COM4_QQ_VP | OV9640_COM4_RSVD }, + { OV9640_COM7, OV9640_COM7_QVGA }, + { OV9640_COM12, OV9640_COM12_RSVD }, + { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, + { OV9640_COM15, OV9640_COM15_OR_10F0 }, +}; + +static const struct ov9640_reg ov9640_regs_qcif[] = { + { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x07) }, + { OV9640_COM4, OV9640_COM4_QQ_VP | OV9640_COM4_RSVD }, + { OV9640_COM7, OV9640_COM7_QCIF }, + { OV9640_COM12, OV9640_COM12_RSVD }, + { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, + { OV9640_COM15, OV9640_COM15_OR_10F0 }, +}; + +static const struct ov9640_reg ov9640_regs_qvga[] = { + { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x03) }, + { OV9640_COM4, OV9640_COM4_QQ_VP | OV9640_COM4_RSVD }, + { OV9640_COM7, OV9640_COM7_QVGA }, + { OV9640_COM12, OV9640_COM12_RSVD }, + { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, + { OV9640_COM15, OV9640_COM15_OR_10F0 }, +}; + +static const struct ov9640_reg ov9640_regs_cif[] = { + { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x03) }, + { OV9640_COM3, OV9640_COM3_VP }, + { OV9640_COM7, OV9640_COM7_CIF }, + { OV9640_COM12, OV9640_COM12_RSVD }, + { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, + { OV9640_COM15, OV9640_COM15_OR_10F0 }, +}; + +static const struct ov9640_reg ov9640_regs_vga[] = { + { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x01) }, + { OV9640_COM3, OV9640_COM3_VP }, + { OV9640_COM7, OV9640_COM7_VGA }, + { OV9640_COM12, OV9640_COM12_RSVD }, + { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, + { OV9640_COM15, OV9640_COM15_OR_10F0 }, +}; + +static const struct ov9640_reg ov9640_regs_sxga[] = { + { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x01) }, + { OV9640_COM3, OV9640_COM3_VP }, + { OV9640_COM7, 0 }, + { OV9640_COM12, OV9640_COM12_RSVD }, + { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, + { OV9640_COM15, OV9640_COM15_OR_10F0 }, +}; + +static const struct ov9640_reg ov9640_regs_yuv[] = { + { OV9640_MTX1, 0x58 }, + { OV9640_MTX2, 0x48 }, + { OV9640_MTX3, 0x10 }, + { OV9640_MTX4, 0x28 }, + { OV9640_MTX5, 0x48 }, + { OV9640_MTX6, 0x70 }, + { OV9640_MTX7, 0x40 }, + { OV9640_MTX8, 0x40 }, + { OV9640_MTX9, 0x40 }, + { OV9640_MTXS, 0x0f }, +}; + +static const struct ov9640_reg ov9640_regs_rgb[] = { + { OV9640_MTX1, 0x71 }, + { OV9640_MTX2, 0x3e }, + { OV9640_MTX3, 0x0c }, + { OV9640_MTX4, 0x33 }, + { OV9640_MTX5, 0x72 }, + { OV9640_MTX6, 0x00 }, + { OV9640_MTX7, 0x2b }, + { OV9640_MTX8, 0x66 }, + { OV9640_MTX9, 0xd2 }, + { OV9640_MTXS, 0x65 }, +}; + +/* + * TODO: this sensor also supports RGB555 and RGB565 formats, but support for + * them has not yet been sufficiently tested and so it is not included with + * this version of the driver. To test and debug these formats add two entries + * to the below array, see ov722x.c for an example. + */ +static const struct soc_camera_data_format ov9640_fmt_lists[] = { + { + .name = "UYVY", + .fourcc = V4L2_PIX_FMT_UYVY, + .depth = 16, + .colorspace = V4L2_COLORSPACE_JPEG, + }, +}; + +static const struct v4l2_queryctrl ov9640_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_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, +}; + +/* read a register */ +static int ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val) +{ + int ret; + u8 data = reg; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &data, + }; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) + goto err; + + msg.flags = I2C_M_RD; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) + goto err; + + *val = data; + return 0; + +err: + dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg); + return ret; +} + +/* write a register */ +static int ov9640_reg_write(struct i2c_client *client, u8 reg, u8 val) +{ + int ret; + u8 _val; + unsigned char data[2] = { reg, val }; + struct i2c_msg msg = { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = data, + }; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) { + dev_err(&client->dev, "Failed writing register 0x%02x!\n", reg); + return ret; + } + + /* we have to read the register back ... no idea why, maybe HW bug */ + ret = ov9640_reg_read(client, reg, &_val); + if (ret) + dev_err(&client->dev, + "Failed reading back register 0x%02x!\n", reg); + + return 0; +} + + +/* Read a register, alter its bits, write it back */ +static int ov9640_reg_rmw(struct i2c_client *client, u8 reg, u8 set, u8 unset) +{ + u8 val; + int ret; + + ret = ov9640_reg_read(client, reg, &val); + if (ret) { + dev_err(&client->dev, + "[Read]-Modify-Write of register %02x failed!\n", reg); + return val; + } + + val |= set; + val &= ~unset; + + ret = ov9640_reg_write(client, reg, val); + if (ret) + dev_err(&client->dev, + "Read-Modify-[Write] of register %02x failed!\n", reg); + + return ret; +} + +/* Soft reset the camera. This has nothing to do with the RESET pin! */ +static int ov9640_reset(struct i2c_client *client) +{ + int ret; + + ret = ov9640_reg_write(client, OV9640_COM7, OV9640_COM7_SCCB_RESET); + if (ret) + dev_err(&client->dev, + "An error occured while entering soft reset!\n"); + + return ret; +} + +/* Start/Stop streaming from the device */ +static int ov9640_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; +} + +/* Alter bus settings on camera side */ +static int ov9640_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) +{ + return 0; +} + +/* Request bus settings on camera side */ +static unsigned long ov9640_query_bus_param(struct soc_camera_device *icd) +{ + struct soc_camera_link *icl = to_soc_camera_link(icd); + + /* + * REVISIT: the camera probably can do 10 bit transfers, but I don't + * have those pins connected on my hardware. + */ + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; + + return soc_camera_apply_sensor_flags(icl, flags); +} + +/* Get status of additional camera capabilities */ +static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = sd->priv; + struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), + struct ov9640_priv, subdev); + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + ctrl->value = priv->flag_vflip; + break; + case V4L2_CID_HFLIP: + ctrl->value = priv->flag_hflip; + break; + } + return 0; +} + +/* Set status of additional camera capabilities */ +static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = sd->priv; + struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), + struct ov9640_priv, subdev); + + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + priv->flag_vflip = ctrl->value; + if (ctrl->value) + ret = ov9640_reg_rmw(client, OV9640_MVFP, + OV9640_MVFP_V, 0); + else + ret = ov9640_reg_rmw(client, OV9640_MVFP, + 0, OV9640_MVFP_V); + break; + case V4L2_CID_HFLIP: + priv->flag_hflip = ctrl->value; + if (ctrl->value) + ret = ov9640_reg_rmw(client, OV9640_MVFP, + OV9640_MVFP_H, 0); + else + ret = ov9640_reg_rmw(client, OV9640_MVFP, + 0, OV9640_MVFP_H); + break; + } + + return ret; +} + +/* Get chip identification */ +static int ov9640_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) +{ + struct i2c_client *client = sd->priv; + struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), + struct ov9640_priv, subdev); + + id->ident = priv->model; + id->revision = priv->revision; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ov9640_get_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = sd->priv; + int ret; + u8 val; + + if (reg->reg & ~0xff) + return -EINVAL; + + reg->size = 1; + + ret = ov9640_reg_read(client, reg->reg, &val); + if (ret) + return ret; + + reg->val = (__u64)val; + + return 0; +} + +static int ov9640_set_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = sd->priv; + + if (reg->reg & ~0xff || reg->val & ~0xff) + return -EINVAL; + + return ov9640_reg_write(client, reg->reg, reg->val); +} +#endif + +/* select nearest higher resolution for capture */ +static void ov9640_res_roundup(u32 *width, u32 *height) +{ + int i; + enum { QQCIF, QQVGA, QCIF, QVGA, CIF, VGA, SXGA }; + int res_x[] = { 88, 160, 176, 320, 352, 640, 1280 }; + int res_y[] = { 72, 120, 144, 240, 288, 480, 960 }; + + for (i = 0; i < ARRAY_SIZE(res_x); i++) { + if (res_x[i] >= *width && res_y[i] >= *height) { + *width = res_x[i]; + *height = res_y[i]; + return; + } + } + + *width = res_x[SXGA]; + *height = res_y[SXGA]; +} + +/* Prepare necessary register changes depending on color encoding */ +static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt) +{ + switch (pixfmt) { + case V4L2_PIX_FMT_UYVY: + alt->com12 = OV9640_COM12_YUV_AVG; + alt->com13 = OV9640_COM13_Y_DELAY_EN | + OV9640_COM13_YUV_DLY(0x01); + break; + case V4L2_PIX_FMT_RGB555: + alt->com7 = OV9640_COM7_RGB; + alt->com13 = OV9640_COM13_RGB_AVG; + alt->com15 = OV9640_COM15_RGB_555; + break; + case V4L2_PIX_FMT_RGB565: + alt->com7 = OV9640_COM7_RGB; + alt->com13 = OV9640_COM13_RGB_AVG; + alt->com15 = OV9640_COM15_RGB_565; + break; + }; +} + +/* Setup registers according to resolution and color encoding */ +static int ov9640_write_regs(struct i2c_client *client, + u32 width, u32 pixfmt, struct ov9640_reg_alt *alts) +{ + const struct ov9640_reg *ov9640_regs, *matrix_regs; + int ov9640_regs_len, matrix_regs_len; + int i, ret; + u8 val; + + /* select register configuration for given resolution */ + switch (width) { + case W_QQCIF: + ov9640_regs = ov9640_regs_qqcif; + ov9640_regs_len = ARRAY_SIZE(ov9640_regs_qqcif); + break; + case W_QQVGA: + ov9640_regs = ov9640_regs_qqvga; + ov9640_regs_len = ARRAY_SIZE(ov9640_regs_qqvga); + break; + case W_QCIF: + ov9640_regs = ov9640_regs_qcif; + ov9640_regs_len = ARRAY_SIZE(ov9640_regs_qcif); + break; + case W_QVGA: + ov9640_regs = ov9640_regs_qvga; + ov9640_regs_len = ARRAY_SIZE(ov9640_regs_qvga); + break; + case W_CIF: + ov9640_regs = ov9640_regs_cif; + ov9640_regs_len = ARRAY_SIZE(ov9640_regs_cif); + break; + case W_VGA: + ov9640_regs = ov9640_regs_vga; + ov9640_regs_len = ARRAY_SIZE(ov9640_regs_vga); + break; + case W_SXGA: + ov9640_regs = ov9640_regs_sxga; + ov9640_regs_len = ARRAY_SIZE(ov9640_regs_sxga); + break; + default: + dev_err(&client->dev, "Failed to select resolution!\n"); + return -EINVAL; + } + + /* select color matrix configuration for given color encoding */ + if (pixfmt == V4L2_PIX_FMT_UYVY) { + matrix_regs = ov9640_regs_yuv; + matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); + } else { + matrix_regs = ov9640_regs_rgb; + matrix_regs_len = ARRAY_SIZE(ov9640_regs_rgb); + } + + /* write register settings into the module */ + for (i = 0; i < ov9640_regs_len; i++) { + val = ov9640_regs[i].val; + + switch (ov9640_regs[i].reg) { + case OV9640_COM7: + val |= alts->com7; + break; + case OV9640_COM12: + val |= alts->com12; + break; + case OV9640_COM13: + val |= alts->com13; + break; + case OV9640_COM15: + val |= alts->com15; + break; + } + + ret = ov9640_reg_write(client, ov9640_regs[i].reg, val); + if (ret) + return ret; + } + + /* write color matrix configuration into the module */ + for (i = 0; i < matrix_regs_len; i++) { + ret = ov9640_reg_write(client, matrix_regs[i].reg, + matrix_regs[i].val); + if (ret) + return ret; + } + + return 0; +} + +/* program default register values */ +static int ov9640_prog_dflt(struct i2c_client *client) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(ov9640_regs_dflt); i++) { + ret = ov9640_reg_write(client, ov9640_regs_dflt[i].reg, + ov9640_regs_dflt[i].val); + if (ret) + return ret; + } + + /* wait for the changes to actually happen, 140ms are not enough yet */ + mdelay(150); + + return 0; +} + +/* set the format we will capture in */ +static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct ov9640_reg_alt alts = {0}; + int ret; + + ov9640_res_roundup(&pix->width, &pix->height); + ov9640_alter_regs(pix->pixelformat, &alts); + + ov9640_reset(client); + + ret = ov9640_prog_dflt(client); + if (ret) + return ret; + + return ov9640_write_regs(client, pix->width, pix->pixelformat, &alts); +} + +static int ov9640_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct v4l2_pix_format *pix = &f->fmt.pix; + + ov9640_res_roundup(&pix->width, &pix->height); + pix->field = V4L2_FIELD_NONE; + + return 0; +} + +static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + a->c.left = 0; + a->c.top = 0; + a->c.width = W_SXGA; + a->c.height = H_SXGA; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = W_SXGA; + a->bounds.height = H_SXGA; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + + + +static int ov9640_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) +{ + struct ov9640_priv *priv = i2c_get_clientdata(client); + u8 pid, ver, midh, midl; + const char *devname; + int ret = 0; + + /* + * 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) { + dev_err(&client->dev, "Parent missing or invalid!\n"); + ret = -ENODEV; + goto err; + } + + icd->formats = ov9640_fmt_lists; + icd->num_formats = ARRAY_SIZE(ov9640_fmt_lists); + + /* + * check and show product ID and manufacturer ID + */ + + ret = ov9640_reg_read(client, OV9640_PID, &pid); + if (ret) + goto err; + + ret = ov9640_reg_read(client, OV9640_VER, &ver); + if (ret) + goto err; + + ret = ov9640_reg_read(client, OV9640_MIDH, &midh); + if (ret) + goto err; + + ret = ov9640_reg_read(client, OV9640_MIDL, &midl); + if (ret) + goto err; + + switch (VERSION(pid, ver)) { + case OV9640_V2: + devname = "ov9640"; + priv->model = V4L2_IDENT_OV9640; + priv->revision = 2; + case OV9640_V3: + devname = "ov9640"; + priv->model = V4L2_IDENT_OV9640; + priv->revision = 3; + break; + default: + dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); + ret = -ENODEV; + goto err; + } + + dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", + devname, pid, ver, midh, midl); + +err: + return ret; +} + +static struct soc_camera_ops ov9640_ops = { + .set_bus_param = ov9640_set_bus_param, + .query_bus_param = ov9640_query_bus_param, + .controls = ov9640_controls, + .num_controls = ARRAY_SIZE(ov9640_controls), +}; + +static struct v4l2_subdev_core_ops ov9640_core_ops = { + .g_ctrl = ov9640_g_ctrl, + .s_ctrl = ov9640_s_ctrl, + .g_chip_ident = ov9640_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ov9640_get_register, + .s_register = ov9640_set_register, +#endif + +}; + +static struct v4l2_subdev_video_ops ov9640_video_ops = { + .s_stream = ov9640_s_stream, + .s_fmt = ov9640_s_fmt, + .try_fmt = ov9640_try_fmt, + .cropcap = ov9640_cropcap, + .g_crop = ov9640_g_crop, + +}; + +static struct v4l2_subdev_ops ov9640_subdev_ops = { + .core = &ov9640_core_ops, + .video = &ov9640_video_ops, +}; + +/* + * i2c_driver function + */ +static int ov9640_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct ov9640_priv *priv; + struct soc_camera_device *icd = client->dev.platform_data; + struct soc_camera_link *icl; + int ret; + + if (!icd) { + dev_err(&client->dev, "Missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); + if (!icl) { + dev_err(&client->dev, "Missing platform_data for driver\n"); + return -EINVAL; + } + + priv = kzalloc(sizeof(struct ov9640_priv), GFP_KERNEL); + if (!priv) { + dev_err(&client->dev, + "Failed to allocate memory for private data!\n"); + return -ENOMEM; + } + + v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops); + + icd->ops = &ov9640_ops; + + ret = ov9640_video_probe(icd, client); + + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(priv); + } + + return ret; +} + +static int ov9640_remove(struct i2c_client *client) +{ + struct ov9640_priv *priv = i2c_get_clientdata(client); + + i2c_set_clientdata(client, NULL); + kfree(priv); + return 0; +} + +static const struct i2c_device_id ov9640_id[] = { + { "ov9640", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ov9640_id); + +static struct i2c_driver ov9640_i2c_driver = { + .driver = { + .name = "ov9640", + }, + .probe = ov9640_probe, + .remove = ov9640_remove, + .id_table = ov9640_id, +}; + +static int __init ov9640_module_init(void) +{ + return i2c_add_driver(&ov9640_i2c_driver); +} + +static void __exit ov9640_module_exit(void) +{ + i2c_del_driver(&ov9640_i2c_driver); +} + +module_init(ov9640_module_init); +module_exit(ov9640_module_exit); + +MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx"); +MODULE_AUTHOR("Marek Vasut "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/video/ov9640.h b/drivers/media/video/ov9640.h new file mode 100644 index 000000000000..f8a51b70792e --- /dev/null +++ b/drivers/media/video/ov9640.h @@ -0,0 +1,209 @@ +/* + * OmniVision OV96xx Camera Header File + * + * Copyright (C) 2009 Marek Vasut + * + * 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 __DRIVERS_MEDIA_VIDEO_OV9640_H__ +#define __DRIVERS_MEDIA_VIDEO_OV9640_H__ + +/* Register definitions */ +#define OV9640_GAIN 0x00 +#define OV9640_BLUE 0x01 +#define OV9640_RED 0x02 +#define OV9640_VFER 0x03 +#define OV9640_COM1 0x04 +#define OV9640_BAVE 0x05 +#define OV9640_GEAVE 0x06 +#define OV9640_RSID 0x07 +#define OV9640_RAVE 0x08 +#define OV9640_COM2 0x09 +#define OV9640_PID 0x0a +#define OV9640_VER 0x0b +#define OV9640_COM3 0x0c +#define OV9640_COM4 0x0d +#define OV9640_COM5 0x0e +#define OV9640_COM6 0x0f +#define OV9640_AECH 0x10 +#define OV9640_CLKRC 0x11 +#define OV9640_COM7 0x12 +#define OV9640_COM8 0x13 +#define OV9640_COM9 0x14 +#define OV9640_COM10 0x15 +/* 0x16 - RESERVED */ +#define OV9640_HSTART 0x17 +#define OV9640_HSTOP 0x18 +#define OV9640_VSTART 0x19 +#define OV9640_VSTOP 0x1a +#define OV9640_PSHFT 0x1b +#define OV9640_MIDH 0x1c +#define OV9640_MIDL 0x1d +#define OV9640_MVFP 0x1e +#define OV9640_LAEC 0x1f +#define OV9640_BOS 0x20 +#define OV9640_GBOS 0x21 +#define OV9640_GROS 0x22 +#define OV9640_ROS 0x23 +#define OV9640_AEW 0x24 +#define OV9640_AEB 0x25 +#define OV9640_VPT 0x26 +#define OV9640_BBIAS 0x27 +#define OV9640_GBBIAS 0x28 +/* 0x29 - RESERVED */ +#define OV9640_EXHCH 0x2a +#define OV9640_EXHCL 0x2b +#define OV9640_RBIAS 0x2c +#define OV9640_ADVFL 0x2d +#define OV9640_ADVFH 0x2e +#define OV9640_YAVE 0x2f +#define OV9640_HSYST 0x30 +#define OV9640_HSYEN 0x31 +#define OV9640_HREF 0x32 +#define OV9640_CHLF 0x33 +#define OV9640_ARBLM 0x34 +/* 0x35..0x36 - RESERVED */ +#define OV9640_ADC 0x37 +#define OV9640_ACOM 0x38 +#define OV9640_OFON 0x39 +#define OV9640_TSLB 0x3a +#define OV9640_COM11 0x3b +#define OV9640_COM12 0x3c +#define OV9640_COM13 0x3d +#define OV9640_COM14 0x3e +#define OV9640_EDGE 0x3f +#define OV9640_COM15 0x40 +#define OV9640_COM16 0x41 +#define OV9640_COM17 0x42 +/* 0x43..0x4e - RESERVED */ +#define OV9640_MTX1 0x4f +#define OV9640_MTX2 0x50 +#define OV9640_MTX3 0x51 +#define OV9640_MTX4 0x52 +#define OV9640_MTX5 0x53 +#define OV9640_MTX6 0x54 +#define OV9640_MTX7 0x55 +#define OV9640_MTX8 0x56 +#define OV9640_MTX9 0x57 +#define OV9640_MTXS 0x58 +/* 0x59..0x61 - RESERVED */ +#define OV9640_LCC1 0x62 +#define OV9640_LCC2 0x63 +#define OV9640_LCC3 0x64 +#define OV9640_LCC4 0x65 +#define OV9640_LCC5 0x66 +#define OV9640_MANU 0x67 +#define OV9640_MANV 0x68 +#define OV9640_HV 0x69 +#define OV9640_MBD 0x6a +#define OV9640_DBLV 0x6b +#define OV9640_GSP 0x6c /* ... till 0x7b */ +#define OV9640_GST 0x7c /* ... till 0x8a */ + +#define OV9640_CLKRC_DPLL_EN 0x80 +#define OV9640_CLKRC_DIRECT 0x40 +#define OV9640_CLKRC_DIV(x) ((x) & 0x3f) + +#define OV9640_PSHFT_VAL(x) ((x) & 0xff) + +#define OV9640_ACOM_2X_ANALOG 0x80 +#define OV9640_ACOM_RSVD 0x12 + +#define OV9640_MVFP_V 0x10 +#define OV9640_MVFP_H 0x20 + +#define OV9640_COM1_HREF_NOSKIP 0x00 +#define OV9640_COM1_HREF_2SKIP 0x04 +#define OV9640_COM1_HREF_3SKIP 0x08 +#define OV9640_COM1_QQFMT 0x20 + +#define OV9640_COM2_SSM 0x10 + +#define OV9640_COM3_VP 0x04 + +#define OV9640_COM4_QQ_VP 0x80 +#define OV9640_COM4_RSVD 0x40 + +#define OV9640_COM5_SYSCLK 0x80 +#define OV9640_COM5_LONGEXP 0x01 + +#define OV9640_COM6_OPT_BLC 0x40 +#define OV9640_COM6_ADBLC_BIAS 0x08 +#define OV9640_COM6_FMT_RST 0x82 +#define OV9640_COM6_ADBLC_OPTEN 0x01 + +#define OV9640_COM7_RAW_RGB 0x01 +#define OV9640_COM7_RGB 0x04 +#define OV9640_COM7_QCIF 0x08 +#define OV9640_COM7_QVGA 0x10 +#define OV9640_COM7_CIF 0x20 +#define OV9640_COM7_VGA 0x40 +#define OV9640_COM7_SCCB_RESET 0x80 + +#define OV9640_TSLB_YVYU_YUYV 0x04 +#define OV9640_TSLB_YUYV_UYVY 0x08 + +#define OV9640_COM12_YUV_AVG 0x04 +#define OV9640_COM12_RSVD 0x40 + +#define OV9640_COM13_GAMMA_NONE 0x00 +#define OV9640_COM13_GAMMA_Y 0x40 +#define OV9640_COM13_GAMMA_RAW 0x80 +#define OV9640_COM13_RGB_AVG 0x20 +#define OV9640_COM13_MATRIX_EN 0x10 +#define OV9640_COM13_Y_DELAY_EN 0x08 +#define OV9640_COM13_YUV_DLY(x) ((x) & 0x07) + +#define OV9640_COM15_OR_00FF 0x00 +#define OV9640_COM15_OR_01FE 0x40 +#define OV9640_COM15_OR_10F0 0xc0 +#define OV9640_COM15_RGB_NORM 0x00 +#define OV9640_COM15_RGB_565 0x10 +#define OV9640_COM15_RGB_555 0x30 + +#define OV9640_COM16_RB_AVG 0x01 + +/* IDs */ +#define OV9640_V2 0x9648 +#define OV9640_V3 0x9649 +#define VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xFF)) + +/* supported resolutions */ +enum { + W_QQCIF = 88, + W_QQVGA = 160, + W_QCIF = 176, + W_QVGA = 320, + W_CIF = 352, + W_VGA = 640, + W_SXGA = 1280 +}; +#define H_SXGA 960 + +/* Misc. structures */ +struct ov9640_reg_alt { + u8 com7; + u8 com12; + u8 com13; + u8 com15; +}; + +struct ov9640_reg { + u8 reg; + u8 val; +}; + +struct ov9640_priv { + struct v4l2_subdev subdev; + + int model; + int revision; + + bool flag_vflip; + bool flag_hflip; +}; + +#endif /* __DRIVERS_MEDIA_VIDEO_OV9640_H__ */ diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index cf16689adba7..5ce56f90f315 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -64,6 +64,7 @@ enum { V4L2_IDENT_OV9650 = 254, V4L2_IDENT_OV9655 = 255, V4L2_IDENT_SOI968 = 256, + V4L2_IDENT_OV9640 = 257, /* module saa7146: reserved range 300-309 */ V4L2_IDENT_SAA7146 = 300, From aa15c0a347be6d5d16c557ed5b6b72345be48bdd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 26 Sep 2009 13:29:35 -0300 Subject: [PATCH 002/345] V4L/DVB (13042): Add NEC protocol to firmware v1.2 handler Currently, dvb_usb_dib0700_ir_proto is supported only with firmwares older than 1.2. Adds support for it also with the newer firmware. This is needed in order to support PixelView SBTVD IR. Cc: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 63 +++++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 6bd8951ea02b..81569deaa192 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -558,8 +558,7 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, struct dib0700_rc_response { u8 report_id; u8 data_state; - u8 system_msb; - u8 system_lsb; + u16 system; u8 data; u8 not_data; }; @@ -589,37 +588,51 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, return 0; } - if (actlen != sizeof(buf)) { - /* We didn't get back the 6 byte message we expected */ - err("Unexpected RC response size [%d]", actlen); - return -1; + printk("IR raw %2X %2X %2X %2X %2X %2X (len %d)\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], actlen); + + switch (dvb_usb_dib0700_ir_proto) { + case 0: + poll_reply.report_id = 0; + poll_reply.data_state = 1; + poll_reply.system = buf[2]; + poll_reply.data = buf[4]; + poll_reply.not_data = buf[5]; + + /* NEC protocol sends repeat code as 0 0 0 FF */ + if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00) + && (poll_reply.not_data == 0xff)) { + poll_reply.data_state = 2; + break; + } + break; + default: + if (actlen != sizeof(buf)) { + /* We didn't get back the 6 byte message we expected */ + err("Unexpected RC response size [%d]", actlen); + return -1; + } + + poll_reply.report_id = buf[0]; + poll_reply.data_state = buf[1]; + poll_reply.system = (buf[2] << 8) | buf[3]; + poll_reply.data = buf[4]; + poll_reply.not_data = buf[5]; + + break; } - poll_reply.report_id = buf[0]; - poll_reply.data_state = buf[1]; - poll_reply.system_msb = buf[2]; - poll_reply.system_lsb = buf[3]; - poll_reply.data = buf[4]; - poll_reply.not_data = buf[5]; - - /* - info("rid=%02x ds=%02x sm=%02x sl=%02x d=%02x nd=%02x\n", - poll_reply.report_id, poll_reply.data_state, - poll_reply.system_msb, poll_reply.system_lsb, - poll_reply.data, poll_reply.not_data); - */ - if ((poll_reply.data + poll_reply.not_data) != 0xff) { /* Key failed integrity check */ - err("key failed integrity check: %02x %02x %02x %02x", - poll_reply.system_msb, poll_reply.system_lsb, + err("key failed integrity check: %04x %02x %02x", + poll_reply.system, poll_reply.data, poll_reply.not_data); return -1; } + /* Find the key in the map */ for (i = 0; i < d->props.rc_key_map_size; i++) { - if (rc5_custom(&keymap[i]) == poll_reply.system_lsb && + if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) && rc5_data(&keymap[i]) == poll_reply.data) { *event = keymap[i].event; found = 1; @@ -628,8 +641,8 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, } if (found == 0) { - err("Unknown remote controller key: %02x %02x %02x %02x", - poll_reply.system_msb, poll_reply.system_lsb, + err("Unknown remote controller key: %04x %02x %02x", + poll_reply.system, poll_reply.data, poll_reply.not_data); d->last_event = 0; return 0; From 4c5128b30dc079d625bd109a94d5937d14f93ece Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 26 Sep 2009 13:31:31 -0300 Subject: [PATCH 003/345] V4L/DVB (13043): Add support for Pixelview SBTVD IR This IR uses NEC protocol. In order to use, dvb_usb_dib0700_ir_proto=0 should be used. Cc: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 81569deaa192..599e03bbb43f 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -887,6 +887,37 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { { 0x1d37, KEY_RECORD }, { 0x1d3b, KEY_GOTO }, { 0x1d3d, KEY_POWER }, + + /* Key codes for the Pixelview SBTVD remote (proto NEC) */ + { 0x8613, KEY_MUTE }, + { 0x8612, KEY_POWER }, + { 0x8601, KEY_1 }, + { 0x8602, KEY_2 }, + { 0x8603, KEY_3 }, + { 0x8604, KEY_4 }, + { 0x8605, KEY_5 }, + { 0x8606, KEY_6 }, + { 0x8607, KEY_7 }, + { 0x8608, KEY_8 }, + { 0x8609, KEY_9 }, + { 0x8600, KEY_0 }, + { 0x860d, KEY_CHANNELUP }, + { 0x8619, KEY_CHANNELDOWN }, + { 0x8610, KEY_VOLUMEUP }, + { 0x860c, KEY_VOLUMEDOWN }, + + { 0x860a, KEY_CAMERA }, + { 0x860b, KEY_ZOOM }, + { 0x861b, KEY_BACKSPACE }, + { 0x8615, KEY_ENTER }, + + { 0x861d, KEY_UP }, + { 0x861e, KEY_DOWN }, + { 0x860e, KEY_LEFT }, + { 0x860f, KEY_RIGHT }, + + { 0x8618, KEY_RECORD }, + { 0x861a, KEY_STOP }, }; /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ From 61b1e58f0e1b9dd0e6ab7199f19b93948af4baa1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 26 Sep 2009 13:45:03 -0300 Subject: [PATCH 004/345] V4L/DVB (13044): dib0700: Be less verbose when an IR key is pressed Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 599e03bbb43f..bf8e83187cba 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -588,7 +588,6 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, return 0; } - printk("IR raw %2X %2X %2X %2X %2X %2X (len %d)\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], actlen); switch (dvb_usb_dib0700_ir_proto) { case 0: From 8171c2059cc4b0507faf3a0e0fdf28cc83d8ac62 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 19 Sep 2009 08:37:40 -0300 Subject: [PATCH 005/345] V4L/DVB (13045): Fix debug messaging for stv0900 demod. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_core.c | 58 +++++++++++----------- drivers/media/dvb/frontends/stv0900_priv.h | 2 +- drivers/media/dvb/frontends/stv0900_sw.c | 31 ++++++------ 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 3bde3324a032..768a1611e8ce 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -34,7 +34,7 @@ #include "stv0900_priv.h" #include "stv0900_init.h" -static int stvdebug = 1; +int stvdebug = 1; module_param_named(debug, stvdebug, int, 0644); /* internal params node */ @@ -146,7 +146,7 @@ void stv0900_write_reg(struct stv0900_internal *i_params, u16 reg_addr, ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1); if (ret != 1) - dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret); + dprintk("%s: i2c error %d\n", __func__, ret); } u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg) @@ -170,7 +170,7 @@ u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg) ret = i2c_transfer(i_params->i2c_adap, msg, 2); if (ret != 2) - dprintk(KERN_ERR "%s: i2c error %d, reg[0x%02x]\n", + dprintk("%s: i2c error %d, reg[0x%02x]\n", __func__, ret, reg); return buf; @@ -281,7 +281,7 @@ u32 stv0900_get_mclk_freq(struct stv0900_internal *i_params, u32 ext_clk) mclk = (div + 1) * ext_clk / ad_div; - dprintk(KERN_INFO "%s: Calculated Mclk = %d\n", __func__, mclk); + dprintk("%s: Calculated Mclk = %d\n", __func__, mclk); return mclk; } @@ -291,7 +291,7 @@ enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *i_params, u32 mc enum fe_stv0900_error error = STV0900_NO_ERROR; u32 m_div, clk_sel; - dprintk(KERN_INFO "%s: Mclk set to %d, Quartz = %d\n", __func__, mclk, + dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk, i_params->quartz); if (i_params == NULL) @@ -381,7 +381,7 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, enum fe_stv0900_clock_type path2_ts) { - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); if (i_params->chip_id >= 0x20) { switch (path1_ts) { @@ -423,7 +423,7 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, case STV0900_DVBCI_CLOCK: stv0900_write_reg(i_params, R0900_TSGENERAL, 0x0A); - dprintk(KERN_INFO "%s: 0x0a\n", __func__); + dprintk("%s: 0x0a\n", __func__); break; } break; @@ -469,7 +469,7 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, case STV0900_DVBCI_CLOCK: stv0900_write_reg(i_params, R0900_TSGENERAL1X, 0x12); - dprintk(KERN_INFO "%s: 0x12\n", __func__); + dprintk("%s: 0x12\n", __func__); break; } @@ -584,7 +584,7 @@ static s32 stv0900_get_rf_level(struct stv0900_internal *i_params, i, rf_lvl = 0; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); if ((lookup != NULL) && lookup->size) { switch (demod) { @@ -622,7 +622,7 @@ static s32 stv0900_get_rf_level(struct stv0900_internal *i_params, } - dprintk(KERN_INFO "%s: RFLevel = %d\n", __func__, rf_lvl); + dprintk("%s: RFLevel = %d\n", __func__, rf_lvl); return rf_lvl; } @@ -654,7 +654,7 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, noise_field1, noise_field0; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); dmd_reg(lock_flag_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF); @@ -876,7 +876,7 @@ void stv0900_stop_all_s2_modcod(struct stv0900_internal *i_params, s32 regflist, i; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); dmd_reg(regflist, R0900_P1_MODCODLST0, R0900_P2_MODCODLST0); @@ -893,7 +893,7 @@ void stv0900_activate_s2_modcode(struct stv0900_internal *i_params, reg_index, field_index; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); if (i_params->chip_id <= 0x11) { msleep(5); @@ -979,7 +979,7 @@ void stv0900_activate_s2_modcode_single(struct stv0900_internal *i_params, { u32 reg_index; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); switch (demod) { case STV0900_DEMOD_1: @@ -1012,7 +1012,7 @@ static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe) static int stb0900_set_property(struct dvb_frontend *fe, struct dtv_property *tvp) { - dprintk(KERN_INFO "%s(..)\n", __func__); + dprintk("%s(..)\n", __func__); return 0; } @@ -1020,7 +1020,7 @@ static int stb0900_set_property(struct dvb_frontend *fe, static int stb0900_get_property(struct dvb_frontend *fe, struct dtv_property *tvp) { - dprintk(KERN_INFO "%s(..)\n", __func__); + dprintk("%s(..)\n", __func__); return 0; } @@ -1191,7 +1191,7 @@ u8 stv0900_get_optim_carr_loop(s32 srate, enum fe_stv0900_modcode modcode, s32 i; const struct stv0900_car_loop_optim *car_loop_s2; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); if (chip_id <= 0x12) car_loop_s2 = FE_STV0900_S2CarLoop; @@ -1294,7 +1294,7 @@ u8 stv0900_get_optim_short_carr_loop(s32 srate, enum fe_stv0900_modulation modul u8 aclc_value = 0x0b; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); switch (modulation) { case STV0900_QPSK: @@ -1351,7 +1351,7 @@ static enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *i_ { enum fe_stv0900_error error = STV0900_NO_ERROR; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); switch (LDPC_Mode) { case STV0900_DUAL: @@ -1398,12 +1398,12 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, struct stv0900_inode *temp_int = find_inode(state->i2c_adap, state->config->demod_address); - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); if (temp_int != NULL) { state->internal = temp_int->internal; (state->internal->dmds_used)++; - dprintk(KERN_INFO "%s: Find Internal Structure!\n", __func__); + dprintk("%s: Find Internal Structure!\n", __func__); return STV0900_NO_ERROR; } else { state->internal = kmalloc(sizeof(struct stv0900_internal), GFP_KERNEL); @@ -1413,7 +1413,7 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, state->internal->i2c_addr = state->config->demod_address; state->internal->clkmode = state->config->clkmode; state->internal->errs = STV0900_NO_ERROR; - dprintk(KERN_INFO "%s: Create New Internal Structure!\n", __func__); + dprintk("%s: Create New Internal Structure!\n", __func__); } if (state->internal != NULL) { @@ -1551,7 +1551,7 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, enum fe_stv0900_error error = STV0900_NO_ERROR; - dprintk(KERN_INFO "%s: ", __func__); + dprintk("%s: ", __func__); p_result.locked = FALSE; p_search.path = state->demod; @@ -1652,10 +1652,10 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, error = STV0900_BAD_PARAMETER; if ((p_result.locked == TRUE) && (error == STV0900_NO_ERROR)) { - dprintk(KERN_INFO "Search Success\n"); + dprintk("Search Success\n"); return DVBFE_ALGO_SEARCH_SUCCESS; } else { - dprintk(KERN_INFO "Search Fail\n"); + dprintk("Search Fail\n"); return DVBFE_ALGO_SEARCH_FAILED; } @@ -1723,7 +1723,7 @@ static int stv0900_diseqc_init(struct dvb_frontend *fe) static int stv0900_init(struct dvb_frontend *fe) { - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); stv0900_stop_ts(fe, 1); stv0900_diseqc_init(fe); @@ -1865,7 +1865,7 @@ static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) enum fe_stv0900_demod_num demod = state->demod; s32 mode_field, reset_field; - dprintk(KERN_INFO "%s: %s\n", __func__, ((tone == 0) ? "Off" : "On")); + dprintk("%s: %s\n", __func__, ((tone == 0) ? "Off" : "On")); dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); dmd_reg(reset_field, F0900_P1_DISEQC_RESET, F0900_P2_DISEQC_RESET); @@ -1889,11 +1889,11 @@ static void stv0900_release(struct dvb_frontend *fe) { struct stv0900_state *state = fe->demodulator_priv; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); if ((--(state->internal->dmds_used)) <= 0) { - dprintk(KERN_INFO "%s: Actually removing\n", __func__); + dprintk("%s: Actually removing\n", __func__); remove_inode(state->internal); kfree(state->internal); diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h index 5ed7a145c7d3..5f4414f8da20 100644 --- a/drivers/media/dvb/frontends/stv0900_priv.h +++ b/drivers/media/dvb/frontends/stv0900_priv.h @@ -60,7 +60,7 @@ } \ } while (0) -static int stvdebug; +extern int stvdebug; #define dprintk(args...) \ do { \ diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c index 962fde1437ce..8c83c8b306a6 100644 --- a/drivers/media/dvb/frontends/stv0900_sw.c +++ b/drivers/media/dvb/frontends/stv0900_sw.c @@ -527,7 +527,7 @@ static void stv0900_set_symbol_rate(struct stv0900_internal *i_params, s32 sfr_init_reg; u32 symb; - dprintk(KERN_INFO "%s: Mclk %d, SR %d, Dmd %d\n", __func__, mclk, + dprintk("%s: Mclk %d, SR %d, Dmd %d\n", __func__, mclk, srate, demod); dmd_reg(sfr_init_reg, R0900_P1_SFRINIT1, R0900_P2_SFRINIT1); @@ -952,7 +952,7 @@ static void stv0900_set_viterbi_tracq(struct stv0900_internal *i_params, s32 vth_reg; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); dmd_reg(vth_reg, R0900_P1_VTH12, R0900_P2_VTH12); @@ -973,7 +973,7 @@ static void stv0900_set_viterbi_standard(struct stv0900_internal *i_params, s32 fecmReg, prvitReg; - dprintk(KERN_INFO "%s: ViterbiStandard = ", __func__); + dprintk("%s: ViterbiStandard = ", __func__); switch (demod) { case STV0900_DEMOD_1: @@ -1055,7 +1055,7 @@ static void stv0900_track_optimization(struct dvb_frontend *fe) enum fe_stv0900_rolloff rolloff; enum fe_stv0900_modcode foundModcod; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); srate += stv0900_get_timing_offst(i_params, srate, demod); @@ -1370,7 +1370,7 @@ static int stv0900_get_fec_lock(struct stv0900_internal *i_params, enum fe_stv09 enum fe_stv0900_search_state dmd_state; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); dmd_reg(header_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); dmd_reg(pktdelin_field, F0900_P1_PKTDELIN_LOCK, F0900_P2_PKTDELIN_LOCK); @@ -1414,7 +1414,7 @@ static int stv0900_wait_for_lock(struct stv0900_internal *i_params, s32 timer = 0, lock = 0, str_merg_rst_fld, str_merg_lock_fld; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); dmd_reg(str_merg_rst_fld, F0900_P1_RST_HWARE, F0900_P2_RST_HWARE); dmd_reg(str_merg_lock_fld, F0900_P1_TSFIFO_LINEOK, F0900_P2_TSFIFO_LINEOK); @@ -1427,7 +1427,8 @@ static int stv0900_wait_for_lock(struct stv0900_internal *i_params, if (lock) { lock = 0; - dprintk(KERN_INFO "%s: Timer = %d, time_out = %d\n", __func__, timer, fec_timeout); + dprintk("%s: Timer = %d, time_out = %d\n", __func__, timer, + fec_timeout); while ((timer < fec_timeout) && (lock == 0)) { lock = stv0900_get_bits(i_params, str_merg_lock_fld); @@ -1437,9 +1438,9 @@ static int stv0900_wait_for_lock(struct stv0900_internal *i_params, } if (lock) - dprintk(KERN_INFO "%s: DEMOD LOCK OK\n", __func__); + dprintk("%s: DEMOD LOCK OK\n", __func__); else - dprintk(KERN_INFO "%s: DEMOD LOCK FAIL\n", __func__); + dprintk("%s: DEMOD LOCK FAIL\n", __func__); if (lock) return TRUE; @@ -1456,7 +1457,7 @@ enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, s32 state_field, dss_dvb_field; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); dmd_reg(state_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); dmd_reg(dss_dvb_field, F0900_P1_DSS_DVB, F0900_P2_DSS_DVB); @@ -1820,7 +1821,7 @@ static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *i_params, s32 i, j, nb_steps, direction; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); switch (demod) { case STV0900_DEMOD_1: @@ -2274,7 +2275,7 @@ static int stv0900_blind_search_algo(struct dvb_frontend *fe) u16 agc2_integr; u8 dstatus2; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); if (i_params->chip_id < 0x20) { k_ref_tmg_max = 233; @@ -2397,7 +2398,7 @@ static void stv0900_set_viterbi_acq(struct stv0900_internal *i_params, { s32 vth_reg; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); dmd_reg(vth_reg, R0900_P1_VTH12, R0900_P2_VTH12); @@ -2415,7 +2416,7 @@ static void stv0900_set_search_standard(struct stv0900_internal *i_params, int sstndrd; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); sstndrd = i_params->dmd1_srch_standard; if (demod == 1) @@ -2578,7 +2579,7 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) enum fe_stv0900_search_algo algo; int no_signal = FALSE; - dprintk(KERN_INFO "%s\n", __func__); + dprintk("%s\n", __func__); switch (demod) { case STV0900_DEMOD_1: From f8731f4ddedb78693ae05e40aac5c4817f740518 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Fri, 18 Sep 2009 04:08:43 -0300 Subject: [PATCH 006/345] V4L/DVB (13049): dib8000: SNR in 10th of dB dib7000p/dib8000: added pid filtering dib8000: the SNR is in 10th of dB (not in dB) dib7000p and dib8000: added the pid filtering. This feature is enabled by module option (dvb-usb module). Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 71 +++++++++++++++++++++ drivers/media/dvb/frontends/dib7000p.c | 18 ++++++ drivers/media/dvb/frontends/dib7000p.h | 13 ++++ drivers/media/dvb/frontends/dib8000.c | 21 +++++- drivers/media/dvb/frontends/dib8000.h | 14 ++++ 5 files changed, 136 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index bf8e83187cba..cda60291c06e 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1252,6 +1252,16 @@ static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) return 0; } +static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) +{ + return dib7000p_pid_filter(adapter->fe, index, pid, onoff); +} + +static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) +{ + return dib7000p_pid_filter_ctrl(adapter->fe, onoff); +} + static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { 60000, 15000, // internal, sampling 1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass @@ -1543,6 +1553,15 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) return 0; } +static int stk807x_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) +{ + return dib8000_pid_filter(adapter->fe, index, pid, onoff); +} + +static int stk807x_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) +{ + return dib8000_pid_filter_ctrl(adapter->fe, onoff); +} /* STK807x */ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap) @@ -1938,6 +1957,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7700p_frontend_attach, .tuner_attach = stk7700p_tuner_attach, @@ -2019,11 +2042,19 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 2, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7700d_frontend_attach, .tuner_attach = stk7700d_tuner_attach, DIB0700_DEFAULT_STREAMING_CONFIG(0x02), }, { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7700d_frontend_attach, .tuner_attach = stk7700d_tuner_attach, @@ -2066,6 +2097,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7700P2_frontend_attach, .tuner_attach = stk7700d_tuner_attach, @@ -2098,6 +2133,14 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7070p_frontend_attach, .tuner_attach = dib7070p_tuner_attach, @@ -2200,6 +2243,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 2, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7070pd_frontend_attach0, .tuner_attach = dib7070p_tuner_attach, @@ -2207,6 +2254,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .size_of_priv = sizeof(struct dib0700_adapter_state), }, { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7070pd_frontend_attach1, .tuner_attach = dib7070p_tuner_attach, @@ -2253,6 +2304,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7700ph_frontend_attach, .tuner_attach = stk7700ph_tuner_attach, @@ -2365,6 +2420,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7070p_frontend_attach, .tuner_attach = dib7770p_tuner_attach, @@ -2396,6 +2455,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk807x_pid_filter, + .pid_filter_ctrl = stk807x_pid_filter_ctrl, .frontend_attach = stk807x_frontend_attach, .tuner_attach = dib807x_tuner_attach, @@ -2427,6 +2490,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 2, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk807x_pid_filter, + .pid_filter_ctrl = stk807x_pid_filter_ctrl, .frontend_attach = stk807xpvr_frontend_attach0, .tuner_attach = dib807x_tuner_attach, @@ -2436,6 +2503,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { sizeof(struct dib0700_adapter_state), }, { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk807x_pid_filter, + .pid_filter_ctrl = stk807x_pid_filter_ctrl, .frontend_attach = stk807xpvr_frontend_attach1, .tuner_attach = dib807x_tuner_attach, diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 0781f94e05d2..60e1aaaec5b3 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -1302,6 +1302,24 @@ struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum di } EXPORT_SYMBOL(dib7000p_get_i2c_master); +int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) +{ + struct dib7000p_state *state = fe->demodulator_priv; + u16 val = dib7000p_read_word(state, 235) & 0xffef; + val |= (onoff & 0x1) << 4; + dprintk("PID filter enabled %d", onoff); + return dib7000p_write_word(state, 235, val); +} +EXPORT_SYMBOL(dib7000p_pid_filter_ctrl); + +int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) +{ + struct dib7000p_state *state = fe->demodulator_priv; + dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff); + return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0); +} +EXPORT_SYMBOL(dib7000p_pid_filter); + int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) { struct dib7000p_state st = { .i2c_adap = i2c }; diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 02a4c82f0c70..3a769df3c86f 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -51,6 +51,8 @@ extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); +extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); +extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff); #else static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, @@ -95,6 +97,17 @@ static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap) printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } +static inline int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} #endif #endif diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 852c790d09d9..44c2dc9b4f11 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -2121,7 +2121,7 @@ static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr) else result -= intlog10(2) * 10 * noise_exp - 100; - *snr = result / (1 << 24); + *snr = result / ((1 << 24) / 10); return 0; } @@ -2195,6 +2195,25 @@ struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000 EXPORT_SYMBOL(dib8000_get_i2c_master); +int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) +{ + struct dib8000_state *st = fe->demodulator_priv; + u16 val = dib8000_read_word(st, 299) & 0xffef; + val |= (onoff & 0x1) << 4; + + dprintk("pid filter enabled %d", onoff); + return dib8000_write_word(st, 299, val); +} +EXPORT_SYMBOL(dib8000_pid_filter_ctrl); + +int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) +{ + struct dib8000_state *st = fe->demodulator_priv; + dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); + return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0); +} +EXPORT_SYMBOL(dib8000_pid_filter); + static const struct dvb_frontend_ops dib8000_ops = { .info = { .name = "DiBcom 8000 ISDB-T", diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index a86de340dd54..8c89482b738a 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h @@ -44,6 +44,8 @@ extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); +extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff); +extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); #else static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) { @@ -74,6 +76,18 @@ int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } + +int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} #endif #endif From eac1fe1050f223d28ebe5bb73b438d82ffd5b675 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Wed, 23 Sep 2009 13:41:27 -0300 Subject: [PATCH 007/345] V4L/DVB (13051): DiB7000P: improve rebostness of HAS_LOCK indicator Update the dib7000p: The status is HAS_LOCK only if the demod is able to decode the TPS. Sometimes, there is a TPS data lock, even if the demod is not able to decode it (ex: no RF signal). For the STK7770P: correct value for the charge pump Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 1 + drivers/media/dvb/frontends/dib7000p.c | 15 ++++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index cda60291c06e..3b7e07749c3c 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1176,6 +1176,7 @@ static struct dib0070_config dib7770p_dib0070_config = { .clock_khz = 12000, .clock_pad_drive = 0, .flip_chip = 1, + .charge_pump = 2, }; static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 60e1aaaec5b3..750ae61a20f4 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -108,7 +108,7 @@ static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) outreg = 0; fifo_threshold = 1792; - smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1); + smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1); dprintk( "setting output mode for demod %p to %d", &state->demod, mode); @@ -162,18 +162,19 @@ static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff) if (state->div_force_off) { dprintk( "diversity combination deactivated - forced by COFDM parameters"); onoff = 0; - } + dib7000p_write_word(state, 207, 0); + } else + dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0)); + state->div_state = (u8)onoff; if (onoff) { dib7000p_write_word(state, 204, 6); dib7000p_write_word(state, 205, 16); /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ - dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0)); } else { dib7000p_write_word(state, 204, 1); dib7000p_write_word(state, 205, 0); - dib7000p_write_word(state, 207, 0); } return 0; @@ -1188,7 +1189,7 @@ static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat) *stat |= FE_HAS_VITERBI; if (lock & 0x0010) *stat |= FE_HAS_SYNC; - if (lock & 0x0008) + if ((lock & 0x0038) == 0x38) *stat |= FE_HAS_LOCK; return 0; @@ -1332,8 +1333,10 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau /* designated i2c address */ new_addr = (0x40 + k) << 1; st.i2c_addr = new_addr; + dib7000p_write_word(&st, 1287, 0x0003); /* sram lead in, rdy */ if (dib7000p_identify(&st) != 0) { st.i2c_addr = default_addr; + dib7000p_write_word(&st, 1287, 0x0003); /* sram lead in, rdy */ if (dib7000p_identify(&st) != 0) { dprintk("DiB7000P #%d: not identified\n", k); return -EIO; @@ -1390,6 +1393,8 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, demod->demodulator_priv = st; memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); + dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */ + if (dib7000p_identify(st) != 0) goto error; From 8a378e8543f044b3e54ddbbb03c349bf054fcedf Mon Sep 17 00:00:00 2001 From: S?rgio Fortier Date: Mon, 28 Sep 2009 04:19:21 -0300 Subject: [PATCH 008/345] V4L/DVB (13052): DiB0700: EvolutePC TvWay+ USB ISDB-Tb fullseg device support Patch for EvolutePC TvWay+ USB ISDB-Tb fullseg device support. Signed-off-by: S?rgio C Fortier Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 3b7e07749c3c..1ec1a4cb0472 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1924,6 +1924,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, + { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -2470,7 +2471,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 2, + .num_device_descs = 3, .devices = { { "DiBcom STK807xP reference design", { &dib0700_usb_id_table[62], NULL }, @@ -2480,6 +2481,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[63], NULL }, { NULL }, }, + { "EvolutePC TVWay+", + { &dib0700_usb_id_table[64], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index a548c14c1944..e852eac8cb5e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -61,6 +61,7 @@ #define USB_VID_XTENSIONS 0x1ae7 #define USB_VID_HUMAX_COEX 0x10b9 #define USB_VID_774 0x7a69 +#define USB_VID_EVOLUTEPC 0x1e59 /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 @@ -276,5 +277,6 @@ #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 #define USB_PID_FRIIO_WHITE 0x0001 +#define USB_PID_TVWAY_PLUS 0x0002 #endif From 486ba12b7ae1edd5549494ae1cbfaa4794d1af5a Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 18 Sep 2009 13:37:57 -0300 Subject: [PATCH 009/345] V4L/DVB (13054): af9015: add USB ID for KWorld PlusTV DVB-T PCI Pro Card (DVB-T PC160-T) Add USB ID 1b80:c161 for KWorld PlusTV DVB-T PCI Pro Card (DVB-T PC160-T). Thanks to Andrew Cruickshank for reporting this. Cc: Andrew Cruickshank Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 9 ++++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index cf042b309b46..ac21c1a8075e 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1283,6 +1283,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, /* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1554,7 +1555,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 4, /* max 9 */ + .num_device_descs = 5, /* max 9 */ .devices = { { .name = "AverMedia AVerTV Volar GPS 805 (A805)", @@ -1577,6 +1578,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[24], NULL}, .warm_ids = {NULL}, }, + { + .name = "KWorld PlusTV DVB-T PCI Pro Card " \ + "(DVB-T PC160-T)", + .cold_ids = {&af9015_usb_table[26], NULL}, + .warm_ids = {NULL}, + }, } }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index e852eac8cb5e..128fca63df95 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -116,6 +116,7 @@ #define USB_PID_KWORLD_395U_3 0xe395 #define USB_PID_KWORLD_MC810 0xc810 #define USB_PID_KWORLD_PC160_2T 0xc160 +#define USB_PID_KWORLD_PC160_T 0xc161 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_WARM 0x17df #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 From 0254294f378cd4c50de550ce0a32c70aba668f17 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 16 Sep 2009 20:33:03 -0300 Subject: [PATCH 010/345] V4L/DVB (13055): af9015: fix few typos Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index ac21c1a8075e..7a885264e86b 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1297,7 +1297,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .firmware = "dvb-usb-af9015.fw", .no_reconnect = 1, - .size_of_priv = sizeof(struct af9015_state), \ + .size_of_priv = sizeof(struct af9015_state), .num_adapters = 2, .adapter = { @@ -1403,7 +1403,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .firmware = "dvb-usb-af9015.fw", .no_reconnect = 1, - .size_of_priv = sizeof(struct af9015_state), \ + .size_of_priv = sizeof(struct af9015_state), .num_adapters = 2, .adapter = { @@ -1509,7 +1509,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .firmware = "dvb-usb-af9015.fw", .no_reconnect = 1, - .size_of_priv = sizeof(struct af9015_state), \ + .size_of_priv = sizeof(struct af9015_state), .num_adapters = 2, .adapter = { From 641342dde7f9cbfcc6b9f6c890c90f99edcae6ca Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 21 Sep 2009 18:56:12 -0300 Subject: [PATCH 011/345] V4L/DVB (13056): af9015: add LeadTek Y04G0051 remote buttons Add missing LeadTek Y04G0051 remote buttons. Thanks to Matthew Skinner Cc: Matthew Skinner Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.h | 143 ++++++++++++++++++----------- 1 file changed, 88 insertions(+), 55 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index c41f30e4a1b8..c1e2b7d1d412 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -119,6 +119,7 @@ enum af9015_remote { /* 5 */ AF9015_REMOTE_AVERMEDIA_KS, }; +/* LeadTek - Y04G0051 */ /* Leadtek WinFast DTV Dongle Gold */ static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = { { 0x001e, KEY_1 }, @@ -131,64 +132,96 @@ static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = { { 0x0025, KEY_8 }, { 0x0026, KEY_9 }, { 0x0027, KEY_0 }, - { 0x0028, KEY_ENTER }, - { 0x004f, KEY_VOLUMEUP }, - { 0x0050, KEY_VOLUMEDOWN }, - { 0x0051, KEY_CHANNELDOWN }, - { 0x0052, KEY_CHANNELUP }, + { 0x0028, KEY_OK }, + { 0x004f, KEY_RIGHT }, + { 0x0050, KEY_LEFT }, + { 0x0051, KEY_DOWN }, + { 0x0052, KEY_UP }, + { 0x011a, KEY_POWER2 }, + { 0x04b4, KEY_TV }, + { 0x04b3, KEY_RED }, + { 0x04b2, KEY_GREEN }, + { 0x04b1, KEY_YELLOW }, + { 0x04b0, KEY_BLUE }, + { 0x003d, KEY_TEXT }, + { 0x0113, KEY_SLEEP }, + { 0x0010, KEY_MUTE }, + { 0x0105, KEY_ESC }, + { 0x0009, KEY_SCREEN }, + { 0x010f, KEY_MENU }, + { 0x003f, KEY_CHANNEL }, + { 0x0013, KEY_REWIND }, + { 0x0012, KEY_PLAY }, + { 0x0011, KEY_FASTFORWARD }, + { 0x0005, KEY_PREVIOUS }, + { 0x0029, KEY_STOP }, + { 0x002b, KEY_NEXT }, + { 0x0041, KEY_EPG }, + { 0x0019, KEY_VIDEO }, + { 0x0016, KEY_AUDIO }, + { 0x0037, KEY_DOT }, + { 0x002a, KEY_AGAIN }, + { 0x002c, KEY_CAMERA }, + { 0x003c, KEY_NEW }, + { 0x0115, KEY_RECORD }, + { 0x010b, KEY_TIME }, + { 0x0043, KEY_VOLUMEUP }, + { 0x0042, KEY_VOLUMEDOWN }, + { 0x004b, KEY_CHANNELUP }, + { 0x004e, KEY_CHANNELDOWN }, }; static u8 af9015_ir_table_leadtek[] = { - 0x03, 0xfc, 0x00, 0xff, 0x1a, 0x01, 0x00, - 0x03, 0xfc, 0x56, 0xa9, 0x00, 0x00, 0x00, - 0x03, 0xfc, 0x4b, 0xb4, 0x00, 0x00, 0x00, - 0x03, 0xfc, 0x4c, 0xb3, 0xb2, 0x04, 0x00, - 0x03, 0xfc, 0x4d, 0xb2, 0x00, 0x00, 0x00, - 0x03, 0xfc, 0x4e, 0xb1, 0x00, 0x00, 0x00, - 0x03, 0xfc, 0x1f, 0xe0, 0x3d, 0x00, 0x00, - 0x03, 0xfc, 0x40, 0xbf, 0x13, 0x01, 0x00, - 0x03, 0xfc, 0x14, 0xeb, 0x10, 0x00, 0x00, - 0x03, 0xfc, 0x49, 0xb6, 0x05, 0x01, 0x00, - 0x03, 0xfc, 0x50, 0xaf, 0x29, 0x00, 0x00, - 0x03, 0xfc, 0x0c, 0xf3, 0x52, 0x00, 0x00, - 0x03, 0xfc, 0x03, 0xfc, 0x09, 0x00, 0x00, - 0x03, 0xfc, 0x08, 0xf7, 0x50, 0x00, 0x00, - 0x03, 0xfc, 0x13, 0xec, 0x28, 0x00, 0x00, - 0x03, 0xfc, 0x04, 0xfb, 0x4f, 0x00, 0x00, - 0x03, 0xfc, 0x4f, 0xb0, 0x0f, 0x01, 0x00, - 0x03, 0xfc, 0x10, 0xef, 0x51, 0x00, 0x00, - 0x03, 0xfc, 0x51, 0xae, 0x3f, 0x00, 0x00, - 0x03, 0xfc, 0x42, 0xbd, 0x13, 0x00, 0x00, - 0x03, 0xfc, 0x43, 0xbc, 0x00, 0x00, 0x00, - 0x03, 0xfc, 0x44, 0xbb, 0x11, 0x00, 0x00, - 0x03, 0xfc, 0x52, 0xad, 0x19, 0x00, 0x00, - 0x03, 0xfc, 0x54, 0xab, 0x05, 0x00, 0x00, - 0x03, 0xfc, 0x46, 0xb9, 0x29, 0x00, 0x00, - 0x03, 0xfc, 0x55, 0xaa, 0x2b, 0x00, 0x00, - 0x03, 0xfc, 0x53, 0xac, 0x41, 0x00, 0x00, - 0x03, 0xfc, 0x05, 0xfa, 0x1e, 0x00, 0x00, - 0x03, 0xfc, 0x06, 0xf9, 0x1f, 0x00, 0x00, - 0x03, 0xfc, 0x07, 0xf8, 0x20, 0x00, 0x00, - 0x03, 0xfc, 0x1e, 0xe1, 0x19, 0x00, 0x00, - 0x03, 0xfc, 0x09, 0xf6, 0x21, 0x00, 0x00, - 0x03, 0xfc, 0x0a, 0xf5, 0x22, 0x00, 0x00, - 0x03, 0xfc, 0x0b, 0xf4, 0x23, 0x00, 0x00, - 0x03, 0xfc, 0x1b, 0xe4, 0x16, 0x00, 0x00, - 0x03, 0xfc, 0x0d, 0xf2, 0x24, 0x00, 0x00, - 0x03, 0xfc, 0x0e, 0xf1, 0x25, 0x00, 0x00, - 0x03, 0xfc, 0x0f, 0xf0, 0x26, 0x00, 0x00, - 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, - 0x03, 0xfc, 0x41, 0xbe, 0x37, 0x00, 0x00, - 0x03, 0xfc, 0x12, 0xed, 0x27, 0x00, 0x00, - 0x03, 0xfc, 0x11, 0xee, 0x2a, 0x00, 0x00, - 0x03, 0xfc, 0x48, 0xb7, 0x2c, 0x00, 0x00, - 0x03, 0xfc, 0x4a, 0xb5, 0x3c, 0x00, 0x00, - 0x03, 0xfc, 0x47, 0xb8, 0x15, 0x01, 0x00, - 0x03, 0xfc, 0x45, 0xba, 0x0b, 0x01, 0x00, - 0x03, 0xfc, 0x5e, 0xa1, 0x43, 0x00, 0x00, - 0x03, 0xfc, 0x5a, 0xa5, 0x42, 0x00, 0x00, - 0x03, 0xfc, 0x5b, 0xa4, 0x4b, 0x00, 0x00, - 0x03, 0xfc, 0x5f, 0xa0, 0x4e, 0x00, 0x00, + 0x03, 0xfc, 0x00, 0xff, 0x1a, 0x01, 0x00, /* KEY_POWER2 */ + 0x03, 0xfc, 0x56, 0xa9, 0xb4, 0x04, 0x00, /* KEY_TV */ + 0x03, 0xfc, 0x4b, 0xb4, 0xb3, 0x04, 0x00, /* KEY_RED */ + 0x03, 0xfc, 0x4c, 0xb3, 0xb2, 0x04, 0x00, /* KEY_GREEN */ + 0x03, 0xfc, 0x4d, 0xb2, 0xb1, 0x04, 0x00, /* KEY_YELLOW */ + 0x03, 0xfc, 0x4e, 0xb1, 0xb0, 0x04, 0x00, /* KEY_BLUE */ + 0x03, 0xfc, 0x1f, 0xe0, 0x3d, 0x00, 0x00, /* KEY_TEXT */ + 0x03, 0xfc, 0x40, 0xbf, 0x13, 0x01, 0x00, /* KEY_SLEEP */ + 0x03, 0xfc, 0x14, 0xeb, 0x10, 0x00, 0x00, /* KEY_MUTE */ + 0x03, 0xfc, 0x49, 0xb6, 0x05, 0x01, 0x00, /* KEY_ESC */ + 0x03, 0xfc, 0x50, 0xaf, 0x29, 0x00, 0x00, /* KEY_STOP (1)*/ + 0x03, 0xfc, 0x0c, 0xf3, 0x52, 0x00, 0x00, /* KEY_UP */ + 0x03, 0xfc, 0x03, 0xfc, 0x09, 0x00, 0x00, /* KEY_SCREEN */ + 0x03, 0xfc, 0x08, 0xf7, 0x50, 0x00, 0x00, /* KEY_LEFT */ + 0x03, 0xfc, 0x13, 0xec, 0x28, 0x00, 0x00, /* KEY_OK (1) */ + 0x03, 0xfc, 0x04, 0xfb, 0x4f, 0x00, 0x00, /* KEY_RIGHT */ + 0x03, 0xfc, 0x4f, 0xb0, 0x0f, 0x01, 0x00, /* KEY_MENU */ + 0x03, 0xfc, 0x10, 0xef, 0x51, 0x00, 0x00, /* KEY_DOWN */ + 0x03, 0xfc, 0x51, 0xae, 0x3f, 0x00, 0x00, /* KEY_CHANNEL */ + 0x03, 0xfc, 0x42, 0xbd, 0x13, 0x00, 0x00, /* KEY_REWIND */ + 0x03, 0xfc, 0x43, 0xbc, 0x12, 0x00, 0x00, /* KEY_PLAY */ + 0x03, 0xfc, 0x44, 0xbb, 0x11, 0x00, 0x00, /* KEY_FASTFORWARD */ + 0x03, 0xfc, 0x52, 0xad, 0x19, 0x00, 0x00, /* KEY_VIDEO (1) */ + 0x03, 0xfc, 0x54, 0xab, 0x05, 0x00, 0x00, /* KEY_PREVIOUS */ + 0x03, 0xfc, 0x46, 0xb9, 0x29, 0x00, 0x00, /* KEY_STOP (2) */ + 0x03, 0xfc, 0x55, 0xaa, 0x2b, 0x00, 0x00, /* KEY_NEXT */ + 0x03, 0xfc, 0x53, 0xac, 0x41, 0x00, 0x00, /* KEY_EPG */ + 0x03, 0xfc, 0x05, 0xfa, 0x1e, 0x00, 0x00, /* KEY_1 */ + 0x03, 0xfc, 0x06, 0xf9, 0x1f, 0x00, 0x00, /* KEY_2 */ + 0x03, 0xfc, 0x07, 0xf8, 0x20, 0x00, 0x00, /* KEY_3 */ + 0x03, 0xfc, 0x1e, 0xe1, 0x19, 0x00, 0x00, /* KEY_VIDEO (2) */ + 0x03, 0xfc, 0x09, 0xf6, 0x21, 0x00, 0x00, /* KEY_4 */ + 0x03, 0xfc, 0x0a, 0xf5, 0x22, 0x00, 0x00, /* KEY_5 */ + 0x03, 0xfc, 0x0b, 0xf4, 0x23, 0x00, 0x00, /* KEY_6 */ + 0x03, 0xfc, 0x1b, 0xe4, 0x16, 0x00, 0x00, /* KEY_AUDIO */ + 0x03, 0xfc, 0x0d, 0xf2, 0x24, 0x00, 0x00, /* KEY_7 */ + 0x03, 0xfc, 0x0e, 0xf1, 0x25, 0x00, 0x00, /* KEY_8 */ + 0x03, 0xfc, 0x0f, 0xf0, 0x26, 0x00, 0x00, /* KEY_9 */ + 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, /* KEY_OK (2) */ + 0x03, 0xfc, 0x41, 0xbe, 0x37, 0x00, 0x00, /* KEY_DOT */ + 0x03, 0xfc, 0x12, 0xed, 0x27, 0x00, 0x00, /* KEY_0 */ + 0x03, 0xfc, 0x11, 0xee, 0x2a, 0x00, 0x00, /* KEY_AGAIN */ + 0x03, 0xfc, 0x48, 0xb7, 0x2c, 0x00, 0x00, /* KEY_CAMERA */ + 0x03, 0xfc, 0x4a, 0xb5, 0x3c, 0x00, 0x00, /* KEY_NEW */ + 0x03, 0xfc, 0x47, 0xb8, 0x15, 0x01, 0x00, /* KEY_RECORD */ + 0x03, 0xfc, 0x45, 0xba, 0x0b, 0x01, 0x00, /* KEY_TIME */ + 0x03, 0xfc, 0x5e, 0xa1, 0x43, 0x00, 0x00, /* KEY_VOLUMEUP */ + 0x03, 0xfc, 0x5a, 0xa5, 0x42, 0x00, 0x00, /* KEY_VOLUMEDOWN */ + 0x03, 0xfc, 0x5b, 0xa4, 0x4b, 0x00, 0x00, /* KEY_CHANNELUP */ + 0x03, 0xfc, 0x5f, 0xa0, 0x4e, 0x00, 0x00, /* KEY_CHANNELDOWN */ }; /* TwinHan AzureWave AD-TU700(704J) */ From e1a7ff84a4c26893ffca19c1c35d008caa89bfde Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 21 Sep 2009 20:52:44 -0300 Subject: [PATCH 012/345] V4L/DVB (13057): af9015: add MSI DIGIVOX mini III remote Support for MSI DIGIVOX mini III remote. Thanks to Aleksandr V. Piskunov Thanks to Roman Cc: Aleksandr V. Piskunov Cc: Roman Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 10 +++++ drivers/media/dvb/dvb-usb/af9015.h | 71 ++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 7a885264e86b..5c898b07ae1e 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -868,6 +868,16 @@ static int af9015_read_config(struct usb_device *udev) af9015_config.ir_table_size = ARRAY_SIZE(af9015_ir_table_avermedia); break; + case USB_VID_MSI_2: + af9015_properties[i].rc_key_map = + af9015_rc_keys_msi_digivox_iii; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii); + af9015_config.ir_table = + af9015_ir_table_msi_digivox_iii; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_msi_digivox_iii); + break; } } } diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index c1e2b7d1d412..e237c4a0702d 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -779,4 +779,75 @@ static u8 af9015_ir_table_trekstor[] = { 0x00, 0xff, 0x84, 0x7b, 0x27, 0x07, 0x00, }; +/* MSI DIGIVOX mini III */ +static struct dvb_usb_rc_key af9015_rc_keys_msi_digivox_iii[] = { + { 0x0713, KEY_POWER }, /* [red power button] */ + { 0x073b, KEY_VIDEO }, /* Source */ + { 0x073e, KEY_ZOOM }, /* Zoom */ + { 0x070b, KEY_POWER2 }, /* ShutDown */ + { 0x071e, KEY_1 }, + { 0x071f, KEY_2 }, + { 0x0720, KEY_3 }, + { 0x0721, KEY_4 }, + { 0x0722, KEY_5 }, + { 0x0723, KEY_6 }, + { 0x0724, KEY_7 }, + { 0x0725, KEY_8 }, + { 0x0726, KEY_9 }, + { 0x0727, KEY_0 }, + { 0x0752, KEY_CHANNELUP }, /* CH+ */ + { 0x0751, KEY_CHANNELDOWN }, /* CH- */ + { 0x0750, KEY_VOLUMEUP }, /* Vol+ */ + { 0x074f, KEY_VOLUMEDOWN }, /* Vol- */ + { 0x0705, KEY_ESC }, /* [back up arrow] */ + { 0x0708, KEY_OK }, /* [enter arrow] */ + { 0x073f, KEY_RECORD }, /* Rec */ + { 0x0716, KEY_STOP }, /* Stop */ + { 0x072a, KEY_PLAY }, /* Play */ + { 0x073c, KEY_MUTE }, /* Mute */ + { 0x0718, KEY_UP }, + { 0x0707, KEY_DOWN }, + { 0x070f, KEY_LEFT }, + { 0x0715, KEY_RIGHT }, + { 0x0736, KEY_RED }, + { 0x0737, KEY_GREEN }, + { 0x072d, KEY_YELLOW }, + { 0x072e, KEY_BLUE }, +}; + +static u8 af9015_ir_table_msi_digivox_iii[] = { + 0x61, 0xd6, 0x43, 0xbc, 0x13, 0x07, 0x00, /* KEY_POWER */ + 0x61, 0xd6, 0x01, 0xfe, 0x3b, 0x07, 0x00, /* KEY_VIDEO */ + 0x61, 0xd6, 0x0b, 0xf4, 0x3e, 0x07, 0x00, /* KEY_ZOOM */ + 0x61, 0xd6, 0x03, 0xfc, 0x0b, 0x07, 0x00, /* KEY_POWER2 */ + 0x61, 0xd6, 0x04, 0xfb, 0x1e, 0x07, 0x00, /* KEY_1 */ + 0x61, 0xd6, 0x08, 0xf7, 0x1f, 0x07, 0x00, /* KEY_2 */ + 0x61, 0xd6, 0x02, 0xfd, 0x20, 0x07, 0x00, /* KEY_3 */ + 0x61, 0xd6, 0x0f, 0xf0, 0x21, 0x07, 0x00, /* KEY_4 */ + 0x61, 0xd6, 0x05, 0xfa, 0x22, 0x07, 0x00, /* KEY_5 */ + 0x61, 0xd6, 0x06, 0xf9, 0x23, 0x07, 0x00, /* KEY_6 */ + 0x61, 0xd6, 0x0c, 0xf3, 0x24, 0x07, 0x00, /* KEY_7 */ + 0x61, 0xd6, 0x0d, 0xf2, 0x25, 0x07, 0x00, /* KEY_8 */ + 0x61, 0xd6, 0x0a, 0xf5, 0x26, 0x07, 0x00, /* KEY_9 */ + 0x61, 0xd6, 0x11, 0xee, 0x27, 0x07, 0x00, /* KEY_0 */ + 0x61, 0xd6, 0x09, 0xf6, 0x52, 0x07, 0x00, /* KEY_CHANNELUP */ + 0x61, 0xd6, 0x07, 0xf8, 0x51, 0x07, 0x00, /* KEY_CHANNELDOWN */ + 0x61, 0xd6, 0x0e, 0xf1, 0x50, 0x07, 0x00, /* KEY_VOLUMEUP */ + 0x61, 0xd6, 0x13, 0xec, 0x4f, 0x07, 0x00, /* KEY_VOLUMEDOWN */ + 0x61, 0xd6, 0x10, 0xef, 0x05, 0x07, 0x00, /* KEY_ESC */ + 0x61, 0xd6, 0x12, 0xed, 0x08, 0x07, 0x00, /* KEY_OK */ + 0x61, 0xd6, 0x14, 0xeb, 0x3f, 0x07, 0x00, /* KEY_RECORD */ + 0x61, 0xd6, 0x15, 0xea, 0x16, 0x07, 0x00, /* KEY_STOP */ + 0x61, 0xd6, 0x16, 0xe9, 0x2a, 0x07, 0x00, /* KEY_PLAY */ + 0x61, 0xd6, 0x17, 0xe8, 0x3c, 0x07, 0x00, /* KEY_MUTE */ + 0x61, 0xd6, 0x18, 0xe7, 0x18, 0x07, 0x00, /* KEY_UP */ + 0x61, 0xd6, 0x19, 0xe6, 0x07, 0x07, 0x00, /* KEY_DOWN */ + 0x61, 0xd6, 0x1a, 0xe5, 0x0f, 0x07, 0x00, /* KEY_LEFT */ + 0x61, 0xd6, 0x1b, 0xe4, 0x15, 0x07, 0x00, /* KEY_RIGHT */ + 0x61, 0xd6, 0x1c, 0xe3, 0x36, 0x07, 0x00, /* KEY_RED */ + 0x61, 0xd6, 0x1d, 0xe2, 0x37, 0x07, 0x00, /* KEY_GREEN */ + 0x61, 0xd6, 0x1e, 0xe1, 0x2d, 0x07, 0x00, /* KEY_YELLOW */ + 0x61, 0xd6, 0x1f, 0xe0, 0x2e, 0x07, 0x00, /* KEY_BLUE */ +}; + #endif From 0f017212567793ecedf86f709f43ca40f9b84655 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 21 Sep 2009 21:26:37 -0300 Subject: [PATCH 013/345] V4L/DVB (13058): af9015: enable remote polling when eeprom contains 0x04 Looks like eeprom IR mode byte value 0x04 means there is remote which should be polled. Patch enables polling also in case of 0x04. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 2 +- drivers/media/dvb/dvb-usb/af9015.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 5c898b07ae1e..bad3e10f3724 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -730,7 +730,7 @@ static int af9015_read_config(struct usb_device *udev) goto error; deb_info("%s: IR mode:%d\n", __func__, val); for (i = 0; i < af9015_properties_count; i++) { - if (val == AF9015_IR_MODE_DISABLED || val == 0x04) { + if (val == AF9015_IR_MODE_DISABLED) { af9015_properties[i].rc_key_map = NULL; af9015_properties[i].rc_key_map_size = 0; } else if (dvb_usb_af9015_remote) { diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index e237c4a0702d..931c8515830d 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -95,6 +95,7 @@ enum af9015_ir_mode { AF9015_IR_MODE_HID, AF9015_IR_MODE_RLC, AF9015_IR_MODE_RC6, + AF9015_IR_MODE_POLLING, /* just guess */ }; struct af9015_state { From 4aebc2893eada9e054a37df8bb342a53f8ca0d2a Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 22 Sep 2009 21:22:19 -0300 Subject: [PATCH 014/345] V4L/DVB (13060): radio-mr800: implement proper locking Implement proper locking Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 187 +++++++++++++++++------------- 1 file changed, 109 insertions(+), 78 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index a1239083472d..75c69755a04c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -168,11 +168,7 @@ static int amradio_set_mute(struct amradio_device *radio, char argument) int retval; int size; - /* safety check */ - if (radio->removed) - return -EIO; - - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); radio->buffer[0] = 0x00; radio->buffer[1] = 0x55; @@ -186,15 +182,11 @@ static int amradio_set_mute(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) { - mutex_unlock(&radio->lock); + if (retval < 0 || size != BUFFER_LENGTH) return retval; - } radio->muted = argument; - mutex_unlock(&radio->lock); - return retval; } @@ -205,11 +197,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) int size; unsigned short freq_send = 0x10 + (freq >> 3) / 25; - /* safety check */ - if (radio->removed) - return -EIO; - - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); radio->buffer[0] = 0x00; radio->buffer[1] = 0x55; @@ -223,10 +211,8 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) { - mutex_unlock(&radio->lock); + if (retval < 0 || size != BUFFER_LENGTH) return retval; - } /* frequency is calculated from freq_send and placed in first 2 bytes */ radio->buffer[0] = (freq_send >> 8) & 0xff; @@ -240,13 +226,6 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) { - mutex_unlock(&radio->lock); - return retval; - } - - mutex_unlock(&radio->lock); - return retval; } @@ -255,11 +234,7 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) int retval; int size; - /* safety check */ - if (radio->removed) - return -EIO; - - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); radio->buffer[0] = 0x00; radio->buffer[1] = 0x55; @@ -275,14 +250,11 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) if (retval < 0 || size != BUFFER_LENGTH) { radio->stereo = -1; - mutex_unlock(&radio->lock); return retval; } radio->stereo = 1; - mutex_unlock(&radio->lock); - return retval; } @@ -325,12 +297,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct amradio_device *radio = video_get_drvdata(video_devdata(file)); int retval; - /* safety check */ - if (radio->removed) - return -EIO; + mutex_lock(&radio->lock); - if (v->index > 0) - return -EINVAL; + /* safety check */ + if (radio->removed) { + retval = -EIO; + goto unlock; + } + + if (v->index > 0) { + retval = -EINVAL; + goto unlock; + } /* TODO: Add function which look is signal stereo or not * amradio_getstat(radio); @@ -357,7 +335,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->audmode = V4L2_TUNER_MODE_MONO; v->signal = 0xffff; /* Can't get the signal strength, sad.. */ v->afc = 0; /* Don't know what is this */ - return 0; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_s_tuner - set tuner attributes */ @@ -367,12 +348,18 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct amradio_device *radio = video_get_drvdata(video_devdata(file)); int retval; - /* safety check */ - if (radio->removed) - return -EIO; + mutex_lock(&radio->lock); - if (v->index > 0) - return -EINVAL; + /* safety check */ + if (radio->removed) { + retval = -EIO; + goto unlock; + } + + if (v->index > 0) { + retval = -EINVAL; + goto unlock; + } /* mono/stereo selector */ switch (v->audmode) { @@ -389,10 +376,12 @@ static int vidioc_s_tuner(struct file *file, void *priv, "set stereo failed\n"); break; default: - return -EINVAL; + retval = -EINVAL; } - return 0; +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_s_frequency - set tuner radio frequency */ @@ -402,19 +391,24 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct amradio_device *radio = video_get_drvdata(video_devdata(file)); int retval; - /* safety check */ - if (radio->removed) - return -EIO; - mutex_lock(&radio->lock); + + /* safety check */ + if (radio->removed) { + retval = -EIO; + goto unlock; + } + radio->curfreq = f->frequency; - mutex_unlock(&radio->lock); retval = amradio_setfreq(radio, radio->curfreq); if (retval < 0) amradio_dev_warn(&radio->videodev->dev, "set frequency failed\n"); - return 0; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_g_frequency - get tuner radio frequency */ @@ -422,14 +416,22 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval = 0; + + mutex_lock(&radio->lock); /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; - return 0; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_queryctrl - enumerate control items */ @@ -449,17 +451,26 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval = -EINVAL; + + mutex_lock(&radio->lock); /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = radio->muted; - return 0; + retval = 0; + break; } - return -EINVAL; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_s_ctrl - set the value of a control */ @@ -467,11 +478,15 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); - int retval; + int retval = -EINVAL; + + mutex_lock(&radio->lock); /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -480,19 +495,20 @@ static int vidioc_s_ctrl(struct file *file, void *priv, if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "amradio_stop failed\n"); - return -1; } } else { retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "amradio_start failed\n"); - return -1; } } - return 0; + break; } - return -EINVAL; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_g_audio - get audio attributes */ @@ -535,9 +551,14 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) static int usb_amradio_open(struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); - int retval; + int retval = 0; - lock_kernel(); + mutex_lock(&radio->lock); + + if (radio->removed) { + retval = -EIO; + goto unlock; + } radio->users = 1; radio->muted = 1; @@ -547,8 +568,7 @@ static int usb_amradio_open(struct file *file) amradio_dev_warn(&radio->videodev->dev, "radio did not start up properly\n"); radio->users = 0; - unlock_kernel(); - return -EIO; + goto unlock; } retval = amradio_set_stereo(radio, WANT_STEREO); @@ -561,22 +581,25 @@ static int usb_amradio_open(struct file *file) amradio_dev_warn(&radio->videodev->dev, "set frequency failed\n"); - unlock_kernel(); - return 0; +unlock: + mutex_unlock(&radio->lock); + return retval; } /*close device */ static int usb_amradio_close(struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); - int retval; - - if (!radio) - return -ENODEV; + int retval = 0; mutex_lock(&radio->lock); + + if (radio->removed) { + retval = -EIO; + goto unlock; + } + radio->users = 0; - mutex_unlock(&radio->lock); if (!radio->removed) { retval = amradio_set_mute(radio, AMRADIO_STOP); @@ -585,7 +608,9 @@ static int usb_amradio_close(struct file *file) "amradio_stop failed\n"); } - return 0; +unlock: + mutex_unlock(&radio->lock); + return retval; } /* Suspend device - stop device. Need to be checked and fixed */ @@ -594,12 +619,15 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) struct amradio_device *radio = usb_get_intfdata(intf); int retval; + mutex_lock(&radio->lock); + retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) dev_warn(&intf->dev, "amradio_stop failed\n"); dev_info(&intf->dev, "going into suspend..\n"); + mutex_unlock(&radio->lock); return 0; } @@ -609,12 +637,15 @@ static int usb_amradio_resume(struct usb_interface *intf) struct amradio_device *radio = usb_get_intfdata(intf); int retval; + mutex_lock(&radio->lock); + retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) dev_warn(&intf->dev, "amradio_start failed\n"); dev_info(&intf->dev, "coming out of suspend..\n"); + mutex_unlock(&radio->lock); return 0; } From 7a7d92e061ed13052d306cadad6972d52acea931 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 22 Sep 2009 21:37:30 -0300 Subject: [PATCH 015/345] V4L/DVB (13061): radio-mr800: simplify video_device allocation simplify video_device allocation Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 53 ++++++++++++------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 75c69755a04c..dd36ba0baab3 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -129,7 +129,7 @@ static int usb_amradio_resume(struct usb_interface *intf); struct amradio_device { /* reference to USB and video device */ struct usb_device *usbdev; - struct video_device *videodev; + struct video_device videodev; struct v4l2_device v4l2_dev; unsigned char *buffer; @@ -272,7 +272,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf) mutex_unlock(&radio->lock); usb_set_intfdata(intf, NULL); - video_unregister_device(radio->videodev); + video_unregister_device(&radio->videodev); v4l2_device_disconnect(&radio->v4l2_dev); } @@ -320,7 +320,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, */ retval = amradio_set_stereo(radio, WANT_STEREO); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); strcpy(v->name, "FM"); @@ -366,13 +366,13 @@ static int vidioc_s_tuner(struct file *file, void *priv, case V4L2_TUNER_MODE_MONO: retval = amradio_set_stereo(radio, WANT_MONO); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set mono failed\n"); break; case V4L2_TUNER_MODE_STEREO: retval = amradio_set_stereo(radio, WANT_STEREO); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); break; default: @@ -403,7 +403,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, retval = amradio_setfreq(radio, radio->curfreq); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n"); unlock: @@ -493,13 +493,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv, if (ctrl->value) { retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) { - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "amradio_stop failed\n"); } } else { retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) { - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "amradio_start failed\n"); } } @@ -565,7 +565,7 @@ static int usb_amradio_open(struct file *file) retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) { - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "radio did not start up properly\n"); radio->users = 0; goto unlock; @@ -573,12 +573,12 @@ static int usb_amradio_open(struct file *file) retval = amradio_set_stereo(radio, WANT_STEREO); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); retval = amradio_setfreq(radio, radio->curfreq); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n"); unlock: @@ -604,7 +604,7 @@ static int usb_amradio_close(struct file *file) if (!radio->removed) { retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "amradio_stop failed\n"); } @@ -676,9 +676,6 @@ static void usb_amradio_video_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); - v4l2_device_unregister(&radio->v4l2_dev); /* free rest memory */ @@ -718,20 +715,12 @@ static int usb_amradio_probe(struct usb_interface *intf, return retval; } - radio->videodev = video_device_alloc(); - - if (!radio->videodev) { - dev_err(&intf->dev, "video_device_alloc failed\n"); - kfree(radio->buffer); - kfree(radio); - return -ENOMEM; - } - - strlcpy(radio->videodev->name, v4l2_dev->name, sizeof(radio->videodev->name)); - radio->videodev->v4l2_dev = v4l2_dev; - radio->videodev->fops = &usb_amradio_fops; - radio->videodev->ioctl_ops = &usb_amradio_ioctl_ops; - radio->videodev->release = usb_amradio_video_device_release; + strlcpy(radio->videodev.name, v4l2_dev->name, + sizeof(radio->videodev.name)); + radio->videodev.v4l2_dev = v4l2_dev; + radio->videodev.fops = &usb_amradio_fops; + radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; + radio->videodev.release = usb_amradio_video_device_release; radio->removed = 0; radio->users = 0; @@ -741,12 +730,12 @@ static int usb_amradio_probe(struct usb_interface *intf, mutex_init(&radio->lock); - video_set_drvdata(radio->videodev, radio); + video_set_drvdata(&radio->videodev, radio); - retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); + retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, + radio_nr); if (retval < 0) { dev_err(&intf->dev, "could not register video device\n"); - video_device_release(radio->videodev); v4l2_device_unregister(v4l2_dev); kfree(radio->buffer); kfree(radio); From 1b8bbb3c0a719f3baac22ea4a7eb1d636383ba3b Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 22 Sep 2009 21:43:19 -0300 Subject: [PATCH 016/345] V4L/DVB (13062): radio-mr800: simplify error paths in usb probe callback Simplify error paths in usb probe callback. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index dd36ba0baab3..0c5d734b00fa 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -689,30 +689,29 @@ static int usb_amradio_probe(struct usb_interface *intf, { struct amradio_device *radio; struct v4l2_device *v4l2_dev; - int retval; + int retval = 0; radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL); if (!radio) { dev_err(&intf->dev, "kmalloc for amradio_device failed\n"); - return -ENOMEM; + retval = -ENOMEM; + goto err; } radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); if (!radio->buffer) { dev_err(&intf->dev, "kmalloc for radio->buffer failed\n"); - kfree(radio); - return -ENOMEM; + retval = -ENOMEM; + goto err_nobuf; } v4l2_dev = &radio->v4l2_dev; retval = v4l2_device_register(&intf->dev, v4l2_dev); if (retval < 0) { dev_err(&intf->dev, "couldn't register v4l2_device\n"); - kfree(radio->buffer); - kfree(radio); - return retval; + goto err_v4l2; } strlcpy(radio->videodev.name, v4l2_dev->name, @@ -736,14 +735,20 @@ static int usb_amradio_probe(struct usb_interface *intf, radio_nr); if (retval < 0) { dev_err(&intf->dev, "could not register video device\n"); - v4l2_device_unregister(v4l2_dev); - kfree(radio->buffer); - kfree(radio); - return -EIO; + goto err_vdev; } usb_set_intfdata(intf, radio); return 0; + +err_vdev: + v4l2_device_unregister(v4l2_dev); +err_v4l2: + kfree(radio->buffer); +err_nobuf: + kfree(radio); +err: + return retval; } static int __init amradio_init(void) From d1939e4c5f053e34dd432b448e221f55586a68ec Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 22 Sep 2009 21:48:43 -0300 Subject: [PATCH 017/345] V4L/DVB (13063): radio-mr800: remove unnecessary local variable Remove unnecessary local variable. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0c5d734b00fa..24c55a5a6cac 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -688,7 +688,6 @@ static int usb_amradio_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct amradio_device *radio; - struct v4l2_device *v4l2_dev; int retval = 0; radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL); @@ -707,16 +706,15 @@ static int usb_amradio_probe(struct usb_interface *intf, goto err_nobuf; } - v4l2_dev = &radio->v4l2_dev; - retval = v4l2_device_register(&intf->dev, v4l2_dev); + retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); if (retval < 0) { dev_err(&intf->dev, "couldn't register v4l2_device\n"); goto err_v4l2; } - strlcpy(radio->videodev.name, v4l2_dev->name, + strlcpy(radio->videodev.name, radio->v4l2_dev.name, sizeof(radio->videodev.name)); - radio->videodev.v4l2_dev = v4l2_dev; + radio->videodev.v4l2_dev = &radio->v4l2_dev; radio->videodev.fops = &usb_amradio_fops; radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; radio->videodev.release = usb_amradio_video_device_release; @@ -742,7 +740,7 @@ static int usb_amradio_probe(struct usb_interface *intf, return 0; err_vdev: - v4l2_device_unregister(v4l2_dev); + v4l2_device_unregister(&radio->v4l2_dev); err_v4l2: kfree(radio->buffer); err_nobuf: From ceb99e1b5a093ae8f439fc55aac28d007145c8ec Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 17:45:31 -0300 Subject: [PATCH 018/345] V4L/DVB (13064): radio-mr800: simplify access to amradio_device Simplify access to amradio_device. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 24c55a5a6cac..5401952004bc 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -141,6 +141,8 @@ struct amradio_device { int muted; }; +#define vdev_to_amradio(r) container_of(r, struct amradio_device, videodev) + /* USB Device ID List */ static struct usb_device_id usb_amradio_device_table[] = { {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT, @@ -280,7 +282,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - struct amradio_device *radio = video_drvdata(file); + struct amradio_device *radio = file->private_data; strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); @@ -294,7 +296,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval; mutex_lock(&radio->lock); @@ -345,7 +347,7 @@ 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 amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval; mutex_lock(&radio->lock); @@ -388,7 +390,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval; mutex_lock(&radio->lock); @@ -415,7 +417,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval = 0; mutex_lock(&radio->lock); @@ -450,7 +452,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval = -EINVAL; mutex_lock(&radio->lock); @@ -477,7 +479,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval = -EINVAL; mutex_lock(&radio->lock); @@ -550,7 +552,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 file *file) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = vdev_to_amradio(video_devdata(file)); int retval = 0; mutex_lock(&radio->lock); @@ -560,6 +562,7 @@ static int usb_amradio_open(struct file *file) goto unlock; } + file->private_data = radio; radio->users = 1; radio->muted = 1; @@ -589,7 +592,7 @@ static int usb_amradio_open(struct file *file) /*close device */ static int usb_amradio_close(struct file *file) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval = 0; mutex_lock(&radio->lock); @@ -674,7 +677,7 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { static void usb_amradio_video_device_release(struct video_device *videodev) { - struct amradio_device *radio = video_get_drvdata(videodev); + struct amradio_device *radio = vdev_to_amradio(videodev); v4l2_device_unregister(&radio->v4l2_dev); From eac000a90e70b990c7d847ac40ff1c33a5f00636 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 17:49:36 -0300 Subject: [PATCH 019/345] V4L/DVB (13065): radio-mr800: simplify locking in ioctl callbacks Simplify locking in ioctl callbacks. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 109 ++++++++---------------------- 1 file changed, 30 insertions(+), 79 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 5401952004bc..0498c4c60d8c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -299,18 +299,8 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct amradio_device *radio = file->private_data; int retval; - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } - - if (v->index > 0) { - retval = -EINVAL; - goto unlock; - } + if (v->index > 0) + return -EINVAL; /* TODO: Add function which look is signal stereo or not * amradio_getstat(radio); @@ -338,8 +328,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->signal = 0xffff; /* Can't get the signal strength, sad.. */ v->afc = 0; /* Don't know what is this */ -unlock: - mutex_unlock(&radio->lock); return retval; } @@ -348,20 +336,10 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct amradio_device *radio = file->private_data; - int retval; + int retval = -EINVAL; - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } - - if (v->index > 0) { - retval = -EINVAL; - goto unlock; - } + if (v->index > 0) + return -EINVAL; /* mono/stereo selector */ switch (v->audmode) { @@ -377,12 +355,8 @@ static int vidioc_s_tuner(struct file *file, void *priv, amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); break; - default: - retval = -EINVAL; } -unlock: - mutex_unlock(&radio->lock); return retval; } @@ -391,15 +365,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = file->private_data; - int retval; - - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } + int retval = 0; radio->curfreq = f->frequency; @@ -408,8 +374,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n"); -unlock: - mutex_unlock(&radio->lock); return retval; } @@ -418,22 +382,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = file->private_data; - int retval = 0; - - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; -unlock: - mutex_unlock(&radio->lock); - return retval; + return 0; } /* vidioc_queryctrl - enumerate control items */ @@ -453,26 +406,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct amradio_device *radio = file->private_data; - int retval = -EINVAL; - - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = radio->muted; - retval = 0; - break; + return 0; } -unlock: - mutex_unlock(&radio->lock); - return retval; + return -EINVAL; } /* vidioc_s_ctrl - set the value of a control */ @@ -482,14 +423,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct amradio_device *radio = file->private_data; int retval = -EINVAL; - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } - switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { @@ -508,8 +441,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, break; } -unlock: - mutex_unlock(&radio->lock); return retval; } @@ -616,6 +547,26 @@ static int usb_amradio_close(struct file *file) return retval; } +static long usb_amradio_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct amradio_device *radio = file->private_data; + long retval = 0; + + mutex_lock(&radio->lock); + + if (radio->removed) { + retval = -EIO; + goto unlock; + } + + retval = video_ioctl2(file, cmd, arg); + +unlock: + mutex_unlock(&radio->lock); + return retval; +} + /* Suspend device - stop device. Need to be checked and fixed */ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) { @@ -657,7 +608,7 @@ static const struct v4l2_file_operations usb_amradio_fops = { .owner = THIS_MODULE, .open = usb_amradio_open, .release = usb_amradio_close, - .ioctl = video_ioctl2, + .ioctl = usb_amradio_ioctl, }; static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { From 26452bfef4ae4798b96281ad8d3aed6e2d79846e Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 17:52:17 -0300 Subject: [PATCH 020/345] V4L/DVB (13066): radio-mr800: remove device removed indicator Remove device removed indicator Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0498c4c60d8c..c4f4cd8dbb6c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -137,7 +137,6 @@ struct amradio_device { int curfreq; int stereo; int users; - int removed; int muted; }; @@ -270,7 +269,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf) struct amradio_device *radio = usb_get_intfdata(intf); mutex_lock(&radio->lock); - radio->removed = 1; + radio->usbdev = NULL; mutex_unlock(&radio->lock); usb_set_intfdata(intf, NULL); @@ -488,7 +487,7 @@ static int usb_amradio_open(struct file *file) mutex_lock(&radio->lock); - if (radio->removed) { + if (!radio->usbdev) { retval = -EIO; goto unlock; } @@ -528,19 +527,17 @@ static int usb_amradio_close(struct file *file) mutex_lock(&radio->lock); - if (radio->removed) { + if (!radio->usbdev) { retval = -EIO; goto unlock; } radio->users = 0; - if (!radio->removed) { - retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "amradio_stop failed\n"); - } + retval = amradio_set_mute(radio, AMRADIO_STOP); + if (retval < 0) + amradio_dev_warn(&radio->videodev.dev, + "amradio_stop failed\n"); unlock: mutex_unlock(&radio->lock); @@ -555,7 +552,7 @@ static long usb_amradio_ioctl(struct file *file, unsigned int cmd, mutex_lock(&radio->lock); - if (radio->removed) { + if (!radio->usbdev) { retval = -EIO; goto unlock; } @@ -673,7 +670,6 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; radio->videodev.release = usb_amradio_video_device_release; - radio->removed = 0; radio->users = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = 95.16 * FREQ_MUL; From 4e3616576e9e65d53f9381b9f334257299c7262e Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:03:52 -0300 Subject: [PATCH 021/345] V4L/DVB (13067): radio-mr800: fix potential use after free Fix portential use after free. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index c4f4cd8dbb6c..dbae50ba250c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -273,8 +273,8 @@ static void usb_amradio_disconnect(struct usb_interface *intf) mutex_unlock(&radio->lock); usb_set_intfdata(intf, NULL); - video_unregister_device(&radio->videodev); v4l2_device_disconnect(&radio->v4l2_dev); + video_unregister_device(&radio->videodev); } /* vidioc_querycap - query device capabilities */ From 8a7cd16f1fa31ef6db9cfc16b1eb0356566e974d Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:09:01 -0300 Subject: [PATCH 022/345] V4L/DVB (13068): radio-mr800: remove device initialization from open/close Remove device initialization from open/close. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 35 ++----------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index dbae50ba250c..399032e8cc18 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -136,7 +136,6 @@ struct amradio_device { struct mutex lock; /* buffer locking */ int curfreq; int stereo; - int users; int muted; }; @@ -493,26 +492,6 @@ static int usb_amradio_open(struct file *file) } file->private_data = radio; - radio->users = 1; - radio->muted = 1; - - retval = amradio_set_mute(radio, AMRADIO_START); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, - "radio did not start up properly\n"); - radio->users = 0; - goto unlock; - } - - retval = amradio_set_stereo(radio, WANT_STEREO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set stereo failed\n"); - - retval = amradio_setfreq(radio, radio->curfreq); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set frequency failed\n"); unlock: mutex_unlock(&radio->lock); @@ -527,19 +506,9 @@ static int usb_amradio_close(struct file *file) mutex_lock(&radio->lock); - if (!radio->usbdev) { + if (!radio->usbdev) retval = -EIO; - goto unlock; - } - radio->users = 0; - - retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "amradio_stop failed\n"); - -unlock: mutex_unlock(&radio->lock); return retval; } @@ -670,10 +639,10 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; radio->videodev.release = usb_amradio_video_device_release; - radio->users = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = 95.16 * FREQ_MUL; radio->stereo = -1; + radio->muted = 1; mutex_init(&radio->lock); From 502d50166cdef6cc8f63ab8c6ab35694ee39f608 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:13:50 -0300 Subject: [PATCH 023/345] V4L/DVB (13069): radio-mr800: ensure the radio is initialized to a consistent state Ensure the radio is initialized to a consistent state. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 399032e8cc18..7db992d3b0db 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -85,6 +85,9 @@ MODULE_LICENSE("GPL"); #define amradio_dev_warn(dev, fmt, arg...) \ dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg) +#define amradio_dev_err(dev, fmt, arg...) \ + dev_err(dev, MR800_DRIVER_NAME " - " fmt, ##arg) + /* Probably USB_TIMEOUT should be modified in module parameter */ #define BUFFER_LENGTH 8 #define USB_TIMEOUT 500 @@ -137,6 +140,7 @@ struct amradio_device { int curfreq; int stereo; int muted; + int initialized; }; #define vdev_to_amradio(r) container_of(r, struct amradio_device, videodev) @@ -478,6 +482,31 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) return 0; } +static int usb_amradio_init(struct amradio_device *radio) +{ + int retval; + + retval = amradio_set_mute(radio, AMRADIO_STOP); + if (retval < 0) { + amradio_dev_warn(&radio->videodev.dev, "amradio_stop failed\n"); + goto out_err; + } + + retval = amradio_set_stereo(radio, WANT_STEREO); + if (retval < 0) { + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); + goto out_err; + } + + radio->initialized = 1; + goto out; + +out_err: + amradio_dev_err(&radio->videodev.dev, "initialization failed\n"); +out: + return retval; +} + /* open device - amradio_start() and amradio_setfreq() */ static int usb_amradio_open(struct file *file) { @@ -493,6 +522,9 @@ static int usb_amradio_open(struct file *file) file->private_data = radio; + if (unlikely(!radio->initialized)) + retval = usb_amradio_init(radio); + unlock: mutex_unlock(&radio->lock); return retval; @@ -641,8 +673,6 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->usbdev = interface_to_usbdev(intf); radio->curfreq = 95.16 * FREQ_MUL; - radio->stereo = -1; - radio->muted = 1; mutex_init(&radio->lock); From 30dd4508b97155a3f826f877d5750d8888bc3183 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:16:38 -0300 Subject: [PATCH 024/345] V4L/DVB (13070): radio-mr800: fix behavior of set_stereo function Fix behavior of set_stereo function. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 7db992d3b0db..9764eca2c498 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -252,12 +252,13 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) { - radio->stereo = -1; + if (retval < 0 || size != BUFFER_LENGTH) return retval; - } - radio->stereo = 1; + if (argument == WANT_STEREO) + radio->stereo = 1; + else + radio->stereo = 0; return retval; } From d8970e5fd9eace437bc2f1aaff1c2a05fb3448ea Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:24:47 -0300 Subject: [PATCH 025/345] V4L/DVB (13071): radio-mr800: preserve radio state during suspend/resume Preserve radio state during suspend/resume. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 35 +++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 9764eca2c498..ac2107378942 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -574,9 +574,12 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) mutex_lock(&radio->lock); - retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) - dev_warn(&intf->dev, "amradio_stop failed\n"); + if (!radio->muted && radio->initialized) { + retval = amradio_set_mute(radio, AMRADIO_STOP); + if (retval < 0) + dev_warn(&intf->dev, "amradio_stop failed\n"); + radio->muted = 0; + } dev_info(&intf->dev, "going into suspend..\n"); @@ -592,10 +595,30 @@ static int usb_amradio_resume(struct usb_interface *intf) mutex_lock(&radio->lock); - retval = amradio_set_mute(radio, AMRADIO_START); - if (retval < 0) - dev_warn(&intf->dev, "amradio_start failed\n"); + if (unlikely(!radio->initialized)) + goto unlock; + if (radio->stereo) + retval = amradio_set_stereo(radio, WANT_STEREO); + else + retval = amradio_set_stereo(radio, WANT_MONO); + + if (retval < 0) + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); + + retval = amradio_setfreq(radio, radio->curfreq); + if (retval < 0) + amradio_dev_warn(&radio->videodev.dev, + "set frequency failed\n"); + + if (!radio->muted) { + retval = amradio_set_mute(radio, AMRADIO_START); + if (retval < 0) + dev_warn(&radio->videodev.dev, + "amradio_start failed\n"); + } + +unlock: dev_info(&intf->dev, "coming out of suspend..\n"); mutex_unlock(&radio->lock); From 16a72f41bb82573d7fe1dfea1cb8356dee307db4 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:28:02 -0300 Subject: [PATCH 026/345] V4L/DVB (13072): radio-mr800: simplify device warnings Simplify device warnings. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 78 +++++++++++-------------------- 1 file changed, 26 insertions(+), 52 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index ac2107378942..5506fac5fd49 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -186,8 +186,10 @@ static int amradio_set_mute(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) + if (retval < 0 || size != BUFFER_LENGTH) { + amradio_dev_warn(&radio->videodev.dev, "set mute failed\n"); return retval; + } radio->muted = argument; @@ -216,7 +218,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); if (retval < 0 || size != BUFFER_LENGTH) - return retval; + goto out_err; /* frequency is calculated from freq_send and placed in first 2 bytes */ radio->buffer[0] = (freq_send >> 8) & 0xff; @@ -230,6 +232,14 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); + if (retval < 0 || size != BUFFER_LENGTH) + goto out_err; + + goto out; + +out_err: + amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n"); +out: return retval; } @@ -252,8 +262,10 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) + if (retval < 0 || size != BUFFER_LENGTH) { + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); return retval; + } if (argument == WANT_STEREO) radio->stereo = 1; @@ -314,9 +326,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, * amradio_set_stereo shouldn't be here */ retval = amradio_set_stereo(radio, WANT_STEREO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set stereo failed\n"); strcpy(v->name, "FM"); v->type = V4L2_TUNER_RADIO; @@ -348,15 +357,9 @@ static int vidioc_s_tuner(struct file *file, void *priv, switch (v->audmode) { case V4L2_TUNER_MODE_MONO: retval = amradio_set_stereo(radio, WANT_MONO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set mono failed\n"); break; case V4L2_TUNER_MODE_STEREO: retval = amradio_set_stereo(radio, WANT_STEREO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set stereo failed\n"); break; } @@ -373,9 +376,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, radio->curfreq = f->frequency; retval = amradio_setfreq(radio, radio->curfreq); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set frequency failed\n"); return retval; } @@ -428,19 +428,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { + if (ctrl->value) retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, - "amradio_stop failed\n"); - } - } else { + else retval = amradio_set_mute(radio, AMRADIO_START); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, - "amradio_start failed\n"); - } - } + break; } @@ -488,16 +480,12 @@ static int usb_amradio_init(struct amradio_device *radio) int retval; retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, "amradio_stop failed\n"); + if (retval) goto out_err; - } retval = amradio_set_stereo(radio, WANT_STEREO); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); + if (retval) goto out_err; - } radio->initialized = 1; goto out; @@ -570,14 +558,11 @@ static long usb_amradio_ioctl(struct file *file, unsigned int cmd, static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) { struct amradio_device *radio = usb_get_intfdata(intf); - int retval; mutex_lock(&radio->lock); if (!radio->muted && radio->initialized) { - retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) - dev_warn(&intf->dev, "amradio_stop failed\n"); + amradio_set_mute(radio, AMRADIO_STOP); radio->muted = 0; } @@ -591,7 +576,6 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) static int usb_amradio_resume(struct usb_interface *intf) { struct amradio_device *radio = usb_get_intfdata(intf); - int retval; mutex_lock(&radio->lock); @@ -599,24 +583,14 @@ static int usb_amradio_resume(struct usb_interface *intf) goto unlock; if (radio->stereo) - retval = amradio_set_stereo(radio, WANT_STEREO); + amradio_set_stereo(radio, WANT_STEREO); else - retval = amradio_set_stereo(radio, WANT_MONO); + amradio_set_stereo(radio, WANT_MONO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); + amradio_setfreq(radio, radio->curfreq); - retval = amradio_setfreq(radio, radio->curfreq); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set frequency failed\n"); - - if (!radio->muted) { - retval = amradio_set_mute(radio, AMRADIO_START); - if (retval < 0) - dev_warn(&radio->videodev.dev, - "amradio_start failed\n"); - } + if (!radio->muted) + amradio_set_mute(radio, AMRADIO_START); unlock: dev_info(&intf->dev, "coming out of suspend..\n"); From 798166dbecafa98ec9b28d056774ec2fc80290df Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:31:26 -0300 Subject: [PATCH 027/345] V4L/DVB (13073): radio-mr800: set radio frequency only upon success Set radio frequency only upon success. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 5506fac5fd49..4064109c4205 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -235,6 +235,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) if (retval < 0 || size != BUFFER_LENGTH) goto out_err; + radio->curfreq = freq; goto out; out_err: @@ -371,13 +372,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = file->private_data; - int retval = 0; - radio->curfreq = f->frequency; - - retval = amradio_setfreq(radio, radio->curfreq); - - return retval; + return amradio_setfreq(radio, f->frequency); } /* vidioc_g_frequency - get tuner radio frequency */ From d7009cdc286d7c9714b357b0e85b3fcbbf9e03a4 Mon Sep 17 00:00:00 2001 From: "Beholder Intl. Ltd. Dmitry Belimov" Date: Thu, 24 Sep 2009 13:13:28 -0300 Subject: [PATCH 028/345] V4L/DVB (13075): xc5000: add FM radio support Add FM radio for the xc5000 silicon tuner chip. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 66 ++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index f4ffcdc9b848..fc7cb74256d0 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -739,15 +739,12 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe) return ret; } -static int xc5000_set_analog_params(struct dvb_frontend *fe, +static int xc5000_set_tv_freq(struct dvb_frontend *fe, struct analog_parameters *params) { struct xc5000_priv *priv = fe->tuner_priv; int ret; - if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) - xc_load_fw_and_init_tuner(fe); - dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", __func__, params->frequency); @@ -827,6 +824,67 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, return 0; } +static int xc5000_set_radio_freq(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct xc5000_priv *priv = fe->tuner_priv; + int ret = -EINVAL; + + dprintk(1, "%s() frequency=%d (in units of khz)\n", + __func__, params->frequency); + + priv->freq_hz = params->frequency * 125 / 2; + + priv->rf_mode = XC_RF_MODE_AIR; + + ret = xc_SetTVStandard(priv, + XC5000_Standard[FM_Radio_INPUT1].VideoMode, + XC5000_Standard[FM_Radio_INPUT1].AudioMode); + + if (ret != XC_RESULT_SUCCESS) { + printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); + return -EREMOTEIO; + } + + ret = xc_SetSignalSource(priv, priv->rf_mode); + if (ret != XC_RESULT_SUCCESS) { + printk(KERN_ERR + "xc5000: xc_SetSignalSource(%d) failed\n", + priv->rf_mode); + return -EREMOTEIO; + } + + xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); + + return 0; +} + +static int xc5000_set_analog_params(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct xc5000_priv *priv = fe->tuner_priv; + int ret = -EINVAL; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) + xc_load_fw_and_init_tuner(fe); + + switch (params->mode) { + case V4L2_TUNER_RADIO: + ret = xc5000_set_radio_freq(fe, params); + break; + case V4L2_TUNER_ANALOG_TV: + case V4L2_TUNER_DIGITAL_TV: + ret = xc5000_set_tv_freq(fe, params); + break; + } + + return ret; +} + + static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) { struct xc5000_priv *priv = fe->tuner_priv; From 496e9057adf55d0e6c9be3805f0bc61288409317 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 24 Sep 2009 13:27:24 -0300 Subject: [PATCH 029/345] V4L/DVB (13076): xc5000: make the definition of the FM input part of the xc5000 config struct Remove hard-coded definition of the xc5000 FM radio input, making it a parameter passed in when doing the attach call. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 25 ++++++++++++++++++++++--- drivers/media/common/tuners/xc5000.h | 6 ++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index fc7cb74256d0..d33bf831e76c 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -61,6 +61,7 @@ struct xc5000_priv { u32 bandwidth; u8 video_standard; u8 rf_mode; + u8 radio_input; }; /* Misc Defines */ @@ -829,17 +830,32 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe, { struct xc5000_priv *priv = fe->tuner_priv; int ret = -EINVAL; + u8 radio_input; dprintk(1, "%s() frequency=%d (in units of khz)\n", __func__, params->frequency); + if (priv->radio_input == XC5000_RADIO_NOT_CONFIGURED) { + dprintk(1, "%s() radio input not configured\n", __func__); + return -EINVAL; + } + + if (priv->radio_input == XC5000_RADIO_FM1) + radio_input = FM_Radio_INPUT1; + else if (priv->radio_input == XC5000_RADIO_FM2) + radio_input = FM_Radio_INPUT2; + else { + dprintk(1, "%s() unknown radio input %d\n", __func__, + priv->radio_input); + return -EINVAL; + } + priv->freq_hz = params->frequency * 125 / 2; priv->rf_mode = XC_RF_MODE_AIR; - ret = xc_SetTVStandard(priv, - XC5000_Standard[FM_Radio_INPUT1].VideoMode, - XC5000_Standard[FM_Radio_INPUT1].AudioMode); + ret = xc_SetTVStandard(priv, XC5000_Standard[radio_input].VideoMode, + XC5000_Standard[radio_input].AudioMode); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); @@ -1058,6 +1074,9 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, priv->if_khz = cfg->if_khz; } + if (priv->radio_input == 0) + priv->radio_input = cfg->radio_input; + /* Check if firmware has been loaded. It is possible that another instance of the driver has loaded the firmware. */ diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index f4c146698a00..e6d7236c9ea1 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h @@ -30,11 +30,17 @@ struct i2c_adapter; struct xc5000_config { u8 i2c_address; u32 if_khz; + u8 radio_input; }; /* xc5000 callback command */ #define XC5000_TUNER_RESET 0 +/* Possible Radio inputs */ +#define XC5000_RADIO_NOT_CONFIGURED 0 +#define XC5000_RADIO_FM1 1 +#define XC5000_RADIO_FM2 2 + /* For each bridge framework, when it attaches either analog or digital, * it has to store a reference back to its _core equivalent structure, * so that it can service the hardware by steering gpio's etc. From f91cb65b94114f30cf43738ff923f272e4f2ae13 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 30 Sep 2009 22:44:19 -0300 Subject: [PATCH 030/345] V4L/DVB (13077): em28xx: Add support for new variant of KWorld 2800d Seems that the reference design used for the KWorld 2800d switched from the em2860 to em2862, so we need to add the new USB id (and the i2c hash remains so all we need is the default em2862 id. Thanks to Ian Young for reporting the issue and testing the fix. Cc: Ian Young Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index b8afef4c0e01..f8ea8acdd894 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/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:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] + 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] 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] diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c0fd5c6feeac..a41256f78d6a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1608,6 +1608,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2861), .driver_info = EM2820_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2862), + .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2870), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2881), From ec994d0505fc3dde5f46203602c76b527e2ac69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uro=C5=A1=20Vampl?= Date: Wed, 30 Sep 2009 22:53:37 -0300 Subject: [PATCH 031/345] V4L/DVB (13078): em28xx: fix support for Terratec Cinergy T XS (005e) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make analog audio, dvb and the remote work on a Terratec Cinergy Hybrid XS (em2882). Note by djh: Thanks go out fo Andrej Suligoi for his contribution in providing and testing pretty much the exact same patch as provided by Uros. Between the two of them, they got all the core functionality working for the device. Cc: Andrej Suligoi Signed-off-by: UroÅ¡ Vampl Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 6 ++++++ drivers/media/video/em28xx/em28xx-dvb.c | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index a41256f78d6a..4cfaa83b64d9 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1384,7 +1384,12 @@ struct em28xx_board em28xx_boards[] = { .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, + .mts_firmware = 1, .decoder = EM28XX_TVP5150, + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, + .ir_codes = &ir_codes_terratec_cinergy_xs_table, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -2052,6 +2057,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) switch (dev->model) { case EM2880_BOARD_EMPIRE_DUAL_TV: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + case EM2882_BOARD_TERRATEC_HYBRID_XS: ctl->demod = XC3028_FE_ZARLINK456; break; case EM2880_BOARD_TERRATEC_HYBRID_XS: diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index db749461e5c6..19f5156f653e 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -493,6 +493,7 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + case EM2882_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, From 2930992c40ad9c665e2e6e2b8870d3f56428a83d Mon Sep 17 00:00:00 2001 From: "Beholder Intl. Ltd. Dmitry Belimov" Date: Wed, 30 Sep 2009 23:02:21 -0300 Subject: [PATCH 032/345] V4L/DVB (13080): saa7134: add support for the digital side of the Behold X7 Add support for the digital side of the Behold X7 Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-dvb.c | 24 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 09013229d4aa..7de7f1f0adda 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5239,6 +5239,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, .inputs = { { .name = name_tv, .vmux = 2, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index a26e997a9ce6..204e2bc9fe7a 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -40,6 +40,7 @@ #include "tda1004x.h" #include "nxt200x.h" #include "tuner-xc2028.h" +#include "xc5000.h" #include "tda10086.h" #include "tda826x.h" @@ -871,6 +872,20 @@ static struct zl10353_config behold_h6_config = { .disable_i2c_gate_ctrl = 1, }; +static struct xc5000_config behold_x7_tunerconfig = { + .i2c_address = 0xc2>>1, + .if_khz = 4560, + .radio_input = 1, +}; + +static struct zl10353_config behold_x7_config = { + .demod_address = 0x1e>>1, + .if2 = 45600, + .no_tuner = 1, + .parallel_ts = 1, + .disable_i2c_gate_ctrl = 1, +}; + /* ================================================================== * tda10086 based DVB-S cards, helper functions */ @@ -1482,6 +1497,15 @@ static int dvb_init(struct saa7134_dev *dev) TUNER_PHILIPS_FMD1216MEX_MK3); } break; + case SAA7134_BOARD_BEHOLD_X7: + fe0->dvb.frontend = dvb_attach(zl10353_attach, + &behold_x7_config, + &dev->i2c_adap); + if (fe0->dvb.frontend) { + dvb_attach(xc5000_attach, fe0->dvb.frontend, + &dev->i2c_adap, &behold_x7_tunerconfig); + } + break; case SAA7134_BOARD_AVERMEDIA_A700_PRO: case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: /* Zarlink ZL10313 */ From 2a0d056015222d534e32e7556de1a684ad9e61f5 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 30 Sep 2009 23:04:39 -0300 Subject: [PATCH 033/345] V4L/DVB (13081): saa7134: use the #define for the xc5000 radio_input field Dmitri's patch for the Behold X7 didn't use the #define I had setup for XC5000_RADIO_FM1, so cut over to using that instead of "1". Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 204e2bc9fe7a..058b56bf6717 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -875,7 +875,7 @@ static struct zl10353_config behold_h6_config = { static struct xc5000_config behold_x7_tunerconfig = { .i2c_address = 0xc2>>1, .if_khz = 4560, - .radio_input = 1, + .radio_input = XC5000_RADIO_FM1, }; static struct zl10353_config behold_x7_config = { From 2e3c4723d5c2d6b4fa705c3dcd062b5004ab9b2f Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 30 Sep 2009 23:10:17 -0300 Subject: [PATCH 034/345] V4L/DVB (13082): em28xx: remove "not validated" status from Terratec Cinergy T XS (005e) The board support has been validated by the user, so get rid of the warning that shows up on board load. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 4cfaa83b64d9..7ccac2095b75 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1381,7 +1381,6 @@ struct em28xx_board em28xx_boards[] = { }, [EM2882_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Hybrid XS (em2882)", - .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, From f56db93cef5d368b4fa5db49b68bc4ab0b20c4fd Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 26 Sep 2009 22:07:10 -0300 Subject: [PATCH 035/345] V4L/DVB (13084): v4l2-chip-ident: Add ID's needed for the cx23885 and cx25840 modules Add identifiers for CX2388[578] chips, CX2310[012] chips, integrated A/V decoders cores, integrated IR controller core, and the CX23417 MPEG encoder. The cx23885 module and cx25840 module will use these identifiers in upcoming changes. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-chip-ident.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 5ce56f90f315..a2d93da38450 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -73,6 +73,7 @@ enum { V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */ V4L2_IDENT_CX23415 = 415, V4L2_IDENT_CX23416 = 416, + V4L2_IDENT_CX23417 = 417, V4L2_IDENT_CX23418 = 418, /* module au0828 */ @@ -166,12 +167,27 @@ enum { /* module mt9v011, just ident 8243 */ V4L2_IDENT_MT9V011 = 8243, + /* module cx23885 and cx25840 */ + V4L2_IDENT_CX23885 = 8850, + V4L2_IDENT_CX23885_AV = 8851, /* Integrated A/V decoder */ + V4L2_IDENT_CX23887 = 8870, + V4L2_IDENT_CX23887_AV = 8871, /* Integrated A/V decoder */ + V4L2_IDENT_CX23888 = 8880, + V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */ + V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */ + /* module tw9910: just ident 9910 */ V4L2_IDENT_TW9910 = 9910, /* module sn9c20x: just ident 10000 */ V4L2_IDENT_SN9C20X = 10000, + /* module cx231xx and cx25840 */ + V4L2_IDENT_CX2310X_AV = 23099, /* Integrated A/V decoder; not in '100 */ + V4L2_IDENT_CX23100 = 23100, + V4L2_IDENT_CX23101 = 23101, + V4L2_IDENT_CX23102 = 23102, + /* module msp3400: reserved range 34000-34999 and 44000-44999 */ V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only use internally (tveeprom.c). */ From 74618244003a5a9e11240af8c5795ae747d9a2e0 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 26 Sep 2009 22:50:44 -0300 Subject: [PATCH 036/345] V4L/DVB (13085): cx23885: Fix support for v4l2-dbg access to CX2388[578] and CX23417 regs This changes corrects the ioctl() operations for both the CX2388[578] analog video and MPEG video device nodes to properly and consistently support VIDIOC_G_CHIP_IDENT, VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER ioctl()s. This caused some ioctl() support routines to be broken out into a separate source file. Now v4l2-dbg can be used to manipulate CX2388[578] and CX23417 registers including the CX2388[57] functions handled by the cx25840 module. This was done in anticipation of developing a new v4l2_subdev for the integrated IR controller of the CX23888. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/Makefile | 1 + drivers/media/video/cx23885/cx23885-417.c | 10 +- drivers/media/video/cx23885/cx23885-ioctl.c | 197 ++++++++++++++++++++ drivers/media/video/cx23885/cx23885-ioctl.h | 39 ++++ drivers/media/video/cx23885/cx23885-video.c | 34 +--- drivers/media/video/cx23885/cx23885.h | 4 + 6 files changed, 253 insertions(+), 32 deletions(-) create mode 100644 drivers/media/video/cx23885/cx23885-ioctl.c create mode 100644 drivers/media/video/cx23885/cx23885-ioctl.h diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index ab8ea35c9bfb..93a954c23f42 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile @@ -1,5 +1,6 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ + cx23885-ioctl.o \ netup-init.o cimax2.o netup-eeprom.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 6c3b51ce3372..0eed852c61e9 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -37,6 +37,7 @@ #include #include "cx23885.h" +#include "cx23885-ioctl.h" #define CX23885_FIRM_IMAGE_SIZE 376836 #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" @@ -318,7 +319,7 @@ static int mc417_wait_ready(struct cx23885_dev *dev) } } -static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value) +int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value) { u32 regval; @@ -382,7 +383,7 @@ static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value) return mc417_wait_ready(dev); } -static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value) +int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value) { int retval; u32 regval; @@ -1724,6 +1725,11 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_log_status = vidioc_log_status, .vidioc_querymenu = vidioc_querymenu, .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_chip_ident = cx23885_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = cx23885_g_register, + .vidioc_s_register = cx23885_s_register, +#endif }; static struct video_device cx23885_mpeg_template = { diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c new file mode 100644 index 000000000000..3a497b6c4fd7 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-ioctl.c @@ -0,0 +1,197 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * Various common ioctl() support functions + * + * Copyright (c) 2009 Andy Walls + * + * 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 "cx23885.h" +#include + +int cx23885_g_chip_ident(struct file *file, void *fh, + struct v4l2_dbg_chip_ident *chip) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; + int err = 0; + u8 rev; + + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + switch (chip->match.type) { + case V4L2_CHIP_MATCH_HOST: + switch (chip->match.addr) { + case 0: + rev = cx_read(RDR_CFG2) & 0xff; + switch (dev->pci->device) { + case 0x8852: + /* rev 0x04 could be '885 or '888. Pick '888. */ + if (rev == 0x04) + chip->ident = V4L2_IDENT_CX23888; + else + chip->ident = V4L2_IDENT_CX23885; + break; + case 0x8880: + if (rev == 0x0e || rev == 0x0f) + chip->ident = V4L2_IDENT_CX23887; + else + chip->ident = V4L2_IDENT_CX23888; + break; + default: + chip->ident = V4L2_IDENT_UNKNOWN; + break; + } + chip->revision = (dev->pci->device << 16) | (rev << 8) | + (dev->hwrevision & 0xff); + break; + case 1: + if (dev->v4l_device != NULL) { + chip->ident = V4L2_IDENT_CX23417; + chip->revision = 0; + } + break; + default: + err = -EINVAL; /* per V4L2 spec */ + break; + } + break; + case V4L2_CHIP_MATCH_I2C_DRIVER: + /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */ + call_all(dev, core, g_chip_ident, chip); + break; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* + * We could return V4L2_IDENT_UNKNOWN, but we don't do the work + * to look if a chip is at the address with no driver. That's a + * dangerous thing to do with EEPROMs anyway. + */ + call_all(dev, core, g_chip_ident, chip); + break; + default: + err = -EINVAL; + break; + } + return err; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int cx23885_g_host_register(struct cx23885_dev *dev, + struct v4l2_dbg_register *reg) +{ + if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) + return -EINVAL; + + reg->size = 4; + reg->val = cx_read(reg->reg); + return 0; +} + +static int cx23417_g_register(struct cx23885_dev *dev, + struct v4l2_dbg_register *reg) +{ + u32 value; + + if (dev->v4l_device == NULL) + return -EINVAL; + + if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000) + return -EINVAL; + + if (mc417_register_read(dev, (u16) reg->reg, &value)) + return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */ + + reg->size = 4; + reg->val = value; + return 0; +} + +int cx23885_g_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (reg->match.type == V4L2_CHIP_MATCH_HOST) { + switch (reg->match.addr) { + case 0: + return cx23885_g_host_register(dev, reg); + case 1: + return cx23417_g_register(dev, reg); + default: + break; + } + } + + /* FIXME - any error returns should not be ignored */ + call_all(dev, core, g_register, reg); + return 0; +} + +static int cx23885_s_host_register(struct cx23885_dev *dev, + struct v4l2_dbg_register *reg) +{ + if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) + return -EINVAL; + + reg->size = 4; + cx_write(reg->reg, reg->val); + return 0; +} + +static int cx23417_s_register(struct cx23885_dev *dev, + struct v4l2_dbg_register *reg) +{ + if (dev->v4l_device == NULL) + return -EINVAL; + + if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000) + return -EINVAL; + + if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val)) + return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */ + + reg->size = 4; + return 0; +} + +int cx23885_s_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (reg->match.type == V4L2_CHIP_MATCH_HOST) { + switch (reg->match.addr) { + case 0: + return cx23885_s_host_register(dev, reg); + case 1: + return cx23417_s_register(dev, reg); + default: + break; + } + } + + /* FIXME - any error returns should not be ignored */ + call_all(dev, core, s_register, reg); + return 0; +} +#endif diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/video/cx23885/cx23885-ioctl.h new file mode 100644 index 000000000000..80b0f4923c6a --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-ioctl.h @@ -0,0 +1,39 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * Various common ioctl() support functions + * + * Copyright (c) 2009 Andy Walls + * + * 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. + */ + +#ifndef _CX23885_IOCTL_H_ +#define _CX23885_IOCTL_H_ + +int cx23885_g_chip_ident(struct file *file, void *fh, + struct v4l2_dbg_chip_ident *chip); + +#ifdef CONFIG_VIDEO_ADV_DEBUG +int cx23885_g_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg); + + +int cx23885_s_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg); + +#endif +#endif diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 654cc253cd50..3f1d07e6490a 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -35,6 +35,7 @@ #include "cx23885.h" #include #include +#include "cx23885-ioctl.h" MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); @@ -1312,34 +1313,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, cx23885_set_freq(dev, f); } -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - - call_all(dev, core, g_register, reg); - - return 0; -} - -static int vidioc_s_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - - call_all(dev, core, s_register, reg); - - return 0; -} -#endif - /* ----------------------------------------------------------- */ static void cx23885_vid_timeout(unsigned long data) @@ -1449,9 +1422,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_chip_ident = cx23885_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = cx23885_g_register, + .vidioc_s_register = cx23885_s_register, #endif }; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index cc7a165561ff..f4c4108f23f3 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -515,6 +515,10 @@ extern void cx23885_417_check_encoder(struct cx23885_dev *dev); extern void cx23885_mc417_init(struct cx23885_dev *dev); extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value); extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value); +extern int mc417_register_read(struct cx23885_dev *dev, + u16 address, u32 *value); +extern int mc417_register_write(struct cx23885_dev *dev, + u16 address, u32 value); extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask); extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask); extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); From 29f8a0a50ac32ac4bc1937dcfdf8de6c406a5f10 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 26 Sep 2009 23:17:30 -0300 Subject: [PATCH 037/345] V4L/DVB (13086): cx23885: Add skeleton v4l2_subdev for the CX23888 integrated IR controller This change adds a skeletal implementation of a v4l2_subdevice to provide encapsulation and abstraction of the CX23888's integrated consumer infrared controller. This change also instantiates the cx23888_ir subdev for the HVR-1850 which has IR hardware physically wired up to a CX23888. The cx23888_ir subdev code is being written with long-term objectives to: 1. port it to the cx25840 module for the CX2584x, CX2583x, CX23885, & CX231xx IR controllers 2. possibly port it to the cx18 module for the CX23418 IR controller 3. have the IR subdevice accessed abstractly in the cx23885 module, so the driver can ignore the difference between the CX23885 and CX23888. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/Makefile | 2 +- drivers/media/video/cx23885/cx23885-cards.c | 11 +- drivers/media/video/cx23885/cx23885-core.c | 20 ++ drivers/media/video/cx23885/cx23885-ioctl.c | 11 + drivers/media/video/cx23885/cx23885.h | 8 + drivers/media/video/cx23885/cx23888-ir.c | 233 ++++++++++++++++++++ drivers/media/video/cx23885/cx23888-ir.h | 28 +++ 7 files changed, 310 insertions(+), 3 deletions(-) create mode 100644 drivers/media/video/cx23885/cx23888-ir.c create mode 100644 drivers/media/video/cx23885/cx23888-ir.h diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index 93a954c23f42..3832a1cb768d 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile @@ -1,6 +1,6 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ - cx23885-ioctl.o \ + cx23885-ioctl.o cx23888-ir.o \ netup-init.o cimax2.o netup-eeprom.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index bfdf79f1033c..4b5aa08036fa 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -28,6 +28,7 @@ #include "cx23885.h" #include "tuner-xc2028.h" #include "netup-init.h" +#include "cx23888-ir.h" /* ------------------------------------------------------------------ */ /* board config info */ @@ -801,6 +802,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) int cx23885_ir_init(struct cx23885_dev *dev) { + int ret = 0; switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: @@ -812,15 +814,20 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: case CX23885_BOARD_HAUPPAUGE_HVR1210: - case CX23885_BOARD_HAUPPAUGE_HVR1850: /* FIXME: Implement me */ break; + case CX23885_BOARD_HAUPPAUGE_HVR1850: + ret = cx23888_ir_probe(dev); + if (ret) + break; + dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); + break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: request_module("ir-kbd-i2c"); break; } - return 0; + return ret; } void cx23885_card_setup(struct cx23885_dev *dev) diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index c31284ba19dd..73be16b0d2a0 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -32,6 +32,7 @@ #include "cx23885.h" #include "cimax2.h" +#include "cx23888-ir.h" MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); @@ -753,6 +754,23 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev) __func__, dev->hwrevision); } +/* Find the first v4l2_subdev member of the group id in hw */ +struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw) +{ + struct v4l2_subdev *result = NULL; + struct v4l2_subdev *sd; + + spin_lock(&dev->v4l2_dev.lock); + v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) { + if (sd->grp_id == hw) { + result = sd; + break; + } + } + spin_unlock(&dev->v4l2_dev.lock); + return result; +} + static int cx23885_dev_setup(struct cx23885_dev *dev) { int i; @@ -1914,6 +1932,8 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) cx23885_shutdown(dev); + cx23888_ir_remove(dev); + pci_disable_device(pci_dev); /* unregister stuff */ diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c index 3a497b6c4fd7..dfb4627fb340 100644 --- a/drivers/media/video/cx23885/cx23885-ioctl.c +++ b/drivers/media/video/cx23885/cx23885-ioctl.c @@ -65,6 +65,17 @@ int cx23885_g_chip_ident(struct file *file, void *fh, chip->revision = 0; } break; + case 2: + /* + * The integrated IR controller on the CX23888 is + * host chip 2. It may not be used/initialized or sd_ir + * may be pointing at the cx25840 subdevice for the + * IR controller on the CX23885. Thus we find it + * without using the dev->sd_ir pointer. + */ + call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident, + chip); + break; default: err = -EINVAL; /* per V4L2 spec */ break; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index f4c4108f23f3..f7ed146566d9 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -355,6 +355,7 @@ struct cx23885_dev { unsigned char radio_addr; unsigned int has_radio; struct v4l2_subdev *sd_cx25840; + struct v4l2_subdev *sd_ir; /* V4l */ u32 freq; @@ -383,6 +384,13 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) #define call_all(dev, o, f, args...) \ v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) +#define CX23885_HW_888_IR (1 << 0) + +#define call_hw(dev, grpid, o, f, args...) \ + v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args) + +extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw); + extern struct list_head cx23885_devlist; #define SRAM_CH01 0 /* Video A */ diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c new file mode 100644 index 000000000000..12df0e3a2354 --- /dev/null +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -0,0 +1,233 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * CX23888 Integrated Consumer Infrared Controller + * + * Copyright (C) 2009 Andy Walls + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include + +#include "cx23885.h" + +#define CX23888_IR_REG_BASE 0x170000 +/* + * These CX23888 register offsets have a straightforward one to one mapping + * to the CX23885 register offsets of 0x200 through 0x218 + */ +#define CX23888_IR_CNTRL_REG 0x170000 +#define CX23888_IR_TXCLK_REG 0x170004 +#define CX23888_IR_RXCLK_REG 0x170008 +#define CX23888_IR_CDUTY_REG 0x17000C +#define CX23888_IR_STATS_REG 0x170010 +#define CX23888_IR_IRQEN_REG 0x170014 +#define CX23888_IR_FILTR_REG 0x170018 +/* This register doesn't follow the pattern; it's 0x23C on a CX23885 */ +#define CX23888_IR_FIFO_REG 0x170040 + +/* CX23888 unique registers */ +#define CX23888_IR_SEEDP_REG 0x17001C +#define CX23888_IR_TIMOL_REG 0x170020 +#define CX23888_IR_WAKE0_REG 0x170024 +#define CX23888_IR_WAKE1_REG 0x170028 +#define CX23888_IR_WAKE2_REG 0x17002C +#define CX23888_IR_MASK0_REG 0x170030 +#define CX23888_IR_MASK1_REG 0x170034 +#define CX23888_IR_MAKS2_REG 0x170038 +#define CX23888_IR_DPIPG_REG 0x17003C +#define CX23888_IR_LEARN_REG 0x170044 + + +struct cx23888_ir_state { + struct v4l2_subdev sd; + struct cx23885_dev *dev; + u32 id; + u32 rev; +}; + +static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) +{ + return v4l2_get_subdevdata(sd); +} + +static int cx23888_ir_write(struct cx23885_dev *dev, u32 addr, u8 value) +{ + u32 reg = (addr & ~3); + int shift = (addr & 3) * 8; + u32 x = cx_read(reg); + + x = (x & ~(0xff << shift)) | ((u32)value << shift); + cx_write(reg, x); + return 0; +} + +static +inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value) +{ + cx_write(addr, value); + return 0; +} + +static u8 cx23888_ir_read(struct cx23885_dev *dev, u32 addr) +{ + u32 x = cx_read((addr & ~3)); + int shift = (addr & 3) * 8; + + return (x >> shift) & 0xff; +} + +static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr) +{ + return cx_read(addr); +} + +static int cx23888_ir_and_or(struct cx23885_dev *dev, u32 addr, + unsigned and_mask, u8 or_value) +{ + return cx23888_ir_write(dev, addr, + (cx23888_ir_read(dev, addr) & and_mask) | + or_value); +} + +static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr, + u32 and_mask, u32 or_value) +{ + cx_andor(addr, and_mask, or_value); + return 0; +} + +static int cx23888_ir_log_status(struct v4l2_subdev *sd) +{ + struct cx23888_ir_state *state = to_state(sd); + struct cx23885_dev *dev = state->dev; + u8 cntrl = cx23888_ir_read(dev, CX23888_IR_CNTRL_REG+1); + v4l2_info(sd, "receiver %sabled\n", cntrl & 0x1 ? "en" : "dis"); + v4l2_info(sd, "transmitter %sabled\n", cntrl & 0x2 ? "en" : "dis"); + return 0; +} + +static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match) +{ + return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2; +} + +static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct cx23888_ir_state *state = to_state(sd); + + if (cx23888_ir_dbg_match(&chip->match)) { + chip->ident = state->id; + chip->revision = state->rev; + } + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int cx23888_ir_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct cx23888_ir_state *state = to_state(sd); + u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; + + if (!cx23888_ir_dbg_match(®->match)) + return -EINVAL; + if ((addr & 0x3) != 0) + return -EINVAL; + if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->size = 4; + reg->val = cx23888_ir_read4(state->dev, addr); + return 0; +} + +static int cx23888_ir_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct cx23888_ir_state *state = to_state(sd); + u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; + + if (!cx23888_ir_dbg_match(®->match)) + return -EINVAL; + if ((addr & 0x3) != 0) + return -EINVAL; + if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + cx23888_ir_write4(state->dev, addr, reg->val); + return 0; +} +#endif + +static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = { + .g_chip_ident = cx23888_ir_g_chip_ident, + .log_status = cx23888_ir_log_status, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = cx23888_ir_g_register, + .s_register = cx23888_ir_s_register, +#endif +}; + +static const struct v4l2_subdev_ops cx23888_ir_controller_ops = { + .core = &cx23888_ir_core_ops, +}; + +int cx23888_ir_probe(struct cx23885_dev *dev) +{ + struct cx23888_ir_state *state; + struct v4l2_subdev *sd; + + state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + + state->dev = dev; + state->id = V4L2_IDENT_CX23888_IR; + state->rev = 0; + sd = &state->sd; + + v4l2_subdev_init(sd, &cx23888_ir_controller_ops); + v4l2_set_subdevdata(sd, state); + /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */ + snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name); + sd->grp_id = CX23885_HW_888_IR; + return v4l2_device_register_subdev(&dev->v4l2_dev, sd); +} + +int cx23888_ir_remove(struct cx23885_dev *dev) +{ + struct v4l2_subdev *sd; + struct cx23888_ir_state *state; + + sd = cx23885_find_hw(dev, CX23885_HW_888_IR); + if (sd == NULL) + return -ENODEV; + + /* Disable receiver and transmitter */ + cx23888_ir_and_or(dev, CX23888_IR_CNTRL_REG+1, 0xfc, 0); + + state = to_state(sd); + v4l2_device_unregister_subdev(sd); + kfree(state); + /* Nothing more to free() as state held the actual v4l2_subdev object */ + return 0; +} diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/video/cx23885/cx23888-ir.h new file mode 100644 index 000000000000..3d446f9eb94b --- /dev/null +++ b/drivers/media/video/cx23885/cx23888-ir.h @@ -0,0 +1,28 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * CX23888 Integrated Consumer Infrared Controller + * + * Copyright (C) 2009 Andy Walls + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef _CX23888_IR_H_ +#define _CX23888_IR_H_ +int cx23888_ir_probe(struct cx23885_dev *dev); +int cx23888_ir_remove(struct cx23885_dev *dev); +#endif From c7dd1ecdc0112b9700ed6ad20a6e4e07d125044b Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 26 Sep 2009 23:32:54 -0300 Subject: [PATCH 038/345] V4L/DVB (13087): cx25840: Improve detection of CX2388[578] A/V cores Add improved logic to detect the exact CX2388[578] A/V core that is being probed. Also cleaned up detection and logging for CX2310[12], CX2583[67], and CX2584[0123] cores and chips. Also added code to identify a CX2388[578] A/V decoder core that is not responding properly. Typical symptoms include registers 0x00-0xff responding properly but all other registers returning the same value (0x13 and 0x5 have been observed). This state will cause proper detection of '885 vs. '887 vs. '888 to fail and the chip won't respond to get configured properly anyway. I have no method of reseting the core to a working state at this time; but I didn't try too hard to work one out either. The problem likely only occurs in development. I suspect configuring the SYS PLL VCO to oscillate too slowly (286.3 MHz?) before post divide may be the root cause, when encountered. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 97 ++++++++++++++++++---- 1 file changed, 79 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 1aeaf18a9bea..e83656729991 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1521,12 +1521,35 @@ static const struct v4l2_subdev_ops cx25840_ops = { /* ----------------------------------------------------------------------- */ +static u32 get_cx2388x_ident(struct i2c_client *client) +{ + u32 ret; + + /* Come out of digital power down */ + cx25840_write(client, 0x000, 0); + + if (cx25840_read4(client, 0x204) & 0xffff) { + /* IR Tx Clk Divider register exists; chip must be a CX23885 */ + ret = V4L2_IDENT_CX23885_AV; + } else if (cx25840_read4(client, 0x300) & 0x0fffffff) { + /* DIF PLL Freq Word reg exists; chip must be a CX23888 */ + ret = V4L2_IDENT_CX23888_AV; + } else { + /* A CX23887 A/V core has neither IR nor DIF */ + ret = V4L2_IDENT_CX23887_AV; + } + + /* Back into digital power down */ + cx25840_write(client, 0x000, 2); + return ret; +} + static int cx25840_probe(struct i2c_client *client, const struct i2c_device_id *did) { struct cx25840_state *state; struct v4l2_subdev *sd; - u32 id; + u32 id = V4L2_IDENT_NONE; u16 device_id; /* Check if the adapter supports the needed features */ @@ -1543,17 +1566,22 @@ static int cx25840_probe(struct i2c_client *client, * 0x83 for the cx2583x and 0x84 for the cx2584x */ if ((device_id & 0xff00) == 0x8300) { id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; - } - else if ((device_id & 0xff00) == 0x8400) { + } else if ((device_id & 0xff00) == 0x8400) { id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); } else if (device_id == 0x0000) { - id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; - } else if (device_id == 0x1313) { - id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; + id = get_cx2388x_ident(client); } else if ((device_id & 0xfff0) == 0x5A30) { - id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); - } - else { + /* The CX23100 (0x5A3C = 23100) doesn't have an A/V decoder */ + id = V4L2_IDENT_CX2310X_AV; + } else if ((device_id & 0xff) == (device_id >> 8)) { + v4l_err(client, + "likely a confused/unresponsive cx2388[578] A/V decoder" + " found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + v4l_err(client, "A method to reset it from the cx25840 driver" + " software is not known at this time\n"); + return -ENODEV; + } else { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); return -ENODEV; } @@ -1564,17 +1592,50 @@ static int cx25840_probe(struct i2c_client *client, 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", - (device_id & 0xfff0) >> 4, - (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), - client->addr << 1, client->adapter->name); + switch (id) { + case V4L2_IDENT_CX23885_AV: + state->is_cx23885 = 1; + v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + break; + case V4L2_IDENT_CX23887_AV: + state->is_cx23885 = 1; + v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + break; + case V4L2_IDENT_CX23888_AV: + state->is_cx23885 = 1; + v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + break; + case V4L2_IDENT_CX2310X_AV: + state->is_cx231xx = 1; + v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n", + device_id, client->addr << 1, client->adapter->name); + break; + case V4L2_IDENT_CX25840: + case V4L2_IDENT_CX25841: + case V4L2_IDENT_CX25842: + case V4L2_IDENT_CX25843: + /* 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", + (device_id & 0xfff0) >> 4, + (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 + : (device_id & 0x0f), + client->addr << 1, client->adapter->name); + break; + case V4L2_IDENT_CX25836: + case V4L2_IDENT_CX25837: + state->is_cx25836 = 1; + default: + v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n", + (device_id & 0xfff0) >> 4, device_id & 0x0f, + client->addr << 1, client->adapter->name); + break; + } state->c = client; - state->is_cx25836 = ((device_id & 0xff00) == 0x8300); - state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); - state->is_cx231xx = (device_id == 0x5a3e); state->vid_input = CX25840_COMPOSITE7; state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; From 2a03f03471d3232037e656570ccaf3ff2ffd01e8 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 26 Sep 2009 23:47:21 -0300 Subject: [PATCH 039/345] V4L/DVB (13088): cx25840: Convert chip/core family checks to static inline functions Change logic to check for various chip or core families to inline functions. Checks for specific chips should be made against the state->id field now. This is in preparation for chip/core specific code for setting up PLLs for the CX2388[578] family of cores, that all run with different crystal frequencies. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-audio.c | 44 +++++++-------- drivers/media/video/cx25840/cx25840-core.c | 55 +++++++++---------- drivers/media/video/cx25840/cx25840-core.h | 22 +++++++- .../media/video/cx25840/cx25840-firmware.c | 10 ++-- 4 files changed, 71 insertions(+), 60 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index 2f846f5e0f9f..fbccbdce26e0 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c @@ -32,19 +32,19 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* common for all inputs and rates */ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ - if (!state->is_cx23885 && !state->is_cx231xx) + if (!is_cx2388x(state) && !is_cx231xx(state)) cx25840_write(client, 0x127, 0x50); if (state->aud_input != CX25840_AUDIO_SERIAL) { switch (freq) { case 32000: - if (state->is_cx23885) { + if (is_cx2388x(state)) { /* We don't have register values * so avoid destroying registers. */ break; } - if (!state->is_cx231xx) { + if (!is_cx231xx(state)) { /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1006040f); @@ -52,7 +52,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) cx25840_write4(client, 0x110, 0x01bb39ee); } - if (state->is_cx25836) + if (is_cx2583x(state)) break; /* src3/4/6_ctl = 0x0801f77f */ @@ -62,13 +62,13 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 44100: - if (state->is_cx23885) { + if (is_cx2388x(state)) { /* We don't have register values * so avoid destroying registers. */ break; } - if (!state->is_cx231xx) { + if (!is_cx231xx(state)) { /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1009040f); @@ -76,7 +76,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) cx25840_write4(client, 0x110, 0x00ec6bd6); } - if (state->is_cx25836) + if (is_cx2583x(state)) break; /* src3/4/6_ctl = 0x08016d59 */ @@ -86,13 +86,13 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 48000: - if (state->is_cx23885) { + if (is_cx2388x(state)) { /* We don't have register values * so avoid destroying registers. */ break; } - if (!state->is_cx231xx) { + if (!is_cx231xx(state)) { /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x100a040f); @@ -100,7 +100,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) cx25840_write4(client, 0x110, 0x0098d6e5); } - if (state->is_cx25836) + if (is_cx2583x(state)) break; /* src3/4/6_ctl = 0x08014faa */ @@ -112,13 +112,13 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } else { switch (freq) { case 32000: - if (state->is_cx23885) { + if (is_cx2388x(state)) { /* We don't have register values * so avoid destroying registers. */ break; } - if (!state->is_cx231xx) { + if (!is_cx231xx(state)) { /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1e08040f); @@ -126,7 +126,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) cx25840_write4(client, 0x110, 0x012a0869); } - if (state->is_cx25836) + if (is_cx2583x(state)) break; /* src1_ctl = 0x08010000 */ @@ -142,14 +142,14 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 44100: - if (state->is_cx23885) { + if (is_cx2388x(state)) { /* We don't have register values * so avoid destroying registers. */ break; } - if (!state->is_cx231xx) { + if (!is_cx231xx(state)) { /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1809040f); @@ -157,7 +157,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) cx25840_write4(client, 0x110, 0x00ec6bd6); } - if (state->is_cx25836) + if (is_cx2583x(state)) break; /* src1_ctl = 0x08010000 */ @@ -170,7 +170,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 48000: - if (!state->is_cx23885 && !state->is_cx231xx) { + if (!is_cx2388x(state) && !is_cx231xx(state)) { /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x180a040f); @@ -178,10 +178,10 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) cx25840_write4(client, 0x110, 0x0098d6e5); } - if (state->is_cx25836) + if (is_cx2583x(state)) break; - if (!state->is_cx23885 && !state->is_cx231xx) { + if (!is_cx2388x(state) && !is_cx231xx(state)) { /* src1_ctl */ cx25840_write4(client, 0x8f8, 0x08018000); @@ -243,7 +243,7 @@ void cx25840_audio_set_path(struct i2c_client *client) cx25840_and_or(client, 0x810, ~0x1, 0x00); /* Ensure the controller is running when we exit */ - if (state->is_cx23885 || state->is_cx231xx) + if (is_cx2388x(state) || is_cx231xx(state)) cx25840_and_or(client, 0x803, ~0x10, 0x10); } @@ -383,7 +383,7 @@ int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) struct cx25840_state *state = to_state(sd); int retval; - if (!state->is_cx25836) + if (!is_cx2583x(state)) cx25840_and_or(client, 0x810, ~0x1, 1); if (state->aud_input != CX25840_AUDIO_SERIAL) { cx25840_and_or(client, 0x803, ~0x10, 0); @@ -392,7 +392,7 @@ int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) retval = set_audclk_freq(client, freq); if (state->aud_input != CX25840_AUDIO_SERIAL) cx25840_and_or(client, 0x803, ~0x10, 0x10); - if (!state->is_cx25836) + if (!is_cx2583x(state)) cx25840_and_or(client, 0x810, ~0x1, 0); return retval; } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index e83656729991..a6446e637f17 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -494,7 +494,7 @@ void cx25840_std_setup(struct i2c_client *client) } /* DEBUG: Displays configured PLL frequency */ - if (!state->is_cx231xx) { + if (!is_cx231xx(state)) { pll_int = cx25840_read(client, 0x108); pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff; pll_post = cx25840_read(client, 0x109); @@ -678,7 +678,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp * configuration in reg (for the cx23885) so we have no * need to attempt to flip bits for earlier av decoders. */ - if (!state->is_cx23885 && !state->is_cx231xx) { + if (!is_cx2388x(state) && !is_cx231xx(state)) { switch (aud_input) { case CX25840_AUDIO_SERIAL: /* do nothing, use serial audio input */ @@ -701,7 +701,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp /* Set INPUT_MODE to Composite (0) or S-Video (1) */ cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); - if (!state->is_cx23885 && !state->is_cx231xx) { + if (!is_cx2388x(state) && !is_cx231xx(state)) { /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */ @@ -720,12 +720,12 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp state->vid_input = vid_input; state->aud_input = aud_input; - if (!state->is_cx25836) { + if (!is_cx2583x(state)) { cx25840_audio_set_path(client); input_change(client); } - if (state->is_cx23885) { + if (is_cx2388x(state)) { /* Audio channel 1 src : Parallel 1 */ cx25840_write(client, 0x124, 0x03); @@ -741,7 +741,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp */ cx25840_write(client, 0x918, 0xa0); cx25840_write(client, 0x919, 0x01); - } else if (state->is_cx231xx) { + } else if (is_cx231xx(state)) { /* Audio channel 1 src : Parallel 1 */ cx25840_write(client, 0x124, 0x03); @@ -805,7 +805,7 @@ static int set_v4lstd(struct i2c_client *client) cx25840_and_or(client, 0x400, ~0xf, fmt); cx25840_and_or(client, 0x403, ~0x3, pal_m); cx25840_std_setup(client); - if (!state->is_cx25836) + if (!is_cx2583x(state)) input_change(client); return 0; } @@ -868,7 +868,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: - if (state->is_cx25836) + if (is_cx2583x(state)) return -EINVAL; return cx25840_audio_s_ctrl(sd, ctrl); @@ -905,7 +905,7 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: - if (state->is_cx25836) + if (is_cx2583x(state)) return -EINVAL; return cx25840_audio_g_ctrl(sd, ctrl); default: @@ -1209,11 +1209,11 @@ static int cx25840_load_fw(struct v4l2_subdev *sd) if (!state->is_initialized) { /* initialize and load firmware */ state->is_initialized = 1; - if (state->is_cx25836) + if (is_cx2583x(state)) cx25836_initialize(client); - else if (state->is_cx23885) + else if (is_cx2388x(state)) cx23885_initialize(client); - else if (state->is_cx231xx) + else if (is_cx231xx(state)) cx231xx_initialize(client); else cx25840_initialize(client); @@ -1256,17 +1256,17 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) v4l_dbg(1, cx25840_debug, client, "%s output\n", enable ? "enable" : "disable"); if (enable) { - if (state->is_cx23885 || state->is_cx231xx) { + if (is_cx2388x(state) || is_cx231xx(state)) { u8 v = (cx25840_read(client, 0x421) | 0x0b); cx25840_write(client, 0x421, v); } else { cx25840_write(client, 0x115, - state->is_cx25836 ? 0x0c : 0x8c); + is_cx2583x(state) ? 0x0c : 0x8c); cx25840_write(client, 0x116, - state->is_cx25836 ? 0x04 : 0x07); + is_cx2583x(state) ? 0x04 : 0x07); } } else { - if (state->is_cx23885 || state->is_cx231xx) { + if (is_cx2388x(state) || is_cx231xx(state)) { u8 v = cx25840_read(client, 0x421) & ~(0x0b); cx25840_write(client, 0x421, v); } else { @@ -1292,7 +1292,7 @@ static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) default: break; } - if (state->is_cx25836) + if (is_cx2583x(state)) return -EINVAL; switch (qc->id) { @@ -1346,7 +1346,7 @@ static int cx25840_s_audio_routing(struct v4l2_subdev *sd, struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (state->is_cx25836) + if (is_cx2583x(state)) return -EINVAL; return set_input(client, state->vid_input, input); } @@ -1356,7 +1356,7 @@ static int cx25840_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fr struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!state->is_cx25836) + if (!is_cx2583x(state)) input_change(client); return 0; } @@ -1373,7 +1373,7 @@ static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; vt->signal = vpres ? 0xffff : 0x0; - if (state->is_cx25836) + if (is_cx2583x(state)) return 0; vt->capability |= @@ -1404,7 +1404,7 @@ 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); - if (state->radio || state->is_cx25836) + if (state->radio || is_cx2583x(state)) return 0; switch (vt->audmode) { @@ -1445,11 +1445,11 @@ 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); - if (state->is_cx25836) + if (is_cx2583x(state)) cx25836_initialize(client); - else if (state->is_cx23885) + else if (is_cx2388x(state)) cx23885_initialize(client); - else if (state->is_cx231xx) + else if (is_cx231xx(state)) cx231xx_initialize(client); else cx25840_initialize(client); @@ -1470,7 +1470,7 @@ static int cx25840_log_status(struct v4l2_subdev *sd) struct i2c_client *client = v4l2_get_subdevdata(sd); log_video_status(client); - if (!state->is_cx25836) + if (!is_cx2583x(state)) log_audio_status(client); return 0; } @@ -1594,22 +1594,18 @@ static int cx25840_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &cx25840_ops); switch (id) { case V4L2_IDENT_CX23885_AV: - state->is_cx23885 = 1; v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; case V4L2_IDENT_CX23887_AV: - state->is_cx23885 = 1; v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; case V4L2_IDENT_CX23888_AV: - state->is_cx23885 = 1; v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; case V4L2_IDENT_CX2310X_AV: - state->is_cx231xx = 1; v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n", device_id, client->addr << 1, client->adapter->name); break; @@ -1627,7 +1623,6 @@ static int cx25840_probe(struct i2c_client *client, break; case V4L2_IDENT_CX25836: case V4L2_IDENT_CX25837: - state->is_cx25836 = 1; default: v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n", (device_id & 0xfff0) >> 4, device_id & 0x0f, diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 814b56536994..55345444417f 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h @@ -23,6 +23,7 @@ #include #include +#include #include /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is @@ -48,9 +49,6 @@ struct cx25840_state { int vbi_line_offset; u32 id; u32 rev; - int is_cx25836; - int is_cx23885; - int is_cx231xx; int is_initialized; wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ struct work_struct fw_work; /* work entry for fw load */ @@ -61,6 +59,24 @@ static inline struct cx25840_state *to_state(struct v4l2_subdev *sd) return container_of(sd, struct cx25840_state, sd); } +static inline bool is_cx2583x(struct cx25840_state *state) +{ + return state->id == V4L2_IDENT_CX25836 || + state->id == V4L2_IDENT_CX25837; +} + +static inline bool is_cx231xx(struct cx25840_state *state) +{ + return state->id == V4L2_IDENT_CX2310X_AV; +} + +static inline bool is_cx2388x(struct cx25840_state *state) +{ + return state->id == V4L2_IDENT_CX23885_AV || + state->id == V4L2_IDENT_CX23887_AV || + state->id == V4L2_IDENT_CX23888_AV; +} + /* ----------------------------------------------------------------------- */ /* cx25850-core.c */ int cx25840_write(struct i2c_client *client, u16 addr, u8 value); diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 1f483c1d0dbe..8150200511da 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -67,9 +67,9 @@ static const char *get_fw_name(struct i2c_client *client) if (firmware[0]) return firmware; - if (state->is_cx23885) + if (is_cx2388x(state)) return "v4l-cx23885-avcore-01.fw"; - if (state->is_cx231xx) + if (is_cx231xx(state)) return "v4l-cx231xx-avcore-01.fw"; return "v4l-cx25840.fw"; } @@ -112,13 +112,13 @@ int cx25840_loadfw(struct i2c_client *client) int MAX_BUF_SIZE = FWSEND; u32 gpio_oe = 0, gpio_da = 0; - if (state->is_cx23885) { + if (is_cx2388x(state)) { /* Preserve the GPIO OE and output bits */ gpio_oe = cx25840_read(client, 0x160); gpio_da = cx25840_read(client, 0x164); } - if ((state->is_cx231xx) && MAX_BUF_SIZE > 16) { + if (is_cx231xx(state) && MAX_BUF_SIZE > 16) { v4l_err(client, " Firmware download size changed to 16 bytes max length\n"); MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ } @@ -156,7 +156,7 @@ int cx25840_loadfw(struct i2c_client *client) size = fw->size; release_firmware(fw); - if (state->is_cx23885) { + if (is_cx2388x(state)) { /* Restore GPIO configuration after f/w load */ cx25840_write(client, 0x160, gpio_oe); cx25840_write(client, 0x164, gpio_da); From 9eef550a9a98c1e3d15aaf490812949fdeb01c7c Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 26 Sep 2009 23:54:20 -0300 Subject: [PATCH 040/345] V4L/DVB (13089): cx25840: Separate set_audclk_freq functionality for the different chips Separate out the set_audclk_freq() function into separate functions for the four families of cores. These cores all use slightly different sample clock schemes and may be assuming slightly (+/- 3 Hz) different reference frequencies. The code resuse was not worth the maintenance and testing headache of have all chips use the same function peppered with conditional logic. Added comments on how PLL and SRC parameters values are computed. Fixed a few bugs related to the shared code having a large number of conditional statements. Noted inconsistencies with FIXME in the comments. This is done in preparation for getting the CX2388[578] PLL/clock setting logic cleaned up for CX23888 analog video and IR (which need the VID PLL set right). Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-audio.c | 417 +++++++++++++++----- 1 file changed, 322 insertions(+), 95 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index fbccbdce26e0..45608d50529c 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c @@ -23,87 +23,137 @@ #include "cx25840-core.h" -static int set_audclk_freq(struct i2c_client *client, u32 freq) +/* + * Note: The PLL and SRC parameters are based on a reference frequency that + * would ideally be: + * + * NTSC Color subcarrier freq * 8 = 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz + * + * However, it's not the exact reference frequency that matters, only that the + * firmware and modules that comprise the driver for a particular board all + * use the same value (close to the ideal value). + * + * Comments below will note which reference frequency is assumed for various + * parameters. They will usually be one of + * + * ref_freq = 28.636360 MHz + * or + * ref_freq = 28.636363 MHz + */ + +static int cx25840_set_audclk_freq(struct i2c_client *client, u32 freq) { struct cx25840_state *state = to_state(i2c_get_clientdata(client)); - if (freq != 32000 && freq != 44100 && freq != 48000) - return -EINVAL; - - /* common for all inputs and rates */ - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ - if (!is_cx2388x(state) && !is_cx231xx(state)) - cx25840_write(client, 0x127, 0x50); - if (state->aud_input != CX25840_AUDIO_SERIAL) { switch (freq) { case 32000: - if (is_cx2388x(state)) { - /* We don't have register values - * so avoid destroying registers. */ - break; - } + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x06, AUX PLL Post Divider = 0x10 + */ + cx25840_write4(client, 0x108, 0x1006040f); - if (!is_cx231xx(state)) { - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1006040f); + /* + * VID_PLL Fraction (register 0x10c) = 0x2be2fe + * 28636360 * 0xf.15f17f0/4 = 108 MHz + * 432 MHz pre-postdivide + */ - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x01bb39ee); - } + /* + * AUX_PLL Fraction = 0x1bb39ee + * 28636363 * 0x6.dd9cf70/0x10 = 32000 * 384 + * 196.6 MHz pre-postdivide + * FIXME < 200 MHz is out of specified valid range + * FIXME 28636363 ref_freq doesn't match VID PLL ref + */ + cx25840_write4(client, 0x110, 0x01bb39ee); + + /* + * SA_MCLK_SEL = 1 + * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider + */ + cx25840_write(client, 0x127, 0x50); if (is_cx2583x(state)) break; - /* src3/4/6_ctl = 0x0801f77f */ + /* src3/4/6_ctl */ + /* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */ cx25840_write4(client, 0x900, 0x0801f77f); cx25840_write4(client, 0x904, 0x0801f77f); cx25840_write4(client, 0x90c, 0x0801f77f); break; case 44100: - if (is_cx2388x(state)) { - /* We don't have register values - * so avoid destroying registers. */ - break; - } + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x10 + */ + cx25840_write4(client, 0x108, 0x1009040f); - if (!is_cx231xx(state)) { - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1009040f); + /* + * VID_PLL Fraction (register 0x10c) = 0x2be2fe + * 28636360 * 0xf.15f17f0/4 = 108 MHz + * 432 MHz pre-postdivide + */ - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x00ec6bd6); - } + /* + * AUX_PLL Fraction = 0x0ec6bd6 + * 28636363 * 0x9.7635eb0/0x10 = 44100 * 384 + * 271 MHz pre-postdivide + * FIXME 28636363 ref_freq doesn't match VID PLL ref + */ + cx25840_write4(client, 0x110, 0x00ec6bd6); + + /* + * SA_MCLK_SEL = 1 + * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider + */ + cx25840_write(client, 0x127, 0x50); if (is_cx2583x(state)) break; - /* src3/4/6_ctl = 0x08016d59 */ + /* src3/4/6_ctl */ + /* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */ cx25840_write4(client, 0x900, 0x08016d59); cx25840_write4(client, 0x904, 0x08016d59); cx25840_write4(client, 0x90c, 0x08016d59); break; case 48000: - if (is_cx2388x(state)) { - /* We don't have register values - * so avoid destroying registers. */ - break; - } + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x10 + */ + cx25840_write4(client, 0x108, 0x100a040f); - if (!is_cx231xx(state)) { - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x100a040f); + /* + * VID_PLL Fraction (register 0x10c) = 0x2be2fe + * 28636360 * 0xf.15f17f0/4 = 108 MHz + * 432 MHz pre-postdivide + */ - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x0098d6e5); - } + /* + * AUX_PLL Fraction = 0x098d6e5 + * 28636363 * 0xa.4c6b728/0x10 = 48000 * 384 + * 295 MHz pre-postdivide + * FIXME 28636363 ref_freq doesn't match VID PLL ref + */ + cx25840_write4(client, 0x110, 0x0098d6e5); + + /* + * SA_MCLK_SEL = 1 + * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider + */ + cx25840_write(client, 0x127, 0x50); if (is_cx2583x(state)) break; - /* src3/4/6_ctl = 0x08014faa */ + /* src3/4/6_ctl */ + /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */ cx25840_write4(client, 0x900, 0x08014faa); cx25840_write4(client, 0x904, 0x08014faa); cx25840_write4(client, 0x90c, 0x08014faa); @@ -112,91 +162,126 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } else { switch (freq) { case 32000: - if (is_cx2388x(state)) { - /* We don't have register values - * so avoid destroying registers. */ - break; - } + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x08, AUX PLL Post Divider = 0x1e + */ + cx25840_write4(client, 0x108, 0x1e08040f); - if (!is_cx231xx(state)) { - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1e08040f); + /* + * VID_PLL Fraction (register 0x10c) = 0x2be2fe + * 28636360 * 0xf.15f17f0/4 = 108 MHz + * 432 MHz pre-postdivide + */ - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x012a0869); - } + /* + * AUX_PLL Fraction = 0x12a0869 + * 28636363 * 0x8.9504348/0x1e = 32000 * 256 + * 246 MHz pre-postdivide + * FIXME 28636363 ref_freq doesn't match VID PLL ref + */ + cx25840_write4(client, 0x110, 0x012a0869); + + /* + * SA_MCLK_SEL = 1 + * SA_MCLK_DIV = 0x14 = 256/384 * AUX_PLL post dvivider + */ + cx25840_write(client, 0x127, 0x54); if (is_cx2583x(state)) break; - /* src1_ctl = 0x08010000 */ + /* src1_ctl */ + /* 0x1.0000 = 32000/32000 */ cx25840_write4(client, 0x8f8, 0x08010000); - /* src3/4/6_ctl = 0x08020000 */ + /* src3/4/6_ctl */ + /* 0x2.0000 = 2 * (32000/32000) */ cx25840_write4(client, 0x900, 0x08020000); cx25840_write4(client, 0x904, 0x08020000); cx25840_write4(client, 0x90c, 0x08020000); - - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ - cx25840_write(client, 0x127, 0x54); break; case 44100: - if (is_cx2388x(state)) { - /* We don't have register values - * so avoid destroying registers. */ - break; - } + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x18 + */ + cx25840_write4(client, 0x108, 0x1809040f); + /* + * VID_PLL Fraction (register 0x10c) = 0x2be2fe + * 28636360 * 0xf.15f17f0/4 = 108 MHz + * 432 MHz pre-postdivide + */ - if (!is_cx231xx(state)) { - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1809040f); + /* + * AUX_PLL Fraction = 0x0ec6bd6 + * 28636363 * 0x9.7635eb0/0x18 = 44100 * 256 + * 271 MHz pre-postdivide + * FIXME 28636363 ref_freq doesn't match VID PLL ref + */ + cx25840_write4(client, 0x110, 0x00ec6bd6); - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x00ec6bd6); - } + /* + * SA_MCLK_SEL = 1 + * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider + */ + cx25840_write(client, 0x127, 0x50); if (is_cx2583x(state)) break; - /* src1_ctl = 0x08010000 */ + /* src1_ctl */ + /* 0x1.60cd = 44100/32000 */ cx25840_write4(client, 0x8f8, 0x080160cd); - /* src3/4/6_ctl = 0x08020000 */ + /* src3/4/6_ctl */ + /* 0x1.7385 = 2 * (32000/44100) */ cx25840_write4(client, 0x900, 0x08017385); cx25840_write4(client, 0x904, 0x08017385); cx25840_write4(client, 0x90c, 0x08017385); break; case 48000: - if (!is_cx2388x(state) && !is_cx231xx(state)) { - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x180a040f); + /* + * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 + * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x18 + */ + cx25840_write4(client, 0x108, 0x180a040f); - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x0098d6e5); - } + /* + * VID_PLL Fraction (register 0x10c) = 0x2be2fe + * 28636360 * 0xf.15f17f0/4 = 108 MHz + * 432 MHz pre-postdivide + */ + + /* + * AUX_PLL Fraction = 0x098d6e5 + * 28636363 * 0xa.4c6b728/0x18 = 48000 * 256 + * 295 MHz pre-postdivide + * FIXME 28636363 ref_freq doesn't match VID PLL ref + */ + cx25840_write4(client, 0x110, 0x0098d6e5); + + /* + * SA_MCLK_SEL = 1 + * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider + */ + cx25840_write(client, 0x127, 0x50); if (is_cx2583x(state)) break; - if (!is_cx2388x(state) && !is_cx231xx(state)) { - /* src1_ctl */ - cx25840_write4(client, 0x8f8, 0x08018000); + /* src1_ctl */ + /* 0x1.8000 = 48000/32000 */ + cx25840_write4(client, 0x8f8, 0x08018000); - /* src3/4/6_ctl */ - cx25840_write4(client, 0x900, 0x08015555); - cx25840_write4(client, 0x904, 0x08015555); - cx25840_write4(client, 0x90c, 0x08015555); - } else { - - cx25840_write4(client, 0x8f8, 0x0801867c); - - cx25840_write4(client, 0x900, 0x08014faa); - cx25840_write4(client, 0x904, 0x08014faa); - cx25840_write4(client, 0x90c, 0x08014faa); - } + /* src3/4/6_ctl */ + /* 0x1.5555 = 2 * (32000/48000) */ + cx25840_write4(client, 0x900, 0x08015555); + cx25840_write4(client, 0x904, 0x08015555); + cx25840_write4(client, 0x90c, 0x08015555); break; } } @@ -206,6 +291,148 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) return 0; } +static inline int cx25836_set_audclk_freq(struct i2c_client *client, u32 freq) +{ + return cx25840_set_audclk_freq(client, freq); +} + +static int cx23885_set_audclk_freq(struct i2c_client *client, u32 freq) +{ + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); + + if (state->aud_input != CX25840_AUDIO_SERIAL) { + switch (freq) { + case 32000: + case 44100: + case 48000: + /* We don't have register values + * so avoid destroying registers. */ + /* FIXME return -EINVAL; */ + break; + } + } else { + switch (freq) { + case 32000: + case 44100: + /* We don't have register values + * so avoid destroying registers. */ + /* FIXME return -EINVAL; */ + break; + + case 48000: + /* src1_ctl */ + /* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */ + cx25840_write4(client, 0x8f8, 0x0801867c); + + /* src3/4/6_ctl */ + /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */ + cx25840_write4(client, 0x900, 0x08014faa); + cx25840_write4(client, 0x904, 0x08014faa); + cx25840_write4(client, 0x90c, 0x08014faa); + break; + } + } + + state->audclk_freq = freq; + + return 0; +} + +static int cx231xx_set_audclk_freq(struct i2c_client *client, u32 freq) +{ + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); + + if (state->aud_input != CX25840_AUDIO_SERIAL) { + switch (freq) { + case 32000: + /* src3/4/6_ctl */ + /* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */ + cx25840_write4(client, 0x900, 0x0801f77f); + cx25840_write4(client, 0x904, 0x0801f77f); + cx25840_write4(client, 0x90c, 0x0801f77f); + break; + + case 44100: + /* src3/4/6_ctl */ + /* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */ + cx25840_write4(client, 0x900, 0x08016d59); + cx25840_write4(client, 0x904, 0x08016d59); + cx25840_write4(client, 0x90c, 0x08016d59); + break; + + case 48000: + /* src3/4/6_ctl */ + /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */ + cx25840_write4(client, 0x900, 0x08014faa); + cx25840_write4(client, 0x904, 0x08014faa); + cx25840_write4(client, 0x90c, 0x08014faa); + break; + } + } else { + switch (freq) { + /* FIXME These cases make different assumptions about audclk */ + case 32000: + /* src1_ctl */ + /* 0x1.0000 = 32000/32000 */ + cx25840_write4(client, 0x8f8, 0x08010000); + + /* src3/4/6_ctl */ + /* 0x2.0000 = 2 * (32000/32000) */ + cx25840_write4(client, 0x900, 0x08020000); + cx25840_write4(client, 0x904, 0x08020000); + cx25840_write4(client, 0x90c, 0x08020000); + break; + + case 44100: + /* src1_ctl */ + /* 0x1.60cd = 44100/32000 */ + cx25840_write4(client, 0x8f8, 0x080160cd); + + /* src3/4/6_ctl */ + /* 0x1.7385 = 2 * (32000/44100) */ + cx25840_write4(client, 0x900, 0x08017385); + cx25840_write4(client, 0x904, 0x08017385); + cx25840_write4(client, 0x90c, 0x08017385); + break; + + case 48000: + /* src1_ctl */ + /* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */ + cx25840_write4(client, 0x8f8, 0x0801867c); + + /* src3/4/6_ctl */ + /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */ + cx25840_write4(client, 0x900, 0x08014faa); + cx25840_write4(client, 0x904, 0x08014faa); + cx25840_write4(client, 0x90c, 0x08014faa); + break; + } + } + + state->audclk_freq = freq; + + return 0; +} + +static int set_audclk_freq(struct i2c_client *client, u32 freq) +{ + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); + + if (freq != 32000 && freq != 44100 && freq != 48000) + return -EINVAL; + + if (is_cx231xx(state)) + return cx231xx_set_audclk_freq(client, freq); + + if (is_cx2388x(state)) + return cx23885_set_audclk_freq(client, freq); + + if (is_cx2583x(state)) + return cx25836_set_audclk_freq(client, freq); + + return cx25840_set_audclk_freq(client, freq); +} + void cx25840_audio_set_path(struct i2c_client *client) { struct cx25840_state *state = to_state(i2c_get_clientdata(client)); From e283d78083271c9faf784daad6367dfb903d0f06 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 27 Sep 2009 00:00:48 -0300 Subject: [PATCH 041/345] V4L/DVB (13090): cx25840: Init PLLs properly for CX2388[578] A/V cores The SYS and AUX PLLs need to be initialized to different values based on the chip: CX23885, CX23887, CX23888, as each uses a different crystal frequency: 28.6363 MHz, 25.0 MHz, 50.0 MHz. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 106 +++++++++++++++++---- 1 file changed, 88 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index a6446e637f17..56ead3d37926 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -259,6 +259,13 @@ static void cx23885_initialize(struct i2c_client *client) struct cx25840_state *state = to_state(i2c_get_clientdata(client)); struct workqueue_struct *q; + /* + * Come out of digital power down + * The CX23888, at least, needs this, otherwise registers aside from + * 0x0-0x2 can't be read or written. + */ + cx25840_write(client, 0x000, 0); + /* Internal Reset */ cx25840_and_or(client, 0x102, ~0x01, 0x01); cx25840_and_or(client, 0x102, ~0x01, 0x00); @@ -269,18 +276,45 @@ static void cx23885_initialize(struct i2c_client *client) /* DIF in reset? */ cx25840_write(client, 0x398, 0); - /* Trust the default xtal, no division */ - /* This changes for the cx23888 products */ + /* + * Trust the default xtal, no division + * '885: 28.636363... MHz + * '887: 25.000000 MHz + * '888: 50.000000 MHz + */ cx25840_write(client, 0x2, 0x76); - /* Bring down the regulator for AUX clk */ + /* Power up all the PLL's and DLL */ cx25840_write(client, 0x1, 0x40); - /* Sys PLL frac */ - cx25840_write4(client, 0x11c, 0x01d1744c); - - /* Sys PLL int */ - cx25840_write4(client, 0x118, 0x00000416); + /* Sys PLL */ + switch (state->id) { + case V4L2_IDENT_CX23888_AV: + /* + * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz + * 572.73 MHz before post divide + */ + cx25840_write4(client, 0x11c, 0x00e8ba26); + cx25840_write4(client, 0x118, 0x0000040b); + break; + case V4L2_IDENT_CX23887_AV: + /* + * 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz + * 572.73 MHz before post divide + */ + cx25840_write4(client, 0x11c, 0x01d1744c); + cx25840_write4(client, 0x118, 0x00000416); + break; + case V4L2_IDENT_CX23885_AV: + default: + /* + * 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz + * 572.73 MHz before post divide + */ + cx25840_write4(client, 0x11c, 0x00000000); + cx25840_write4(client, 0x118, 0x00000414); + break; + } /* Disable DIF bypass */ cx25840_write4(client, 0x33c, 0x00000001); @@ -288,11 +322,15 @@ static void cx23885_initialize(struct i2c_client *client) /* DIF Src phase inc */ cx25840_write4(client, 0x340, 0x0df7df83); - /* Vid PLL frac */ - cx25840_write4(client, 0x10c, 0x01b6db7b); - - /* Vid PLL int */ - cx25840_write4(client, 0x108, 0x00000512); + /* + * Vid PLL + * Setup for a BT.656 pixel clock of 13.5 Mpixels/second + * + * 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz + * 432.0 MHz before post divide + */ + cx25840_write4(client, 0x10c, 0x002be2c9); + cx25840_write4(client, 0x108, 0x0000040f); /* Luma */ cx25840_write4(client, 0x414, 0x00107d12); @@ -300,11 +338,43 @@ static void cx23885_initialize(struct i2c_client *client) /* Chroma */ cx25840_write4(client, 0x420, 0x3d008282); - /* Aux PLL frac */ - cx25840_write4(client, 0x114, 0x017dbf48); - - /* Aux PLL int */ - cx25840_write4(client, 0x110, 0x000a030e); + /* + * Aux PLL + * Initial setup for audio sample clock: + * 48 ksps, 16 bits/sample, x160 multiplier = 122.88 MHz + * Intial I2S output/master clock(?): + * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz + */ + switch (state->id) { + case V4L2_IDENT_CX23888_AV: + /* + * 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz + * 368.64 MHz before post divide + * 122.88 MHz / 0xa = 12.288 MHz + */ + cx25840_write4(client, 0x114, 0x00bedfa4); + cx25840_write4(client, 0x110, 0x000a0307); + break; + case V4L2_IDENT_CX23887_AV: + /* + * 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz + * 368.64 MHz before post divide + * 122.88 MHz / 0xa = 12.288 MHz + */ + cx25840_write4(client, 0x114, 0x017dbf48); + cx25840_write4(client, 0x110, 0x000a030e); + break; + case V4L2_IDENT_CX23885_AV: + default: + /* + * 28.636363 MHz * (0xc + 0x1bf0c9e/0x2000000)/3 = 122.88 MHz + * 368.64 MHz before post divide + * 122.88 MHz / 0xa = 12.288 MHz + */ + cx25840_write4(client, 0x114, 0x01bf0c9e); + cx25840_write4(client, 0x110, 0x000a030c); + break; + }; /* ADC2 input select */ cx25840_write(client, 0x102, 0x10); From c6b7053bbc3b1ec556780327cef0d0463e1537ea Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 27 Sep 2009 00:14:33 -0300 Subject: [PATCH 042/345] V4L/DVB (13091): cx23885: Enable HVR-1850 CX23888 A/V core to get VID_CLK running for IR For the IR controller on the CX23888 to work for the HVR-1850 and in general, the A/V core must be initialized to get the VID_CLK going. The VID_CLK is the timing reference for the CX23888's integrated IR controller. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 4b5aa08036fa..7c5d13ac538e 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -946,6 +946,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: + case CX23885_BOARD_HAUPPAUGE_HVR1850: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, "cx25840", "cx25840", 0x88 >> 1, NULL); From 8c2d7821d4e3827c29e4e4e345ee25390a141e55 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sun, 27 Sep 2009 15:54:47 -0300 Subject: [PATCH 043/345] V4L/DVB (13092): cx25840: Improvements to the cx23885/7/8 chip detection mechanism. The prior mechanism wasn't reliable with the cx23887. This new mechanism tests correctly against cx23885, 7 and 8 based products. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 56ead3d37926..904e9a5a9065 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1598,14 +1598,29 @@ static u32 get_cx2388x_ident(struct i2c_client *client) /* Come out of digital power down */ cx25840_write(client, 0x000, 0); + /* Detecting whether the part is cx23885/7/8 is more + * difficult than it needs to be. No ID register. Instead we + * probe certain registers indicated in the datasheets to look + * for specific defaults that differ between the silicon designs. */ + + /* It's either 885/7 if the IR Tx Clk Divider register exists */ if (cx25840_read4(client, 0x204) & 0xffff) { - /* IR Tx Clk Divider register exists; chip must be a CX23885 */ - ret = V4L2_IDENT_CX23885_AV; + /* CX23885 returns bogus repetitive byte values for the DIF, + * which doesn't exist for it. (Ex. 8a8a8a8a or 31313131) */ + ret = cx25840_read4(client, 0x300); + if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) { + /* No DIF */ + ret = V4L2_IDENT_CX23885_AV; + } else { + /* CX23887 has a broken DIF, but the registers + * appear valid (but unsed), good enough to detect. */ + ret = V4L2_IDENT_CX23887_AV; + } } else if (cx25840_read4(client, 0x300) & 0x0fffffff) { /* DIF PLL Freq Word reg exists; chip must be a CX23888 */ ret = V4L2_IDENT_CX23888_AV; } else { - /* A CX23887 A/V core has neither IR nor DIF */ + v4l_err(client, "Unable to detect h/w, assuming cx23887\n"); ret = V4L2_IDENT_CX23887_AV; } From 1d986add96a06f311cfef377b36602514db54507 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 27 Sep 2009 17:50:04 -0300 Subject: [PATCH 044/345] V4L/DVB (13096): v4l2-subdev: Add v4l2_subdev_ir_ops and IR notify defines for v4l2_device Add v4l2_subdev_ir_ops and IR notify defines for v4l2_device. This change is specifically needed at this time to support the integrated IR controller in the CX2388[58] chips. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 94 +++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index d411345f244b..ecc2818938b3 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -23,6 +23,16 @@ #include +/* generic v4l2_device notify callback notification values */ +#define V4L2_SUBDEV_IR_RX_NOTIFY _IOW('v', 0, u32) +#define V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ 0x00000001 +#define V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED 0x00000002 +#define V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN 0x00000004 +#define V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN 0x00000008 + +#define V4L2_SUBDEV_IR_TX_NOTIFY _IOW('v', 1, u32) +#define V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ 0x00000001 + struct v4l2_device; struct v4l2_subdev; struct tuner_setup; @@ -231,11 +241,95 @@ struct v4l2_subdev_video_ops { int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival); }; +/* + interrupt_service_routine: Called by the bridge chip's interrupt service + handler, when an IR interrupt status has be raised due to this subdev, + so that this subdev can handle the details. It may schedule work to be + performed later. It must not sleep. *Called from an IRQ context*. + + [rt]x_g_parameters: Get the current operating parameters and state of the + the IR receiver or transmitter. + + [rt]x_s_parameters: Set the current operating parameters and state of the + the IR receiver or transmitter. It is recommended to call + [rt]x_g_parameters first to fill out the current state, and only change + the fields that need to be changed. Upon return, the actual device + operating parameters and state will be returned. Note that hardware + limitations may prevent the actual settings from matching the requested + settings - e.g. an actual carrier setting of 35,904 Hz when 36,000 Hz + was requested. An exception is when the shutdown parameter is true. + The last used operational parameters will be returned, but the actual + state of the hardware be different to minimize power consumption and + processing when shutdown is true. + + rx_read: Reads received codes or pulse width data. + The semantics are similar to a non-blocking read() call. + + tx_write: Writes codes or pulse width data for transmission. + The semantics are similar to a non-blocking write() call. + */ + +enum v4l2_subdev_ir_mode { + V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, /* space & mark widths in nanosecs */ +}; + +/* Data format of data read or written for V4L2_SUBDEV_IR_MODE_PULSE_WIDTH */ +#define V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS 0x7fffffff +#define V4L2_SUBDEV_IR_PULSE_LEVEL_MASK 0x80000000 +#define V4L2_SUBDEV_IR_PULSE_RX_SEQ_END 0xffffffff + +struct v4l2_subdev_ir_parameters { + /* Either Rx or Tx */ + unsigned int bytes_per_data_element; /* of data in read or write call */ + enum v4l2_subdev_ir_mode mode; + + bool enable; + bool interrupt_enable; + bool shutdown; /* true: set hardware to low/no power, false: normal */ + + bool modulation; /* true: uses carrier, false: baseband */ + u32 max_pulse_width; /* ns, valid only for baseband signal */ + unsigned int carrier_freq; /* Hz, valid only for modulated signal*/ + unsigned int duty_cycle; /* percent, valid only for modulated signal*/ + bool invert; /* logically invert sense of mark/space */ + + /* Rx only */ + u32 noise_filter_min_width; /* ns, min time of a valid pulse */ + unsigned int carrier_range_lower; /* Hz, valid only for modulated sig */ + unsigned int carrier_range_upper; /* Hz, valid only for modulated sig */ + u32 resolution; /* ns */ +}; + +struct v4l2_subdev_ir_ops { + /* Common to receiver and transmitter */ + int (*interrupt_service_routine)(struct v4l2_subdev *sd, + u32 status, bool *handled); + + /* Receiver */ + int (*rx_read)(struct v4l2_subdev *sd, u8 *buf, size_t count, + ssize_t *num); + + int (*rx_g_parameters)(struct v4l2_subdev *sd, + struct v4l2_subdev_ir_parameters *params); + int (*rx_s_parameters)(struct v4l2_subdev *sd, + struct v4l2_subdev_ir_parameters *params); + + /* Transmitter */ + int (*tx_write)(struct v4l2_subdev *sd, u8 *buf, size_t count, + ssize_t *num); + + int (*tx_g_parameters)(struct v4l2_subdev *sd, + struct v4l2_subdev_ir_parameters *params); + int (*tx_s_parameters)(struct v4l2_subdev *sd, + struct v4l2_subdev_ir_parameters *params); +}; + 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; + const struct v4l2_subdev_ir_ops *ir; }; #define V4L2_SUBDEV_NAME_SIZE 32 From 1a0b9d89c62ddf0aed12798686fe452e7e97de42 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 27 Sep 2009 18:31:37 -0300 Subject: [PATCH 045/345] V4L/DVB (13097): cx23885: Complete CX23888 IR subdev implementation for Rx & almost for Tx This change completes the v4l2_subdev implementation for IR receive for the IR controller built into the CX23888. This changes almost completes the IR transmit side also, but doesn't. Instead notes in the comments describe what needs to be done for IR Tx to work in the subdevice implementation. The current Tx behavior is skeletal and benign. If left alone, it does nothing. It will only ever generate a Tx interrupt on Tx init by a caller or when the tx_write() method is called. The ISR, when called, will then disable the Tx FIFO service interrupt. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23888-ir.c | 1073 +++++++++++++++++++++- 1 file changed, 1039 insertions(+), 34 deletions(-) diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index 12df0e3a2354..e8d949ae06b9 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -21,25 +21,79 @@ * 02110-1301, USA. */ +#include + #include #include #include "cx23885.h" +static unsigned int ir_888_debug; +module_param(ir_888_debug, int, 0644); +MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]"); + #define CX23888_IR_REG_BASE 0x170000 /* * These CX23888 register offsets have a straightforward one to one mapping * to the CX23885 register offsets of 0x200 through 0x218 */ #define CX23888_IR_CNTRL_REG 0x170000 +#define CNTRL_WIN_3_3 0x00000000 +#define CNTRL_WIN_4_3 0x00000001 +#define CNTRL_WIN_3_4 0x00000002 +#define CNTRL_WIN_4_4 0x00000003 +#define CNTRL_WIN 0x00000003 +#define CNTRL_EDG_NONE 0x00000000 +#define CNTRL_EDG_FALL 0x00000004 +#define CNTRL_EDG_RISE 0x00000008 +#define CNTRL_EDG_BOTH 0x0000000C +#define CNTRL_EDG 0x0000000C +#define CNTRL_DMD 0x00000010 +#define CNTRL_MOD 0x00000020 +#define CNTRL_RFE 0x00000040 +#define CNTRL_TFE 0x00000080 +#define CNTRL_RXE 0x00000100 +#define CNTRL_TXE 0x00000200 +#define CNTRL_RIC 0x00000400 +#define CNTRL_TIC 0x00000800 +#define CNTRL_CPL 0x00001000 +#define CNTRL_LBM 0x00002000 +#define CNTRL_R 0x00004000 + #define CX23888_IR_TXCLK_REG 0x170004 +#define TXCLK_TCD 0x0000FFFF + #define CX23888_IR_RXCLK_REG 0x170008 +#define RXCLK_RCD 0x0000FFFF + #define CX23888_IR_CDUTY_REG 0x17000C +#define CDUTY_CDC 0x0000000F + #define CX23888_IR_STATS_REG 0x170010 +#define STATS_RTO 0x00000001 +#define STATS_ROR 0x00000002 +#define STATS_RBY 0x00000004 +#define STATS_TBY 0x00000008 +#define STATS_RSR 0x00000010 +#define STATS_TSR 0x00000020 + #define CX23888_IR_IRQEN_REG 0x170014 +#define IRQEN_RTE 0x00000001 +#define IRQEN_ROE 0x00000002 +#define IRQEN_RSE 0x00000010 +#define IRQEN_TSE 0x00000020 + #define CX23888_IR_FILTR_REG 0x170018 +#define FILTR_LPF 0x0000FFFF + /* This register doesn't follow the pattern; it's 0x23C on a CX23885 */ #define CX23888_IR_FIFO_REG 0x170040 +#define FIFO_RXTX 0x0000FFFF +#define FIFO_RXTX_LVL 0x00010000 +#define FIFO_RXTX_RTO 0x0001FFFF +#define FIFO_RX_NDV 0x00020000 +#define FIFO_RX_DEPTH 8 +#define FIFO_TX_DEPTH 8 /* CX23888 unique registers */ #define CX23888_IR_SEEDP_REG 0x17001C @@ -53,12 +107,32 @@ #define CX23888_IR_DPIPG_REG 0x17003C #define CX23888_IR_LEARN_REG 0x170044 +#define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */ +#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ/2) + +#define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32)) +#define CX23888_IR_TX_KFIFO_SIZE (512 * sizeof(u32)) struct cx23888_ir_state { struct v4l2_subdev sd; struct cx23885_dev *dev; u32 id; u32 rev; + + struct v4l2_subdev_ir_parameters rx_params; + struct mutex rx_params_lock; + atomic_t rxclk_divider; + atomic_t rx_invert; + + struct kfifo *rx_kfifo; + spinlock_t rx_kfifo_lock; + + struct v4l2_subdev_ir_parameters tx_params; + struct mutex tx_params_lock; + atomic_t txclk_divider; + + struct kfifo *tx_kfifo; + spinlock_t tx_kfifo_lock; }; static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) @@ -66,17 +140,9 @@ static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) return v4l2_get_subdevdata(sd); } -static int cx23888_ir_write(struct cx23885_dev *dev, u32 addr, u8 value) -{ - u32 reg = (addr & ~3); - int shift = (addr & 3) * 8; - u32 x = cx_read(reg); - - x = (x & ~(0xff << shift)) | ((u32)value << shift); - cx_write(reg, x); - return 0; -} - +/* + * IR register block read and write functions + */ static inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value) { @@ -84,41 +150,893 @@ inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value) return 0; } -static u8 cx23888_ir_read(struct cx23885_dev *dev, u32 addr) -{ - u32 x = cx_read((addr & ~3)); - int shift = (addr & 3) * 8; - - return (x >> shift) & 0xff; -} - static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr) { return cx_read(addr); } -static int cx23888_ir_and_or(struct cx23885_dev *dev, u32 addr, - unsigned and_mask, u8 or_value) -{ - return cx23888_ir_write(dev, addr, - (cx23888_ir_read(dev, addr) & and_mask) | - or_value); -} - static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr, u32 and_mask, u32 or_value) { - cx_andor(addr, and_mask, or_value); + cx_andor(addr, ~and_mask, or_value); return 0; } +/* + * Rx and Tx Clock Divider register computations + * + * Note the largest clock divider value of 0xffff corresponds to: + * (0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns + * which fits in 21 bits, so we'll use unsigned int for time arguments. + */ +static inline u16 count_to_clock_divider(unsigned int d) +{ + if (d > RXCLK_RCD+1) + d = RXCLK_RCD; + else if (d < 2) + d = 1; + else + d--; + return (u16) d; +} + +static inline u16 ns_to_clock_divider(unsigned int ns) +{ + return count_to_clock_divider( + DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ/1000000 * ns, 1000)); +} + +static inline unsigned int clock_divider_to_ns(unsigned int divider) +{ + /* Period of the Rx or Tx clock in ns */ + return DIV_ROUND_CLOSEST((divider + 1) * 1000, + CX23888_IR_REFCLK_FREQ/1000000); +} + +static inline u16 carrier_freq_to_clock_divider(unsigned int freq) +{ + return count_to_clock_divider( + DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * 16)); +} + +static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider) +{ + return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, (divider + 1) * 16); +} + +static inline u16 freq_to_clock_divider(unsigned int freq, + unsigned int rollovers) +{ + return count_to_clock_divider( + DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * rollovers)); +} + +static inline unsigned int clock_divider_to_freq(unsigned int divider, + unsigned int rollovers) +{ + return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, + (divider + 1) * rollovers); +} + +/* + * Low Pass Filter register calculations + * + * Note the largest count value of 0xffff corresponds to: + * 0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns + * which fits in 21 bits, so we'll use unsigned int for time arguments. + */ +static inline u16 count_to_lpf_count(unsigned int d) +{ + if (d > FILTR_LPF) + d = FILTR_LPF; + else if (d < 4) + d = 0; + return (u16) d; +} + +static inline u16 ns_to_lpf_count(unsigned int ns) +{ + return count_to_lpf_count( + DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ/1000000 * ns, 1000)); +} + +static inline unsigned int lpf_count_to_ns(unsigned int count) +{ + /* Duration of the Low Pass Filter rejection window in ns */ + return DIV_ROUND_CLOSEST(count * 1000, CX23888_IR_REFCLK_FREQ/1000000); +} + +static inline unsigned int lpf_count_to_us(unsigned int count) +{ + /* Duration of the Low Pass Filter rejection window in us */ + return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ/1000000); +} + +/* + * FIFO register pulse width count compuations + */ +static u32 clock_divider_to_resolution(u16 divider) +{ + /* + * Resolution is the duration of 1 tick of the readable portion of + * of the pulse width counter as read from the FIFO. The two lsb's are + * not readable, hence the << 2. This function returns ns. + */ + return DIV_ROUND_CLOSEST((1 << 2) * ((u32) divider + 1) * 1000, + CX23888_IR_REFCLK_FREQ/1000000); +} + +static u64 pulse_width_count_to_ns(u16 count, u16 divider) +{ + u64 n; + u32 rem; + + /* + * The 2 lsb's of the pulse width timer count are not readable, hence + * the (count << 2) | 0x3 + */ + n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */ + rem = do_div(n, CX23888_IR_REFCLK_FREQ/1000000); /* / MHz => ns */ + if (rem >= CX23888_IR_REFCLK_FREQ/1000000/2) + n++; + return n; +} + +static unsigned int pulse_width_count_to_us(u16 count, u16 divider) +{ + u64 n; + u32 rem; + + /* + * The 2 lsb's of the pulse width timer count are not readable, hence + * the (count << 2) | 0x3 + */ + n = (((u64) count << 2) | 0x3) * (divider + 1); /* cycles */ + rem = do_div(n, CX23888_IR_REFCLK_FREQ/1000000); /* / MHz => us */ + if (rem >= CX23888_IR_REFCLK_FREQ/1000000/2) + n++; + return (unsigned int) n; +} + +/* + * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts + * + * The total pulse clock count is an 18 bit pulse width timer count as the most + * significant part and (up to) 16 bit clock divider count as a modulus. + * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse + * width timer count's least significant bit. + */ +static u64 ns_to_pulse_clocks(u32 ns) +{ + u64 clocks; + u32 rem; + clocks = CX23888_IR_REFCLK_FREQ/1000000 * (u64) ns; /* millicycles */ + rem = do_div(clocks, 1000); /* /1000 = cycles */ + if (rem >= 1000/2) + clocks++; + return clocks; +} + +static u16 pulse_clocks_to_clock_divider(u64 count) +{ + u32 rem; + + rem = do_div(count, (FIFO_RXTX << 2) | 0x3); + + /* net result needs to be rounded down and decremented by 1 */ + if (count > RXCLK_RCD+1) + count = RXCLK_RCD; + else if (count < 2) + count = 1; + else + count--; + return (u16) count; +} + +/* + * IR Control Register helpers + */ +enum tx_fifo_watermark { + TX_FIFO_HALF_EMPTY = 0, + TX_FIFO_EMPTY = CNTRL_TIC, +}; + +enum rx_fifo_watermark { + RX_FIFO_HALF_FULL = 0, + RX_FIFO_NOT_EMPTY = CNTRL_RIC, +}; + +static inline void control_tx_irq_watermark(struct cx23885_dev *dev, + enum tx_fifo_watermark level) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_TIC, level); +} + +static inline void control_rx_irq_watermark(struct cx23885_dev *dev, + enum rx_fifo_watermark level) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_RIC, level); +} + +static inline void control_tx_enable(struct cx23885_dev *dev, bool enable) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE), + enable ? (CNTRL_TXE | CNTRL_TFE) : 0); +} + +static inline void control_rx_enable(struct cx23885_dev *dev, bool enable) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE), + enable ? (CNTRL_RXE | CNTRL_RFE) : 0); +} + +static inline void control_tx_modulation_enable(struct cx23885_dev *dev, + bool enable) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_MOD, + enable ? CNTRL_MOD : 0); +} + +static inline void control_rx_demodulation_enable(struct cx23885_dev *dev, + bool enable) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_DMD, + enable ? CNTRL_DMD : 0); +} + +static inline void control_rx_s_edge_detection(struct cx23885_dev *dev, + u32 edge_types) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_EDG_BOTH, + edge_types & CNTRL_EDG_BOTH); +} + +static void control_rx_s_carrier_window(struct cx23885_dev *dev, + unsigned int carrier, + unsigned int *carrier_range_low, + unsigned int *carrier_range_high) +{ + u32 v; + unsigned int c16 = carrier * 16; + + if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) { + v = CNTRL_WIN_3_4; + *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4); + } else { + v = CNTRL_WIN_3_3; + *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3); + } + + if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) { + v |= CNTRL_WIN_4_3; + *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4); + } else { + v |= CNTRL_WIN_3_3; + *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3); + } + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_WIN, v); +} + +static inline void control_tx_polarity_invert(struct cx23885_dev *dev, + bool invert) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_CPL, + invert ? CNTRL_CPL : 0); +} + +/* + * IR Rx & Tx Clock Register helpers + */ +static unsigned int txclk_tx_s_carrier(struct cx23885_dev *dev, + unsigned int freq, + u16 *divider) +{ + *divider = carrier_freq_to_clock_divider(freq); + cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); + return clock_divider_to_carrier_freq(*divider); +} + +static unsigned int rxclk_rx_s_carrier(struct cx23885_dev *dev, + unsigned int freq, + u16 *divider) +{ + *divider = carrier_freq_to_clock_divider(freq); + cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); + return clock_divider_to_carrier_freq(*divider); +} + +static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns, + u16 *divider) +{ + u64 pulse_clocks; + + if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) + ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; + pulse_clocks = ns_to_pulse_clocks(ns); + *divider = pulse_clocks_to_clock_divider(pulse_clocks); + cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); + return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider); +} + +static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns, + u16 *divider) +{ + u64 pulse_clocks; + + if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) + ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; + pulse_clocks = ns_to_pulse_clocks(ns); + *divider = pulse_clocks_to_clock_divider(pulse_clocks); + cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); + return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider); +} + +/* + * IR Tx Carrier Duty Cycle register helpers + */ +static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev, + unsigned int duty_cycle) +{ + u32 n; + n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */ + if (n != 0) + n--; + if (n > 15) + n = 15; + cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n); + return DIV_ROUND_CLOSEST((n+1) * 100, 16); +} + +/* + * IR Filter Register helpers + */ +static u32 filter_rx_s_min_width(struct cx23885_dev *dev, u32 min_width_ns) +{ + u32 count = ns_to_lpf_count(min_width_ns); + cx23888_ir_write4(dev, CX23888_IR_FILTR_REG, count); + return lpf_count_to_ns(count); +} + +/* + * IR IRQ Enable Register helpers + */ +static inline void irqenable_rx(struct cx23885_dev *dev, u32 mask) +{ + mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE); + cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, + ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask); +} + +static inline void irqenable_tx(struct cx23885_dev *dev, u32 mask) +{ + mask &= IRQEN_TSE; + cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, ~IRQEN_TSE, mask); +} + +/* + * V4L2 Subdevice IR Ops + */ +static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, + bool *handled) +{ + struct cx23888_ir_state *state = to_state(sd); + struct cx23885_dev *dev = state->dev; + + u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); + u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); + u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); + + u32 rx_data[FIFO_RX_DEPTH]; + int i, j, k; + u32 events, v; + int tsr, rsr, rto, ror, tse, rse, rte, roe, kror; + + tsr = stats & STATS_TSR; /* Tx FIFO Service Request */ + rsr = stats & STATS_RSR; /* Rx FIFO Service Request */ + rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */ + ror = stats & STATS_ROR; /* Rx FIFO Over Run */ + + tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */ + rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */ + rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */ + roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */ + + *handled = false; + v4l2_dbg(2, ir_888_debug, sd, "IRQ Status: %s %s %s %s %s %s\n", + tsr ? "tsr" : " ", rsr ? "rsr" : " ", + rto ? "rto" : " ", ror ? "ror" : " ", + stats & STATS_TBY ? "tby" : " ", + stats & STATS_RBY ? "rby" : " "); + + v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n", + tse ? "tse" : " ", rse ? "rse" : " ", + rte ? "rte" : " ", roe ? "roe" : " "); + + /* + * Transmitter interrupt service + */ + if (tse && tsr) { + /* + * TODO: + * Check the watermark threshold setting + * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo + * Push the data to the hardware FIFO. + * If there was nothing more to send in the tx_kfifo, disable + * the TSR IRQ and notify the v4l2_device. + * If there was something in the tx_kfifo, check the tx_kfifo + * level and notify the v4l2_device, if it is low. + */ + /* For now, inhibit TSR interrupt until Tx is implemented */ + irqenable_tx(dev, 0); + events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ; + v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events); + *handled = true; + } + + /* + * Receiver interrupt service + */ + kror = 0; + if ((rse && rsr) || (rte && rto)) { + /* + * Receive data on RSR to clear the STATS_RSR. + * Receive data on RTO, since we may not have yet hit the RSR + * watermark when we receive the RTO. + */ + for (i = 0, v = FIFO_RX_NDV; + (v & FIFO_RX_NDV) && !kror; i = 0) { + for (j = 0; + (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) { + v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG); + rx_data[i++] = v & ~FIFO_RX_NDV; + } + if (i == 0) + break; + j = i * sizeof(u32); + k = kfifo_put(state->rx_kfifo, + (unsigned char *) rx_data, j); + if (k != j) + kror++; /* rx_kfifo over run */ + } + *handled = true; + } + + events = 0; + v = 0; + if (kror) { + events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN; + v4l2_err(sd, "IR receiver software FIFO overrun\n"); + } + if (roe && ror) { + /* + * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear + * the Rx FIFO Over Run status (STATS_ROR) + */ + v |= CNTRL_RFE; + events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN; + v4l2_err(sd, "IR receiver hardware FIFO overrun\n"); + } + if (rte && rto) { + /* + * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear + * the Rx Pulse Width Timer Time Out (STATS_RTO) + */ + v |= CNTRL_RXE; + events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED; + } + if (v) { + /* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */ + cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v); + cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl); + *handled = true; + } + if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE/2) + events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; + + if (events) + v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events); + return 0; +} + +/* Receiver */ +static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, + ssize_t *num) +{ + struct cx23888_ir_state *state = to_state(sd); + bool invert = (bool) atomic_read(&state->rx_invert); + u16 divider = (u16) atomic_read(&state->rxclk_divider); + + unsigned int i, n; + u32 *p; + u32 u, v; + + n = count / sizeof(u32) * sizeof(u32); + if (n == 0) { + *num = 0; + return 0; + } + + n = kfifo_get(state->rx_kfifo, buf, n); + + n /= sizeof(u32); + *num = n * sizeof(u32); + + for (p = (u32 *) buf, i = 0; i < n; p++, i++) { + if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) { + *p = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; + v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n"); + continue; + } + + u = (*p & FIFO_RXTX_LVL) ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0; + if (invert) + u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK; + + v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX), + divider); + if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) + v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1; + + *p = u | v; + + v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n", + v, u ? "mark" : "space"); + } + return 0; +} + +static int cx23888_ir_rx_g_parameters(struct v4l2_subdev *sd, + struct v4l2_subdev_ir_parameters *p) +{ + struct cx23888_ir_state *state = to_state(sd); + mutex_lock(&state->rx_params_lock); + memcpy(p, &state->rx_params, sizeof(struct v4l2_subdev_ir_parameters)); + mutex_unlock(&state->rx_params_lock); + return 0; +} + +static int cx23888_ir_rx_shutdown(struct v4l2_subdev *sd) +{ + struct cx23888_ir_state *state = to_state(sd); + struct cx23885_dev *dev = state->dev; + + mutex_lock(&state->rx_params_lock); + + /* Disable or slow down all IR Rx circuits and counters */ + irqenable_rx(dev, 0); + control_rx_enable(dev, false); + control_rx_demodulation_enable(dev, false); + control_rx_s_edge_detection(dev, CNTRL_EDG_NONE); + filter_rx_s_min_width(dev, 0); + cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, RXCLK_RCD); + + state->rx_params.shutdown = true; + + mutex_unlock(&state->rx_params_lock); + return 0; +} + +static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, + struct v4l2_subdev_ir_parameters *p) +{ + struct cx23888_ir_state *state = to_state(sd); + struct cx23885_dev *dev = state->dev; + struct v4l2_subdev_ir_parameters *o = &state->rx_params; + u16 rxclk_divider; + + if (p->shutdown) + return cx23888_ir_rx_shutdown(sd); + + if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH) + return -ENOSYS; + + mutex_lock(&state->rx_params_lock); + + o->shutdown = p->shutdown; + + o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; + + o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); + + /* Before we tweak the hardware, we have to disable the receiver */ + irqenable_rx(dev, 0); + control_rx_enable(dev, false); + + control_rx_demodulation_enable(dev, p->modulation); + o->modulation = p->modulation; + + if (p->modulation) { + p->carrier_freq = rxclk_rx_s_carrier(dev, p->carrier_freq, + &rxclk_divider); + + o->carrier_freq = p->carrier_freq; + + o->duty_cycle = p->duty_cycle = 50; + + control_rx_s_carrier_window(dev, p->carrier_freq, + &p->carrier_range_lower, + &p->carrier_range_upper); + o->carrier_range_lower = p->carrier_range_lower; + o->carrier_range_upper = p->carrier_range_upper; + } else { + p->max_pulse_width = + rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width, + &rxclk_divider); + o->max_pulse_width = p->max_pulse_width; + } + atomic_set(&state->rxclk_divider, rxclk_divider); + + p->noise_filter_min_width = + filter_rx_s_min_width(dev, p->noise_filter_min_width); + o->noise_filter_min_width = p->noise_filter_min_width; + + p->resolution = clock_divider_to_resolution(rxclk_divider); + o->resolution = p->resolution; + + /* FIXME - make this dependent on resolution for better performance */ + control_rx_irq_watermark(dev, RX_FIFO_HALF_FULL); + + control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH); + + o->invert = p->invert; + atomic_set(&state->rx_invert, p->invert); + + o->interrupt_enable = p->interrupt_enable; + o->enable = p->enable; + if (p->enable) { + kfifo_reset(state->rx_kfifo); + if (p->interrupt_enable) + irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE); + control_rx_enable(dev, p->enable); + } + + mutex_unlock(&state->rx_params_lock); + return 0; +} + +/* Transmitter */ +static int cx23888_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count, + ssize_t *num) +{ + struct cx23888_ir_state *state = to_state(sd); + struct cx23885_dev *dev = state->dev; + /* For now enable the Tx FIFO Service interrupt & pretend we did work */ + irqenable_tx(dev, IRQEN_TSE); + *num = count; + return 0; +} + +static int cx23888_ir_tx_g_parameters(struct v4l2_subdev *sd, + struct v4l2_subdev_ir_parameters *p) +{ + struct cx23888_ir_state *state = to_state(sd); + mutex_lock(&state->tx_params_lock); + memcpy(p, &state->tx_params, sizeof(struct v4l2_subdev_ir_parameters)); + mutex_unlock(&state->tx_params_lock); + return 0; +} + +static int cx23888_ir_tx_shutdown(struct v4l2_subdev *sd) +{ + struct cx23888_ir_state *state = to_state(sd); + struct cx23885_dev *dev = state->dev; + + mutex_lock(&state->tx_params_lock); + + /* Disable or slow down all IR Tx circuits and counters */ + irqenable_tx(dev, 0); + control_tx_enable(dev, false); + control_tx_modulation_enable(dev, false); + cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, TXCLK_TCD); + + state->tx_params.shutdown = true; + + mutex_unlock(&state->tx_params_lock); + return 0; +} + +static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, + struct v4l2_subdev_ir_parameters *p) +{ + struct cx23888_ir_state *state = to_state(sd); + struct cx23885_dev *dev = state->dev; + struct v4l2_subdev_ir_parameters *o = &state->tx_params; + u16 txclk_divider; + + if (p->shutdown) + return cx23888_ir_tx_shutdown(sd); + + if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH) + return -ENOSYS; + + mutex_lock(&state->tx_params_lock); + + o->shutdown = p->shutdown; + + o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; + + o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); + + /* Before we tweak the hardware, we have to disable the transmitter */ + irqenable_tx(dev, 0); + control_tx_enable(dev, false); + + control_tx_modulation_enable(dev, p->modulation); + o->modulation = p->modulation; + + if (p->modulation) { + p->carrier_freq = txclk_tx_s_carrier(dev, p->carrier_freq, + &txclk_divider); + o->carrier_freq = p->carrier_freq; + + p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle); + o->duty_cycle = p->duty_cycle; + } else { + p->max_pulse_width = + txclk_tx_s_max_pulse_width(dev, p->max_pulse_width, + &txclk_divider); + o->max_pulse_width = p->max_pulse_width; + } + atomic_set(&state->txclk_divider, txclk_divider); + + p->resolution = clock_divider_to_resolution(txclk_divider); + o->resolution = p->resolution; + + /* FIXME - make this dependent on resolution for better performance */ + control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY); + + control_tx_polarity_invert(dev, p->invert); + o->invert = p->invert; + + o->interrupt_enable = p->interrupt_enable; + o->enable = p->enable; + if (p->enable) { + kfifo_reset(state->tx_kfifo); + if (p->interrupt_enable) + irqenable_tx(dev, IRQEN_TSE); + control_tx_enable(dev, p->enable); + } + + mutex_unlock(&state->tx_params_lock); + return 0; +} + + +/* + * V4L2 Subdevice Core Ops + */ static int cx23888_ir_log_status(struct v4l2_subdev *sd) { struct cx23888_ir_state *state = to_state(sd); struct cx23885_dev *dev = state->dev; - u8 cntrl = cx23888_ir_read(dev, CX23888_IR_CNTRL_REG+1); - v4l2_info(sd, "receiver %sabled\n", cntrl & 0x1 ? "en" : "dis"); - v4l2_info(sd, "transmitter %sabled\n", cntrl & 0x2 ? "en" : "dis"); + char *s; + int i, j; + + u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); + u32 txclk = cx23888_ir_read4(dev, CX23888_IR_TXCLK_REG) & TXCLK_TCD; + u32 rxclk = cx23888_ir_read4(dev, CX23888_IR_RXCLK_REG) & RXCLK_RCD; + u32 cduty = cx23888_ir_read4(dev, CX23888_IR_CDUTY_REG) & CDUTY_CDC; + u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); + u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); + u32 filtr = cx23888_ir_read4(dev, CX23888_IR_FILTR_REG) & FILTR_LPF; + + v4l2_info(sd, "IR Receiver:\n"); + v4l2_info(sd, "\tEnabled: %s\n", + cntrl & CNTRL_RXE ? "yes" : "no"); + v4l2_info(sd, "\tDemodulation from a carrier: %s\n", + cntrl & CNTRL_DMD ? "enabled" : "disabled"); + v4l2_info(sd, "\tFIFO: %s\n", + cntrl & CNTRL_RFE ? "enabled" : "disabled"); + switch (cntrl & CNTRL_EDG) { + case CNTRL_EDG_NONE: + s = "disabled"; + break; + case CNTRL_EDG_FALL: + s = "falling edge"; + break; + case CNTRL_EDG_RISE: + s = "rising edge"; + break; + case CNTRL_EDG_BOTH: + s = "rising & falling edges"; + break; + default: + s = "??? edge"; + break; + } + v4l2_info(sd, "\tPulse timers' start/stop trigger: %s\n", s); + v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n", + cntrl & CNTRL_R ? "not loaded" : "overflow marker"); + v4l2_info(sd, "\tFIFO interrupt watermark: %s\n", + cntrl & CNTRL_RIC ? "not empty" : "half full or greater"); + v4l2_info(sd, "\tLoopback mode: %s\n", + cntrl & CNTRL_LBM ? "loopback active" : "normal receive"); + if (cntrl & CNTRL_DMD) { + v4l2_info(sd, "\tExpected carrier (16 clocks): %u Hz\n", + clock_divider_to_carrier_freq(rxclk)); + switch (cntrl & CNTRL_WIN) { + case CNTRL_WIN_3_3: + i = 3; + j = 3; + break; + case CNTRL_WIN_4_3: + i = 4; + j = 3; + break; + case CNTRL_WIN_3_4: + i = 3; + j = 4; + break; + case CNTRL_WIN_4_4: + i = 4; + j = 4; + break; + default: + i = 0; + j = 0; + break; + } + v4l2_info(sd, "\tNext carrier edge window: 16 clocks " + "-%1d/+%1d, %u to %u Hz\n", i, j, + clock_divider_to_freq(rxclk, 16 + j), + clock_divider_to_freq(rxclk, 16 - i)); + } else { + v4l2_info(sd, "\tMax measurable pulse width: %u us, " + "%llu ns\n", + pulse_width_count_to_us(FIFO_RXTX, rxclk), + pulse_width_count_to_ns(FIFO_RXTX, rxclk)); + } + v4l2_info(sd, "\tLow pass filter: %s\n", + filtr ? "enabled" : "disabled"); + if (filtr) + v4l2_info(sd, "\tMin acceptable pulse width (LPF): %u us, " + "%u ns\n", + lpf_count_to_us(filtr), + lpf_count_to_ns(filtr)); + v4l2_info(sd, "\tPulse width timer timed-out: %s\n", + stats & STATS_RTO ? "yes" : "no"); + v4l2_info(sd, "\tPulse width timer time-out intr: %s\n", + irqen & IRQEN_RTE ? "enabled" : "disabled"); + v4l2_info(sd, "\tFIFO overrun: %s\n", + stats & STATS_ROR ? "yes" : "no"); + v4l2_info(sd, "\tFIFO overrun interrupt: %s\n", + irqen & IRQEN_ROE ? "enabled" : "disabled"); + v4l2_info(sd, "\tBusy: %s\n", + stats & STATS_RBY ? "yes" : "no"); + v4l2_info(sd, "\tFIFO service requested: %s\n", + stats & STATS_RSR ? "yes" : "no"); + v4l2_info(sd, "\tFIFO service request interrupt: %s\n", + irqen & IRQEN_RSE ? "enabled" : "disabled"); + + v4l2_info(sd, "IR Transmitter:\n"); + v4l2_info(sd, "\tEnabled: %s\n", + cntrl & CNTRL_TXE ? "yes" : "no"); + v4l2_info(sd, "\tModulation onto a carrier: %s\n", + cntrl & CNTRL_MOD ? "enabled" : "disabled"); + v4l2_info(sd, "\tFIFO: %s\n", + cntrl & CNTRL_TFE ? "enabled" : "disabled"); + v4l2_info(sd, "\tFIFO interrupt watermark: %s\n", + cntrl & CNTRL_TIC ? "not empty" : "half full or less"); + v4l2_info(sd, "\tSignal polarity: %s\n", + cntrl & CNTRL_CPL ? "0:mark 1:space" : "0:space 1:mark"); + if (cntrl & CNTRL_MOD) { + v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n", + clock_divider_to_carrier_freq(txclk)); + v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n", + cduty + 1); + } else { + v4l2_info(sd, "\tMax pulse width: %u us, " + "%llu ns\n", + pulse_width_count_to_us(FIFO_RXTX, txclk), + pulse_width_count_to_ns(FIFO_RXTX, txclk)); + } + v4l2_info(sd, "\tBusy: %s\n", + stats & STATS_TBY ? "yes" : "no"); + v4l2_info(sd, "\tFIFO service requested: %s\n", + stats & STATS_TSR ? "yes" : "no"); + v4l2_info(sd, "\tFIFO service request interrupt: %s\n", + irqen & IRQEN_TSE ? "enabled" : "disabled"); + return 0; } @@ -187,19 +1105,81 @@ static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = { #endif }; +static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = { + .interrupt_service_routine = cx23888_ir_irq_handler, + + .rx_read = cx23888_ir_rx_read, + .rx_g_parameters = cx23888_ir_rx_g_parameters, + .rx_s_parameters = cx23888_ir_rx_s_parameters, + + .tx_write = cx23888_ir_tx_write, + .tx_g_parameters = cx23888_ir_tx_g_parameters, + .tx_s_parameters = cx23888_ir_tx_s_parameters, +}; + static const struct v4l2_subdev_ops cx23888_ir_controller_ops = { .core = &cx23888_ir_core_ops, + .ir = &cx23888_ir_ir_ops, +}; + +static const struct v4l2_subdev_ir_parameters default_rx_params = { + .bytes_per_data_element = sizeof(u32), + .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, + + .enable = false, + .interrupt_enable = false, + .shutdown = true, + + .modulation = true, + .carrier_freq = 36000, /* 36 kHz - RC-5, RC-6, and RC-6A carrier */ + + /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */ + /* RC-6A: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */ + .noise_filter_min_width = 333333, /* ns */ + .carrier_range_lower = 35000, + .carrier_range_upper = 37000, + .invert = false, +}; + +static const struct v4l2_subdev_ir_parameters default_tx_params = { + .bytes_per_data_element = sizeof(u32), + .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, + + .enable = false, + .interrupt_enable = false, + .shutdown = true, + + .modulation = true, + .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */ + .duty_cycle = 25, /* 25 % - RC-5 carrier */ + .invert = false, }; int cx23888_ir_probe(struct cx23885_dev *dev) { struct cx23888_ir_state *state; struct v4l2_subdev *sd; + struct v4l2_subdev_ir_parameters default_params; + int ret; state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; + spin_lock_init(&state->rx_kfifo_lock); + state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL, + &state->rx_kfifo_lock); + if (state->rx_kfifo == NULL) + return -ENOMEM; + + spin_lock_init(&state->tx_kfifo_lock); + state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL, + &state->tx_kfifo_lock); + if (state->tx_kfifo == NULL) { + kfifo_free(state->rx_kfifo); + return -ENOMEM; + } + state->dev = dev; state->id = V4L2_IDENT_CX23888_IR; state->rev = 0; @@ -210,7 +1190,30 @@ int cx23888_ir_probe(struct cx23885_dev *dev) /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */ snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name); sd->grp_id = CX23885_HW_888_IR; - return v4l2_device_register_subdev(&dev->v4l2_dev, sd); + + ret = v4l2_device_register_subdev(&dev->v4l2_dev, sd); + if (ret == 0) { + /* + * Ensure no interrupts arrive from '888 specific conditions, + * since we ignore them in this driver to have commonality with + * similar IR controller cores. + */ + cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0); + + mutex_init(&state->rx_params_lock); + memcpy(&default_params, &default_rx_params, + sizeof(struct v4l2_subdev_ir_parameters)); + v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params); + + mutex_init(&state->tx_params_lock); + memcpy(&default_params, &default_tx_params, + sizeof(struct v4l2_subdev_ir_parameters)); + v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params); + } else { + kfifo_free(state->rx_kfifo); + kfifo_free(state->tx_kfifo); + } + return ret; } int cx23888_ir_remove(struct cx23885_dev *dev) @@ -222,11 +1225,13 @@ int cx23888_ir_remove(struct cx23885_dev *dev) if (sd == NULL) return -ENODEV; - /* Disable receiver and transmitter */ - cx23888_ir_and_or(dev, CX23888_IR_CNTRL_REG+1, 0xfc, 0); + cx23888_ir_rx_shutdown(sd); + cx23888_ir_tx_shutdown(sd); state = to_state(sd); v4l2_device_unregister_subdev(sd); + kfifo_free(state->rx_kfifo); + kfifo_free(state->tx_kfifo); kfree(state); /* Nothing more to free() as state held the actual v4l2_subdev object */ return 0; From f59ad611acccd4057b8e685c7fd5532ab1a17f66 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 27 Sep 2009 19:51:50 -0300 Subject: [PATCH 046/345] V4L/DVB (13098): cx23885: Add integrated IR subdevice interrupt and notification handling Add integrated IR subdevice interrupt and notification handling. This is in preparation of input keypress handling changes for the cx23885 module. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/Makefile | 2 +- drivers/media/video/cx23885/cx23885-cards.c | 23 +++++ drivers/media/video/cx23885/cx23885-core.c | 74 +++++++++++++--- drivers/media/video/cx23885/cx23885-ir.c | 97 +++++++++++++++++++++ drivers/media/video/cx23885/cx23885-ir.h | 31 +++++++ drivers/media/video/cx23885/cx23885-reg.h | 5 +- drivers/media/video/cx23885/cx23885.h | 10 ++- 7 files changed, 224 insertions(+), 18 deletions(-) create mode 100644 drivers/media/video/cx23885/cx23885-ir.c create mode 100644 drivers/media/video/cx23885/cx23885-ir.h diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index 3832a1cb768d..330cff3f77ac 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile @@ -1,6 +1,6 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ - cx23885-ioctl.o cx23888-ir.o \ + cx23885-ioctl.o cx23885-ir.o cx23888-ir.o \ netup-init.o cimax2.o netup-eeprom.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 7c5d13ac538e..c0e2409f3cbd 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -821,6 +821,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) if (ret) break; dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); + dev->pci_irqmask |= PCI_MSK_IR; break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: request_module("ir-kbd-i2c"); @@ -830,6 +831,28 @@ int cx23885_ir_init(struct cx23885_dev *dev) return ret; } +void cx23885_ir_fini(struct cx23885_dev *dev) +{ + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1850: + dev->pci_irqmask &= ~PCI_MSK_IR; + cx_clear(PCI_INT_MSK, PCI_MSK_IR); + cx23888_ir_remove(dev); + dev->sd_ir = NULL; + break; + } +} + +void cx23885_ir_pci_int_enable(struct cx23885_dev *dev) +{ + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1850: + if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR)) + cx_set(PCI_INT_MSK, PCI_MSK_IR); + break; + } +} + void cx23885_card_setup(struct cx23885_dev *dev) { struct cx23885_tsport *ts1 = &dev->ts1; diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 73be16b0d2a0..c879211a704d 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -33,6 +33,7 @@ #include "cx23885.h" #include "cimax2.h" #include "cx23888-ir.h" +#include "cx23885-ir.h" MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); @@ -1655,6 +1656,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) u32 ts1_status, ts1_mask; u32 ts2_status, ts2_mask; int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; + bool ir_handled = false; pci_status = cx_read(PCI_INT_STAT); pci_mask = cx_read(PCI_INT_MSK); @@ -1680,18 +1682,12 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", ts2_status, ts2_mask, ts2_count); - if ((pci_status & PCI_MSK_RISC_RD) || - (pci_status & PCI_MSK_RISC_WR) || - (pci_status & PCI_MSK_AL_RD) || - (pci_status & PCI_MSK_AL_WR) || - (pci_status & PCI_MSK_APB_DMA) || - (pci_status & PCI_MSK_VID_C) || - (pci_status & PCI_MSK_VID_B) || - (pci_status & PCI_MSK_VID_A) || - (pci_status & PCI_MSK_AUD_INT) || - (pci_status & PCI_MSK_AUD_EXT) || - (pci_status & PCI_MSK_GPIO0) || - (pci_status & PCI_MSK_GPIO1)) { + if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR | + PCI_MSK_AL_RD | PCI_MSK_AL_WR | PCI_MSK_APB_DMA | + PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A | + PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT | + PCI_MSK_GPIO0 | PCI_MSK_GPIO1 | + PCI_MSK_IR)) { if (pci_status & PCI_MSK_RISC_RD) dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", @@ -1740,6 +1736,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) if (pci_status & PCI_MSK_GPIO1) dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", PCI_MSK_GPIO1); + + if (pci_status & PCI_MSK_IR) + dprintk(7, " (PCI_MSK_IR 0x%08x)\n", + PCI_MSK_IR); } if (cx23885_boards[dev->board].cimax > 0 && @@ -1770,12 +1770,48 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) if (vida_status) handled += cx23885_video_irq(dev, vida_status); + if (pci_status & PCI_MSK_IR) { + v4l2_subdev_call(dev->sd_ir, ir, interrupt_service_routine, + pci_status, &ir_handled); + if (ir_handled) + handled++; + } + if (handled) cx_write(PCI_INT_STAT, pci_status); out: return IRQ_RETVAL(handled); } +static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd, + unsigned int notification, void *arg) +{ + struct cx23885_dev *dev; + + if (sd == NULL) + return; + + dev = to_cx23885(sd->v4l2_dev); + + switch (notification) { + case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */ + if (sd == dev->sd_ir) + cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg); + break; + case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */ + if (sd == dev->sd_ir) + cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg); + break; + } +} + +static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev) +{ + INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler); + INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler); + dev->v4l2_dev.notify = cx23885_v4l2_dev_notify; +} + static inline int encoder_on_portb(struct cx23885_dev *dev) { return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; @@ -1872,6 +1908,9 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, if (err < 0) goto fail_free; + /* Prepare to handle notifications from subdevices */ + cx23885_v4l2_dev_notify_init(dev); + /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { @@ -1914,6 +1953,13 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, break; } + /* + * The CX2388[58] IR controller can start firing interrupts when + * enabled, so these have to take place after the cx23885_irq() handler + * is hooked up by the call to request_irq() above. + */ + cx23885_ir_pci_int_enable(dev); + return 0; fail_irq: @@ -1930,9 +1976,9 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); struct cx23885_dev *dev = to_cx23885(v4l2_dev); - cx23885_shutdown(dev); + cx23885_ir_fini(dev); - cx23888_ir_remove(dev); + cx23885_shutdown(dev); pci_disable_device(pci_dev); diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c new file mode 100644 index 000000000000..e84f90c75bf1 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-ir.c @@ -0,0 +1,97 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * Infrared device support routines - non-input, non-vl42_subdev routines + * + * Copyright (C) 2009 Andy Walls + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include "cx23885.h" + +#define CX23885_IR_RX_FIFO_SERVICE_REQ 0 +#define CX23885_IR_RX_END_OF_RX_DETECTED 1 +#define CX23885_IR_RX_HW_FIFO_OVERRUN 2 +#define CX23885_IR_RX_SW_FIFO_OVERRUN 3 + +#define CX23885_IR_TX_FIFO_SERVICE_REQ 0 + + +void cx23885_ir_rx_work_handler(struct work_struct *work) +{ + struct cx23885_dev *dev = + container_of(work, struct cx23885_dev, ir_rx_work); + u32 events = 0; + unsigned long *notifications = &dev->ir_rx_notifications; + + if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications)) + events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN; + if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications)) + events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN; + if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications)) + events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED; + if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications)) + events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; + + if (events == 0) + return; +} + +void cx23885_ir_tx_work_handler(struct work_struct *work) +{ + struct cx23885_dev *dev = + container_of(work, struct cx23885_dev, ir_tx_work); + u32 events = 0; + unsigned long *notifications = &dev->ir_tx_notifications; + + if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications)) + events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ; + + if (events == 0) + return; + +} + +/* Called in an IRQ context */ +void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) +{ + struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); + unsigned long *notifications = &dev->ir_rx_notifications; + + if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ) + set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications); + if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED) + set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications); + if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN) + set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications); + if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN) + set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications); + schedule_work(&dev->ir_rx_work); +} + +/* Called in an IRQ context */ +void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) +{ + struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); + unsigned long *notifications = &dev->ir_tx_notifications; + + if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ) + set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications); + schedule_work(&dev->ir_tx_work); +} diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/video/cx23885/cx23885-ir.h new file mode 100644 index 000000000000..9b8a6d5d1ef6 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-ir.h @@ -0,0 +1,31 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * Infrared device support routines - non-input, non-vl42_subdev routines + * + * Copyright (C) 2009 Andy Walls + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef _CX23885_IR_H_ +#define _CX23885_IR_H_ +void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events); +void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events); + +void cx23885_ir_rx_work_handler(struct work_struct *work); +void cx23885_ir_tx_work_handler(struct work_struct *work); +#endif diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h index eafbe5226bae..c0bc9a068954 100644 --- a/drivers/media/video/cx23885/cx23885-reg.h +++ b/drivers/media/video/cx23885/cx23885-reg.h @@ -212,8 +212,9 @@ Channel manager Data Structure entry = 20 DWORD #define DEV_CNTRL2 0x00040000 -#define PCI_MSK_GPIO1 (1 << 24) -#define PCI_MSK_GPIO0 (1 << 23) +#define PCI_MSK_IR (1 << 28) +#define PCI_MSK_GPIO1 (1 << 24) +#define PCI_MSK_GPIO0 (1 << 23) #define PCI_MSK_APB_DMA (1 << 12) #define PCI_MSK_AL_WR (1 << 11) #define PCI_MSK_AL_RD (1 << 10) diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index f7ed146566d9..ce82698db5f7 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -355,7 +355,13 @@ struct cx23885_dev { unsigned char radio_addr; unsigned int has_radio; struct v4l2_subdev *sd_cx25840; - struct v4l2_subdev *sd_ir; + + /* Infrared */ + struct v4l2_subdev *sd_ir; + struct work_struct ir_rx_work; + unsigned long ir_rx_notifications; + struct work_struct ir_tx_work; + unsigned long ir_tx_notifications; /* V4l */ u32 freq; @@ -479,6 +485,8 @@ extern int cx23885_tuner_callback(void *priv, int component, int command, int arg); extern void cx23885_card_list(struct cx23885_dev *dev); extern int cx23885_ir_init(struct cx23885_dev *dev); +extern void cx23885_ir_pci_int_enable(struct cx23885_dev *dev); +extern void cx23885_ir_fini(struct cx23885_dev *dev); extern void cx23885_gpio_setup(struct cx23885_dev *dev); extern void cx23885_card_setup(struct cx23885_dev *dev); extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev); From 1d23a002434802078d806ddc2937bd69bbbd6dc8 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 27 Sep 2009 20:05:23 -0300 Subject: [PATCH 047/345] V4L/DVB (13099): ir-functions: Export ir_rc5_decode() for use by the cx23885 module Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-functions.c | 3 ++- include/media/ir-common.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index abd4791acb0e..fc2d8941459f 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -275,7 +275,7 @@ EXPORT_SYMBOL_GPL(ir_decode_biphase); * saa7134 */ /* decode raw bit pattern to RC5 code */ -static u32 ir_rc5_decode(unsigned int code) +u32 ir_rc5_decode(unsigned int code) { unsigned int org_code = code; unsigned int pair; @@ -304,6 +304,7 @@ static u32 ir_rc5_decode(unsigned int code) RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); return rc5; } +EXPORT_SYMBOL_GPL(ir_rc5_decode); void ir_rc5_timer_end(unsigned long data) { diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 29f0e53cff94..af3257e6b808 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -111,6 +111,7 @@ u32 ir_extract_bits(u32 data, u32 mask); int ir_dump_samples(u32 *samples, int count); int ir_decode_biphase(u32 *samples, int count, int low, int high); int ir_decode_pulsedistance(u32 *samples, int count, int low, int high); +u32 ir_rc5_decode(unsigned int code); void ir_rc5_timer_end(unsigned long data); void ir_rc5_timer_keyup(unsigned long data); From dbda8f701abb0e4693a30e9bef4a2301d1c8ea80 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 27 Sep 2009 20:55:41 -0300 Subject: [PATCH 048/345] V4L/DVB (13100): cx23885: Add IR input keypress handling and enable for the HVR-1850 This changes adds IR Rx keypress input event handling to the CX23885 module. This change specifically only adds input handling for IR devices implemented as v4l2_subdevices, using only the pulse width mode (for now), and only with RC-5 remotes. The V4L-DVB infrastructure is missing too much to support RC-6 mode 6A as used in many media center remotes. The grey Hauppauge RC-5 remote and HVR-1850 IR receiver work now. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/Makefile | 2 +- drivers/media/video/cx23885/cx23885-core.c | 3 + drivers/media/video/cx23885/cx23885-input.c | 418 ++++++++++++++++++++ drivers/media/video/cx23885/cx23885-input.h | 30 ++ drivers/media/video/cx23885/cx23885-ir.c | 4 + drivers/media/video/cx23885/cx23885.h | 3 + 6 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 drivers/media/video/cx23885/cx23885-input.c create mode 100644 drivers/media/video/cx23885/cx23885-input.h diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index 330cff3f77ac..bb462589b53b 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile @@ -1,6 +1,6 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ - cx23885-ioctl.o cx23885-ir.o cx23888-ir.o \ + cx23885-ioctl.o cx23885-ir.o cx23885-input.o cx23888-ir.o \ netup-init.o cimax2.o netup-eeprom.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index c879211a704d..d6e41db500ef 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -34,6 +34,7 @@ #include "cimax2.h" #include "cx23888-ir.h" #include "cx23885-ir.h" +#include "cx23885-input.h" MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); @@ -1959,6 +1960,7 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, * is hooked up by the call to request_irq() above. */ cx23885_ir_pci_int_enable(dev); + cx23885_input_init(dev); return 0; @@ -1976,6 +1978,7 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); struct cx23885_dev *dev = to_cx23885(v4l2_dev); + cx23885_input_fini(dev); cx23885_ir_fini(dev); cx23885_shutdown(dev); diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c new file mode 100644 index 000000000000..c208079f4e9d --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -0,0 +1,418 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * Infrared remote control input device + * + * Most of this file is + * + * Copyright (C) 2009 Andy Walls + * + * However, the cx23885_input_{init,fini} functions contained herein are + * derived from Linux kernel files linux/media/video/.../...-input.c marked as: + * + * Copyright (C) 2008 + * Copyright (C) 2005 Ludovico Cavedon + * Markus Rechberger + * Mauro Carvalho Chehab + * Sascha Sommer + * Copyright (C) 2004, 2005 Chris Pascoe + * Copyright (C) 2003, 2004 Gerd Knorr + * Copyright (C) 2003 Pavel Machek + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +#include "cx23885.h" + +#define RC5_BITS 14 +#define RC5_HALF_BITS (2*RC5_BITS) +#define RC5_HALF_BITS_MASK ((1 << RC5_HALF_BITS) - 1) + +#define RC5_START_BITS_NORMAL 0x3 /* Command range 0 - 63 */ +#define RC5_START_BITS_EXTENDED 0x2 /* Command range 64 - 127 */ + +#define RC5_EXTENDED_COMMAND_OFFSET 64 + +static inline unsigned int rc5_command(u32 rc5_baseband) +{ + return RC5_INSTR(rc5_baseband) + + ((RC5_START(rc5_baseband) == RC5_START_BITS_EXTENDED) + ? RC5_EXTENDED_COMMAND_OFFSET : 0); +} + +static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev) +{ + struct card_ir *ir_input = dev->ir_input; + unsigned int code, command; + u32 rc5; + + /* Ignore codes that are too short to be valid RC-5 */ + if (ir_input->last_bit < (RC5_HALF_BITS - 1)) + return; + + /* The library has the manchester coding backwards; XOR to adapt. */ + code = (ir_input->code & RC5_HALF_BITS_MASK) ^ RC5_HALF_BITS_MASK; + rc5 = ir_rc5_decode(code); + + switch (RC5_START(rc5)) { + case RC5_START_BITS_NORMAL: + break; + case RC5_START_BITS_EXTENDED: + /* Don't allow if the remote only emits standard commands */ + if (ir_input->start == RC5_START_BITS_NORMAL) + return; + break; + default: + return; + } + + if (ir_input->addr != RC5_ADDR(rc5)) + return; + + /* Don't generate a keypress for RC-5 auto-repeated keypresses */ + command = rc5_command(rc5); + if (RC5_TOGGLE(rc5) != RC5_TOGGLE(ir_input->last_rc5) || + command != rc5_command(ir_input->last_rc5) || + /* Catch T == 0, CMD == 0 (e.g. '0') as first keypress after init */ + RC5_START(ir_input->last_rc5) == 0) { + /* This keypress is differnet: not an auto repeat */ + ir_input_nokey(ir_input->dev, &ir_input->ir); + ir_input_keydown(ir_input->dev, &ir_input->ir, + command, ir_input->code); + } + ir_input->last_rc5 = rc5; + + /* Schedule when we should do the key up event: ir_input_nokey() */ + mod_timer(&ir_input->timer_keyup, + jiffies + msecs_to_jiffies(ir_input->rc5_key_timeout)); +} + +static void cx23885_input_next_pulse_width_rc5(struct cx23885_dev *dev, + u32 ns_pulse) +{ + const int rc5_quarterbit_ns = 444444; /* 32 cycles/36 kHz/2 = 444 us */ + struct card_ir *ir_input = dev->ir_input; + int i, level, quarterbits, halfbits; + + if (!ir_input->active) { + ir_input->active = 1; + /* assume an initial space that we may not detect or measure */ + ir_input->code = 0; + ir_input->last_bit = 0; + } + + if (ns_pulse == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) { + ir_input->last_bit++; /* Account for the final space */ + ir_input->active = 0; + cx23885_input_process_raw_rc5(dev); + return; + } + + level = (ns_pulse & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? 1 : 0; + + /* Skip any leading space to sync to the start bit */ + if (ir_input->last_bit == 0 && level == 0) + return; + + /* + * With valid RC-5 we can get up to two consecutive half-bits in a + * single pulse measurment. Experiments have shown that the duration + * of a half-bit can vary. Make sure we always end up with an even + * number of quarter bits at the same level (mark or space). + */ + ns_pulse &= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; + quarterbits = ns_pulse / rc5_quarterbit_ns; + if (quarterbits & 1) + quarterbits++; + halfbits = quarterbits / 2; + + for (i = 0; i < halfbits; i++) { + ir_input->last_bit++; + ir_input->code |= (level << ir_input->last_bit); + + if (ir_input->last_bit >= RC5_HALF_BITS-1) { + ir_input->active = 0; + cx23885_input_process_raw_rc5(dev); + /* + * If level is 1, a leading mark is invalid for RC5. + * If level is 0, we scan past extra intial space. + * Either way we don't want to reactivate collecting + * marks or spaces here with any left over half-bits. + */ + break; + } + } +} + +static void cx23885_input_process_pulse_widths_rc5(struct cx23885_dev *dev, + bool add_eom) +{ + struct card_ir *ir_input = dev->ir_input; + struct ir_input_state *ir_input_state = &ir_input->ir; + + u32 ns_pulse[RC5_HALF_BITS+1]; + ssize_t num = 0; + int count, i; + + do { + v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ns_pulse, + sizeof(ns_pulse), &num); + + count = num / sizeof(u32); + + /* Append an end of Rx seq, if the caller requested */ + if (add_eom && count < ARRAY_SIZE(ns_pulse)) { + ns_pulse[count] = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; + count++; + } + + /* Just drain the Rx FIFO, if we're called, but not RC-5 */ + if (ir_input_state->ir_type != IR_TYPE_RC5) + continue; + + for (i = 0; i < count; i++) + cx23885_input_next_pulse_width_rc5(dev, ns_pulse[i]); + } while (num != 0); +} + +void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) +{ + struct v4l2_subdev_ir_parameters params; + int overrun, data_available; + + if (dev->sd_ir == NULL || events == 0) + return; + + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1850: + /* + * The only board we handle right now. However other boards + * using the CX2388x integrated IR controller should be similar + */ + break; + default: + return; + } + + overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN | + V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN); + + data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED | + V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ); + + if (overrun) { + /* If there was a FIFO overrun, stop the device */ + v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); + params.enable = false; + /* Mitigate race with cx23885_input_ir_stop() */ + params.shutdown = atomic_read(&dev->ir_input_stopping); + v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); + } + + if (data_available) + cx23885_input_process_pulse_widths_rc5(dev, overrun); + + if (overrun) { + /* If there was a FIFO overrun, clear & restart the device */ + params.enable = true; + /* Mitigate race with cx23885_input_ir_stop() */ + params.shutdown = atomic_read(&dev->ir_input_stopping); + v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); + } +} + +static void cx23885_input_ir_start(struct cx23885_dev *dev) +{ + struct card_ir *ir_input = dev->ir_input; + struct ir_input_state *ir_input_state = &ir_input->ir; + struct v4l2_subdev_ir_parameters params; + + if (dev->sd_ir == NULL) + return; + + atomic_set(&dev->ir_input_stopping, 0); + + /* keyup timer set up, if needed */ + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1850: + setup_timer(&ir_input->timer_keyup, + ir_rc5_timer_keyup, /* Not actually RC-5 specific */ + (unsigned long) ir_input); + if (ir_input_state->ir_type == IR_TYPE_RC5) { + /* + * RC-5 repeats a held key every + * 64 bits * (2 * 32/36000) sec/bit = 113.778 ms + */ + ir_input->rc5_key_timeout = 115; + } + break; + } + + v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1850: + /* + * The IR controller on this board only returns pulse widths. + * Any other mode setting will fail to set up the device. + */ + params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; + params.enable = true; + params.interrupt_enable = true; + params.shutdown = false; + + /* Setup for baseband compatible with both RC-5 and RC-6A */ + params.modulation = false; + /* RC-5: 2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/ + /* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/ + params.max_pulse_width = 3333333; /* ns */ + /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */ + /* RC-6A: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */ + params.noise_filter_min_width = 333333; /* ns */ + /* + * This board has inverted receive sense: + * mark is received as low logic level; + * falling edges are detected as rising edges; etc. + */ + params.invert = true; + break; + } + v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); +} + +static void cx23885_input_ir_stop(struct cx23885_dev *dev) +{ + struct card_ir *ir_input = dev->ir_input; + struct v4l2_subdev_ir_parameters params; + + if (dev->sd_ir == NULL) + return; + + /* + * Stop the sd_ir subdevice from generating notifications and + * scheduling work. + * It is shutdown this way in order to mitigate a race with + * cx23885_input_rx_work_handler() in the overrun case, which could + * re-enable the subdevice. + */ + atomic_set(&dev->ir_input_stopping, 1); + v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); + while (params.shutdown == false) { + params.enable = false; + params.interrupt_enable = false; + params.shutdown = true; + v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); + v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); + } + + flush_scheduled_work(); + + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1850: + del_timer_sync(&ir_input->timer_keyup); + break; + } +} + +int cx23885_input_init(struct cx23885_dev *dev) +{ + struct card_ir *ir; + struct input_dev *input_dev; + struct ir_scancode_table *ir_codes = NULL; + int ir_type, ir_addr, ir_start; + int ret; + + /* + * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't + * encapsulated in a v4l2_subdev, then I'm not going to deal with it. + */ + if (dev->sd_ir == NULL) + return -ENODEV; + + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1850: + /* Parameters for the grey Hauppauge remote for the HVR-1850 */ + ir_codes = &ir_codes_hauppauge_new_table; + ir_type = IR_TYPE_RC5; + ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ + ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ + break; + } + if (ir_codes == NULL) + return -ENODEV; + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ir || !input_dev) { + ret = -ENOMEM; + goto err_out_free; + } + + ir->dev = input_dev; + ir->addr = ir_addr; + ir->start = ir_start; + + /* init input device */ + snprintf(ir->name, sizeof(ir->name), "cx23885 IR (%s)", + cx23885_boards[dev->board].name); + snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); + + ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + input_dev->name = ir->name; + input_dev->phys = ir->phys; + input_dev->id.bustype = BUS_PCI; + input_dev->id.version = 1; + if (dev->pci->subsystem_vendor) { + input_dev->id.vendor = dev->pci->subsystem_vendor; + input_dev->id.product = dev->pci->subsystem_device; + } else { + input_dev->id.vendor = dev->pci->vendor; + input_dev->id.product = dev->pci->device; + } + input_dev->dev.parent = &dev->pci->dev; + + dev->ir_input = ir; + cx23885_input_ir_start(dev); + + ret = input_register_device(ir->dev); + if (ret) + goto err_out_stop; + + return 0; + +err_out_stop: + cx23885_input_ir_stop(dev); + dev->ir_input = NULL; +err_out_free: + input_free_device(input_dev); + kfree(ir); + return ret; +} + +void cx23885_input_fini(struct cx23885_dev *dev) +{ + /* Always stop the IR hardware from generating interrupts */ + cx23885_input_ir_stop(dev); + + if (dev->ir_input == NULL) + return; + input_unregister_device(dev->ir_input->dev); + kfree(dev->ir_input); + dev->ir_input = NULL; +} diff --git a/drivers/media/video/cx23885/cx23885-input.h b/drivers/media/video/cx23885/cx23885-input.h new file mode 100644 index 000000000000..3572cb1ecfc2 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-input.h @@ -0,0 +1,30 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * Infrared remote control input device + * + * Copyright (C) 2009 Andy Walls + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef _CX23885_INPUT_H_ +#define _CX23885_INPUT_H_ +int cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events); + +int cx23885_input_init(struct cx23885_dev *dev); +void cx23885_input_fini(struct cx23885_dev *dev); +#endif diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c index e84f90c75bf1..6ae982cc9856 100644 --- a/drivers/media/video/cx23885/cx23885-ir.c +++ b/drivers/media/video/cx23885/cx23885-ir.c @@ -24,6 +24,7 @@ #include #include "cx23885.h" +#include "cx23885-input.h" #define CX23885_IR_RX_FIFO_SERVICE_REQ 0 #define CX23885_IR_RX_END_OF_RX_DETECTED 1 @@ -51,6 +52,9 @@ void cx23885_ir_rx_work_handler(struct work_struct *work) if (events == 0) return; + + if (dev->ir_input) + cx23885_input_rx_work_handler(dev, events); } void cx23885_ir_tx_work_handler(struct work_struct *work) diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index ce82698db5f7..1e0e93548061 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -363,6 +363,9 @@ struct cx23885_dev { struct work_struct ir_tx_work; unsigned long ir_tx_notifications; + struct card_ir *ir_input; + atomic_t ir_input_stopping; + /* V4l */ u32 freq; struct video_device *video_dev; From 9133aee09e3689c116c526fa9011c33b872e65c1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 23 May 2009 18:00:59 -0300 Subject: [PATCH 049/345] V4L/DVB (13103): create a standard method for dvb adapter drivers to override frontend ioctls Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 20 +++++++++++++++- drivers/media/dvb/dvb-core/dvbdev.h | 28 +++++++++++++++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 2 +- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- drivers/media/video/videobuf-dvb.c | 11 ++++++--- include/media/videobuf-dvb.h | 4 +++- 7 files changed, 61 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 98082416aa52..e9ec8e911056 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1712,7 +1712,18 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; - int err = -EOPNOTSUPP; + int cb_err, err = -EOPNOTSUPP; + + if (fe->dvb->fe_ioctl_override) { + cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg, + DVB_FE_IOCTL_PRE); + if (cb_err < 0) + return cb_err; + if (cb_err > 0) + return 0; + /* fe_ioctl_override returning 0 allows + * dvb-core to continue handling the ioctl */ + } switch (cmd) { case FE_GET_INFO: { @@ -1978,6 +1989,13 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, break; }; + if (fe->dvb->fe_ioctl_override) { + cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg, + DVB_FE_IOCTL_POST); + if (cb_err < 0) + return cb_err; + } + return err; } diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index 01fc70484743..f7b499d4a3c0 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h @@ -54,6 +54,8 @@ module_param_array(adapter_nr, short, NULL, 0444); \ MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers") +struct dvb_frontend; + struct dvb_adapter { int num; struct list_head list_head; @@ -69,6 +71,32 @@ struct dvb_adapter { int mfe_shared; /* indicates mutually exclusive frontends */ struct dvb_device *mfe_dvbdev; /* frontend device in use */ struct mutex mfe_lock; /* access lock for thread creation */ + + /* Allow the adapter/bridge driver to perform an action before and/or + * after the core handles an ioctl: + * + * DVB_FE_IOCTL_PRE indicates that the ioctl has not yet been handled. + * DVB_FE_IOCTL_POST indicates that the ioctl has been handled. + * + * When DVB_FE_IOCTL_PRE is passed to the callback as the stage arg: + * + * return 0 to allow dvb-core to handle the ioctl. + * return a positive int to prevent dvb-core from handling the ioctl, + * and exit without error. + * return a negative int to prevent dvb-core from handling the ioctl, + * and return that value as an error. + * + * When DVB_FE_IOCTL_POST is passed to the callback as the stage arg: + * + * return 0 to allow the dvb_frontend ioctl handler to exit normally. + * return a negative int to cause the dvb_frontend ioctl handler to + * return that value as an error. + */ +#define DVB_FE_IOCTL_PRE 0 +#define DVB_FE_IOCTL_POST 1 + int (*fe_ioctl_override)(struct dvb_frontend *fe, + unsigned int cmd, void *parg, + unsigned int stage); }; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 45e13ee66dc7..0a03e02b119b 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -904,7 +904,7 @@ static int dvb_register(struct cx23885_tsport *port) /* register everything */ ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, - &dev->pci->dev, adapter_nr, 0); + &dev->pci->dev, adapter_nr, 0, NULL); /* init CI & MAC */ switch (dev->board) { diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 518bcfe18bcb..d9e402b25b56 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -1174,7 +1174,7 @@ static int dvb_register(struct cx8802_dev *dev) /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, mfe_shared); + &dev->pci->dev, adapter_nr, mfe_shared, NULL); frontend_detach: core->gate_ctrl = NULL; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 058b56bf6717..96d3668f4691 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1574,7 +1574,7 @@ static int dvb_init(struct saa7134_dev *dev) /* register everything else */ ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, 0); + &dev->pci->dev, adapter_nr, 0, NULL); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 0e7dcba8e4ae..a56cf0d3a6d6 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -139,7 +139,9 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe, struct device *device, char *adapter_name, short *adapter_nr, - int mfe_shared) + int mfe_shared, + int (*fe_ioctl_override)(struct dvb_frontend *, + unsigned int, void *, unsigned int)) { int result; @@ -154,6 +156,7 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe, } fe->adapter.priv = adapter_priv; fe->adapter.mfe_shared = mfe_shared; + fe->adapter.fe_ioctl_override = fe_ioctl_override; return result; } @@ -253,7 +256,9 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, void *adapter_priv, struct device *device, short *adapter_nr, - int mfe_shared) + int mfe_shared, + int (*fe_ioctl_override)(struct dvb_frontend *, + unsigned int, void *, unsigned int)) { struct list_head *list, *q; struct videobuf_dvb_frontend *fe; @@ -267,7 +272,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, /* Bring up the adapter */ res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, - fe->dvb.name, adapter_nr, mfe_shared); + fe->dvb.name, adapter_nr, mfe_shared, fe_ioctl_override); if (res < 0) { printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res); return res; diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h index 6ba4f1271d23..07cf4b9d0a65 100644 --- a/include/media/videobuf-dvb.h +++ b/include/media/videobuf-dvb.h @@ -42,7 +42,9 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, void *adapter_priv, struct device *device, short *adapter_nr, - int mfe_shared); + int mfe_shared, + int (*fe_ioctl_override)(struct dvb_frontend *, + unsigned int, void *, unsigned int)); void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f); From 5bdd39621eb139630683b52c8e71202a2cc08291 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 8 May 2009 22:39:24 -0300 Subject: [PATCH 050/345] V4L/DVB (13104): cx23885: define a dvb frontend ioctl override function override set_frontend to allow rf input path switching on the HVR1275 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-dvb.c | 37 +++++++++++++++++------ drivers/media/video/cx23885/cx23885.h | 4 --- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 0a03e02b119b..875597640d74 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -487,10 +487,34 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, } break; } - return (port->set_frontend_save) ? - port->set_frontend_save(fe, param) : -ENODEV; + return 0; } +static int cx23885_dvb_fe_ioctl_override(struct dvb_frontend *fe, + unsigned int cmd, void *parg, + unsigned int stage) +{ + int err = 0; + + switch (stage) { + case DVB_FE_IOCTL_PRE: + + switch (cmd) { + case FE_SET_FRONTEND: + err = cx23885_dvb_set_frontend(fe, + (struct dvb_frontend_parameters *) parg); + break; + } + break; + + case DVB_FE_IOCTL_POST: + /* no post-ioctl handling required */ + break; + } + return err; +}; + + static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { .prod = LGS8GXX_PROD_LGS8G75, .demod_address = 0x19, @@ -550,12 +574,6 @@ static int dvb_register(struct cx23885_tsport *port) 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr127x_config); } - - /* FIXME: temporary hack */ - /* define bridge override to set_frontend */ - port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; - fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; - break; case CX23885_BOARD_HAUPPAUGE_HVR1255: i2c_bus = &dev->i2c_bus[0]; @@ -904,7 +922,8 @@ static int dvb_register(struct cx23885_tsport *port) /* register everything */ ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, - &dev->pci->dev, adapter_nr, 0, NULL); + &dev->pci->dev, adapter_nr, 0, + cx23885_dvb_fe_ioctl_override); /* init CI & MAC */ switch (dev->board) { diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 1e0e93548061..d2fbc6807ce9 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -297,10 +297,6 @@ struct cx23885_tsport { /* Allow a single tsport to have multiple frontends */ u32 num_frontends; void *port_priv; - - /* FIXME: temporary hack */ - int (*set_frontend_save) (struct dvb_frontend *, - struct dvb_frontend_parameters *); }; struct cx23885_dev { From 94d983143e981c389c3849d8baecb41b71c134b3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 7 Sep 2009 13:32:29 -0300 Subject: [PATCH 051/345] V4L/DVB (13105): dvb-usb: add fe_ioctl_override callback to dvb_usb_adapter_properties Allow dvb-usb adapter drivers to specify a fe_ioctl_override callback to enable device-specific handling of DVB frontend operations. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | 1 + drivers/media/dvb/dvb-usb/dvb-usb.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c index 8a7d87bcd1d9..df1ec3e69f4a 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c @@ -88,6 +88,7 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums) goto err; } adap->dvb_adap.priv = adap; + adap->dvb_adap.fe_ioctl_override = adap->props.fe_ioctl_override; if (adap->dev->props.read_mac_address) { if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index fe2b87efb3f1..0143aef19ecd 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -162,6 +162,9 @@ struct dvb_usb_adapter_properties { struct usb_data_stream_properties stream; int size_of_priv; + + int (*fe_ioctl_override) (struct dvb_frontend *, + unsigned int, void *, unsigned int); }; /** From b450b92e162a454b82fea6373c83e447e28ce4d6 Mon Sep 17 00:00:00 2001 From: Henk Vergonet Date: Sun, 27 Sep 2009 18:19:58 -0300 Subject: [PATCH 052/345] V4L/DVB (13108): tda8290: enable deemphasis_50 module parameter This adds a forgotten module_param macro needed to set a deemphasis of 50us. It is the standard setting for commercial FM radio broadcasts outside the US. Signed-off-by: Henk Vergonet Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda8290.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index 064d14c8d7b2..c190b0dedee4 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -33,6 +33,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); static int deemphasis_50; +module_param(deemphasis_50, int, 0644); MODULE_PARM_DESC(deemphasis_50, "0 - 75us deemphasis; 1 - 50us deemphasis"); /* ---------------------------------------------------------------------- */ From 3986bd116f3c53d695aef1781e14b6c5670d4cdd Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 27 Sep 2009 17:00:13 -0300 Subject: [PATCH 053/345] V4L/DVB (13110): tda18271: use temporary variables in tda18271_rf_tracking_filters_init Use temporary variables for signed calulations between unsigned values Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 3a50ce96fcb9..8b515a7d93f8 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -572,6 +572,7 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; unsigned char *regs = priv->tda18271_regs; int bcal, rf, i; + s32 divisor, dividend; #define RF1 0 #define RF2 1 #define RF3 2 @@ -614,15 +615,17 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) map[i].rf1 = rf_freq[RF1] / 1000; break; case RF2: - map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] - - prog_cal[RF1] + prog_tab[RF1]) / - (s32)((rf_freq[RF2] - rf_freq[RF1]) / 1000); + dividend = (s32)(prog_cal[RF2] - prog_tab[RF2]) - + (s32)(prog_cal[RF1] + prog_tab[RF1]); + divisor = (s32)(rf_freq[RF2] - rf_freq[RF1]) / 1000; + map[i].rf_a1 = (dividend / divisor); map[i].rf2 = rf_freq[RF2] / 1000; break; case RF3: - map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] - - prog_cal[RF2] + prog_tab[RF2]) / - (s32)((rf_freq[RF3] - rf_freq[RF2]) / 1000); + dividend = (s32)(prog_cal[RF3] - prog_tab[RF3]) - + (s32)(prog_cal[RF2] + prog_tab[RF2]); + divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000; + map[i].rf_a2 = (dividend / divisor); map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2]; map[i].rf3 = rf_freq[RF3] / 1000; break; From 3a6b49fef6cd18ce3de9de3db12bfbeacf39f9e9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 27 Sep 2009 23:10:20 -0300 Subject: [PATCH 054/345] V4L/DVB (13111): tda18271: more signedness fixes Convert tda18271_rf_tracking_filter_cal.rf_[ab][12] from int to s32. Convert tda18271_priv.tm_rfcal from unsigned int to u8. Cast subtractions between u32 values as s32. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 21 +++++++++++---------- drivers/media/common/tuners/tda18271-priv.h | 11 ++++++----- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 8b515a7d93f8..e0fd9f5d5944 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -256,8 +256,9 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; unsigned char *regs = priv->tda18271_regs; - int tm_current, rfcal_comp, approx, i, ret; - u8 dc_over_dt, rf_tab; + int i, ret; + u8 tm_current, dc_over_dt, rf_tab; + s32 rfcal_comp, approx; /* power up */ ret = tda18271_set_standby_mode(fe, 0, 0, 0); @@ -277,11 +278,11 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, return i; if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) { - approx = map[i].rf_a1 * - (freq / 1000 - map[i].rf1) + map[i].rf_b1 + rf_tab; + approx = map[i].rf_a1 * (s32)(freq / 1000 - map[i].rf1) + + map[i].rf_b1 + rf_tab; } else { - approx = map[i].rf_a2 * - (freq / 1000 - map[i].rf2) + map[i].rf_b2 + rf_tab; + approx = map[i].rf_a2 * (s32)(freq / 1000 - map[i].rf2) + + map[i].rf_b2 + rf_tab; } if (approx < 0) @@ -292,9 +293,9 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt); /* calculate temperature compensation */ - rfcal_comp = dc_over_dt * (tm_current - priv->tm_rfcal) / 1000; + rfcal_comp = dc_over_dt * (s32)(tm_current - priv->tm_rfcal) / 1000; - regs[R_EB14] = approx + rfcal_comp; + regs[R_EB14] = (unsigned char)(approx + rfcal_comp); ret = tda18271_write_regs(fe, R_EB14, 1); fail: return ret; @@ -611,7 +612,7 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) switch (rf) { case RF1: map[i].rf_a1 = 0; - map[i].rf_b1 = prog_cal[RF1] - prog_tab[RF1]; + map[i].rf_b1 = (s32)(prog_cal[RF1] - prog_tab[RF1]); map[i].rf1 = rf_freq[RF1] / 1000; break; case RF2: @@ -626,7 +627,7 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) (s32)(prog_cal[RF2] + prog_tab[RF2]); divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000; map[i].rf_a2 = (dividend / divisor); - map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2]; + map[i].rf_b2 = (s32)(prog_cal[RF2] - prog_tab[RF2]); map[i].rf3 = rf_freq[RF3] / 1000; break; default: diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h index 2bee229acd91..74075be4dea3 100644 --- a/drivers/media/common/tuners/tda18271-priv.h +++ b/drivers/media/common/tuners/tda18271-priv.h @@ -80,10 +80,10 @@ struct tda18271_rf_tracking_filter_cal { u32 rf1; u32 rf2; u32 rf3; - int rf_a1; - int rf_b1; - int rf_a2; - int rf_b2; + s32 rf_a1; + s32 rf_b1; + s32 rf_a2; + s32 rf_b2; }; enum tda18271_pll { @@ -111,10 +111,11 @@ struct tda18271_priv { enum tda18271_output_options output_opt; unsigned int config; /* interface to saa713x / tda829x */ - unsigned int tm_rfcal; unsigned int cal_initialized:1; unsigned int small_i2c:1; + u8 tm_rfcal; + struct tda18271_map_layout *maps; struct tda18271_std_map std; struct tda18271_rf_tracking_filter_cal rf_cal_state[8]; From c0faeee5a3b70c894a27fa81a0d98a3ab223aff0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 28 Sep 2009 03:13:49 -0300 Subject: [PATCH 055/345] V4L/DVB (13112): tda18271: display some state information in debug output Display i2c adapter id, address and master / slave role in debug output. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-maps.c | 1 + drivers/media/common/tuners/tda18271-priv.h | 32 ++++++++++++++------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/common/tuners/tda18271-maps.c index e21fdeff3ddf..e7f84c705da8 100644 --- a/drivers/media/common/tuners/tda18271-maps.c +++ b/drivers/media/common/tuners/tda18271-maps.c @@ -978,6 +978,7 @@ static struct tda18271_cid_target_map tda18271_cid_target[] = { int tda18271_lookup_cid_target(struct dvb_frontend *fe, u32 *freq, u8 *cid_target, u16 *count_limit) { + struct tda18271_priv *priv = fe->tuner_priv; int i = 0; while ((tda18271_cid_target[i].rfmax * 1000) < *freq) { diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h index 74075be4dea3..7047680cdbd1 100644 --- a/drivers/media/common/tuners/tda18271-priv.h +++ b/drivers/media/common/tuners/tda18271-priv.h @@ -136,27 +136,37 @@ extern int tda18271_debug; #define DBG_ADV 8 #define DBG_CAL 16 -#define tda_printk(kern, fmt, arg...) \ - printk(kern "%s: " fmt, __func__, ##arg) +#define tda_printk(st, kern, fmt, arg...) do {\ + if (st) { \ + struct tda18271_priv *state = st; \ + printk(kern "%s: [%d-%04x|%s] " fmt, __func__, \ + i2c_adapter_id(state->i2c_props.adap), \ + state->i2c_props.addr, \ + (state->role == TDA18271_MASTER) \ + ? "M" : "S", ##arg); \ + } else \ + printk(kern "%s: " fmt, __func__, ##arg); \ +} while (0) -#define tda_dprintk(lvl, fmt, arg...) do {\ +#define tda_dprintk(st, lvl, fmt, arg...) do {\ if (tda18271_debug & lvl) \ - tda_printk(KERN_DEBUG, fmt, ##arg); } while (0) + tda_printk(st, KERN_DEBUG, fmt, ##arg); } while (0) #define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg) -#define tda_warn(fmt, arg...) tda_printk(KERN_WARNING, fmt, ##arg) -#define tda_err(fmt, arg...) tda_printk(KERN_ERR, fmt, ##arg) -#define tda_dbg(fmt, arg...) tda_dprintk(DBG_INFO, fmt, ##arg) -#define tda_map(fmt, arg...) tda_dprintk(DBG_MAP, fmt, ##arg) -#define tda_reg(fmt, arg...) tda_dprintk(DBG_REG, fmt, ##arg) -#define tda_cal(fmt, arg...) tda_dprintk(DBG_CAL, fmt, ##arg) +#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg) +#define tda_err(fmt, arg...) tda_printk(priv, KERN_ERR, fmt, ##arg) +#define tda_dbg(fmt, arg...) tda_dprintk(priv, DBG_INFO, fmt, ##arg) +#define tda_map(fmt, arg...) tda_dprintk(priv, DBG_MAP, fmt, ##arg) +#define tda_reg(fmt, arg...) tda_dprintk(priv, DBG_REG, fmt, ##arg) +#define tda_cal(fmt, arg...) tda_dprintk(priv, DBG_CAL, fmt, ##arg) #define tda_fail(ret) \ ({ \ int __ret; \ __ret = (ret < 0); \ if (__ret) \ - tda_printk(KERN_ERR, "error %d on line %d\n", ret, __LINE__);\ + tda_printk(priv, KERN_ERR, \ + "error %d on line %d\n", ret, __LINE__); \ __ret; \ }) From 1d76331ddbb43c04d4d62bf5b9cc93efc05149c7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 18 Sep 2009 05:36:24 -0300 Subject: [PATCH 056/345] V4L/DVB (13114): gspca - zc3xx.c: Bad init sequences of sensor cs2102. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 399 +++++++++--------------------- 1 file changed, 112 insertions(+), 287 deletions(-) diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index cdf3357b4c9f..e544630757c8 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -420,9 +420,7 @@ static const struct usb_action adcm2700_NoFliker[] = { {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ {} }; -static const struct usb_action cs2102_Initial[] = { - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0008}, +static const struct usb_action cs2102_Initial[] = { /* 320x240 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, @@ -471,88 +469,10 @@ static const struct usb_action cs2102_Initial[] = { {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, {0xa0, 0x68, ZC3XX_R18D_YTARGET}, {0xa0, 0x00, 0x01ad}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x24, ZC3XX_R120_GAMMA00}, /* gamma 5 */ - {0xa0, 0x44, ZC3XX_R121_GAMMA01}, - {0xa0, 0x64, ZC3XX_R122_GAMMA02}, - {0xa0, 0x84, ZC3XX_R123_GAMMA03}, - {0xa0, 0x9d, ZC3XX_R124_GAMMA04}, - {0xa0, 0xb2, ZC3XX_R125_GAMMA05}, - {0xa0, 0xc4, ZC3XX_R126_GAMMA06}, - {0xa0, 0xd3, ZC3XX_R127_GAMMA07}, - {0xa0, 0xe0, ZC3XX_R128_GAMMA08}, - {0xa0, 0xeb, ZC3XX_R129_GAMMA09}, - {0xa0, 0xf4, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xfb, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xff, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xff, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xff, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x18, ZC3XX_R130_GAMMA10}, - {0xa0, 0x20, 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, 0x0e, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x00, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x00, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x00, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x01, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf4, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf4, ZC3XX_R10D_RGB10}, - {0xa0, 0x58, ZC3XX_R10E_RGB11}, - {0xa0, 0xf4, ZC3XX_R10F_RGB12}, - {0xa0, 0xf4, ZC3XX_R110_RGB20}, - {0xa0, 0xf4, ZC3XX_R111_RGB21}, - {0xa0, 0x58, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x23, 0x0001}, - {0xaa, 0x24, 0x0055}, - {0xaa, 0x25, 0x00cc}, - {0xaa, 0x21, 0x003f}, - {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x39, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x70, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, {} }; -static const struct usb_action cs2102_InitialScale[] = { - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0008}, +static const struct usb_action cs2102_InitialScale[] = { /* 640x480 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, @@ -601,57 +521,75 @@ static const struct usb_action cs2102_InitialScale[] = { {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, {0xa0, 0x68, ZC3XX_R18D_YTARGET}, {0xa0, 0x00, 0x01ad}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x24, ZC3XX_R120_GAMMA00}, /* gamma 5 */ - {0xa0, 0x44, ZC3XX_R121_GAMMA01}, - {0xa0, 0x64, ZC3XX_R122_GAMMA02}, - {0xa0, 0x84, ZC3XX_R123_GAMMA03}, - {0xa0, 0x9d, ZC3XX_R124_GAMMA04}, - {0xa0, 0xb2, ZC3XX_R125_GAMMA05}, - {0xa0, 0xc4, ZC3XX_R126_GAMMA06}, - {0xa0, 0xd3, ZC3XX_R127_GAMMA07}, - {0xa0, 0xe0, ZC3XX_R128_GAMMA08}, - {0xa0, 0xeb, ZC3XX_R129_GAMMA09}, - {0xa0, 0xf4, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xfb, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xff, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xff, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xff, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x18, ZC3XX_R130_GAMMA10}, - {0xa0, 0x20, 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, 0x0e, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x00, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x00, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x00, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x01, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf4, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf4, ZC3XX_R10D_RGB10}, - {0xa0, 0x58, ZC3XX_R10E_RGB11}, - {0xa0, 0xf4, ZC3XX_R10F_RGB12}, - {0xa0, 0xf4, ZC3XX_R110_RGB20}, - {0xa0, 0xf4, ZC3XX_R111_RGB21}, - {0xa0, 0x58, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, + {} +}; +static const struct usb_action cs2102_50HZ[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xaa, 0x23, 0x0001}, + {0xaa, 0x24, 0x005f}, + {0xaa, 0x25, 0x0090}, + {0xaa, 0x21, 0x00dd}, + {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x3a, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x98, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0xdd, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0xe4, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, + {} +}; +static const struct usb_action cs2102_50HZScale[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xaa, 0x23, 0x0000}, + {0xaa, 0x24, 0x00af}, + {0xaa, 0x25, 0x00c8}, + {0xaa, 0x21, 0x0068}, + {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x90, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x1d, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x4c, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x68, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0xe3, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, + {} +}; +static const struct usb_action cs2102_60HZ[] = { + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xaa, 0x23, 0x0001}, + {0xaa, 0x24, 0x0055}, + {0xaa, 0x25, 0x00cc}, + {0xaa, 0x21, 0x003f}, + {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x39, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x70, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, + {} +}; +static const struct usb_action cs2102_60HZScale[] = { {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, {0xaa, 0x23, 0x0000}, {0xaa, 0x24, 0x00aa}, @@ -671,162 +609,50 @@ static const struct usb_action cs2102_InitialScale[] = { {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1}, {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {} -}; -static const struct usb_action cs2102_50HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0f, 0x008c}, /* 00,0f,8c,aa */ - {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ - {0xaa, 0x04, 0x00ac}, /* 00,04,ac,aa */ - {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ - {0xaa, 0x11, 0x00ac}, /* 00,11,ac,aa */ - {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ - {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ - {0xaa, 0x1d, 0x00ac}, /* 00,1d,ac,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,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, 0x42, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,42,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x8c, ZC3XX_R01D_HSYNC_0}, /* 00,1d,8c,cc */ - {0xa0, 0xb0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,b0,cc */ - {0xa0, 0xd0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,d0,cc */ - {} -}; -static const struct usb_action cs2102_50HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0f, 0x0093}, /* 00,0f,93,aa */ - {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ - {0xaa, 0x04, 0x00a1}, /* 00,04,a1,aa */ - {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ - {0xaa, 0x11, 0x00a1}, /* 00,11,a1,aa */ - {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ - {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ - {0xaa, 0x1d, 0x00a1}, /* 00,1d,a1,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ - {0xa0, 0xf7, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f7,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x93, ZC3XX_R01D_HSYNC_0}, /* 00,1d,93,cc */ - {0xa0, 0xb0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,b0,cc */ - {0xa0, 0xd0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,d0,cc */ - {} -}; -static const struct usb_action cs2102_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0f, 0x005d}, /* 00,0f,5d,aa */ - {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ - {0xaa, 0x04, 0x00aa}, /* 00,04,aa,aa */ - {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ - {0xaa, 0x11, 0x00aa}, /* 00,11,aa,aa */ - {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ - {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ - {0xaa, 0x1d, 0x00aa}, /* 00,1d,aa,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ - {0xa0, 0xe4, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e4,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3a,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x5d, ZC3XX_R01D_HSYNC_0}, /* 00,1d,5d,cc */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ - {0xa0, 0xd0, 0x00c8}, /* 00,c8,d0,cc */ - {} -}; -static const struct usb_action cs2102_60HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0f, 0x00b7}, /* 00,0f,b7,aa */ - {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ - {0xaa, 0x04, 0x00be}, /* 00,04,be,aa */ - {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ - {0xaa, 0x11, 0x00be}, /* 00,11,be,aa */ - {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ - {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ - {0xaa, 0x1d, 0x00be}, /* 00,1d,be,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ - {0xa0, 0xfc, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,fc,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x69, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,69,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0xb7, ZC3XX_R01D_HSYNC_0}, /* 00,1d,b7,cc */ - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ - {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */ {} }; static const struct usb_action cs2102_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0f, 0x0059}, /* 00,0f,59,aa */ - {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ - {0xaa, 0x04, 0x0080}, /* 00,04,80,aa */ - {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ - {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */ - {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ - {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ - {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,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, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,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, 0x59, ZC3XX_R01D_HSYNC_0}, /* 00,1d,59,cc */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xaa, 0x23, 0x0001}, + {0xaa, 0x24, 0x005f}, + {0xaa, 0x25, 0x0000}, + {0xaa, 0x21, 0x0001}, + {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x01, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, {} }; static const struct usb_action cs2102_NoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0f, 0x0059}, /* 00,0f,59,aa */ - {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ - {0xaa, 0x04, 0x0080}, /* 00,04,80,aa */ - {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ - {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */ - {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ - {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ - {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,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, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,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, 0x59, ZC3XX_R01D_HSYNC_0}, /* 00,1d,59,cc */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xaa, 0x23, 0x0000}, + {0xaa, 0x24, 0x00af}, + {0xaa, 0x25, 0x0080}, + {0xaa, 0x21, 0x0001}, + {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x01, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, {} }; @@ -6384,7 +6210,7 @@ static void setmatrix(struct gspca_dev *gspca_dev) {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; static const __u8 *matrix_tb[SENSOR_MAX] = { adcm2700_matrix, /* SENSOR_ADCM2700 0 */ - NULL, /* SENSOR_CS2102 1 */ + ov7620_matrix, /* SENSOR_CS2102 1 */ NULL, /* SENSOR_CS2102K 2 */ gc0305_matrix, /* SENSOR_GC0305 3 */ NULL, /* SENSOR_HDCS2020b 4 */ @@ -7025,7 +6851,7 @@ static int sd_config(struct gspca_dev *gspca_dev, int vga = 1; /* 1: vga, 0: sif */ static const __u8 gamma[SENSOR_MAX] = { 4, /* SENSOR_ADCM2700 0 */ - 5, /* SENSOR_CS2102 1 */ + 4, /* SENSOR_CS2102 1 */ 5, /* SENSOR_CS2102K 2 */ 4, /* SENSOR_GC0305 3 */ 4, /* SENSOR_HDCS2020b 4 */ @@ -7310,8 +7136,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* set the gamma tables when not set */ switch (sd->sensor) { - case SENSOR_CS2102: /* gamma set in xxx_Initial */ - case SENSOR_CS2102K: + case SENSOR_CS2102K: /* gamma set in xxx_Initial */ case SENSOR_HDCS2020b: case SENSOR_PB0330: /* pb with chip_revision - see above */ case SENSOR_OV7630C: From 0d07e240c5da04db7c26dd4e337b3845be99d5f8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 1 Oct 2009 13:44:49 -0300 Subject: [PATCH 057/345] V4L/DVB (13115): gspca - main: More information messages. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 23d3fb776918..179cbc14ee51 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -980,7 +980,7 @@ static void gspca_release(struct video_device *vfd) { struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); - PDEBUG(D_STREAM, "device released"); + PDEBUG(D_PROBE, "/dev/video%d released", gspca_dev->vdev.num); kfree(gspca_dev->usb_buf); kfree(gspca_dev); @@ -991,7 +991,7 @@ static int dev_open(struct file *file) struct gspca_dev *gspca_dev; int ret; - PDEBUG(D_STREAM, "%s open", current->comm); + PDEBUG(D_STREAM, "[%s] open", current->comm); gspca_dev = (struct gspca_dev *) video_devdata(file); if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; @@ -1037,7 +1037,7 @@ static int dev_close(struct file *file) { struct gspca_dev *gspca_dev = file->private_data; - PDEBUG(D_STREAM, "%s close", current->comm); + PDEBUG(D_STREAM, "[%s] close", current->comm); if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; gspca_dev->users--; @@ -2001,11 +2001,15 @@ int gspca_dev_probe(struct usb_interface *intf, PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct); /* we don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) + if (dev->descriptor.bNumConfigurations != 1) { + PDEBUG(D_ERR, "Too many config"); return -ENODEV; + } interface = &intf->cur_altsetting->desc; - if (interface->bInterfaceNumber > 0) + if (interface->bInterfaceNumber > 0) { + PDEBUG(D_ERR, "intf != 0"); return -ENODEV; + } /* create the device */ if (dev_size < sizeof *gspca_dev) @@ -2059,7 +2063,7 @@ int gspca_dev_probe(struct usb_interface *intf, } usb_set_intfdata(intf, gspca_dev); - PDEBUG(D_PROBE, "probe ok"); + PDEBUG(D_PROBE, "/dev/video%d created", gspca_dev->vdev.num); return 0; out: kfree(gspca_dev->usb_buf); @@ -2078,6 +2082,7 @@ void gspca_disconnect(struct usb_interface *intf) { struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + PDEBUG(D_PROBE, "/dev/video%d disconnect", gspca_dev->vdev.num); mutex_lock(&gspca_dev->usb_lock); gspca_dev->present = 0; @@ -2096,7 +2101,7 @@ void gspca_disconnect(struct usb_interface *intf) /* (this will call gspca_release() immediatly or on last close) */ video_unregister_device(&gspca_dev->vdev); - PDEBUG(D_PROBE, "disconnect complete"); +/* PDEBUG(D_PROBE, "disconnect complete"); */ } EXPORT_SYMBOL(gspca_disconnect); From 518c8df77c21b7d1690dd8b96eb0e54c4ec1c9c1 Mon Sep 17 00:00:00 2001 From: Rafal Milecki Date: Fri, 2 Oct 2009 03:54:44 -0300 Subject: [PATCH 058/345] V4L/DVB (13116): gspca - ov519: Webcam 041e:4067 added. Signed-off-by: Rafal Milecki Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/ov519.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 3f61825be499..90e85a8a8817 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -37,6 +37,7 @@ ov519 041e:405f Creative Live! VISTA VF0330 ov519 041e:4060 Creative Live! VISTA VF0350 ov519 041e:4061 Creative Live! VISTA VF0400 ov519 041e:4064 Creative Live! VISTA VF0420 +ov519 041e:4067 Creative Live! Cam Video IM (VF0350) ov519 041e:4068 Creative Live! VISTA VF0470 spca561 0458:7004 Genius VideoCAM Express V2 sunplus 0458:7006 Genius Dsc 1.3 Smart diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index a5c190e93799..e16557819782 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3364,6 +3364,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, From ff75e99c62bcef8ccd6fb70151ad2b87aa52a165 Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Sun, 4 Oct 2009 13:51:26 -0300 Subject: [PATCH 059/345] V4L/DVB (13117): gspca - pac7311: remove magic value for SKIP. Change the magic value 0xaa to SKIP for better understandability. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7311.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 052714484e83..f05bc800a7cb 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -316,7 +316,8 @@ static const __u8 start_7302[] = { 0, 0 /* end of sequence */ }; -/* page 3 - the value 0xaa says skip the index - see reg_w_page() */ +#define SKIP 0xaa +/* page 3 - the value SKIP says skip the index - see reg_w_page() */ static const __u8 page3_7302[] = { 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, @@ -383,13 +384,13 @@ static const __u8 start_7311[] = { 0, 0 /* end of sequence */ }; -/* page 4 - the value 0xaa says skip the index - see reg_w_page() */ +/* page 4 - the value SKIP says skip the index - see reg_w_page() */ static const __u8 page4_7311[] = { - 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, - 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62, - 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa, - 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68, + SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, + 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62, + 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP, + SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68, 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 }; @@ -438,7 +439,7 @@ static void reg_w_page(struct gspca_dev *gspca_dev, int index; for (index = 0; index < len; index++) { - if (page[index] == 0xaa) /* skip this index */ + if (page[index] == SKIP) /* skip this index */ continue; gspca_dev->usb_buf[0] = page[index]; usb_control_msg(gspca_dev->dev, From 5a2e8d9fc15901d6ee4ec177b3845a84b6b960bd Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Sun, 4 Oct 2009 13:53:22 -0300 Subject: [PATCH 060/345] V4L/DVB (13118): gspca - pac7311: remove magic values for END_OF_SEQUENCE and LOAD_PAGE. Change the magic values 0, 254 and 255 to END_OF_SEQUENCE, LOAD_PAGE4 and LOAD_PAGE3 respectively for better source code readability. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7311.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index f05bc800a7cb..418d1a36beb0 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -244,6 +244,10 @@ static const struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; +#define LOAD_PAGE3 255 +#define LOAD_PAGE4 254 +#define END_OF_SEQUENCE 0 + /* pac 7302 */ static const __u8 init_7302[] = { /* index,value */ @@ -302,7 +306,7 @@ static const __u8 start_7302[] = { 0xff, 1, 0x02, /* page 2 */ 0x22, 1, 0x00, 0xff, 1, 0x03, /* page 3 */ - 0x00, 255, /* load the page 3 */ + 0, LOAD_PAGE3, /* load the page 3 */ 0x11, 1, 0x01, 0xff, 1, 0x02, /* page 2 */ 0x13, 1, 0x00, @@ -313,7 +317,7 @@ static const __u8 start_7302[] = { 0x6e, 1, 0x08, 0xff, 1, 0x01, /* page 1 */ 0x78, 1, 0x00, - 0, 0 /* end of sequence */ + 0, END_OF_SEQUENCE /* end of sequence */ }; #define SKIP 0xaa @@ -379,9 +383,9 @@ static const __u8 start_7311[] = { 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, 0x3f, 0x00, 0x0a, 0x01, 0x00, 0xff, 1, 0x04, /* page 4 */ - 0x00, 254, /* load the page 4 */ + 0, LOAD_PAGE4, /* load the page 4 */ 0x11, 1, 0x01, - 0, 0 /* end of sequence */ + 0, END_OF_SEQUENCE /* end of sequence */ }; /* page 4 - the value SKIP says skip the index - see reg_w_page() */ @@ -461,12 +465,12 @@ static void reg_w_var(struct gspca_dev *gspca_dev, index = *seq++; len = *seq++; switch (len) { - case 0: + case END_OF_SEQUENCE: return; - case 254: + case LOAD_PAGE4: reg_w_page(gspca_dev, page4_7311, sizeof page4_7311); break; - case 255: + case LOAD_PAGE3: reg_w_page(gspca_dev, page3_7302, sizeof page3_7302); break; default: From 24067bb552ae8be647372359d6a3ea6ce7de1525 Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Sun, 4 Oct 2009 13:54:48 -0300 Subject: [PATCH 061/345] V4L/DVB (13119): gspca - pac7311: remove magic value for USB_BUF_SZ The length check in reg_w_var() function is because the buffer contents is copied to gspca_dev->usb_buf which has the size of USB_BUF_SZ bytes as defined in drivers/media/video/gspca/gspca.h. Replace the number with symbol for better readability and maintainability. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7311.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 418d1a36beb0..26514285a844 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -474,7 +474,7 @@ static void reg_w_var(struct gspca_dev *gspca_dev, reg_w_page(gspca_dev, page3_7302, sizeof page3_7302); break; default: - if (len > 64) { + if (len > USB_BUF_SZ) { PDEBUG(D_ERR|D_STREAM, "Incorrect variable sequence"); return; From 4fc8b64823ef0c42213a89af6c4c13066f210981 Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Sun, 4 Oct 2009 13:56:50 -0300 Subject: [PATCH 062/345] V4L/DVB (13120): gspca - pac7311: remove redundant register page switching Remove redundant register page switching to page 0 when changing the color control. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7311.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 26514285a844..b21c5e155f46 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -579,7 +579,6 @@ static void setcolors(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ reg_w(gspca_dev, 0x11, 0x01); reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ for (i = 0; i < 9; i++) { v = a[i] * sd->colors / COLOR_MAX + b[i]; reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); From 56f6f5582f7f422f142035dd92b521e72ffdb348 Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Sun, 4 Oct 2009 13:58:19 -0300 Subject: [PATCH 063/345] V4L/DVB (13121): gspca - pac7311: add comment about JPEG header Add comment about the meaning of the fixed JPEG header bytes used to create each image. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7311.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index b21c5e155f46..f954900c451b 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -801,13 +801,32 @@ static void do_autogain(struct gspca_dev *gspca_dev) sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; } +/* JPEG header, part 1 */ static const unsigned char pac7311_jpeg_header1[] = { - 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08 + 0xff, 0xd8, /* SOI: Start of Image */ + + 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ + 0x00, 0x11, /* length = 17 bytes (including this length field) */ + 0x08 /* Precision: 8 */ + /* 2 bytes is placed here: number of image lines */ + /* 2 bytes is placed here: samples per line */ }; +/* JPEG header, continued */ static const unsigned char pac7311_jpeg_header2[] = { - 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, - 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 + 0x03, /* Number of image components: 3 */ + 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ + 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ + 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ + + 0xff, 0xda, /* SOS: Start Of Scan */ + 0x00, 0x0c, /* length = 12 bytes (including this length field) */ + 0x03, /* number of components: 3 */ + 0x01, 0x00, /* selector 1, table 0x00 */ + 0x02, 0x11, /* selector 2, table 0x11 */ + 0x03, 0x11, /* selector 3, table 0x11 */ + 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ + 0x00 /* Successive approximation: 0 */ }; /* this function is run at interrupt level */ From b1de7aeba1d7592b97507c21ea986ec6243a4165 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 5 Oct 2009 12:48:20 -0300 Subject: [PATCH 064/345] V4L/DVB (13127): sh_mobile_ceu: add soft reset function Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 42 ++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 9c8b7c7b89ee..edb6ec3d2bcd 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -153,6 +153,40 @@ static u32 ceu_read(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs) return ioread32(priv->base + reg_offs); } +static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) +{ + int i, success = 0; + struct soc_camera_device *icd = pcdev->icd; + + ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ + + /* wait CSTSR.CPTON bit */ + for (i = 0; i < 1000; i++) { + if (!(ceu_read(pcdev, CSTSR) & 1)) { + success++; + break; + } + udelay(1); + } + + /* wait CAPSR.CPKIL bit */ + for (i = 0; i < 1000; i++) { + if (!(ceu_read(pcdev, CAPSR) & (1 << 16))) { + success++; + break; + } + udelay(1); + } + + + if (2 != success) { + dev_warn(&icd->dev, "soft reset time out\n"); + return -EIO; + } + + return 0; +} + /* * Videobuf operations */ @@ -407,13 +441,9 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) pm_runtime_get_sync(ici->v4l2_dev.dev); - ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ - while (ceu_read(pcdev, CSTSR) & 1) - msleep(1); - pcdev->icd = icd; - return 0; + return sh_mobile_ceu_soft_reset(pcdev); } /* Called with .video_lock held */ @@ -427,7 +457,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) /* disable capture, disable interrupts */ ceu_write(pcdev, CEIER, 0); - ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ + sh_mobile_ceu_soft_reset(pcdev); /* make sure active buffer is canceled */ spin_lock_irqsave(&pcdev->lock, flags); From 5cf93f1dcaff4960bdfea22196963556778b22b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 5 Oct 2009 12:48:59 -0300 Subject: [PATCH 065/345] V4L/DVB (13128): sh_mobile_ceu_camera: add VBP error support If CEU driver can not receive data from camera, CETCR has VBP error state. Then, CEU is stopped and cure operation is needed. This patch add VBP error cure operation. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 41 +++++++++++++++++----- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index edb6ec3d2bcd..a4f3472d4db8 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -236,26 +236,45 @@ static void free_buffer(struct videobuf_queue *vq, #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_CEIER_VBP (1 << 20) /* vbp error */ #define CEU_CAPCR_CTNCP (1 << 16) /* continuous capture mode (if set) */ +#define CEU_CEIER_MASK (CEU_CEIER_CPEIE | CEU_CEIER_VBP) -static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) +/* + * return value doesn't reflex the success/failure to queue the new buffer, + * but rather the status of the previous buffer. + */ +static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { struct soc_camera_device *icd = pcdev->icd; dma_addr_t phys_addr_top, phys_addr_bottom; + u32 status; + int ret = 0; /* 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, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_MASK); + status = ceu_read(pcdev, CETCR); + ceu_write(pcdev, CETCR, ~status & CEU_CETCR_MAGIC); + ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_MASK); ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); + /* + * When a VBP interrupt occurs, a capture end interrupt does not occur + * and the image of that frame is not captured correctly. So, soft reset + * is needed here. + */ + if (status & CEU_CEIER_VBP) { + sh_mobile_ceu_soft_reset(pcdev); + ret = -EIO; + } + if (!pcdev->active) - return; + return ret; phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); @@ -281,6 +300,8 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) pcdev->active->state = VIDEOBUF_ACTIVE; ceu_write(pcdev, CAPSR, 0x1); /* start capture */ + + return ret; } static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, @@ -353,6 +374,11 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, list_add_tail(&vb->queue, &pcdev->capture); if (!pcdev->active) { + /* + * Because there were no active buffer at this moment, + * we are not interested in the return value of + * sh_mobile_ceu_capture here. + */ pcdev->active = vb; sh_mobile_ceu_capture(pcdev); } @@ -413,9 +439,8 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) else pcdev->active = NULL; - sh_mobile_ceu_capture(pcdev); - - vb->state = VIDEOBUF_DONE; + vb->state = (sh_mobile_ceu_capture(pcdev) < 0) ? + VIDEOBUF_ERROR : VIDEOBUF_DONE; do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); From 8f37cf25badd0ba9de7cd05c3f1d5362607c1bf9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 5 Oct 2009 12:54:04 -0300 Subject: [PATCH 066/345] V4L/DVB (13130): soc-camera: add a new driver for the RJ54N1CB0C camera sensor from Sharp This adds an soc-camera / v4l2-subdev driver for the RJ54N1CB0C CMOS camera sensor from Sharp. The sensor is very picky about initialisation and configuration sequences. The driver limits artificially maximum window size by 800x600, although the sensor supports 1600x1200. Sizes above 800x600 don't seem to work correctly, besides, examples from the system integrator use sizes above 640x480 only for still photography. Unfortunately, I had to use "magic" register-value pairs for undocumented and "reserved" registers. This version of the driver also omits some functionality, like cropping, which hasn't been sufficiently tested yet and will be added later. create mode 100644 drivers/media/video/rj54n1cb0c.c Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 6 + drivers/media/video/Makefile | 1 + drivers/media/video/rj54n1cb0c.c | 1219 ++++++++++++++++++++++++++++++ include/media/v4l2-chip-ident.h | 3 + 4 files changed, 1229 insertions(+) create mode 100644 drivers/media/video/rj54n1cb0c.c diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index c318676f2d29..0ab7ccd8729b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -847,6 +847,12 @@ config SOC_CAMERA_MT9V022 help This driver supports MT9V022 cameras from Micron +config SOC_CAMERA_RJ54N1 + tristate "rj54n1cb0c support" + depends on SOC_CAMERA && I2C + help + This is a rj54n1cb0c video driver + config SOC_CAMERA_TW9910 tristate "tw9910 support" depends on SOC_CAMERA && I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index e706ceecef84..7a2dcc34111c 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -78,6 +78,7 @@ 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_OV9640) += ov9640.o +obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o # And now the v4l2 drivers: diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c new file mode 100644 index 000000000000..373f2a30a677 --- /dev/null +++ b/drivers/media/video/rj54n1cb0c.c @@ -0,0 +1,1219 @@ +/* + * Driver for RJ54N1CB0C CMOS Image Sensor from Micron + * + * Copyright (C) 2009, 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 + +#define RJ54N1_DEV_CODE 0x0400 +#define RJ54N1_DEV_CODE2 0x0401 +#define RJ54N1_OUT_SEL 0x0403 +#define RJ54N1_XY_OUTPUT_SIZE_S_H 0x0404 +#define RJ54N1_X_OUTPUT_SIZE_S_L 0x0405 +#define RJ54N1_Y_OUTPUT_SIZE_S_L 0x0406 +#define RJ54N1_XY_OUTPUT_SIZE_P_H 0x0407 +#define RJ54N1_X_OUTPUT_SIZE_P_L 0x0408 +#define RJ54N1_Y_OUTPUT_SIZE_P_L 0x0409 +#define RJ54N1_LINE_LENGTH_PCK_S_H 0x040a +#define RJ54N1_LINE_LENGTH_PCK_S_L 0x040b +#define RJ54N1_LINE_LENGTH_PCK_P_H 0x040c +#define RJ54N1_LINE_LENGTH_PCK_P_L 0x040d +#define RJ54N1_RESIZE_N 0x040e +#define RJ54N1_RESIZE_N_STEP 0x040f +#define RJ54N1_RESIZE_STEP 0x0410 +#define RJ54N1_RESIZE_HOLD_H 0x0411 +#define RJ54N1_RESIZE_HOLD_L 0x0412 +#define RJ54N1_H_OBEN_OFS 0x0413 +#define RJ54N1_V_OBEN_OFS 0x0414 +#define RJ54N1_RESIZE_CONTROL 0x0415 +#define RJ54N1_INC_USE_SEL_H 0x0425 +#define RJ54N1_INC_USE_SEL_L 0x0426 +#define RJ54N1_MIRROR_STILL_MODE 0x0427 +#define RJ54N1_INIT_START 0x0428 +#define RJ54N1_SCALE_1_2_LEV 0x0429 +#define RJ54N1_SCALE_4_LEV 0x042a +#define RJ54N1_Y_GAIN 0x04d8 +#define RJ54N1_APT_GAIN_UP 0x04fa +#define RJ54N1_RA_SEL_UL 0x0530 +#define RJ54N1_BYTE_SWAP 0x0531 +#define RJ54N1_OUT_SIGPO 0x053b +#define RJ54N1_FRAME_LENGTH_S_H 0x0595 +#define RJ54N1_FRAME_LENGTH_S_L 0x0596 +#define RJ54N1_FRAME_LENGTH_P_H 0x0597 +#define RJ54N1_FRAME_LENGTH_P_L 0x0598 +#define RJ54N1_IOC 0x05ef +#define RJ54N1_TG_BYPASS 0x0700 +#define RJ54N1_PLL_L 0x0701 +#define RJ54N1_PLL_N 0x0702 +#define RJ54N1_PLL_EN 0x0704 +#define RJ54N1_RATIO_TG 0x0706 +#define RJ54N1_RATIO_T 0x0707 +#define RJ54N1_RATIO_R 0x0708 +#define RJ54N1_RAMP_TGCLK_EN 0x0709 +#define RJ54N1_OCLK_DSP 0x0710 +#define RJ54N1_RATIO_OP 0x0711 +#define RJ54N1_RATIO_O 0x0712 +#define RJ54N1_OCLK_SEL_EN 0x0713 +#define RJ54N1_CLK_RST 0x0717 +#define RJ54N1_RESET_STANDBY 0x0718 + +#define E_EXCLK (1 << 7) +#define SOFT_STDBY (1 << 4) +#define SEN_RSTX (1 << 2) +#define TG_RSTX (1 << 1) +#define DSP_RSTX (1 << 0) + +#define RESIZE_HOLD_SEL (1 << 2) +#define RESIZE_GO (1 << 1) + +#define RJ54N1_COLUMN_SKIP 0 +#define RJ54N1_ROW_SKIP 0 +#define RJ54N1_MAX_WIDTH 1600 +#define RJ54N1_MAX_HEIGHT 1200 + +/* I2C addresses: 0x50, 0x51, 0x60, 0x61 */ + +static const struct soc_camera_data_format rj54n1_colour_formats[] = { + { + .name = "YUYV", + .depth = 16, + .fourcc = V4L2_PIX_FMT_YUYV, + .colorspace = V4L2_COLORSPACE_JPEG, + }, { + .name = "RGB565", + .depth = 16, + .fourcc = V4L2_PIX_FMT_RGB565, + .colorspace = V4L2_COLORSPACE_SRGB, + } +}; + +struct rj54n1_clock_div { + u8 ratio_tg; + u8 ratio_t; + u8 ratio_r; + u8 ratio_op; + u8 ratio_o; +}; + +struct rj54n1 { + struct v4l2_subdev subdev; + struct v4l2_rect rect; /* Sensor window */ + unsigned short width; /* Output window */ + unsigned short height; + unsigned short resize; /* Sensor * 1024 / resize = Output */ + struct rj54n1_clock_div clk_div; + u32 fourcc; + unsigned short scale; + u8 bank; +}; + +struct rj54n1_reg_val { + u16 reg; + u8 val; +}; + +const static struct rj54n1_reg_val bank_4[] = { + {0x417, 0}, + {0x42c, 0}, + {0x42d, 0xf0}, + {0x42e, 0}, + {0x42f, 0x50}, + {0x430, 0xf5}, + {0x431, 0x16}, + {0x432, 0x20}, + {0x433, 0}, + {0x434, 0xc8}, + {0x43c, 8}, + {0x43e, 0x90}, + {0x445, 0x83}, + {0x4ba, 0x58}, + {0x4bb, 4}, + {0x4bc, 0x20}, + {0x4db, 4}, + {0x4fe, 2}, +}; + +const static struct rj54n1_reg_val bank_5[] = { + {0x514, 0}, + {0x516, 0}, + {0x518, 0}, + {0x51a, 0}, + {0x51d, 0xff}, + {0x56f, 0x28}, + {0x575, 0x40}, + {0x5bc, 0x48}, + {0x5c1, 6}, + {0x5e5, 0x11}, + {0x5e6, 0x43}, + {0x5e7, 0x33}, + {0x5e8, 0x21}, + {0x5e9, 0x30}, + {0x5ea, 0x0}, + {0x5eb, 0xa5}, + {0x5ec, 0xff}, + {0x5fe, 2}, +}; + +const static struct rj54n1_reg_val bank_7[] = { + {0x70a, 0}, + {0x714, 0xff}, + {0x715, 0xff}, + {0x716, 0x1f}, + {0x7FE, 0x02}, +}; + +const static struct rj54n1_reg_val bank_8[] = { + {0x800, 0x00}, + {0x801, 0x01}, + {0x802, 0x61}, + {0x805, 0x00}, + {0x806, 0x00}, + {0x807, 0x00}, + {0x808, 0x00}, + {0x809, 0x01}, + {0x80A, 0x61}, + {0x80B, 0x00}, + {0x80C, 0x01}, + {0x80D, 0x00}, + {0x80E, 0x00}, + {0x80F, 0x00}, + {0x810, 0x00}, + {0x811, 0x01}, + {0x812, 0x61}, + {0x813, 0x00}, + {0x814, 0x11}, + {0x815, 0x00}, + {0x816, 0x41}, + {0x817, 0x00}, + {0x818, 0x51}, + {0x819, 0x01}, + {0x81A, 0x1F}, + {0x81B, 0x00}, + {0x81C, 0x01}, + {0x81D, 0x00}, + {0x81E, 0x11}, + {0x81F, 0x00}, + {0x820, 0x41}, + {0x821, 0x00}, + {0x822, 0x51}, + {0x823, 0x00}, + {0x824, 0x00}, + {0x825, 0x00}, + {0x826, 0x47}, + {0x827, 0x01}, + {0x828, 0x4F}, + {0x829, 0x00}, + {0x82A, 0x00}, + {0x82B, 0x00}, + {0x82C, 0x30}, + {0x82D, 0x00}, + {0x82E, 0x40}, + {0x82F, 0x00}, + {0x830, 0xB3}, + {0x831, 0x00}, + {0x832, 0xE3}, + {0x833, 0x00}, + {0x834, 0x00}, + {0x835, 0x00}, + {0x836, 0x00}, + {0x837, 0x00}, + {0x838, 0x00}, + {0x839, 0x01}, + {0x83A, 0x61}, + {0x83B, 0x00}, + {0x83C, 0x01}, + {0x83D, 0x00}, + {0x83E, 0x00}, + {0x83F, 0x00}, + {0x840, 0x00}, + {0x841, 0x01}, + {0x842, 0x61}, + {0x843, 0x00}, + {0x844, 0x1D}, + {0x845, 0x00}, + {0x846, 0x00}, + {0x847, 0x00}, + {0x848, 0x00}, + {0x849, 0x01}, + {0x84A, 0x1F}, + {0x84B, 0x00}, + {0x84C, 0x05}, + {0x84D, 0x00}, + {0x84E, 0x19}, + {0x84F, 0x01}, + {0x850, 0x21}, + {0x851, 0x01}, + {0x852, 0x5D}, + {0x853, 0x00}, + {0x854, 0x00}, + {0x855, 0x00}, + {0x856, 0x19}, + {0x857, 0x01}, + {0x858, 0x21}, + {0x859, 0x00}, + {0x85A, 0x00}, + {0x85B, 0x00}, + {0x85C, 0x00}, + {0x85D, 0x00}, + {0x85E, 0x00}, + {0x85F, 0x00}, + {0x860, 0xB3}, + {0x861, 0x00}, + {0x862, 0xE3}, + {0x863, 0x00}, + {0x864, 0x00}, + {0x865, 0x00}, + {0x866, 0x00}, + {0x867, 0x00}, + {0x868, 0x00}, + {0x869, 0xE2}, + {0x86A, 0x00}, + {0x86B, 0x01}, + {0x86C, 0x06}, + {0x86D, 0x00}, + {0x86E, 0x00}, + {0x86F, 0x00}, + {0x870, 0x60}, + {0x871, 0x8C}, + {0x872, 0x10}, + {0x873, 0x00}, + {0x874, 0xE0}, + {0x875, 0x00}, + {0x876, 0x27}, + {0x877, 0x01}, + {0x878, 0x00}, + {0x879, 0x00}, + {0x87A, 0x00}, + {0x87B, 0x03}, + {0x87C, 0x00}, + {0x87D, 0x00}, + {0x87E, 0x00}, + {0x87F, 0x00}, + {0x880, 0x00}, + {0x881, 0x00}, + {0x882, 0x00}, + {0x883, 0x00}, + {0x884, 0x00}, + {0x885, 0x00}, + {0x886, 0xF8}, + {0x887, 0x00}, + {0x888, 0x03}, + {0x889, 0x00}, + {0x88A, 0x64}, + {0x88B, 0x00}, + {0x88C, 0x03}, + {0x88D, 0x00}, + {0x88E, 0xB1}, + {0x88F, 0x00}, + {0x890, 0x03}, + {0x891, 0x01}, + {0x892, 0x1D}, + {0x893, 0x00}, + {0x894, 0x03}, + {0x895, 0x01}, + {0x896, 0x4B}, + {0x897, 0x00}, + {0x898, 0xE5}, + {0x899, 0x00}, + {0x89A, 0x01}, + {0x89B, 0x00}, + {0x89C, 0x01}, + {0x89D, 0x04}, + {0x89E, 0xC8}, + {0x89F, 0x00}, + {0x8A0, 0x01}, + {0x8A1, 0x01}, + {0x8A2, 0x61}, + {0x8A3, 0x00}, + {0x8A4, 0x01}, + {0x8A5, 0x00}, + {0x8A6, 0x00}, + {0x8A7, 0x00}, + {0x8A8, 0x00}, + {0x8A9, 0x00}, + {0x8AA, 0x7F}, + {0x8AB, 0x03}, + {0x8AC, 0x00}, + {0x8AD, 0x00}, + {0x8AE, 0x00}, + {0x8AF, 0x00}, + {0x8B0, 0x00}, + {0x8B1, 0x00}, + {0x8B6, 0x00}, + {0x8B7, 0x01}, + {0x8B8, 0x00}, + {0x8B9, 0x00}, + {0x8BA, 0x02}, + {0x8BB, 0x00}, + {0x8BC, 0xFF}, + {0x8BD, 0x00}, + {0x8FE, 0x02}, +}; + +const static struct rj54n1_reg_val bank_10[] = { + {0x10bf, 0x69} +}; + +/* Clock dividers - these are default register values, divider = register + 1 */ +const static struct rj54n1_clock_div clk_div = { + .ratio_tg = 3 /* default: 5 */, + .ratio_t = 4 /* default: 1 */, + .ratio_r = 4 /* default: 0 */, + .ratio_op = 1 /* default: 5 */, + .ratio_o = 9 /* default: 0 */, +}; + +static struct rj54n1 *to_rj54n1(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct rj54n1, subdev); +} + +static int reg_read(struct i2c_client *client, const u16 reg) +{ + struct rj54n1 *rj54n1 = to_rj54n1(client); + int ret; + + /* set bank */ + if (rj54n1->bank != reg >> 8) { + dev_dbg(&client->dev, "[0x%x] = 0x%x\n", 0xff, reg >> 8); + ret = i2c_smbus_write_byte_data(client, 0xff, reg >> 8); + if (ret < 0) + return ret; + rj54n1->bank = reg >> 8; + } + return i2c_smbus_read_byte_data(client, reg & 0xff); +} + +static int reg_write(struct i2c_client *client, const u16 reg, + const u8 data) +{ + struct rj54n1 *rj54n1 = to_rj54n1(client); + int ret; + + /* set bank */ + if (rj54n1->bank != reg >> 8) { + dev_dbg(&client->dev, "[0x%x] = 0x%x\n", 0xff, reg >> 8); + ret = i2c_smbus_write_byte_data(client, 0xff, reg >> 8); + if (ret < 0) + return ret; + rj54n1->bank = reg >> 8; + } + dev_dbg(&client->dev, "[0x%x] = 0x%x\n", reg & 0xff, data); + return i2c_smbus_write_byte_data(client, reg & 0xff, data); +} + +static int reg_set(struct i2c_client *client, const u16 reg, + const u8 data, const u8 mask) +{ + int ret; + + ret = reg_read(client, reg); + if (ret < 0) + return ret; + return reg_write(client, reg, (ret & ~mask) | (data & mask)); +} + +static int reg_write_multiple(struct i2c_client *client, + const struct rj54n1_reg_val *rv, const int n) +{ + int i, ret; + + for (i = 0; i < n; i++) { + ret = reg_write(client, rv->reg, rv->val); + if (ret < 0) + return ret; + rv++; + } + + return 0; +} + +static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable) +{ + /* TODO: start / stop streaming */ + return 0; +} + +static int rj54n1_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct i2c_client *client = sd->priv; + /* Figures 2.5-1 to 2.5-3 - default falling pixclk edge */ + + if (flags & SOCAM_PCLK_SAMPLE_RISING) + return reg_write(client, RJ54N1_OUT_SIGPO, 1 << 4); + else + return reg_write(client, RJ54N1_OUT_SIGPO, 0); +} + +static unsigned long rj54n1_query_bus_param(struct soc_camera_device *icd) +{ + struct soc_camera_link *icl = to_soc_camera_link(icd); + const unsigned long flags = + SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | + SOCAM_MASTER | SOCAM_DATAWIDTH_8 | + SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_HIGH; + + return soc_camera_apply_sensor_flags(icl, flags); +} + +static int rj54n1_set_rect(struct i2c_client *client, + u16 reg_x, u16 reg_y, u16 reg_xy, + u32 width, u32 height) +{ + int ret; + + ret = reg_write(client, reg_xy, + ((width >> 4) & 0x70) | + ((height >> 8) & 7)); + + if (!ret) + ret = reg_write(client, reg_x, width & 0xff); + if (!ret) + ret = reg_write(client, reg_y, height & 0xff); + + return ret; +} + +/* + * Some commands, specifically certain initialisation sequences, require + * a commit operation. + */ +static int rj54n1_commit(struct i2c_client *client) +{ + int ret = reg_write(client, RJ54N1_INIT_START, 1); + msleep(10); + if (!ret) + ret = reg_write(client, RJ54N1_INIT_START, 0); + return ret; +} + +static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct rj54n1 *rj54n1 = to_rj54n1(client); + + a->c = rj54n1->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = RJ54N1_COLUMN_SKIP; + a->bounds.top = RJ54N1_ROW_SKIP; + a->bounds.width = RJ54N1_MAX_WIDTH; + a->bounds.height = RJ54N1_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int rj54n1_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct rj54n1 *rj54n1 = to_rj54n1(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->pixelformat = rj54n1->fourcc; + pix->field = V4L2_FIELD_NONE; + pix->width = rj54n1->width; + pix->height = rj54n1->height; + + return 0; +} + +/* + * The actual geometry configuration routine. It scales the input window into + * the output one, updates the window sizes and returns an error or the resize + * coefficient on success. Note: we only use the "Fixed Scaling" on this camera. + */ +static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, + u32 *out_w, u32 *out_h) +{ + struct i2c_client *client = sd->priv; + unsigned int skip, resize, input_w = *in_w, input_h = *in_h, + output_w = *out_w, output_h = *out_h; + u16 inc_sel; + int ret; + + ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_S_L, + RJ54N1_Y_OUTPUT_SIZE_S_L, + RJ54N1_XY_OUTPUT_SIZE_S_H, output_w, output_h); + if (!ret) + ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_P_L, + RJ54N1_Y_OUTPUT_SIZE_P_L, + RJ54N1_XY_OUTPUT_SIZE_P_H, output_w, output_h); + + if (ret < 0) + return ret; + + if (output_w > input_w || output_h > input_h) { + input_w = output_w; + input_h = output_h; + + resize = 1024; + } else { + unsigned int resize_x, resize_y; + resize_x = input_w * 1024 / output_w; + resize_y = input_h * 1024 / output_h; + + resize = min(resize_x, resize_y); + + /* Prohibited value ranges */ + switch (resize) { + case 2040 ... 2047: + resize = 2039; + break; + case 4080 ... 4095: + resize = 4079; + break; + case 8160 ... 8191: + resize = 8159; + break; + case 16320 ... 16383: + resize = 16319; + } + + input_w = output_w * resize / 1024; + input_h = output_h * resize / 1024; + } + + /* Set scaling */ + ret = reg_write(client, RJ54N1_RESIZE_HOLD_L, resize & 0xff); + if (!ret) + ret = reg_write(client, RJ54N1_RESIZE_HOLD_H, resize >> 8); + + if (ret < 0) + return ret; + + /* + * Configure a skipping bitmask. The sensor will select a skipping value + * among set bits automatically. + */ + skip = min(resize / 1024, (unsigned)15); + inc_sel = 1 << skip; + + if (inc_sel <= 2) + inc_sel = 0xc; + else if (resize & 1023 && skip < 15) + inc_sel |= 1 << (skip + 1); + + ret = reg_write(client, RJ54N1_INC_USE_SEL_L, inc_sel & 0xfc); + if (!ret) + ret = reg_write(client, RJ54N1_INC_USE_SEL_H, inc_sel >> 8); + + /* Start resizing */ + if (!ret) + ret = reg_write(client, RJ54N1_RESIZE_CONTROL, + RESIZE_HOLD_SEL | RESIZE_GO | 1); + + if (ret < 0) + return ret; + + dev_dbg(&client->dev, "resize %u, skip %u\n", resize, skip); + + /* Constant taken from manufacturer's example */ + msleep(230); + + ret = reg_write(client, RJ54N1_RESIZE_CONTROL, RESIZE_HOLD_SEL | 1); + if (ret < 0) + return ret; + + *in_w = input_w; + *in_h = input_h; + *out_w = output_w; + *out_h = output_h; + + return resize; +} + +static int rj54n1_set_clock(struct i2c_client *client) +{ + struct rj54n1 *rj54n1 = to_rj54n1(client); + int ret; + + /* Enable external clock */ + ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK | SOFT_STDBY); + /* Leave stand-by */ + if (!ret) + ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK); + + if (!ret) + ret = reg_write(client, RJ54N1_PLL_L, 2); + if (!ret) + ret = reg_write(client, RJ54N1_PLL_N, 0x31); + + /* TGCLK dividers */ + if (!ret) + ret = reg_write(client, RJ54N1_RATIO_TG, + rj54n1->clk_div.ratio_tg); + if (!ret) + ret = reg_write(client, RJ54N1_RATIO_T, + rj54n1->clk_div.ratio_t); + if (!ret) + ret = reg_write(client, RJ54N1_RATIO_R, + rj54n1->clk_div.ratio_r); + + /* Enable TGCLK & RAMP */ + if (!ret) + ret = reg_write(client, RJ54N1_RAMP_TGCLK_EN, 3); + + /* Disable clock output */ + if (!ret) + ret = reg_write(client, RJ54N1_OCLK_DSP, 0); + + /* Set divisors */ + if (!ret) + ret = reg_write(client, RJ54N1_RATIO_OP, + rj54n1->clk_div.ratio_op); + if (!ret) + ret = reg_write(client, RJ54N1_RATIO_O, + rj54n1->clk_div.ratio_o); + + /* Enable OCLK */ + if (!ret) + ret = reg_write(client, RJ54N1_OCLK_SEL_EN, 1); + + /* Use PLL for Timing Generator, write 2 to reserved bits */ + if (!ret) + ret = reg_write(client, RJ54N1_TG_BYPASS, 2); + + /* Take sensor out of reset */ + if (!ret) + ret = reg_write(client, RJ54N1_RESET_STANDBY, + E_EXCLK | SEN_RSTX); + /* Enable PLL */ + if (!ret) + ret = reg_write(client, RJ54N1_PLL_EN, 1); + + /* Wait for PLL to stabilise */ + msleep(10); + + /* Enable clock to frequency divider */ + if (!ret) + ret = reg_write(client, RJ54N1_CLK_RST, 1); + + if (!ret) + ret = reg_read(client, RJ54N1_CLK_RST); + if (ret != 1) { + dev_err(&client->dev, + "Resetting RJ54N1CB0C clock failed: %d!\n", ret); + return -EIO; + } + /* Start the PLL */ + ret = reg_set(client, RJ54N1_OCLK_DSP, 1, 1); + + /* Enable OCLK */ + if (!ret) + ret = reg_write(client, RJ54N1_OCLK_SEL_EN, 1); + + return ret; +} + +static int rj54n1_reg_init(struct i2c_client *client) +{ + int ret = rj54n1_set_clock(client); + + if (!ret) + ret = reg_write_multiple(client, bank_7, ARRAY_SIZE(bank_7)); + if (!ret) + ret = reg_write_multiple(client, bank_10, ARRAY_SIZE(bank_10)); + + /* Set binning divisors */ + if (!ret) + ret = reg_write(client, RJ54N1_SCALE_1_2_LEV, 3 | (7 << 4)); + if (!ret) + ret = reg_write(client, RJ54N1_SCALE_4_LEV, 0xf); + + /* Switch to fixed resize mode */ + if (!ret) + ret = reg_write(client, RJ54N1_RESIZE_CONTROL, + RESIZE_HOLD_SEL | 1); + + /* Set gain */ + if (!ret) + ret = reg_write(client, RJ54N1_Y_GAIN, 0x84); + + /* Mirror the image back: default is upside down and left-to-right... */ + if (!ret) + ret = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 3, 3); + + if (!ret) + ret = reg_write_multiple(client, bank_4, ARRAY_SIZE(bank_4)); + if (!ret) + ret = reg_write_multiple(client, bank_5, ARRAY_SIZE(bank_5)); + if (!ret) + ret = reg_write_multiple(client, bank_8, ARRAY_SIZE(bank_8)); + + if (!ret) + ret = reg_write(client, RJ54N1_RESET_STANDBY, + E_EXCLK | DSP_RSTX | SEN_RSTX); + + /* Commit init */ + if (!ret) + ret = rj54n1_commit(client); + + /* Take DSP, TG, sensor out of reset */ + if (!ret) + ret = reg_write(client, RJ54N1_RESET_STANDBY, + E_EXCLK | DSP_RSTX | TG_RSTX | SEN_RSTX); + + if (!ret) + ret = reg_write(client, 0x7fe, 2); + + /* Constant taken from manufacturer's example */ + msleep(700); + + return ret; +} + +/* FIXME: streaming output only up to 800x600 is functional */ +static int rj54n1_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->field = V4L2_FIELD_NONE; + + if (pix->width > 800) + pix->width = 800; + if (pix->height > 600) + pix->height = 600; + + return 0; +} + +static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct rj54n1 *rj54n1 = to_rj54n1(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + unsigned int output_w, output_h, + input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; + int ret; + + /* + * The host driver can call us without .try_fmt(), so, we have to take + * care ourseleves + */ + ret = rj54n1_try_fmt(sd, f); + + /* + * Verify if the sensor has just been powered on. TODO: replace this + * with proper PM, when a suitable API is available. + */ + if (!ret) + ret = reg_read(client, RJ54N1_RESET_STANDBY); + if (ret < 0) + return ret; + + if (!(ret & E_EXCLK)) { + ret = rj54n1_reg_init(client); + if (ret < 0) + return ret; + } + + /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */ + switch (pix->pixelformat) { + case V4L2_PIX_FMT_YUYV: + ret = reg_write(client, RJ54N1_OUT_SEL, 0); + if (!ret) + ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); + break; + case V4L2_PIX_FMT_RGB565: + ret = reg_write(client, RJ54N1_OUT_SEL, 0x11); + if (!ret) + ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); + break; + default: + ret = -EINVAL; + } + + if (ret < 0) + return ret; + + /* Supported scales 1:1 - 1:16 */ + if (pix->width < input_w / 16) + pix->width = input_w / 16; + if (pix->height < input_h / 16) + pix->height = input_h / 16; + + output_w = pix->width; + output_h = pix->height; + + ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); + if (ret < 0) + return ret; + + rj54n1->fourcc = pix->pixelformat; + rj54n1->resize = ret; + rj54n1->rect.width = input_w; + rj54n1->rect.height = input_h; + rj54n1->width = output_w; + rj54n1->height = output_h; + + pix->width = output_w; + pix->height = output_h; + pix->field = V4L2_FIELD_NONE; + + return ret; +} + +static int rj54n1_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) +{ + struct i2c_client *client = sd->priv; + + if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match.addr != client->addr) + return -ENODEV; + + id->ident = V4L2_IDENT_RJ54N1CB0C; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int rj54n1_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = sd->priv; + + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || + reg->reg < 0x400 || reg->reg > 0x1fff) + /* Registers > 0x0800 are only available from Sharp support */ + return -EINVAL; + + if (reg->match.addr != client->addr) + return -ENODEV; + + reg->size = 1; + reg->val = reg_read(client, reg->reg); + + if (reg->val > 0xff) + return -EIO; + + return 0; +} + +static int rj54n1_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = sd->priv; + + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || + reg->reg < 0x400 || reg->reg > 0x1fff) + /* Registers >= 0x0800 are only available from Sharp support */ + return -EINVAL; + + if (reg->match.addr != client->addr) + return -ENODEV; + + if (reg_write(client, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static const struct v4l2_queryctrl rj54n1_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_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .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 = 66, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, +}; + +static struct soc_camera_ops rj54n1_ops = { + .set_bus_param = rj54n1_set_bus_param, + .query_bus_param = rj54n1_query_bus_param, + .controls = rj54n1_controls, + .num_controls = ARRAY_SIZE(rj54n1_controls), +}; + +static int rj54n1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = sd->priv; + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + data = reg_read(client, RJ54N1_MIRROR_STILL_MODE); + if (data < 0) + return -EIO; + ctrl->value = !(data & 1); + break; + case V4L2_CID_HFLIP: + data = reg_read(client, RJ54N1_MIRROR_STILL_MODE); + if (data < 0) + return -EIO; + ctrl->value = !(data & 2); + break; + case V4L2_CID_GAIN: + data = reg_read(client, RJ54N1_Y_GAIN); + if (data < 0) + return -EIO; + + ctrl->value = data / 2; + break; + } + + return 0; +} + +static int rj54n1_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + int data; + struct i2c_client *client = sd->priv; + const struct v4l2_queryctrl *qctrl; + + qctrl = soc_camera_find_qctrl(&rj54n1_ops, ctrl->id); + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (ctrl->value) + data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 1); + else + data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 1, 1); + if (data < 0) + return -EIO; + break; + case V4L2_CID_HFLIP: + if (ctrl->value) + data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 2); + else + data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 2, 2); + if (data < 0) + return -EIO; + break; + case V4L2_CID_GAIN: + if (ctrl->value > qctrl->maximum || + ctrl->value < qctrl->minimum) + return -EINVAL; + else if (reg_write(client, RJ54N1_Y_GAIN, ctrl->value * 2) < 0) + return -EIO; + break; + } + + return 0; +} + +static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = { + .g_ctrl = rj54n1_g_ctrl, + .s_ctrl = rj54n1_s_ctrl, + .g_chip_ident = rj54n1_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = rj54n1_g_register, + .s_register = rj54n1_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = { + .s_stream = rj54n1_s_stream, + .s_fmt = rj54n1_s_fmt, + .g_fmt = rj54n1_g_fmt, + .try_fmt = rj54n1_try_fmt, + .g_crop = rj54n1_g_crop, + .cropcap = rj54n1_cropcap, +}; + +static struct v4l2_subdev_ops rj54n1_subdev_ops = { + .core = &rj54n1_subdev_core_ops, + .video = &rj54n1_subdev_video_ops, +}; + +static int rj54n1_pin_config(struct i2c_client *client) +{ + /* + * Experimentally found out IOCTRL wired to 0. TODO: add to platform + * data: 0 or 1 << 7. + */ + return reg_write(client, RJ54N1_IOC, 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 rj54n1_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) +{ + int data1, data2; + int ret; + + /* This could be a BUG_ON() or a WARN_ON(), or remove it completely */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* Read out the chip version register */ + data1 = reg_read(client, RJ54N1_DEV_CODE); + data2 = reg_read(client, RJ54N1_DEV_CODE2); + + if (data1 != 0x51 || data2 != 0x10) { + ret = -ENODEV; + dev_info(&client->dev, "No RJ54N1CB0C found, read 0x%x:0x%x\n", + data1, data2); + goto ei2c; + } + + ret = rj54n1_pin_config(client); + if (ret < 0) + goto ei2c; + + dev_info(&client->dev, "Detected a RJ54N1CB0C chip ID 0x%x:0x%x\n", + data1, data2); + +ei2c: + return ret; +} + +static int rj54n1_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct rj54n1 *rj54n1; + struct soc_camera_device *icd = client->dev.platform_data; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl; + int ret; + + if (!icd) { + dev_err(&client->dev, "RJ54N1CB0C: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); + if (!icl) { + dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); + return -EIO; + } + + rj54n1 = kzalloc(sizeof(struct rj54n1), GFP_KERNEL); + if (!rj54n1) + return -ENOMEM; + + v4l2_i2c_subdev_init(&rj54n1->subdev, client, &rj54n1_subdev_ops); + + icd->ops = &rj54n1_ops; + + rj54n1->clk_div = clk_div; + rj54n1->rect.left = RJ54N1_COLUMN_SKIP; + rj54n1->rect.top = RJ54N1_ROW_SKIP; + rj54n1->rect.width = RJ54N1_MAX_WIDTH; + rj54n1->rect.height = RJ54N1_MAX_HEIGHT; + rj54n1->width = RJ54N1_MAX_WIDTH; + rj54n1->height = RJ54N1_MAX_HEIGHT; + rj54n1->fourcc = V4L2_PIX_FMT_YUYV; + rj54n1->resize = 1024; + + ret = rj54n1_video_probe(icd, client); + if (ret < 0) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(rj54n1); + return ret; + } + + icd->formats = rj54n1_colour_formats; + icd->num_formats = ARRAY_SIZE(rj54n1_colour_formats); + + return ret; +} + +static int rj54n1_remove(struct i2c_client *client) +{ + struct rj54n1 *rj54n1 = to_rj54n1(client); + struct soc_camera_device *icd = client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); + + icd->ops = NULL; + if (icl->free_bus) + icl->free_bus(icl); + i2c_set_clientdata(client, NULL); + client->driver = NULL; + kfree(rj54n1); + + return 0; +} + +static const struct i2c_device_id rj54n1_id[] = { + { "rj54n1cb0c", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rj54n1_id); + +static struct i2c_driver rj54n1_i2c_driver = { + .driver = { + .name = "rj54n1cb0c", + }, + .probe = rj54n1_probe, + .remove = rj54n1_remove, + .id_table = rj54n1_id, +}; + +static int __init rj54n1_mod_init(void) +{ + return i2c_add_driver(&rj54n1_i2c_driver); +} + +static void __exit rj54n1_mod_exit(void) +{ + i2c_del_driver(&rj54n1_i2c_driver); +} + +module_init(rj54n1_mod_init); +module_exit(rj54n1_mod_exit); + +MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL v2"); diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index a2d93da38450..43cf26ea6734 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -281,6 +281,9 @@ enum { /* module m52790: just ident 52790 */ V4L2_IDENT_M52790 = 52790, + + /* Sharp RJ54N1CB0C, 0xCB0C = 51980 */ + V4L2_IDENT_RJ54N1CB0C = 51980, }; #endif From d8d8622552088ca94fab4e4997f948514d0bdc27 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 19 Sep 2009 09:51:12 -0300 Subject: [PATCH 067/345] V4L/DVB (13134): Add support for TBS-likes remotes The patch brings infrared remote support for some cx88 based cards. Such as: TeVii S460,S420; Omicom SS4; SatTrade ST4200; TBS 8920,8910; Prof 7300,6200. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 40 +++++++++++++++++++++++++++ drivers/media/video/cx88/cx88-input.c | 24 ++++++++++++++++ include/media/ir-common.h | 1 + 3 files changed, 65 insertions(+) diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index f6790172736a..a2c80a7a3ae4 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2964,6 +2964,46 @@ struct ir_scancode_table ir_codes_dm1105_nec_table = { }; EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec_table); +static struct ir_scancode ir_codes_tbs_nec[] = { + { 0x04, KEY_POWER2}, /*power*/ + { 0x14, KEY_MUTE}, /*mute*/ + { 0x07, KEY_1}, + { 0x06, KEY_2}, + { 0x05, KEY_3}, + { 0x0b, KEY_4}, + { 0x0a, KEY_5}, + { 0x09, KEY_6}, + { 0x0f, KEY_7}, + { 0x0e, KEY_8}, + { 0x0d, KEY_9}, + { 0x12, KEY_0}, + { 0x16, KEY_CHANNELUP}, /*ch+*/ + { 0x11, KEY_CHANNELDOWN},/*ch-*/ + { 0x13, KEY_VOLUMEUP}, /*vol+*/ + { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ + { 0x03, KEY_RECORD}, /*rec*/ + { 0x18, KEY_PAUSE}, /*pause*/ + { 0x19, KEY_OK}, /*ok*/ + { 0x1a, KEY_CAMERA}, /* snapshot */ + { 0x01, KEY_UP}, + { 0x10, KEY_LEFT}, + { 0x02, KEY_RIGHT}, + { 0x08, KEY_DOWN}, + { 0x15, KEY_FAVORITES}, + { 0x17, KEY_SUBTITLE}, + { 0x1d, KEY_ZOOM}, + { 0x1f, KEY_EXIT}, + { 0x1e, KEY_MENU}, + { 0x1c, KEY_EPG}, + { 0x00, KEY_PREVIOUS}, + { 0x1b, KEY_MODE}, +}; +struct ir_scancode_table ir_codes_tbs_nec_table = { + .scan = ir_codes_tbs_nec, + .size = ARRAY_SIZE(ir_codes_tbs_nec), +}; +EXPORT_SYMBOL_GPL(ir_codes_tbs_nec_table); + /* Terratec Cinergy Hybrid T USB XS Devin Heitmueller */ diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 78b3635178af..33437e403144 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -303,6 +303,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keydown = 0x02; ir->polling = 50; /* ms */ break; + case CX88_BOARD_OMICOM_SS4_PCI: + case CX88_BOARD_SATTRADE_ST4200: + case CX88_BOARD_TBS_8920: + case CX88_BOARD_TBS_8910: + case CX88_BOARD_PROF_7300: + case CX88_BOARD_PROF_6200: + ir_codes = &ir_codes_tbs_nec_table; + ir_type = IR_TYPE_PD; + ir->sampling = 0xff00; /* address */ + break; + case CX88_BOARD_TEVII_S460: + case CX88_BOARD_TEVII_S420: + ir_codes = &ir_codes_dm1105_nec_table; + ir_type = IR_TYPE_PD; + ir->sampling = 0xff00; /* address */ + break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: ir_codes = &ir_codes_dntv_live_dvbt_pro_table; ir_type = IR_TYPE_PD; @@ -432,8 +448,16 @@ void cx88_ir_irq(struct cx88_core *core) /* decode it */ switch (core->boardnr) { + case CX88_BOARD_TEVII_S460: + case CX88_BOARD_TEVII_S420: case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: + case CX88_BOARD_OMICOM_SS4_PCI: + case CX88_BOARD_SATTRADE_ST4200: + case CX88_BOARD_TBS_8920: + case CX88_BOARD_TBS_8910: + case CX88_BOARD_PROF_7300: + case CX88_BOARD_PROF_6200: ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); if (ircode == 0xffffffff) { /* decoding error */ diff --git a/include/media/ir-common.h b/include/media/ir-common.h index af3257e6b808..c2d515dd94d2 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -173,6 +173,7 @@ extern struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table; extern struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table; extern struct ir_scancode_table ir_codes_kaiomy_table; extern struct ir_scancode_table ir_codes_dm1105_nec_table; +extern struct ir_scancode_table ir_codes_tbs_nec_table; extern struct ir_scancode_table ir_codes_evga_indtube_table; extern struct ir_scancode_table ir_codes_terratec_cinergy_xs_table; extern struct ir_scancode_table ir_codes_videomate_s350_table; From 9d2ba7ad802300d6a1830df9268d8ba478c66a18 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Wed, 23 Sep 2009 14:44:12 -0300 Subject: [PATCH 068/345] V4L/DVB (13135): Add support for TeVii remotes The patch brings infrared remote support for some cx88 based cards. Such as TeVii S460,S420. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 55 +++++++++++++++++++++++++++ drivers/media/video/cx88/cx88-input.c | 2 +- include/media/ir-common.h | 1 + 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index a2c80a7a3ae4..32f765e6e5fd 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2964,6 +2964,61 @@ struct ir_scancode_table ir_codes_dm1105_nec_table = { }; EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec_table); +static struct ir_scancode ir_codes_tevii_nec[] = { + { 0x0a, KEY_POWER2}, + { 0x0c, KEY_MUTE}, + { 0x11, KEY_1}, + { 0x12, KEY_2}, + { 0x13, KEY_3}, + { 0x14, KEY_4}, + { 0x15, KEY_5}, + { 0x16, KEY_6}, + { 0x17, KEY_7}, + { 0x18, KEY_8}, + { 0x19, KEY_9}, + { 0x10, KEY_0}, + { 0x1c, KEY_MENU}, + { 0x0f, KEY_VOLUMEDOWN}, + { 0x1a, KEY_LAST}, + { 0x0e, KEY_OPEN}, + { 0x04, KEY_RECORD}, + { 0x09, KEY_VOLUMEUP}, + { 0x08, KEY_CHANNELUP}, + { 0x07, KEY_PVR}, + { 0x0b, KEY_TIME}, + { 0x02, KEY_RIGHT}, + { 0x03, KEY_LEFT}, + { 0x00, KEY_UP}, + { 0x1f, KEY_OK}, + { 0x01, KEY_DOWN}, + { 0x05, KEY_TUNER}, + { 0x06, KEY_CHANNELDOWN}, + { 0x40, KEY_PLAYPAUSE}, + { 0x1e, KEY_REWIND}, + { 0x1b, KEY_FAVORITES}, + { 0x1d, KEY_BACK}, + { 0x4d, KEY_FASTFORWARD}, + { 0x44, KEY_EPG}, + { 0x4c, KEY_INFO}, + { 0x41, KEY_AB}, + { 0x43, KEY_AUDIO}, + { 0x45, KEY_SUBTITLE}, + { 0x4a, KEY_LIST}, + { 0x46, KEY_F1}, + { 0x47, KEY_F2}, + { 0x5e, KEY_F3}, + { 0x5c, KEY_F4}, + { 0x52, KEY_F5}, + { 0x5a, KEY_F6}, + { 0x56, KEY_MODE}, + { 0x58, KEY_SWITCHVIDEOMODE}, +}; +struct ir_scancode_table ir_codes_tevii_nec_table = { + .scan = ir_codes_tevii_nec, + .size = ARRAY_SIZE(ir_codes_tevii_nec), +}; +EXPORT_SYMBOL_GPL(ir_codes_tevii_nec_table); + static struct ir_scancode ir_codes_tbs_nec[] = { { 0x04, KEY_POWER2}, /*power*/ { 0x14, KEY_MUTE}, /*mute*/ diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 33437e403144..c0047c1960cc 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -315,7 +315,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_TEVII_S460: case CX88_BOARD_TEVII_S420: - ir_codes = &ir_codes_dm1105_nec_table; + ir_codes = &ir_codes_tevii_nec_table; ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index c2d515dd94d2..5921776929e7 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -173,6 +173,7 @@ extern struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table; extern struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table; extern struct ir_scancode_table ir_codes_kaiomy_table; extern struct ir_scancode_table ir_codes_dm1105_nec_table; +extern struct ir_scancode_table ir_codes_tevii_nec_table; extern struct ir_scancode_table ir_codes_tbs_nec_table; extern struct ir_scancode_table ir_codes_evga_indtube_table; extern struct ir_scancode_table ir_codes_terratec_cinergy_xs_table; From 930bf78c20187f3cbbf0775cd317616c6b681a8a Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Mon, 5 Oct 2009 05:11:35 -0300 Subject: [PATCH 069/345] V4L/DVB (13137): gspca_mr97310a: Add controls for vga cams with sensor type 0 This patch adds controls for vga cams with sensor type 0, in order to correctly report the present controls, the probing of the sensor type has been moved from sd_start to sd_config, since this made the sensor type probing unreliable the detection method was changed. Note this requires the camera to enter streaming mode, so sd_config now briefly makes the camera stream. Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 506 +++++++++++++++------------ 1 file changed, 291 insertions(+), 215 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index f8328b9efae5..f4c83b367900 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -1,23 +1,28 @@ /* * Mars MR97310A library * + * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is * Copyright (C) 2009 Kyle Guinn * * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ * and for the routines for detecting and classifying these various cameras, + * is Copyright (C) 2009 Theodore Kilgore * + * Support for the control settings for the CIF cameras is + * Copyright (C) 2009 Hans de Goede and + * Thomas Kaiser + * + * Support for the control settings for the VGA cameras is * Copyright (C) 2009 Theodore Kilgore * - * Acknowledgements: + * Several previously unsupported cameras are owned and have been tested by + * Hans de Goede and + * Thomas Kaiser and + * Theodore Kilgore * * The MR97311A support in gspca/mars.c has been helpful in understanding some * of the registers in these cameras. * - * Hans de Goede and - * Thomas Kaiser - * have assisted with their experience. Each of them has also helped by - * testing a previously unsupported camera. - * * 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 @@ -40,11 +45,9 @@ #define CAM_TYPE_CIF 0 #define CAM_TYPE_VGA 1 -#define MR97310A_BRIGHTNESS_MIN -254 -#define MR97310A_BRIGHTNESS_MAX 255 #define MR97310A_BRIGHTNESS_DEFAULT 0 -#define MR97310A_EXPOSURE_MIN 300 +#define MR97310A_EXPOSURE_MIN 0 #define MR97310A_EXPOSURE_MAX 4095 #define MR97310A_EXPOSURE_DEFAULT 1000 @@ -82,6 +85,7 @@ struct sensor_w_data { int len; }; +static void sd_stopN(struct gspca_dev *gspca_dev); static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); @@ -94,14 +98,16 @@ static void setgain(struct gspca_dev *gspca_dev); /* V4L2 controls supported by the driver */ static struct ctrl sd_ctrls[] = { +/* Seprate brightness control description for Argus QuickClix as it has + different limits from to other mr97310a camera's */ { -#define BRIGHTNESS_IDX 0 +#define NORM_BRIGHTNESS_IDX 0 { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", - .minimum = MR97310A_BRIGHTNESS_MIN, - .maximum = MR97310A_BRIGHTNESS_MAX, + .minimum = -254, + .maximum = 255, .step = 1, .default_value = MR97310A_BRIGHTNESS_DEFAULT, .flags = 0, @@ -110,7 +116,22 @@ static struct ctrl sd_ctrls[] = { .get = sd_getbrightness, }, { -#define EXPOSURE_IDX 1 +#define ARGUS_QC_BRIGHTNESS_IDX 1 + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 15, + .step = 1, + .default_value = MR97310A_BRIGHTNESS_DEFAULT, + .flags = 0, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, + { +#define EXPOSURE_IDX 2 { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -125,7 +146,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getexposure, }, { -#define GAIN_IDX 2 +#define GAIN_IDX 3 { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -230,12 +251,17 @@ static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) int rc; buf = data; - rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1); + if (sd->cam_type == CAM_TYPE_CIF) { + rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1); + confirm_reg = sd->sensor_type ? 0x13 : 0x11; + } else { + rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1); + confirm_reg = 0x11; + } if (rc < 0) return rc; buf = 0x01; - confirm_reg = sd->sensor_type ? 0x13 : 0x11; rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1); if (rc < 0) return rc; @@ -243,18 +269,26 @@ static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) return 0; } -static int cam_get_response16(struct gspca_dev *gspca_dev) +static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose) { - __u8 *data = gspca_dev->usb_buf; int err_code; - data[0] = 0x21; + gspca_dev->usb_buf[0] = reg; err_code = mr_write(gspca_dev, 1); if (err_code < 0) return err_code; err_code = mr_read(gspca_dev, 16); - return err_code; + if (err_code < 0) + return err_code; + + if (verbose) + PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg, + gspca_dev->usb_buf[0], + gspca_dev->usb_buf[1], + gspca_dev->usb_buf[2]); + + return 0; } static int zero_the_pointer(struct gspca_dev *gspca_dev) @@ -264,7 +298,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) u8 status = 0; int tries = 0; - err_code = cam_get_response16(gspca_dev); + err_code = cam_get_response16(gspca_dev, 0x21, 0); if (err_code < 0) return err_code; @@ -275,7 +309,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; - err_code = cam_get_response16(gspca_dev); + err_code = cam_get_response16(gspca_dev, 0x21, 0); if (err_code < 0) return err_code; @@ -285,7 +319,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; - err_code = cam_get_response16(gspca_dev); + err_code = cam_get_response16(gspca_dev, 0x21, 0); if (err_code < 0) return err_code; @@ -295,7 +329,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; - err_code = cam_get_response16(gspca_dev); + err_code = cam_get_response16(gspca_dev, 0x21, 0); if (err_code < 0) return err_code; @@ -306,7 +340,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) return err_code; while (status != 0x0a && tries < 256) { - err_code = cam_get_response16(gspca_dev); + err_code = cam_get_response16(gspca_dev, 0x21, 0); status = data[0]; tries++; if (err_code < 0) @@ -323,7 +357,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; - err_code = cam_get_response16(gspca_dev); + err_code = cam_get_response16(gspca_dev, 0x21, 0); status = data[0]; tries++; if (err_code < 0) @@ -342,22 +376,34 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) return 0; } -static u8 get_sensor_id(struct gspca_dev *gspca_dev) +static int stream_start(struct gspca_dev *gspca_dev) { - int err_code; + gspca_dev->usb_buf[0] = 0x01; + gspca_dev->usb_buf[1] = 0x01; + return mr_write(gspca_dev, 2); +} - gspca_dev->usb_buf[0] = 0x1e; - err_code = mr_write(gspca_dev, 1); - if (err_code < 0) - return err_code; +static void stream_stop(struct gspca_dev *gspca_dev) +{ + gspca_dev->usb_buf[0] = 0x01; + gspca_dev->usb_buf[1] = 0x00; + if (mr_write(gspca_dev, 2) < 0) + PDEBUG(D_ERR, "Stream Stop failed"); +} - err_code = mr_read(gspca_dev, 16); - if (err_code < 0) - return err_code; +static void lcd_stop(struct gspca_dev *gspca_dev) +{ + gspca_dev->usb_buf[0] = 0x19; + gspca_dev->usb_buf[1] = 0x54; + if (mr_write(gspca_dev, 2) < 0) + PDEBUG(D_ERR, "LCD Stop failed"); +} - PDEBUG(D_PROBE, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); - - return gspca_dev->usb_buf[0]; +static int isoc_enable(struct gspca_dev *gspca_dev) +{ + gspca_dev->usb_buf[0] = 0x00; + gspca_dev->usb_buf[1] = 0x4d; /* ISOC transfering enable... */ + return mr_write(gspca_dev, 2); } /* this function is called at probe time */ @@ -366,60 +412,172 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; - __u8 *data = gspca_dev->usb_buf; int err_code; cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); + sd->do_lcd_stop = 0; + + /* Now, logical layout of the driver must fall sacrifice to the + * realities of the hardware supported. We have to sort out several + * cameras which share the USB ID but are in fact different inside. + * We need to start the initialization process for the cameras in + * order to classify them. Some of the supported cameras require the + * memory pointer to be set to 0 as the very first item of business + * or else they will not stream. So we do that immediately. + */ + err_code = zero_the_pointer(gspca_dev); + if (err_code < 0) + return err_code; if (id->idProduct == 0x010e) { sd->cam_type = CAM_TYPE_CIF; cam->nmodes--; + err_code = stream_start(gspca_dev); + if (err_code < 0) + return err_code; + err_code = cam_get_response16(gspca_dev, 0x06, 1); + if (err_code < 0) + return err_code; + /* + * The various CIF cameras share the same USB ID but use + * different init routines and different controls. We need to + * detect which one is connected! + * + * A list of known CIF cameras follows. They all report either + * 0002 for type 0 or 0003 for type 1. + * If you have another to report, please do + * + * Name sd->sensor_type reported by + * + * Sakar Spy-shot 0 T. Kilgore + * Innovage 0 T. Kilgore + * Vivitar Mini 0 H. De Goede + * Vivitar Mini 0 E. Rodriguez + * Vivitar Mini 1 T. Kilgore + * Elta-Media 8212dc 1 T. Kaiser + * Philips dig. keych. 1 T. Kilgore + */ + switch (gspca_dev->usb_buf[1]) { + case 2: + sd->sensor_type = 0; + break; + case 3: + sd->sensor_type = 1; + break; + default: + PDEBUG(D_ERR, "Unknown CIF Sensor id : %02x", + gspca_dev->usb_buf[1]); + return -ENODEV; + } + PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", + sd->sensor_type); + } else { + sd->cam_type = CAM_TYPE_VGA; - data[0] = 0x01; - data[1] = 0x01; - err_code = mr_write(gspca_dev, 2); + /* + * VGA cams also have two different sensor types. Detection + * requires a two-step process. + * + * Here is a report on the result of the first test for the + * known MR97310a VGA cameras. If you have another to report, + * please do. + * + * Name byte just read sd->sensor_type + * sd->do_lcd_stop + * Aiptek Pencam VGA+ 0x31 0 1 + * ION digital 0x31 0 1 + * Sakar Digital 77379 0x31 0 1 + * Argus DC-1620 0x30 1 0 + * Argus QuickClix 0x30 1 1 (see note) + * Note that this test fails to distinguish sd->sensor_type + * for the two cameras which have reported 0x30. + * Another test will be run on them. + * But the sd->do_lcd_stop setting is needed, too. + */ + + err_code = cam_get_response16(gspca_dev, 0x20, 1); + if (err_code < 0) + return err_code; + sd->sensor_type = gspca_dev->usb_buf[0] & 1; + sd->do_lcd_stop = (~gspca_dev->usb_buf[0]) & 1; + err_code = stream_start(gspca_dev); if (err_code < 0) return err_code; - msleep(200); - data[0] = get_sensor_id(gspca_dev); /* - * Known CIF cameras. If you have another to report, please do + * A second test can now resolve any remaining ambiguity in the + * identification of the camera's sensor type. Specifically, + * it now gives the correct sensor_type for the Argus DC-1620 + * and the Argus QuickClix. * - * Name byte just read sd->sensor_type - * reported by - * Sakar Spy-shot 0x28 T. Kilgore 0 - * Innovage 0xf5 (unstable) T. Kilgore 0 - * Vivitar Mini 0x53 H. De Goede 0 - * Vivitar Mini 0x04 / 0x24 E. Rodriguez 0 - * Vivitar Mini 0x08 T. Kilgore 1 - * Elta-Media 8212dc 0x23 T. Kaiser 1 - * Philips dig. keych. 0x37 T. Kilgore 1 + * This second test is only run if needed, + * but additional results from testing some other cameras + * are recorded here, too: + * + * Name gspca_dev->usb_buf[] sd->sensor_type + * + * Aiptek Pencam VGA+ 0300 (test not needed) 1 + * ION digital 0350 (test not needed) 1 + * Argus DC-1620 0450 (remains as type 0) 0 + * Argus QuickClix 0420 (corrected to type 1) 1 + * + * This test even seems able to distinguish one VGA cam from + * another which may be useful. However, the CIF type 1 cameras + * do not like it. */ - if ((data[0] & 0x78) == 8 || - ((data[0] & 0x2) == 0x2 && data[0] != 0x53)) - sd->sensor_type = 1; - else - sd->sensor_type = 0; - PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", - sd->sensor_type); + if (!sd->sensor_type) { + err_code = cam_get_response16(gspca_dev, 0x07, 1); + if (err_code < 0) + return err_code; - if (force_sensor_type != -1) { - sd->sensor_type = !! force_sensor_type; - PDEBUG(D_PROBE, "Forcing sensor type to: %d", - sd->sensor_type); + switch (gspca_dev->usb_buf[1]) { + case 0x50: + break; + case 0x20: + sd->sensor_type = 1; + PDEBUG(D_PROBE, "sensor_type corrected to 1"); + break; + default: + PDEBUG(D_ERR, "Unknown VGA Sensor id : %02x", + gspca_dev->usb_buf[1]); + return -ENODEV; + } } + PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", + sd->sensor_type); + } + /* Stop streaming as we've started it to probe the sensor type. */ + sd_stopN(gspca_dev); + if (force_sensor_type != -1) { + sd->sensor_type = !!force_sensor_type; + PDEBUG(D_PROBE, "Forcing sensor type to: %d", + sd->sensor_type); + } + + /* Setup controls depending on camera type */ + if (sd->cam_type == CAM_TYPE_CIF) { + /* No brightness for sensor_type 0 */ if (sd->sensor_type == 0) - gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); + gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | + (1 << ARGUS_QC_BRIGHTNESS_IDX); + else + gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); } else { - sd->cam_type = CAM_TYPE_VGA; - PDEBUG(D_PROBE, "MR97310A VGA camera detected"); - gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | - (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); + /* All controls need to be disabled if VGA sensor_type is 0 */ + if (sd->sensor_type == 0) + gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | + (1 << ARGUS_QC_BRIGHTNESS_IDX) | + (1 << EXPOSURE_IDX) | + (1 << GAIN_IDX); + else if (sd->do_lcd_stop) + /* Argus QuickClix has different brightness limits */ + gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); + else + gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); } sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; @@ -455,11 +613,6 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) }; /* Note: Some of the above descriptions guessed from MR97113A driver */ - data[0] = 0x01; - data[1] = 0x01; - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; memcpy(data, startup_string, 11); if (sd->sensor_type) @@ -533,22 +686,7 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, ARRAY_SIZE(cif_sensor1_init_data)); } - if (err_code < 0) - return err_code; - - setbrightness(gspca_dev); - setexposure(gspca_dev); - setgain(gspca_dev); - - msleep(200); - - data[0] = 0x00; - data[1] = 0x4d; /* ISOC transfering enable... */ - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; - - return 0; + return err_code; } static int start_vga_cam(struct gspca_dev *gspca_dev) @@ -558,84 +696,8 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) int err_code; const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x50, 0xc0}; - /* What some of these mean is explained in start_cif_cam(), above */ - sd->sof_read = 0; - /* - * We have to know which camera we have, because the register writes - * depend upon the camera. This test, run before we actually enter - * the initialization routine, distinguishes most of the cameras, If - * needed, another routine is done later, too. - */ - memset(data, 0, 16); - data[0] = 0x20; - err_code = mr_write(gspca_dev, 1); - if (err_code < 0) - return err_code; - - err_code = mr_read(gspca_dev, 16); - if (err_code < 0) - return err_code; - - PDEBUG(D_PROBE, "Byte reported is %02x", data[0]); - - msleep(200); - /* - * Known VGA cameras. If you have another to report, please do - * - * Name byte just read sd->sensor_type - * sd->do_lcd_stop - * Aiptek Pencam VGA+ 0x31 0 1 - * ION digital 0x31 0 1 - * Argus DC-1620 0x30 1 0 - * Argus QuickClix 0x30 1 1 (not caught here) - */ - sd->sensor_type = data[0] & 1; - sd->do_lcd_stop = (~data[0]) & 1; - - - - /* Streaming setup begins here. */ - - - data[0] = 0x01; - data[1] = 0x01; - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; - - /* - * A second test can now resolve any remaining ambiguity in the - * identification of the camera type, - */ - if (!sd->sensor_type) { - data[0] = get_sensor_id(gspca_dev); - if (data[0] == 0x7f) { - sd->sensor_type = 1; - PDEBUG(D_PROBE, "sensor_type corrected to 1"); - } - msleep(200); - } - - if (force_sensor_type != -1) { - sd->sensor_type = !! force_sensor_type; - PDEBUG(D_PROBE, "Forcing sensor type to: %d", - sd->sensor_type); - } - - /* - * Known VGA cameras. - * This test is only run if the previous test returned 0x30, but - * here is the information for all others, too, just for reference. - * - * Name byte just read sd->sensor_type - * - * Aiptek Pencam VGA+ 0xfb (this test not run) 1 - * ION digital 0xbd (this test not run) 1 - * Argus DC-1620 0xe5 (no change) 0 - * Argus QuickClix 0x7f (reclassified) 1 - */ memcpy(data, startup_string, 11); if (!sd->sensor_type) { data[5] = 0x00; @@ -704,14 +766,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, ARRAY_SIZE(vga_sensor1_init_data)); } - if (err_code < 0) - return err_code; - - msleep(200); - data[0] = 0x00; - data[1] = 0x4d; /* ISOC transfering enable... */ - err_code = mr_write(gspca_dev, 2); - return err_code; } @@ -719,82 +773,101 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int err_code; - struct cam *cam; - cam = &gspca_dev->cam; sd->sof_read = 0; - /* - * Some of the supported cameras require the memory pointer to be - * set to 0, or else they will not stream. - */ - zero_the_pointer(gspca_dev); - msleep(200); + + /* Some of the VGA cameras require the memory pointer + * to be set to 0 again. We have been forced to start the + * stream somewhere else to detect the hardware, and closed it, + * and now since we are restarting the stream we need to do a + * completely fresh and clean start. */ + err_code = zero_the_pointer(gspca_dev); + if (err_code < 0) + return err_code; + + err_code = stream_start(gspca_dev); + if (err_code < 0) + return err_code; + if (sd->cam_type == CAM_TYPE_CIF) { err_code = start_cif_cam(gspca_dev); } else { err_code = start_vga_cam(gspca_dev); } - return err_code; + if (err_code < 0) + return err_code; + + setbrightness(gspca_dev); + setexposure(gspca_dev); + setgain(gspca_dev); + + return isoc_enable(gspca_dev); } static void sd_stopN(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int result; - - gspca_dev->usb_buf[0] = 1; - gspca_dev->usb_buf[1] = 0; - result = mr_write(gspca_dev, 2); - if (result < 0) - PDEBUG(D_ERR, "Camera Stop failed"); + stream_stop(gspca_dev); /* Not all the cams need this, but even if not, probably a good idea */ zero_the_pointer(gspca_dev); - if (sd->do_lcd_stop) { - gspca_dev->usb_buf[0] = 0x19; - gspca_dev->usb_buf[1] = 0x54; - result = mr_write(gspca_dev, 2); - if (result < 0) - PDEBUG(D_ERR, "Camera Stop failed"); - } + if (sd->do_lcd_stop) + lcd_stop(gspca_dev); } static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; u8 val; - - if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX)) + u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */ + u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ + const u8 quick_clix_table[] = + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ + { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; + /* + * This control is disabled for CIF type 1 and VGA type 0 cameras. + * It does not quite act linearly for the Argus QuickClix camera, + * but it does control brightness. The values are 0 - 15 only, and + * the table above makes them act consecutively. + */ + if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) && + (gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX))) return; + if (sd->cam_type == CAM_TYPE_VGA) { + sign_reg += 4; + value_reg += 4; + } + /* Note register 7 is also seen as 0x8x or 0xCx in dumps */ if (sd->brightness > 0) { - sensor_write1(gspca_dev, 7, 0x00); + sensor_write1(gspca_dev, sign_reg, 0x00); val = sd->brightness; } else { - sensor_write1(gspca_dev, 7, 0x01); - val = 257 - sd->brightness; + sensor_write1(gspca_dev, sign_reg, 0x01); + val = (257 - sd->brightness); } - sensor_write1(gspca_dev, 8, val); + /* Use lookup table for funky Argus QuickClix brightness */ + if (sd->do_lcd_stop) + val = quick_clix_table[val]; + + sensor_write1(gspca_dev, value_reg, val); } static void setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - u8 val; + int exposure; if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) return; - if (sd->sensor_type) { - val = sd->exposure >> 4; - sensor_write1(gspca_dev, 3, val); - val = sd->exposure & 0xf; - sensor_write1(gspca_dev, 4, val); + if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { + /* This cam does not like very low exposure settings */ + exposure = (sd->exposure < 300) ? 300 : sd->exposure; + sensor_write1(gspca_dev, 3, exposure >> 4); + sensor_write1(gspca_dev, 4, exposure & 0x0f); } else { - u8 clockdiv; - int exposure; - /* We have both a clock divider and an exposure register. We first calculate the clock divider, as that determines the maximum exposure and then we calculayte the exposure @@ -802,7 +875,7 @@ static void setexposure(struct gspca_dev *gspca_dev) Note our 0 - 4095 exposure is mapped to 0 - 511 milliseconds exposure time */ - clockdiv = (60 * sd->exposure + 7999) / 8000; + u8 clockdiv = (60 * sd->exposure + 7999) / 8000; /* Limit framerate to not exceed usb bandwidth */ if (clockdiv < 3 && gspca_dev->width >= 320) @@ -810,6 +883,9 @@ static void setexposure(struct gspca_dev *gspca_dev) else if (clockdiv < 2) clockdiv = 2; + if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4) + clockdiv = 4; + /* Frame exposure time in ms = 1000 * clockdiv / 60 -> exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv); @@ -832,7 +908,7 @@ static void setgain(struct gspca_dev *gspca_dev) if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) return; - if (sd->sensor_type) { + if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { sensor_write1(gspca_dev, 0x0e, sd->gain); } else { sensor_write1(gspca_dev, 0x10, sd->gain); From 8519110040ca98dfbc89c473921cca390c81460c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 5 Oct 2009 05:58:18 -0300 Subject: [PATCH 070/345] V4L/DVB (13138): gspca_sq905: cleanup sq905_dostream -Remove use of unneeded discarding variable -Cleanup locking to only take usb_lock around access to the control endpoint, by no longer taking the lock around the bulk transfer (which takes most of the time) we can remove the msleep(1) which was needed to give the gspca core a chance to grab the usb_lock to signal us to stop. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sq905.c | 56 ++++++++++++++----------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c index 715a68f0156e..547d1fd5191d 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/video/gspca/sq905.c @@ -168,18 +168,22 @@ static int sq905_ack_frame(struct gspca_dev *gspca_dev) * request and read a block of data - see warning on sq905_command. */ static int -sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size) +sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock) { int ret; int act_len; gspca_dev->usb_buf[0] = '\0'; + if (need_lock) + mutex_lock(&gspca_dev->usb_lock); ret = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), USB_REQ_SYNCH_FRAME, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, SQ905_BULK_READ, size, gspca_dev->usb_buf, 1, SQ905_CMD_TIMEOUT); + if (need_lock) + mutex_unlock(&gspca_dev->usb_lock); if (ret < 0) { PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret); return ret; @@ -214,7 +218,6 @@ static void sq905_dostream(struct work_struct *work) int bytes_left; /* bytes remaining in current frame. */ int data_len; /* size to use for the next read. */ int header_read; /* true if we have already read the frame header. */ - int discarding; /* true if we failed to get space for frame. */ int packet_type; int frame_sz; int ret; @@ -222,7 +225,6 @@ static void sq905_dostream(struct work_struct *work) u8 *buffer; buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); - mutex_lock(&gspca_dev->usb_lock); if (!buffer) { PDEBUG(D_ERR, "Couldn't allocate USB buffer"); goto quit_stream; @@ -232,28 +234,22 @@ static void sq905_dostream(struct work_struct *work) + FRAME_HEADER_LEN; while (gspca_dev->present && gspca_dev->streaming) { - /* Need a short delay to ensure streaming flag was set by - * gspca and to make sure gspca can grab the mutex. */ - mutex_unlock(&gspca_dev->usb_lock); - msleep(1); - /* request some data and then read it until we have * a complete frame. */ bytes_left = frame_sz; header_read = 0; - discarding = 0; - while (bytes_left > 0) { + /* Note we do not check for gspca_dev->streaming here, as + we must finish reading an entire frame, otherwise the + next time we stream we start reading in the middle of a + frame. */ + while (bytes_left > 0 && gspca_dev->present) { data_len = bytes_left > SQ905_MAX_TRANSFER ? SQ905_MAX_TRANSFER : bytes_left; - mutex_lock(&gspca_dev->usb_lock); - if (!gspca_dev->present) - goto quit_stream; - ret = sq905_read_data(gspca_dev, buffer, data_len); + ret = sq905_read_data(gspca_dev, buffer, data_len, 1); if (ret < 0) goto quit_stream; - mutex_unlock(&gspca_dev->usb_lock); - PDEBUG(D_STREAM, + PDEBUG(D_PACK, "Got %d bytes out of %d for frame", data_len, bytes_left); bytes_left -= data_len; @@ -271,7 +267,7 @@ static void sq905_dostream(struct work_struct *work) packet_type = INTER_PACKET; } frame = gspca_get_i_frame(gspca_dev); - if (frame && !discarding) { + if (frame) { frame = gspca_frame_add(gspca_dev, packet_type, frame, data, data_len); /* If entire frame fits in one packet we still @@ -281,23 +277,23 @@ static void sq905_dostream(struct work_struct *work) frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); - } else { - discarding = 1; } } - /* acknowledge the frame */ - mutex_lock(&gspca_dev->usb_lock); - if (!gspca_dev->present) - goto quit_stream; - ret = sq905_ack_frame(gspca_dev); - if (ret < 0) - goto quit_stream; + if (gspca_dev->present) { + /* acknowledge the frame */ + mutex_lock(&gspca_dev->usb_lock); + ret = sq905_ack_frame(gspca_dev); + mutex_unlock(&gspca_dev->usb_lock); + if (ret < 0) + goto quit_stream; + } } quit_stream: - /* the usb_lock is already acquired */ - if (gspca_dev->present) + if (gspca_dev->present) { + mutex_lock(&gspca_dev->usb_lock); sq905_command(gspca_dev, SQ905_CLEAR); - mutex_unlock(&gspca_dev->usb_lock); + mutex_unlock(&gspca_dev->usb_lock); + } kfree(buffer); } @@ -346,7 +342,7 @@ static int sd_init(struct gspca_dev *gspca_dev) ret = sq905_command(gspca_dev, SQ905_ID); if (ret < 0) return ret; - ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4); + ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0); if (ret < 0) return ret; /* usb_buf is allocated with kmalloc so is aligned. From b3e440eef8a842736d63cc6a6594d80dfbb75fd9 Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Fri, 9 Oct 2009 03:54:49 -0300 Subject: [PATCH 071/345] V4L/DVB (13139): gspca_mr97310a: Improve VGA sensor type detection Improve (and also simplify :) gspca_mr97310a: VGA sensor type detection. As it was still failing on some machines (not with some cams, but on some machines interesting enough). Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 89 +++++++++++----------------- 1 file changed, 34 insertions(+), 55 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index f4c83b367900..abc56e37efcb 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -431,12 +431,13 @@ static int sd_config(struct gspca_dev *gspca_dev, if (err_code < 0) return err_code; + err_code = stream_start(gspca_dev); + if (err_code < 0) + return err_code; + if (id->idProduct == 0x010e) { sd->cam_type = CAM_TYPE_CIF; cam->nmodes--; - err_code = stream_start(gspca_dev); - if (err_code < 0) - return err_code; err_code = cam_get_response16(gspca_dev, 0x06, 1); if (err_code < 0) return err_code; @@ -476,74 +477,52 @@ static int sd_config(struct gspca_dev *gspca_dev, } else { sd->cam_type = CAM_TYPE_VGA; - /* - * VGA cams also have two different sensor types. Detection - * requires a two-step process. - * - * Here is a report on the result of the first test for the - * known MR97310a VGA cameras. If you have another to report, - * please do. - * - * Name byte just read sd->sensor_type - * sd->do_lcd_stop - * Aiptek Pencam VGA+ 0x31 0 1 - * ION digital 0x31 0 1 - * Sakar Digital 77379 0x31 0 1 - * Argus DC-1620 0x30 1 0 - * Argus QuickClix 0x30 1 1 (see note) - * Note that this test fails to distinguish sd->sensor_type - * for the two cameras which have reported 0x30. - * Another test will be run on them. - * But the sd->do_lcd_stop setting is needed, too. - */ - - err_code = cam_get_response16(gspca_dev, 0x20, 1); - if (err_code < 0) - return err_code; - sd->sensor_type = gspca_dev->usb_buf[0] & 1; - sd->do_lcd_stop = (~gspca_dev->usb_buf[0]) & 1; - err_code = stream_start(gspca_dev); + err_code = cam_get_response16(gspca_dev, 0x07, 1); if (err_code < 0) return err_code; /* - * A second test can now resolve any remaining ambiguity in the - * identification of the camera's sensor type. Specifically, - * it now gives the correct sensor_type for the Argus DC-1620 - * and the Argus QuickClix. - * - * This second test is only run if needed, - * but additional results from testing some other cameras - * are recorded here, too: + * Here is a table of the responses to the previous command + * from the known MR97310A VGA cameras. * * Name gspca_dev->usb_buf[] sd->sensor_type + * sd->do_lcd_stop + * Aiptek Pencam VGA+ 0300 0 1 + * ION digital 0350 0 1 + * Argus DC-1620 0450 1 0 + * Argus QuickClix 0420 1 1 * - * Aiptek Pencam VGA+ 0300 (test not needed) 1 - * ION digital 0350 (test not needed) 1 - * Argus DC-1620 0450 (remains as type 0) 0 - * Argus QuickClix 0420 (corrected to type 1) 1 + * Based upon these results, we assume default settings + * and then correct as necessary, as follows. * - * This test even seems able to distinguish one VGA cam from - * another which may be useful. However, the CIF type 1 cameras - * do not like it. */ - if (!sd->sensor_type) { - err_code = cam_get_response16(gspca_dev, 0x07, 1); - if (err_code < 0) - return err_code; - + sd->sensor_type = 1; + sd->do_lcd_stop = 0; + if ((gspca_dev->usb_buf[0] != 0x03) && + (gspca_dev->usb_buf[0] != 0x04)) { + PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", + gspca_dev->usb_buf[1]); + PDEBUG(D_ERR, "Defaults assumed, may not work"); + PDEBUG(D_ERR, "Please report this"); + } + if (gspca_dev->usb_buf[0] == 0x04) { + sd->do_lcd_stop = 1; switch (gspca_dev->usb_buf[1]) { case 0x50: + sd->sensor_type = 0; + PDEBUG(D_PROBE, "sensor_type corrected to 0"); break; case 0x20: - sd->sensor_type = 1; - PDEBUG(D_PROBE, "sensor_type corrected to 1"); + /* Nothing to do here. */ break; default: - PDEBUG(D_ERR, "Unknown VGA Sensor id : %02x", - gspca_dev->usb_buf[1]); - return -ENODEV; + PDEBUG(D_ERR, + "Unknown VGA Sensor id Byte 1: %02x", + gspca_dev->usb_buf[1]); + PDEBUG(D_ERR, + "Defaults assumed, may not work"); + PDEBUG(D_ERR, "Please report this"); } } PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", From 6ca3f255f790764f9cfc41d3ac02823d83dfa5ac Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Oct 2009 03:58:35 -0300 Subject: [PATCH 072/345] V4L/DVB (13140): gspca_jeilinj: once one frame is discarded it keeps discarding all frames While checking all gspca sub drivers pkt_scan functions for a bug I found in 1 of them (and after checking also in another), I noticed a bug in the gspca_jeilinj work queue function, once it has decided to start discard a frame because the application is not reading fast enough (and thus returning buffers to fill fast enough), it never stops discarding. This patch fixes this by simply completely removing the "discarding" variable, if we need to discard the current frame because there is no buffer to store it, the "frame" pointer will be NULL, so that is all we need to check. I've also moved the gspca_get_i_frame() call and the writing of the jpg header to the buffer to after the first usb_bulk_msg() call, as we don't need it before that, and that will give the app slightly more time to queue a buffer for us to fill. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/jeilinj.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c index a11c97ebeb0f..d679970d5b3e 100644 --- a/drivers/media/video/gspca/jeilinj.c +++ b/drivers/media/video/gspca/jeilinj.c @@ -185,7 +185,6 @@ static void jlj_dostream(struct work_struct *work) int blocks_left; /* 0x200-sized blocks remaining in current frame. */ int size_in_blocks; int act_len; - int discarding = 0; /* true if we failed to get space for frame. */ int packet_type; int ret; u8 *buffer; @@ -196,15 +195,6 @@ static void jlj_dostream(struct work_struct *work) goto quit_stream; } while (gspca_dev->present && gspca_dev->streaming) { - if (!gspca_dev->present) - goto quit_stream; - /* Start a new frame, and add the JPEG header, first thing */ - frame = gspca_get_i_frame(gspca_dev); - if (frame && !discarding) - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - dev->jpeg_hdr, JPEG_HDR_SZ); - else - discarding = 1; /* * Now request data block 0. Line 0 reports the size * to download, in blocks of size 0x200, and also tells the @@ -222,14 +212,17 @@ static void jlj_dostream(struct work_struct *work) size_in_blocks = buffer[0x0a]; blocks_left = buffer[0x0a] - 1; PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left); - packet_type = INTER_PACKET; - if (frame && !discarding) + + /* Start a new frame, and add the JPEG header, first thing */ + frame = gspca_get_i_frame(gspca_dev); + if (frame) { + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + dev->jpeg_hdr, JPEG_HDR_SZ); /* Toss line 0 of data block 0, keep the rest. */ - gspca_frame_add(gspca_dev, packet_type, + gspca_frame_add(gspca_dev, INTER_PACKET, frame, buffer + FRAME_HEADER_LEN, JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); - else - discarding = 1; + } while (blocks_left > 0) { if (!gspca_dev->present) goto quit_stream; @@ -246,12 +239,10 @@ static void jlj_dostream(struct work_struct *work) packet_type = LAST_PACKET; else packet_type = INTER_PACKET; - if (frame && !discarding) + if (frame) gspca_frame_add(gspca_dev, packet_type, frame, buffer, JEILINJ_MAX_TRANSFER); - else - discarding = 1; } } quit_stream: From 205260102c5cef4180982eec88aaeb6934faf214 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Oct 2009 04:17:42 -0300 Subject: [PATCH 073/345] V4L/DVB (13141): gspca_sq905c: once one frame is discarded it keeps discarding all frames While checking all gspca sub drivers pkt_scan functions for a bug I found in 1 of them (and after checking also in another), I noticed a bug in the gspca_sq905c work queue function, once it has decided to start discarding a frame because the application is not reading fast enough (and thus returning buffers to fill fast enough), it never stops discarding. This patch fixes this by simply completely removing the "discarding" variable, if we need to discard the current frame because there is no buffer to store it, the "frame" pointer will be NULL, so that is all we need to check. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sq905c.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index 916892505432..81020f6f739e 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c @@ -119,7 +119,6 @@ static void sq905c_dostream(struct work_struct *work) int bytes_left; /* bytes remaining in current frame. */ int data_len; /* size to use for the next read. */ int act_len; - int discarding = 0; /* true if we failed to get space for frame. */ int packet_type; int ret; u8 *buffer; @@ -131,8 +130,6 @@ static void sq905c_dostream(struct work_struct *work) } while (gspca_dev->present && gspca_dev->streaming) { - if (!gspca_dev->present) - goto quit_stream; /* Request the header, which tells the size to download */ ret = usb_bulk_msg(gspca_dev->dev, usb_rcvbulkpipe(gspca_dev->dev, 0x81), @@ -150,16 +147,12 @@ static void sq905c_dostream(struct work_struct *work) /* We keep the header. It has other information, too. */ packet_type = FIRST_PACKET; frame = gspca_get_i_frame(gspca_dev); - if (frame && !discarding) { + if (frame) gspca_frame_add(gspca_dev, packet_type, frame, buffer, FRAME_HEADER_LEN); - } else - discarding = 1; - while (bytes_left > 0) { + while (bytes_left > 0 && gspca_dev->present) { data_len = bytes_left > SQ905C_MAX_TRANSFER ? SQ905C_MAX_TRANSFER : bytes_left; - if (!gspca_dev->present) - goto quit_stream; ret = usb_bulk_msg(gspca_dev->dev, usb_rcvbulkpipe(gspca_dev->dev, 0x81), buffer, data_len, &act_len, @@ -174,19 +167,17 @@ static void sq905c_dostream(struct work_struct *work) packet_type = LAST_PACKET; else packet_type = INTER_PACKET; - frame = gspca_get_i_frame(gspca_dev); - if (frame && !discarding) + if (frame) gspca_frame_add(gspca_dev, packet_type, frame, buffer, data_len); - else - discarding = 1; } } quit_stream: - mutex_lock(&gspca_dev->usb_lock); - if (gspca_dev->present) + if (gspca_dev->present) { + mutex_lock(&gspca_dev->usb_lock); sq905c_command(gspca_dev, SQ905C_CLEAR, 0); - mutex_unlock(&gspca_dev->usb_lock); + mutex_unlock(&gspca_dev->usb_lock); + } kfree(buffer); } From d76f975c574230fb00d07848d330e04d97e51475 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 11 Oct 2009 05:22:29 -0300 Subject: [PATCH 074/345] V4L/DVB (13142): gspca_mr97310a: small tweak to CIF sensor type 1 exposure setting The CIF sensor type 1 exposure setting got clamped at 300, as settings below 300 do not work well (and do work for the other sensors). This patch scales the 0-4095 range to 300-4095 instead of ignoring changes between 300, avoiding have a part of the control range where nothing happens. This is esp. important for software autogain as done by libv4l. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index abc56e37efcb..f282f8000701 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -842,8 +842,9 @@ static void setexposure(struct gspca_dev *gspca_dev) return; if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { - /* This cam does not like very low exposure settings */ - exposure = (sd->exposure < 300) ? 300 : sd->exposure; + /* This cam does not like exposure settings > 300, + so scale 0 - 4095 to 300 - 4095 */ + exposure = (sd->exposure * 9267) / 10000 + 300; sensor_write1(gspca_dev, 3, exposure >> 4); sensor_write1(gspca_dev, 4, exposure & 0x0f); } else { From 229bb7dc5181b3264550532a26a9c698be56fcb8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 11 Oct 2009 07:41:46 -0300 Subject: [PATCH 075/345] V4L/DVB (13143): gspca_ov519 cleanup sensor detection gspca_ov519 cleanup sensor detection Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 55 +++++++++++++------------------ 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index e16557819782..bb9976dc1e24 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -416,6 +416,7 @@ static const struct v4l2_pix_format ov511_sif_mode[] = { /* I2C ADDRESSES */ #define OV7xx0_SID 0x42 +#define OV_HIRES_SID 0x60 /* OV9xxx / OV2xxx / OV3xxx */ #define OV8xx0_SID 0xa0 #define OV6xx0_SID 0xc0 @@ -1423,13 +1424,18 @@ static inline int ov51x_restart(struct sd *sd) return 0; } +static int ov51x_set_slave_ids(struct sd *sd, __u8 slave); + /* This does an initial reset of an OmniVision sensor and ensures that I2C * is synchronized. Returns <0 on failure. */ -static int init_ov_sensor(struct sd *sd) +static int init_ov_sensor(struct sd *sd, __u8 slave) { int i; + if (ov51x_set_slave_ids(sd, slave) < 0) + return -EIO; + /* Reset the sensor */ if (i2c_w(sd, 0x12, 0x80) < 0) return -EIO; @@ -1996,46 +2002,31 @@ static int sd_config(struct gspca_dev *gspca_dev, ov51x_led_control(sd, 0); /* turn LED off */ - /* Test for 76xx */ - if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0) - goto error; - /* The OV519 must be more aggressive about sensor detection since * I2C write will never fail if the sensor is not present. We have * to try to initialize the sensor to detect its presence */ - if (init_ov_sensor(sd) >= 0) { + + /* Test for 76xx */ + if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { if (ov7xx0_configure(sd) < 0) { PDEBUG(D_ERR, "Failed to configure OV7xx0"); goto error; } - } else { - - /* Test for 6xx0 */ - if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0) + /* Test for 6xx0 */ + } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { + if (ov6xx0_configure(sd) < 0) { + PDEBUG(D_ERR, "Failed to configure OV6xx0"); goto error; - - if (init_ov_sensor(sd) >= 0) { - if (ov6xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV6xx0"); - goto error; - } - } else { - - /* Test for 8xx0 */ - if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0) - goto error; - - if (init_ov_sensor(sd) < 0) { - PDEBUG(D_ERR, - "Can't determine sensor slave IDs"); - goto error; - } - if (ov8xx0_configure(sd) < 0) { - PDEBUG(D_ERR, - "Failed to configure OV8xx0 sensor"); - goto error; - } } + /* Test for 8xx0 */ + } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { + if (ov8xx0_configure(sd) < 0) { + PDEBUG(D_ERR, "Failed to configure OV8xx0"); + goto error; + } + } else { + PDEBUG(D_ERR, "Can't determine sensor slave IDs"); + goto error; } cam = &gspca_dev->cam; From 635118d5b19c4ad562d425a3f3491c721d6a8293 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 11 Oct 2009 09:49:03 -0300 Subject: [PATCH 076/345] V4L/DVB (13144): gspca_ov519: Add support for OV2610 and OV3610 sensors This patch adds support for the OV2610 and OV3610 sensors to the gspca ov519 subdriver. This is a preparation patch for adding ovfx2 bridge support. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 892 +++++++++++++++++++++++++++++- 1 file changed, 882 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index bb9976dc1e24..bfc88360132d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -58,6 +58,7 @@ struct sd { #define BRIDGE_OV518 2 #define BRIDGE_OV518PLUS 3 #define BRIDGE_OV519 4 +#define BRIDGE_OVFX2 5 #define BRIDGE_MASK 7 char invert_led; @@ -81,15 +82,17 @@ struct sd { char sensor; /* Type of image sensor chip (SEN_*) */ #define SEN_UNKNOWN 0 -#define SEN_OV6620 1 -#define SEN_OV6630 2 -#define SEN_OV66308AF 3 -#define SEN_OV7610 4 -#define SEN_OV7620 5 -#define SEN_OV7640 6 -#define SEN_OV7670 7 -#define SEN_OV76BE 8 -#define SEN_OV8610 9 +#define SEN_OV2610 1 +#define SEN_OV3610 2 +#define SEN_OV6620 3 +#define SEN_OV6630 4 +#define SEN_OV66308AF 5 +#define SEN_OV7610 6 +#define SEN_OV7620 7 +#define SEN_OV7640 8 +#define SEN_OV7670 9 +#define SEN_OV76BE 10 +#define SEN_OV8610 11 }; /* V4L2 controls supported by the driver */ @@ -345,6 +348,70 @@ static const struct v4l2_pix_format ov511_sif_mode[] = { .priv = 0}, }; +static const struct v4l2_pix_format ovfx2_vga_mode[] = { + {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; +static const struct v4l2_pix_format ovfx2_cif_mode[] = { + {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 3}, + {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 176, + .sizeimage = 176 * 144, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2}, + {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 352, + .sizeimage = 352 * 288, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; +static const struct v4l2_pix_format ovfx2_ov2610_mode[] = { + {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 1600, + .sizeimage = 1600 * 1200, + .colorspace = V4L2_COLORSPACE_SRGB}, +}; +static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { + {2080, 1544, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 2080, + .sizeimage = 2080 * 1544, + .colorspace = V4L2_COLORSPACE_SRGB}, + {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 1600, + .sizeimage = 1600 * 1200, + .colorspace = V4L2_COLORSPACE_SRGB}, + {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 1024, + .sizeimage = 1024 * 768, + .colorspace = V4L2_COLORSPACE_SRGB}, + {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 800, + .sizeimage = 800 * 600, + .colorspace = V4L2_COLORSPACE_SRGB}, + {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB}, +}; + + /* Registers common to OV511 / OV518 */ #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ #define R51x_SYS_RESET 0x50 @@ -509,6 +576,696 @@ struct ov_i2c_regvals { __u8 val; }; +/* Settings for OV2610 camera chip */ +static const struct ov_i2c_regvals norm_2610[] = +{ + { 0x10, 0x80 }, /* reset */ +}; + +static const struct ov_i2c_regvals norm_3620b[] = +{ + /* + * From the datasheet: "Note that after writing to register COMH + * (0x12) to change the sensor mode, registers related to the + * sensor’s cropping window will be reset back to their default + * values." + * + * "wait 4096 external clock ... to make sure the sensor is + * stable and ready to access registers" i.e. 160us at 24MHz + */ + + { 0x12, 0x80 }, /* COMH reset */ + { 0x12, 0x00 }, /* QXGA, master */ + + /* + * 11 CLKRC "Clock Rate Control" + * [7] internal frequency doublers: on + * [6] video port mode: master + * [5:0] clock divider: 1 + */ + { 0x11, 0x80 }, + + /* + * 13 COMI "Common Control I" + * = 192 (0xC0) 11000000 + * COMI[7] "AEC speed selection" + * = 1 (0x01) 1....... "Faster AEC correction" + * COMI[6] "AEC speed step selection" + * = 1 (0x01) .1...... "Big steps, fast" + * COMI[5] "Banding filter on off" + * = 0 (0x00) ..0..... "Off" + * COMI[4] "Banding filter option" + * = 0 (0x00) ...0.... "Main clock is 48 MHz and + * the PLL is ON" + * COMI[3] "Reserved" + * = 0 (0x00) ....0... + * COMI[2] "AGC auto manual control selection" + * = 0 (0x00) .....0.. "Manual" + * COMI[1] "AWB auto manual control selection" + * = 0 (0x00) ......0. "Manual" + * COMI[0] "Exposure control" + * = 0 (0x00) .......0 "Manual" + */ + { 0x13, 0xC0 }, + + /* + * 09 COMC "Common Control C" + * = 8 (0x08) 00001000 + * COMC[7:5] "Reserved" + * = 0 (0x00) 000..... + * COMC[4] "Sleep Mode Enable" + * = 0 (0x00) ...0.... "Normal mode" + * COMC[3:2] "Sensor sampling reset timing selection" + * = 2 (0x02) ....10.. "Longer reset time" + * COMC[1:0] "Output drive current select" + * = 0 (0x00) ......00 "Weakest" + */ + { 0x09, 0x08 }, + + /* + * 0C COMD "Common Control D" + * = 8 (0x08) 00001000 + * COMD[7] "Reserved" + * = 0 (0x00) 0....... + * COMD[6] "Swap MSB and LSB at the output port" + * = 0 (0x00) .0...... "False" + * COMD[5:3] "Reserved" + * = 1 (0x01) ..001... + * COMD[2] "Output Average On Off" + * = 0 (0x00) .....0.. "Output Normal" + * COMD[1] "Sensor precharge voltage selection" + * = 0 (0x00) ......0. "Selects internal + * reference precharge + * voltage" + * COMD[0] "Snapshot option" + * = 0 (0x00) .......0 "Enable live video output + * after snapshot sequence" + */ + { 0x0c, 0x08 }, + + /* + * 0D COME "Common Control E" + * = 161 (0xA1) 10100001 + * COME[7] "Output average option" + * = 1 (0x01) 1....... "Output average of 4 pixels" + * COME[6] "Anti-blooming control" + * = 0 (0x00) .0...... "Off" + * COME[5:3] "Reserved" + * = 4 (0x04) ..100... + * COME[2] "Clock output power down pin status" + * = 0 (0x00) .....0.. "Tri-state data output pin + * on power down" + * COME[1] "Data output pin status selection at power down" + * = 0 (0x00) ......0. "Tri-state VSYNC, PCLK, + * HREF, and CHSYNC pins on + * power down" + * COME[0] "Auto zero circuit select" + * = 1 (0x01) .......1 "On" + */ + { 0x0d, 0xA1 }, + + /* + * 0E COMF "Common Control F" + * = 112 (0x70) 01110000 + * COMF[7] "System clock selection" + * = 0 (0x00) 0....... "Use 24 MHz system clock" + * COMF[6:4] "Reserved" + * = 7 (0x07) .111.... + * COMF[3] "Manual auto negative offset canceling selection" + * = 0 (0x00) ....0... "Auto detect negative + * offset and cancel it" + * COMF[2:0] "Reserved" + * = 0 (0x00) .....000 + */ + { 0x0e, 0x70 }, + + /* + * 0F COMG "Common Control G" + * = 66 (0x42) 01000010 + * COMG[7] "Optical black output selection" + * = 0 (0x00) 0....... "Disable" + * COMG[6] "Black level calibrate selection" + * = 1 (0x01) .1...... "Use optical black pixels + * to calibrate" + * COMG[5:4] "Reserved" + * = 0 (0x00) ..00.... + * COMG[3] "Channel offset adjustment" + * = 0 (0x00) ....0... "Disable offset adjustment" + * COMG[2] "ADC black level calibration option" + * = 0 (0x00) .....0.. "Use B/G line and G/R + * line to calibrate each + * channel's black level" + * COMG[1] "Reserved" + * = 1 (0x01) ......1. + * COMG[0] "ADC black level calibration enable" + * = 0 (0x00) .......0 "Disable" + */ + { 0x0f, 0x42 }, + + /* + * 14 COMJ "Common Control J" + * = 198 (0xC6) 11000110 + * COMJ[7:6] "AGC gain ceiling" + * = 3 (0x03) 11...... "8x" + * COMJ[5:4] "Reserved" + * = 0 (0x00) ..00.... + * COMJ[3] "Auto banding filter" + * = 0 (0x00) ....0... "Banding filter is always + * on off depending on + * COMI[5] setting" + * COMJ[2] "VSYNC drop option" + * = 1 (0x01) .....1.. "SYNC is dropped if frame + * data is dropped" + * COMJ[1] "Frame data drop" + * = 1 (0x01) ......1. "Drop frame data if + * exposure is not within + * tolerance. In AEC mode, + * data is normally dropped + * when data is out of + * range." + * COMJ[0] "Reserved" + * = 0 (0x00) .......0 + */ + { 0x14, 0xC6 }, + + /* + * 15 COMK "Common Control K" + * = 2 (0x02) 00000010 + * COMK[7] "CHSYNC pin output swap" + * = 0 (0x00) 0....... "CHSYNC" + * COMK[6] "HREF pin output swap" + * = 0 (0x00) .0...... "HREF" + * COMK[5] "PCLK output selection" + * = 0 (0x00) ..0..... "PCLK always output" + * COMK[4] "PCLK edge selection" + * = 0 (0x00) ...0.... "Data valid on falling edge" + * COMK[3] "HREF output polarity" + * = 0 (0x00) ....0... "positive" + * COMK[2] "Reserved" + * = 0 (0x00) .....0.. + * COMK[1] "VSYNC polarity" + * = 1 (0x01) ......1. "negative" + * COMK[0] "HSYNC polarity" + * = 0 (0x00) .......0 "positive" + */ + { 0x15, 0x02 }, + + /* + * 33 CHLF "Current Control" + * = 9 (0x09) 00001001 + * CHLF[7:6] "Sensor current control" + * = 0 (0x00) 00...... + * CHLF[5] "Sensor current range control" + * = 0 (0x00) ..0..... "normal range" + * CHLF[4] "Sensor current" + * = 0 (0x00) ...0.... "normal current" + * CHLF[3] "Sensor buffer current control" + * = 1 (0x01) ....1... "half current" + * CHLF[2] "Column buffer current control" + * = 0 (0x00) .....0.. "normal current" + * CHLF[1] "Analog DSP current control" + * = 0 (0x00) ......0. "normal current" + * CHLF[1] "ADC current control" + * = 0 (0x00) ......0. "normal current" + */ + { 0x33, 0x09 }, + + /* + * 34 VBLM "Blooming Control" + * = 80 (0x50) 01010000 + * VBLM[7] "Hard soft reset switch" + * = 0 (0x00) 0....... "Hard reset" + * VBLM[6:4] "Blooming voltage selection" + * = 5 (0x05) .101.... + * VBLM[3:0] "Sensor current control" + * = 0 (0x00) ....0000 + */ + { 0x34, 0x50 }, + + /* + * 36 VCHG "Sensor Precharge Voltage Control" + * = 0 (0x00) 00000000 + * VCHG[7] "Reserved" + * = 0 (0x00) 0....... + * VCHG[6:4] "Sensor precharge voltage control" + * = 0 (0x00) .000.... + * VCHG[3:0] "Sensor array common reference" + * = 0 (0x00) ....0000 + */ + { 0x36, 0x00 }, + + /* + * 37 ADC "ADC Reference Control" + * = 4 (0x04) 00000100 + * ADC[7:4] "Reserved" + * = 0 (0x00) 0000.... + * ADC[3] "ADC input signal range" + * = 0 (0x00) ....0... "Input signal 1.0x" + * ADC[2:0] "ADC range control" + * = 4 (0x04) .....100 + */ + { 0x37, 0x04 }, + + /* + * 38 ACOM "Analog Common Ground" + * = 82 (0x52) 01010010 + * ACOM[7] "Analog gain control" + * = 0 (0x00) 0....... "Gain 1x" + * ACOM[6] "Analog black level calibration" + * = 1 (0x01) .1...... "On" + * ACOM[5:0] "Reserved" + * = 18 (0x12) ..010010 + */ + { 0x38, 0x52 }, + + /* + * 3A FREFA "Internal Reference Adjustment" + * = 0 (0x00) 00000000 + * FREFA[7:0] "Range" + * = 0 (0x00) 00000000 + */ + { 0x3a, 0x00 }, + + /* + * 3C FVOPT "Internal Reference Adjustment" + * = 31 (0x1F) 00011111 + * FVOPT[7:0] "Range" + * = 31 (0x1F) 00011111 + */ + { 0x3c, 0x1F }, + + /* + * 44 Undocumented = 0 (0x00) 00000000 + * 44[7:0] "It's a secret" + * = 0 (0x00) 00000000 + */ + { 0x44, 0x00 }, + + /* + * 40 Undocumented = 0 (0x00) 00000000 + * 40[7:0] "It's a secret" + * = 0 (0x00) 00000000 + */ + { 0x40, 0x00 }, + + /* + * 41 Undocumented = 0 (0x00) 00000000 + * 41[7:0] "It's a secret" + * = 0 (0x00) 00000000 + */ + { 0x41, 0x00 }, + + /* + * 42 Undocumented = 0 (0x00) 00000000 + * 42[7:0] "It's a secret" + * = 0 (0x00) 00000000 + */ + { 0x42, 0x00 }, + + /* + * 43 Undocumented = 0 (0x00) 00000000 + * 43[7:0] "It's a secret" + * = 0 (0x00) 00000000 + */ + { 0x43, 0x00 }, + + /* + * 45 Undocumented = 128 (0x80) 10000000 + * 45[7:0] "It's a secret" + * = 128 (0x80) 10000000 + */ + { 0x45, 0x80 }, + + /* + * 48 Undocumented = 192 (0xC0) 11000000 + * 48[7:0] "It's a secret" + * = 192 (0xC0) 11000000 + */ + { 0x48, 0xC0 }, + + /* + * 49 Undocumented = 25 (0x19) 00011001 + * 49[7:0] "It's a secret" + * = 25 (0x19) 00011001 + */ + { 0x49, 0x19 }, + + /* + * 4B Undocumented = 128 (0x80) 10000000 + * 4B[7:0] "It's a secret" + * = 128 (0x80) 10000000 + */ + { 0x4B, 0x80 }, + + /* + * 4D Undocumented = 196 (0xC4) 11000100 + * 4D[7:0] "It's a secret" + * = 196 (0xC4) 11000100 + */ + { 0x4D, 0xC4 }, + + /* + * 35 VREF "Reference Voltage Control" + * = 76 (0x4C) 01001100 + * VREF[7:5] "Column high reference control" + * = 2 (0x02) 010..... "higher voltage" + * VREF[4:2] "Column low reference control" + * = 3 (0x03) ...011.. "Highest voltage" + * VREF[1:0] "Reserved" + * = 0 (0x00) ......00 + */ + { 0x35, 0x4C }, + + /* + * 3D Undocumented = 0 (0x00) 00000000 + * 3D[7:0] "It's a secret" + * = 0 (0x00) 00000000 + */ + { 0x3D, 0x00 }, + + /* + * 3E Undocumented = 0 (0x00) 00000000 + * 3E[7:0] "It's a secret" + * = 0 (0x00) 00000000 + */ + { 0x3E, 0x00 }, + + /* + * 3B FREFB "Internal Reference Adjustment" + * = 24 (0x18) 00011000 + * FREFB[7:0] "Range" + * = 24 (0x18) 00011000 + */ + { 0x3b, 0x18 }, + + /* + * 33 CHLF "Current Control" + * = 25 (0x19) 00011001 + * CHLF[7:6] "Sensor current control" + * = 0 (0x00) 00...... + * CHLF[5] "Sensor current range control" + * = 0 (0x00) ..0..... "normal range" + * CHLF[4] "Sensor current" + * = 1 (0x01) ...1.... "double current" + * CHLF[3] "Sensor buffer current control" + * = 1 (0x01) ....1... "half current" + * CHLF[2] "Column buffer current control" + * = 0 (0x00) .....0.. "normal current" + * CHLF[1] "Analog DSP current control" + * = 0 (0x00) ......0. "normal current" + * CHLF[1] "ADC current control" + * = 0 (0x00) ......0. "normal current" + */ + { 0x33, 0x19 }, + + /* + * 34 VBLM "Blooming Control" + * = 90 (0x5A) 01011010 + * VBLM[7] "Hard soft reset switch" + * = 0 (0x00) 0....... "Hard reset" + * VBLM[6:4] "Blooming voltage selection" + * = 5 (0x05) .101.... + * VBLM[3:0] "Sensor current control" + * = 10 (0x0A) ....1010 + */ + { 0x34, 0x5A }, + + /* + * 3B FREFB "Internal Reference Adjustment" + * = 0 (0x00) 00000000 + * FREFB[7:0] "Range" + * = 0 (0x00) 00000000 + */ + { 0x3b, 0x00 }, + + /* + * 33 CHLF "Current Control" + * = 9 (0x09) 00001001 + * CHLF[7:6] "Sensor current control" + * = 0 (0x00) 00...... + * CHLF[5] "Sensor current range control" + * = 0 (0x00) ..0..... "normal range" + * CHLF[4] "Sensor current" + * = 0 (0x00) ...0.... "normal current" + * CHLF[3] "Sensor buffer current control" + * = 1 (0x01) ....1... "half current" + * CHLF[2] "Column buffer current control" + * = 0 (0x00) .....0.. "normal current" + * CHLF[1] "Analog DSP current control" + * = 0 (0x00) ......0. "normal current" + * CHLF[1] "ADC current control" + * = 0 (0x00) ......0. "normal current" + */ + { 0x33, 0x09 }, + + /* + * 34 VBLM "Blooming Control" + * = 80 (0x50) 01010000 + * VBLM[7] "Hard soft reset switch" + * = 0 (0x00) 0....... "Hard reset" + * VBLM[6:4] "Blooming voltage selection" + * = 5 (0x05) .101.... + * VBLM[3:0] "Sensor current control" + * = 0 (0x00) ....0000 + */ + { 0x34, 0x50 }, + + /* + * 12 COMH "Common Control H" + * = 64 (0x40) 01000000 + * COMH[7] "SRST" + * = 0 (0x00) 0....... "No-op" + * COMH[6:4] "Resolution selection" + * = 4 (0x04) .100.... "XGA" + * COMH[3] "Master slave selection" + * = 0 (0x00) ....0... "Master mode" + * COMH[2] "Internal B/R channel option" + * = 0 (0x00) .....0.. "B/R use same channel" + * COMH[1] "Color bar test pattern" + * = 0 (0x00) ......0. "Off" + * COMH[0] "Reserved" + * = 0 (0x00) .......0 + */ + { 0x12, 0x40 }, + + /* + * 17 HREFST "Horizontal window start" + * = 31 (0x1F) 00011111 + * HREFST[7:0] "Horizontal window start, 8 MSBs" + * = 31 (0x1F) 00011111 + */ + { 0x17, 0x1F }, + + /* + * 18 HREFEND "Horizontal window end" + * = 95 (0x5F) 01011111 + * HREFEND[7:0] "Horizontal Window End, 8 MSBs" + * = 95 (0x5F) 01011111 + */ + { 0x18, 0x5F }, + + /* + * 19 VSTRT "Vertical window start" + * = 0 (0x00) 00000000 + * VSTRT[7:0] "Vertical Window Start, 8 MSBs" + * = 0 (0x00) 00000000 + */ + { 0x19, 0x00 }, + + /* + * 1A VEND "Vertical window end" + * = 96 (0x60) 01100000 + * VEND[7:0] "Vertical Window End, 8 MSBs" + * = 96 (0x60) 01100000 + */ + { 0x1a, 0x60 }, + + /* + * 32 COMM "Common Control M" + * = 18 (0x12) 00010010 + * COMM[7:6] "Pixel clock divide option" + * = 0 (0x00) 00...... "/1" + * COMM[5:3] "Horizontal window end position, 3 LSBs" + * = 2 (0x02) ..010... + * COMM[2:0] "Horizontal window start position, 3 LSBs" + * = 2 (0x02) .....010 + */ + { 0x32, 0x12 }, + + /* + * 03 COMA "Common Control A" + * = 74 (0x4A) 01001010 + * COMA[7:4] "AWB Update Threshold" + * = 4 (0x04) 0100.... + * COMA[3:2] "Vertical window end line control 2 LSBs" + * = 2 (0x02) ....10.. + * COMA[1:0] "Vertical window start line control 2 LSBs" + * = 2 (0x02) ......10 + */ + { 0x03, 0x4A }, + + /* + * 11 CLKRC "Clock Rate Control" + * = 128 (0x80) 10000000 + * CLKRC[7] "Internal frequency doublers on off seclection" + * = 1 (0x01) 1....... "On" + * CLKRC[6] "Digital video master slave selection" + * = 0 (0x00) .0...... "Master mode, sensor + * provides PCLK" + * CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }" + * = 0 (0x00) ..000000 + */ + { 0x11, 0x80 }, + + /* + * 12 COMH "Common Control H" + * = 0 (0x00) 00000000 + * COMH[7] "SRST" + * = 0 (0x00) 0....... "No-op" + * COMH[6:4] "Resolution selection" + * = 0 (0x00) .000.... "QXGA" + * COMH[3] "Master slave selection" + * = 0 (0x00) ....0... "Master mode" + * COMH[2] "Internal B/R channel option" + * = 0 (0x00) .....0.. "B/R use same channel" + * COMH[1] "Color bar test pattern" + * = 0 (0x00) ......0. "Off" + * COMH[0] "Reserved" + * = 0 (0x00) .......0 + */ + { 0x12, 0x00 }, + + /* + * 12 COMH "Common Control H" + * = 64 (0x40) 01000000 + * COMH[7] "SRST" + * = 0 (0x00) 0....... "No-op" + * COMH[6:4] "Resolution selection" + * = 4 (0x04) .100.... "XGA" + * COMH[3] "Master slave selection" + * = 0 (0x00) ....0... "Master mode" + * COMH[2] "Internal B/R channel option" + * = 0 (0x00) .....0.. "B/R use same channel" + * COMH[1] "Color bar test pattern" + * = 0 (0x00) ......0. "Off" + * COMH[0] "Reserved" + * = 0 (0x00) .......0 + */ + { 0x12, 0x40 }, + + /* + * 17 HREFST "Horizontal window start" + * = 31 (0x1F) 00011111 + * HREFST[7:0] "Horizontal window start, 8 MSBs" + * = 31 (0x1F) 00011111 + */ + { 0x17, 0x1F }, + + /* + * 18 HREFEND "Horizontal window end" + * = 95 (0x5F) 01011111 + * HREFEND[7:0] "Horizontal Window End, 8 MSBs" + * = 95 (0x5F) 01011111 + */ + { 0x18, 0x5F }, + + /* + * 19 VSTRT "Vertical window start" + * = 0 (0x00) 00000000 + * VSTRT[7:0] "Vertical Window Start, 8 MSBs" + * = 0 (0x00) 00000000 + */ + { 0x19, 0x00 }, + + /* + * 1A VEND "Vertical window end" + * = 96 (0x60) 01100000 + * VEND[7:0] "Vertical Window End, 8 MSBs" + * = 96 (0x60) 01100000 + */ + { 0x1a, 0x60 }, + + /* + * 32 COMM "Common Control M" + * = 18 (0x12) 00010010 + * COMM[7:6] "Pixel clock divide option" + * = 0 (0x00) 00...... "/1" + * COMM[5:3] "Horizontal window end position, 3 LSBs" + * = 2 (0x02) ..010... + * COMM[2:0] "Horizontal window start position, 3 LSBs" + * = 2 (0x02) .....010 + */ + { 0x32, 0x12 }, + + /* + * 03 COMA "Common Control A" + * = 74 (0x4A) 01001010 + * COMA[7:4] "AWB Update Threshold" + * = 4 (0x04) 0100.... + * COMA[3:2] "Vertical window end line control 2 LSBs" + * = 2 (0x02) ....10.. + * COMA[1:0] "Vertical window start line control 2 LSBs" + * = 2 (0x02) ......10 + */ + { 0x03, 0x4A }, + + /* + * 02 RED "Red Gain Control" + * = 175 (0xAF) 10101111 + * RED[7] "Action" + * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" + * RED[6:0] "Value" + * = 47 (0x2F) .0101111 + */ + { 0x02, 0xAF }, + + /* + * 2D ADDVSL "VSYNC Pulse Width" + * = 210 (0xD2) 11010010 + * ADDVSL[7:0] "VSYNC pulse width, LSB" + * = 210 (0xD2) 11010010 + */ + { 0x2d, 0xD2 }, + + /* + * 00 GAIN = 24 (0x18) 00011000 + * GAIN[7:6] "Reserved" + * = 0 (0x00) 00...... + * GAIN[5] "Double" + * = 0 (0x00) ..0..... "False" + * GAIN[4] "Double" + * = 1 (0x01) ...1.... "True" + * GAIN[3:0] "Range" + * = 8 (0x08) ....1000 + */ + { 0x00, 0x18 }, + + /* + * 01 BLUE "Blue Gain Control" + * = 240 (0xF0) 11110000 + * BLUE[7] "Action" + * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" + * BLUE[6:0] "Value" + * = 112 (0x70) .1110000 + */ + { 0x01, 0xF0 }, + + /* + * 10 AEC "Automatic Exposure Control" + * = 10 (0x0A) 00001010 + * AEC[7:0] "Automatic Exposure Control, 8 MSBs" + * = 10 (0x0A) 00001010 + */ + { 0x10, 0x0A }, + + { 0xE1, 0x67 }, + { 0xE3, 0x03 }, + { 0xE4, 0x26 }, + { 0xE5, 0x3E }, + { 0xF8, 0x01 }, + { 0xFF, 0x01 }, +}; + static const struct ov_i2c_regvals norm_6x20[] = { { 0x12, 0x80 }, /* reset */ { 0x11, 0x01 }, @@ -1514,6 +2271,39 @@ static int write_i2c_regvals(struct sd *sd, * ***************************************************************************/ +/* This initializes the OV2x10 / OV3610 / OV3620 */ +static int ov_hires_configure(struct sd *sd) +{ + int high, low; + + if (sd->bridge != BRIDGE_OVFX2) { + PDEBUG(D_ERR, "error hires sensors only supported with ovfx2"); + return -1; + } + + PDEBUG(D_PROBE, "starting ov hires configuration"); + + /* Detect sensor (sub)type */ + high = i2c_r(sd, 0x0a); + low = i2c_r(sd, 0x0b); + /* info("%x, %x", high, low); */ + if (high == 0x96 && low == 0x40) { + PDEBUG(D_PROBE, "Sensor is an OV2610"); + sd->sensor = SEN_OV2610; + } else if (high == 0x36 && (low & 0x0f) == 0x00) { + PDEBUG(D_PROBE, "Sensor is an OV3610"); + sd->sensor = SEN_OV3610; + } else { + PDEBUG(D_ERR, "Error unknown sensor type: 0x%02x%02x", + high, low); + return -1; + } + + /* Set sensor-specific vars */ + return 0; +} + + /* This initializes the OV8110, OV8610 sensor. The OV8110 uses * the same register settings as the OV8610, since they are very similar. */ @@ -2024,6 +2814,12 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_ERR, "Failed to configure OV8xx0"); goto error; } + /* Test for 3xxx / 2xxx */ + } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { + if (ov_hires_configure(sd) < 0) { + PDEBUG(D_ERR, "Failed to configure high res OV"); + goto error; + } } else { PDEBUG(D_ERR, "Can't determine sensor slave IDs"); goto error; @@ -2060,6 +2856,21 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = ARRAY_SIZE(ov519_sif_mode); } break; + case BRIDGE_OVFX2: + if (sd->sensor == SEN_OV2610) { + cam->cam_mode = ovfx2_ov2610_mode; + cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode); + } else if (sd->sensor == SEN_OV3610) { + cam->cam_mode = ovfx2_ov3610_mode; + cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode); + } else if (!sd->sif) { + cam->cam_mode = ov519_vga_mode; + cam->nmodes = ARRAY_SIZE(ov519_vga_mode); + } else { + cam->cam_mode = ov519_sif_mode; + cam->nmodes = ARRAY_SIZE(ov519_sif_mode); + } + break; } sd->brightness = BRIGHTNESS_DEF; if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) @@ -2083,6 +2894,9 @@ static int sd_config(struct gspca_dev *gspca_dev, /* OV8610 Frequency filter control should work but needs testing */ if (sd->sensor == SEN_OV8610) gspca_dev->ctrl_dis |= 1 << FREQ_IDX; + /* No controls for the OV2610/OV3610 */ + if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) + gspca_dev->ctrl_dis |= 0xFF; return 0; error: @@ -2097,6 +2911,20 @@ static int sd_init(struct gspca_dev *gspca_dev) /* initialize the sensor */ switch (sd->sensor) { + case SEN_OV2610: + if (write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610))) + return -EIO; + /* Enable autogain, autoexpo, awb, bandfilter */ + if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) + return -EIO; + break; + case SEN_OV3610: + if (write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b))) + return -EIO; + /* Enable autogain, autoexpo, awb, bandfilter */ + if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) + return -EIO; + break; case SEN_OV6620: if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) return -EIO; @@ -2546,6 +3374,42 @@ static int mode_init_ov_sensor_regs(struct sd *sd) /******** Mode (VGA/QVGA) and sensor specific regs ********/ switch (sd->sensor) { + case SEN_OV2610: + i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); + i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); + i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); + i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); + i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); + i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); + i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); + return 0; + case SEN_OV3610: { + int xstart, xend, ystart, yend; + + if (qvga) { + xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); + ystart = (772 - gspca_dev->height) / 2; + } else { + xstart = (2080 - gspca_dev->width) / 2 + (0x10 << 4); + ystart = (1544 - gspca_dev->height) / 2; + } + xend = xstart + gspca_dev->width; + yend = ystart + gspca_dev->height; + /* Writing to the COMH register resets the other windowing regs + to their default values, so we must do this first. */ + i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0); + i2c_w_mask(sd, 0x32, + (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7), + 0x3f); + i2c_w_mask(sd, 0x03, + (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3), + 0x0f); + i2c_w(sd, 0x17, xstart >> 4); + i2c_w(sd, 0x18, xend >> 4); + i2c_w(sd, 0x19, ystart >> 3); + i2c_w(sd, 0x1a, yend >> 3); + return 0; + } case SEN_OV8610: /* For OV8610 qvga means qsvga */ i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); @@ -2653,6 +3517,10 @@ static int set_ov_sensor_window(struct sd *sd) int ret, hstart, hstop, vstop, vstart; __u8 v; + /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ + if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) + return mode_init_ov_sensor_regs(sd); + gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2; @@ -3115,7 +3983,8 @@ static void setcolors(struct gspca_dev *gspca_dev) static void setautobrightness(struct sd *sd) { - if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) + if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670 || + sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) return; i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10); @@ -3123,6 +3992,9 @@ static void setautobrightness(struct sd *sd) static void setfreq(struct sd *sd) { + if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) + return; + if (sd->sensor == SEN_OV7670) { switch (sd->freq) { case 0: /* Banding filter disabled */ From b46aaa02648cd8c1ebc20191304e2f6a2382d04c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 12 Oct 2009 10:07:57 -0300 Subject: [PATCH 077/345] V4L/DVB (13145): gscpa_ov519: add support for the ovfx2 bridge gscpa_ov519: add support for the ovfx2 bridge Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 206 ++++++++++++++++++++++++++---- 1 file changed, 181 insertions(+), 25 deletions(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index bfc88360132d..30e91c365ea4 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2,14 +2,19 @@ * OV519 driver * * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) + * Copyright (C) 2009 Hans de Goede * * 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 + * Copyright (c) 1999-2006 Mark W. McClelland * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach + * Many improvements by Bret Wallach + * Color fixes by by Orion Sky Lawlor (2/26/2000) + * OV7620 fixes by Charl P. Botha + * Changes by Claudio Matsuoka * * ov51x-jpeg original copyright is: * @@ -389,26 +394,31 @@ static const struct v4l2_pix_format ovfx2_ov2610_mode[] = { .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { - {2080, 1544, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 2080, - .sizeimage = 2080 * 1544, - .colorspace = V4L2_COLORSPACE_SRGB}, - {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 1600, - .sizeimage = 1600 * 1200, - .colorspace = V4L2_COLORSPACE_SRGB}, - {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 1024, - .sizeimage = 1024 * 768, - .colorspace = V4L2_COLORSPACE_SRGB}, - {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 800, - .sizeimage = 800 * 600, - .colorspace = V4L2_COLORSPACE_SRGB}, {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB}, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 800, + .sizeimage = 800 * 600, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 1024, + .sizeimage = 1024 * 768, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 1600, + .sizeimage = 1600 * 1200, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 2048, + .sizeimage = 2048 * 1536, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, }; @@ -473,6 +483,30 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ +/* + * The FX2 chip does not give us a zero length read at end of frame. + * It does, however, give a short read at the end of a frame, if + * neccessary, rather than run two frames together. + * + * By choosing the right bulk transfer size, we are guaranteed to always + * get a short read for the last read of each frame. Frame sizes are + * always a composite number (width * height, or a multiple) so if we + * choose a prime number, we are guaranteed that the last read of a + * frame will be short. + * + * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB, + * otherwise EOVERFLOW "babbling" errors occur. I have not been able + * to figure out why. [PMiller] + * + * The constant (13 * 4096) is the largest "prime enough" number less than 64KB. + * + * It isn't enough to know the number of bytes per frame, in case we + * have data dropouts or buffer overruns (even though the FX2 double + * buffers, there are some pretty strict real time constraints for + * isochronous transfer for larger frame sizes). + */ +#define OVFX2_BULK_SIZE (13 * 4096) + /* I2C registers */ #define R51x_I2C_W_SID 0x41 #define R51x_I2C_SADDR_3 0x42 @@ -480,6 +514,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define R51x_I2C_R_SID 0x44 #define R51x_I2C_DATA 0x45 #define R518_I2C_CTL 0x47 /* OV518(+) only */ +#define OVFX2_I2C_ADDR 0x00 /* I2C ADDRESSES */ #define OV7xx0_SID 0x42 @@ -579,7 +614,7 @@ struct ov_i2c_regvals { /* Settings for OV2610 camera chip */ static const struct ov_i2c_regvals norm_2610[] = { - { 0x10, 0x80 }, /* reset */ + { 0x12, 0x80 }, /* reset */ }; static const struct ov_i2c_regvals norm_3620b[] = @@ -1803,7 +1838,23 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) static int reg_w(struct sd *sd, __u16 index, __u8 value) { int ret; - int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1; + int req; + + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + req = 2; + break; + case BRIDGE_OVFX2: + ret = usb_control_msg(sd->gspca_dev.dev, + usb_sndctrlpipe(sd->gspca_dev.dev, 0), + 0x0a, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + (__u16)value, index, NULL, 0, 500); + goto leave; + default: + req = 1; + } sd->gspca_dev.usb_buf[0] = value; ret = usb_control_msg(sd->gspca_dev.dev, @@ -1812,6 +1863,7 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, sd->gspca_dev.usb_buf, 1, 500); +leave: if (ret < 0) PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value); return ret; @@ -1822,7 +1874,19 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) static int reg_r(struct sd *sd, __u16 index) { int ret; - int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1; + int req; + + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + req = 3; + break; + case BRIDGE_OVFX2: + req = 0x0b; + break; + default: + req = 1; + } ret = usb_control_msg(sd->gspca_dev.dev, usb_rcvctrlpipe(sd->gspca_dev.dev, 0), @@ -2082,6 +2146,43 @@ static int ov518_i2c_r(struct sd *sd, __u8 reg) return value; } +static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) +{ + int ret; + + ret = usb_control_msg(sd->gspca_dev.dev, + usb_sndctrlpipe(sd->gspca_dev.dev, 0), + 0x02, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + (__u16)value, (__u16)reg, NULL, 0, 500); + + if (ret >= 0) + PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + else + PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); + + return ret; +} + +static int ovfx2_i2c_r(struct sd *sd, __u8 reg) +{ + int ret; + + ret = usb_control_msg(sd->gspca_dev.dev, + usb_rcvctrlpipe(sd->gspca_dev.dev, 0), + 0x03, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500); + + if (ret >= 0) { + ret = sd->gspca_dev.usb_buf[0]; + PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret); + } else + PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg); + + return ret; +} + static int i2c_w(struct sd *sd, __u8 reg, __u8 value) { switch (sd->bridge) { @@ -2092,6 +2193,8 @@ static int i2c_w(struct sd *sd, __u8 reg, __u8 value) case BRIDGE_OV518PLUS: case BRIDGE_OV519: return ov518_i2c_w(sd, reg, value); + case BRIDGE_OVFX2: + return ovfx2_i2c_w(sd, reg, value); } return -1; /* Should never happen */ } @@ -2106,6 +2209,8 @@ static int i2c_r(struct sd *sd, __u8 reg) case BRIDGE_OV518PLUS: case BRIDGE_OV519: return ov518_i2c_r(sd, reg); + case BRIDGE_OVFX2: + return ovfx2_i2c_r(sd, reg); } return -1; /* Should never happen */ } @@ -2147,6 +2252,8 @@ static inline int ov51x_stop(struct sd *sd) return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); case BRIDGE_OV519: return reg_w(sd, OV519_SYS_RESET1, 0x0f); + case BRIDGE_OVFX2: + return reg_w_mask(sd, 0x0f, 0x00, 0x02); } return 0; @@ -2176,6 +2283,8 @@ static inline int ov51x_restart(struct sd *sd) return reg_w(sd, R51x_SYS_RESET, 0x00); case BRIDGE_OV519: return reg_w(sd, OV519_SYS_RESET1, 0x00); + case BRIDGE_OVFX2: + return reg_w_mask(sd, 0x0f, 0x02, 0x02); } return 0; @@ -2229,6 +2338,9 @@ static int ov51x_set_slave_ids(struct sd *sd, { int rc; + if (sd->bridge == BRIDGE_OVFX2) + return reg_w(sd, OVFX2_I2C_ADDR, slave); + rc = reg_w(sd, R51x_I2C_W_SID, slave); if (rc < 0) return rc; @@ -2762,12 +2874,29 @@ static int ov519_configure(struct sd *sd) return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); } +static int ovfx2_configure(struct sd *sd) +{ + static const struct ov_regvals init_fx2[] = { + { 0x00, 0x60 }, + { 0x02, 0x01 }, + { 0x0f, 0x1d }, + { 0xe9, 0x82 }, + { 0xea, 0xc7 }, + { 0xeb, 0x10 }, + { 0xec, 0xf6 }, + }; + + sd->stopped = 1; + + return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; + struct cam *cam = &gspca_dev->cam; int ret = 0; sd->bridge = id->driver_info & BRIDGE_MASK; @@ -2785,6 +2914,12 @@ static int sd_config(struct gspca_dev *gspca_dev, case BRIDGE_OV519: ret = ov519_configure(sd); break; + case BRIDGE_OVFX2: + ret = ovfx2_configure(sd); + cam->bulk_size = OVFX2_BULK_SIZE; + cam->bulk_nurbs = MAX_NURBS; + cam->bulk = 1; + break; } if (ret) @@ -2825,7 +2960,6 @@ static int sd_config(struct gspca_dev *gspca_dev, goto error; } - cam = &gspca_dev->cam; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -3388,9 +3522,9 @@ static int mode_init_ov_sensor_regs(struct sd *sd) if (qvga) { xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); - ystart = (772 - gspca_dev->height) / 2; + ystart = (776 - gspca_dev->height) / 2; } else { - xstart = (2080 - gspca_dev->width) / 2 + (0x10 << 4); + xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4); ystart = (1544 - gspca_dev->height) / 2; } xend = xstart + gspca_dev->width; @@ -3685,6 +3819,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case BRIDGE_OV519: ret = ov519_mode_init_regs(sd); break; + /* case BRIDGE_OVFX2: nothing to do */ } if (ret < 0) goto out; @@ -3850,6 +3985,20 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, data, len); } +static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + /* A short read signals EOF */ + if (len < OVFX2_BULK_SIZE) { + gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + return; + } + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -3869,6 +4018,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, case BRIDGE_OV519: ov519_pkt_scan(gspca_dev, frame, data, len); break; + case BRIDGE_OVFX2: + ovfx2_pkt_scan(gspca_dev, frame, data, len); + break; } } @@ -4237,11 +4389,15 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, + {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, + {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, + {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, {} }; From ebbb5c3e0eb73db4da5bee57cd0344a74cf73319 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 12 Oct 2009 11:32:44 -0300 Subject: [PATCH 078/345] V4L/DVB (13146): gspca_ov519: cleanup sensor handling There were various "if (sensor == foo)" pieces of code inside ov519.c, move these bits to the sensor specific init functions, where they belong. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 159 +++++++++++------------------- 1 file changed, 59 insertions(+), 100 deletions(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 30e91c365ea4..4d6a762a6f3d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3501,7 +3501,8 @@ static int ov519_mode_init_regs(struct sd *sd) static int mode_init_ov_sensor_regs(struct sd *sd) { struct gspca_dev *gspca_dev; - int qvga; + int qvga, xstart, xend, ystart, yend; + __u8 v; gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; @@ -3517,9 +3518,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); return 0; - case SEN_OV3610: { - int xstart, xend, ystart, yend; - + case SEN_OV3610: if (qvga) { xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); ystart = (776 - gspca_dev->height) / 2; @@ -3543,13 +3542,19 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w(sd, 0x19, ystart >> 3); i2c_w(sd, 0x1a, yend >> 3); return 0; - } case SEN_OV8610: /* For OV8610 qvga means qsvga */ i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); + i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ + i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ + i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */ + i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */ break; case SEN_OV7610: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); + i2c_w(sd, 0x35, qvga?0x1e:0x9e); + i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ + i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ break; case SEN_OV7620: case SEN_OV76BE: @@ -3560,6 +3565,10 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); + i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ + i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ + if (sd->sensor == SEN_OV76BE) + i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); break; case SEN_OV7640: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); @@ -3569,6 +3578,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) /* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */ /* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */ /* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */ + i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ break; case SEN_OV7670: /* set COM7_FMT_VGA or COM7_FMT_QVGA @@ -3577,55 +3587,56 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, OV7670_REG_COM7, qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, OV7670_COM7_FMT_MASK); + i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ + i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, + OV7670_COM8_AWB); + if (qvga) { /* QVGA from ov7670.c by + * Jonathan Corbet */ + xstart = 164; + xend = 28; + ystart = 14; + yend = 494; + } else { /* VGA */ + xstart = 158; + xend = 14; + ystart = 10; + yend = 490; + } + /* OV7670 hardware window registers are split across + * multiple locations */ + i2c_w(sd, OV7670_REG_HSTART, xstart >> 3); + i2c_w(sd, OV7670_REG_HSTOP, xend >> 3); + v = i2c_r(sd, OV7670_REG_HREF); + v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); + msleep(10); /* need to sleep between read and write to + * same reg! */ + i2c_w(sd, OV7670_REG_HREF, v); + + i2c_w(sd, OV7670_REG_VSTART, ystart >> 2); + i2c_w(sd, OV7670_REG_VSTOP, yend >> 2); + v = i2c_r(sd, OV7670_REG_VREF); + v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); + msleep(10); /* need to sleep between read and write to + * same reg! */ + i2c_w(sd, OV7670_REG_VREF, v); break; case SEN_OV6620: + i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); + i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ + i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ + break; case SEN_OV6630: case SEN_OV66308AF: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); + i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ break; default: return -EINVAL; } - /******** Palette-specific regs ********/ - - /* The OV518 needs special treatment. Although both the OV518 - * and the OV6630 support a 16-bit video bus, only the 8 bit Y - * bus is actually used. The UV bus is tied to ground. - * Therefore, the OV6630 needs to be in 8-bit multiplexed - * output mode */ - - /* OV7640 is 8-bit only */ - - if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV66308AF && - sd->sensor != SEN_OV7640) - i2c_w_mask(sd, 0x13, 0x00, 0x20); - /******** Clock programming ********/ i2c_w(sd, 0x11, sd->clockdiv); - /******** Special Features ********/ -/* no evidence this is possible with OV7670, either */ - /* Test Pattern */ - if (sd->sensor != SEN_OV7640 && sd->sensor != SEN_OV7670) - i2c_w_mask(sd, 0x12, 0x00, 0x02); - - /* Enable auto white balance */ - if (sd->sensor == SEN_OV7670) - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, - OV7670_COM8_AWB); - else - i2c_w_mask(sd, 0x12, 0x04, 0x04); - - /* This will go away as soon as ov51x_mode_init_sensor_regs() */ - /* is fully tested. */ - /* 7620/6620/6630? don't have register 0x35, so play it safe */ - if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { - if (!qvga) - i2c_w(sd, 0x35, 0x9e); - else - i2c_w(sd, 0x35, 0x1e); - } return 0; } @@ -3648,11 +3659,11 @@ static int set_ov_sensor_window(struct sd *sd) struct gspca_dev *gspca_dev; int qvga, crop; int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; - int ret, hstart, hstop, vstop, vstart; - __u8 v; + int ret; /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) + if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || + sd->sensor == SEN_OV7670) return mode_init_ov_sensor_regs(sd); gspca_dev = &sd->gspca_dev; @@ -3701,11 +3712,6 @@ static int set_ov_sensor_window(struct sd *sd) hwebase = 0x1a; vwsbase = vwebase = 0x03; break; - case SEN_OV7670: - /*handling of OV7670 hardware sensor start and stop values - * is very odd, compared to the other OV sensors */ - vwsbase = vwebase = hwebase = hwsbase = 0x00; - break; default: return -EINVAL; } @@ -3746,58 +3752,11 @@ static int set_ov_sensor_window(struct sd *sd) if (ret < 0) return ret; - if (sd->sensor == SEN_OV8610) { - i2c_w_mask(sd, 0x2d, 0x05, 0x40); - /* old 0x95, new 0x05 from windrv 090403 */ - /* bits 5-7: reserved */ - i2c_w_mask(sd, 0x28, 0x20, 0x20); - /* bit 5: progressive mode on */ - } + i2c_w(sd, 0x17, hwsbase); + i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); + i2c_w(sd, 0x19, vwsbase); + i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); - /* The below is wrong for OV7670s because their window registers - * only store the high bits in 0x17 to 0x1a */ - - /* SRH Use sd->max values instead of requested win values */ - /* SCS Since we're sticking with only the max hardware widths - * for a given mode */ - /* I can hard code this for OV7670s */ - /* Yes, these numbers do look odd, but they're tested and work! */ - if (sd->sensor == SEN_OV7670) { - if (qvga) { /* QVGA from ov7670.c by - * Jonathan Corbet */ - hstart = 164; - hstop = 28; - vstart = 14; - vstop = 494; - } else { /* VGA */ - hstart = 158; - hstop = 14; - vstart = 10; - vstop = 490; - } - /* OV7670 hardware window registers are split across - * multiple locations */ - i2c_w(sd, OV7670_REG_HSTART, hstart >> 3); - i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3); - v = i2c_r(sd, OV7670_REG_HREF); - v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07); - msleep(10); /* need to sleep between read and write to - * same reg! */ - i2c_w(sd, OV7670_REG_HREF, v); - - i2c_w(sd, OV7670_REG_VSTART, vstart >> 2); - i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2); - v = i2c_r(sd, OV7670_REG_VREF); - v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03); - msleep(10); /* need to sleep between read and write to - * same reg! */ - i2c_w(sd, OV7670_REG_VREF, v); - } else { - i2c_w(sd, 0x17, hwsbase); - i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); - i2c_w(sd, 0x19, vwsbase); - i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); - } return 0; } From f4eabafeb3ea41801260fba624cbf2da971d19f8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 6 Aug 2009 06:05:40 -0300 Subject: [PATCH 079/345] V4L/DVB (13148): uvcvideo: Handle V4L2_CTRL_TYPE_BUTTON control type in VIDIOC_QUERYCTRL Return minimum, maximum and step set to 0 without querying the hardware. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 1b89735e62fd..6f1487fc3d7c 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -826,6 +826,13 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, ret = 0; goto out; + case V4L2_CTRL_TYPE_BUTTON: + v4l2_ctrl->minimum = 0; + v4l2_ctrl->maximum = 0; + v4l2_ctrl->step = 0; + ret = 0; + goto out; + default: break; } From 663a419203cc9690d16502be509ffb8acc40552a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 6 Aug 2009 11:41:17 -0300 Subject: [PATCH 080/345] V4L/DVB (13149): uvcvideo: Add a new UVC_TRACE_VIDEO trace level Use the trace level for messages related to video URB buffers allocation and alternate setting selection. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 18 ++++++++++++++---- drivers/media/video/uvc/uvcvideo.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index a6e41d12b221..bb9fed669363 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -781,10 +781,15 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, if (i == UVC_URBS) { stream->urb_size = psize * npackets; + uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers " + "of %ux%u bytes each.\n", UVC_URBS, npackets, + psize); return npackets; } } + uvc_trace(UVC_TRACE_VIDEO, "Failed to allocate URB buffers (%u bytes " + "per packet).\n", psize); return 0; } @@ -935,10 +940,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) bandwidth = stream->ctrl.dwMaxPayloadTransferSize; if (bandwidth == 0) { - uvc_printk(KERN_WARNING, "device %s requested null " - "bandwidth, defaulting to lowest.\n", - stream->dev->name); + uvc_trace(UVC_TRACE_VIDEO, "Device requested null " + "bandwidth, defaulting to lowest.\n"); bandwidth = 1; + } else { + uvc_trace(UVC_TRACE_VIDEO, "Device requested %u " + "B/frame bandwidth.\n", bandwidth); } for (i = 0; i < intf->num_altsetting; ++i) { @@ -955,8 +962,11 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) break; } - if (i >= intf->num_altsetting) + if (i >= intf->num_altsetting) { + uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " + "for requested bandwidth.\n"); return -EIO; + } ret = usb_set_interface(stream->dev->udev, intfnum, i); if (ret < 0) diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index e7958aa454ce..f5c40c0f0b49 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -533,6 +533,7 @@ struct uvc_driver { #define UVC_TRACE_FRAME (1 << 7) #define UVC_TRACE_SUSPEND (1 << 8) #define UVC_TRACE_STATUS (1 << 9) +#define UVC_TRACE_VIDEO (1 << 10) #define UVC_WARN_MINMAX 0 #define UVC_WARN_PROBE_DEF 1 From 4e7387858f35eace117493e4ad69d3b7ccc84a41 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 2 Sep 2009 03:09:02 -0300 Subject: [PATCH 081/345] V4L/DVB (13150): uvcvideo: Don't acquire privileges in VIDIOC_TRY_FMT The VIDIOC_TRY_FMT ioctl doesn't interfere with video streaming and thus should succeed on an unprivileged file handle. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_v4l2.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index a2bdd806efab..7c555712411a 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -371,7 +371,6 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, * - VIDIOC_S_INPUT * - VIDIOC_S_PARM * - VIDIOC_S_FMT - * - VIDIOC_TRY_FMT * - VIDIOC_REQBUFS */ static int uvc_acquire_privileges(struct uvc_fh *handle) @@ -731,9 +730,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct uvc_streaming_control probe; - if ((ret = uvc_acquire_privileges(handle)) < 0) - return ret; - return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL); } From 1a969d9863a0c8890eb799ec710dda9701f10483 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 2 Sep 2009 03:12:26 -0300 Subject: [PATCH 082/345] V4L/DVB (13151): uvcvideo: Dismiss privileges when freeing video buffers Dismiss privileges on the file handle when calling VIDIOC_REQBUFS with a buffer count of 0. This allows applications to release the streaming permissions on the file handle without closing it. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_v4l2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 7c555712411a..94c1d6696af5 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -364,7 +364,8 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, * unprivileged state. Only a single instance can be in a privileged state at * a given time. Trying to perform an operation that requires privileges will * automatically acquire the required privileges if possible, or return -EBUSY - * otherwise. Privileges are dismissed when closing the instance. + * otherwise. Privileges are dismissed when closing the instance or when + * freeing the video buffers using VIDIOC_REQBUFS. * * Operations that require privileges are: * @@ -884,6 +885,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (ret < 0) return ret; + if (ret == 0) + uvc_dismiss_privileges(handle); + rb->count = ret; ret = 0; break; From 716fdee110ceb816cca8c46c0890d08c5a1addb9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 29 Sep 2009 21:07:19 -0300 Subject: [PATCH 083/345] V4L/DVB (13152): uvcvideo: Rely on videodev to reference-count the device The uvcvideo driver has a driver-wide lock and a reference count to protect against a disconnect/open race. Now that videodev handles the race itself, reference-counting in the driver can be removed. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 155 ++++++++++++++------------- drivers/media/video/uvc/uvc_v4l2.c | 32 ++---- drivers/media/video/uvc/uvcvideo.h | 5 +- 3 files changed, 88 insertions(+), 104 deletions(-) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 8756be569154..ebddf006a4f4 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1530,6 +1530,66 @@ static int uvc_scan_device(struct uvc_device *dev) * Video device registration and unregistration */ +/* + * Delete the UVC device. + * + * Called by the kernel when the last reference to the uvc_device structure + * is released. + * + * As this function is called after or during disconnect(), all URBs have + * already been canceled by the USB core. There is no need to kill the + * interrupt URB manually. + */ +static void uvc_delete(struct uvc_device *dev) +{ + struct list_head *p, *n; + + usb_put_intf(dev->intf); + usb_put_dev(dev->udev); + + uvc_status_cleanup(dev); + uvc_ctrl_cleanup_device(dev); + + list_for_each_safe(p, n, &dev->chains) { + struct uvc_video_chain *chain; + chain = list_entry(p, struct uvc_video_chain, list); + kfree(chain); + } + + list_for_each_safe(p, n, &dev->entities) { + struct uvc_entity *entity; + entity = list_entry(p, struct uvc_entity, list); + kfree(entity); + } + + list_for_each_safe(p, n, &dev->streams) { + struct uvc_streaming *streaming; + streaming = list_entry(p, struct uvc_streaming, list); + usb_driver_release_interface(&uvc_driver.driver, + streaming->intf); + usb_put_intf(streaming->intf); + kfree(streaming->format); + kfree(streaming->header.bmaControls); + kfree(streaming); + } + + kfree(dev); +} + +static void uvc_release(struct video_device *vdev) +{ + struct uvc_streaming *stream = video_get_drvdata(vdev); + struct uvc_device *dev = stream->dev; + + video_device_release(vdev); + + /* Decrement the registered streams count and delete the device when it + * reaches zero. + */ + if (atomic_dec_and_test(&dev->nstreams)) + uvc_delete(dev); +} + /* * Unregister the video devices. */ @@ -1537,16 +1597,26 @@ static void uvc_unregister_video(struct uvc_device *dev) { struct uvc_streaming *stream; + /* Unregistering all video devices might result in uvc_delete() being + * called from inside the loop if there's no open file handle. To avoid + * that, increment the stream count before iterating over the streams + * and decrement it when done. + */ + atomic_inc(&dev->nstreams); + list_for_each_entry(stream, &dev->streams, list) { if (stream->vdev == NULL) continue; - if (stream->vdev->minor == -1) - video_device_release(stream->vdev); - else - video_unregister_device(stream->vdev); + video_unregister_device(stream->vdev); stream->vdev = NULL; } + + /* Decrement the stream count and call uvc_delete explicitly if there + * are no stream left. + */ + if (atomic_dec_and_test(&dev->nstreams)) + uvc_delete(dev); } static int uvc_register_video(struct uvc_device *dev, @@ -1580,7 +1650,7 @@ static int uvc_register_video(struct uvc_device *dev, vdev->parent = &dev->intf->dev; vdev->minor = -1; vdev->fops = &uvc_fops; - vdev->release = video_device_release; + vdev->release = uvc_release; strlcpy(vdev->name, dev->name, sizeof vdev->name); /* Set the driver data before calling video_register_device, otherwise @@ -1598,6 +1668,7 @@ static int uvc_register_video(struct uvc_device *dev, return ret; } + atomic_inc(&dev->nstreams); return 0; } @@ -1653,61 +1724,6 @@ static int uvc_register_chains(struct uvc_device *dev) * USB probe, disconnect, suspend and resume */ -/* - * Delete the UVC device. - * - * Called by the kernel when the last reference to the uvc_device structure - * is released. - * - * Unregistering the video devices is done here because every opened instance - * must be closed before the device can be unregistered. An alternative would - * have been to use another reference count for uvc_v4l2_open/uvc_release, and - * unregister the video devices on disconnect when that reference count drops - * to zero. - * - * As this function is called after or during disconnect(), all URBs have - * already been canceled by the USB core. There is no need to kill the - * interrupt URB manually. - */ -void uvc_delete(struct kref *kref) -{ - struct uvc_device *dev = container_of(kref, struct uvc_device, kref); - struct list_head *p, *n; - - /* Unregister the video devices. */ - uvc_unregister_video(dev); - usb_put_intf(dev->intf); - usb_put_dev(dev->udev); - - uvc_status_cleanup(dev); - uvc_ctrl_cleanup_device(dev); - - list_for_each_safe(p, n, &dev->chains) { - struct uvc_video_chain *chain; - chain = list_entry(p, struct uvc_video_chain, list); - kfree(chain); - } - - list_for_each_safe(p, n, &dev->entities) { - struct uvc_entity *entity; - entity = list_entry(p, struct uvc_entity, list); - kfree(entity); - } - - list_for_each_safe(p, n, &dev->streams) { - struct uvc_streaming *streaming; - streaming = list_entry(p, struct uvc_streaming, list); - usb_driver_release_interface(&uvc_driver.driver, - streaming->intf); - usb_put_intf(streaming->intf); - kfree(streaming->format); - kfree(streaming->header.bmaControls); - kfree(streaming); - } - - kfree(dev); -} - static int uvc_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1730,7 +1746,7 @@ static int uvc_probe(struct usb_interface *intf, INIT_LIST_HEAD(&dev->entities); INIT_LIST_HEAD(&dev->chains); INIT_LIST_HEAD(&dev->streams); - kref_init(&dev->kref); + atomic_set(&dev->nstreams, 0); atomic_set(&dev->users, 0); dev->udev = usb_get_dev(udev); @@ -1792,7 +1808,7 @@ static int uvc_probe(struct usb_interface *intf, return 0; error: - kref_put(&dev->kref, uvc_delete); + uvc_unregister_video(dev); return -ENODEV; } @@ -1809,21 +1825,9 @@ static void uvc_disconnect(struct usb_interface *intf) UVC_SC_VIDEOSTREAMING) return; - /* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide - * lock is needed to prevent uvc_disconnect from releasing its - * reference to the uvc_device instance after uvc_v4l2_open() received - * the pointer to the device (video_devdata) but before it got the - * chance to increase the reference count (kref_get). - * - * Note that the reference can't be released with the lock held, - * otherwise a AB-BA deadlock can occur with videodev_lock that - * videodev acquires in videodev_open() and video_unregister_device(). - */ - mutex_lock(&uvc_driver.open_mutex); dev->state |= UVC_DEV_DISCONNECTED; - mutex_unlock(&uvc_driver.open_mutex); - kref_put(&dev->kref, uvc_delete); + uvc_unregister_video(dev); } static int uvc_suspend(struct usb_interface *intf, pm_message_t message) @@ -2159,7 +2163,6 @@ static int __init uvc_init(void) INIT_LIST_HEAD(&uvc_driver.devices); INIT_LIST_HEAD(&uvc_driver.controls); - mutex_init(&uvc_driver.open_mutex); mutex_init(&uvc_driver.ctrl_mutex); uvc_ctrl_init(); diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 94c1d6696af5..b3478d0eaf41 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -376,25 +376,18 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, */ static int uvc_acquire_privileges(struct uvc_fh *handle) { - int ret = 0; - /* Always succeed if the handle is already privileged. */ if (handle->state == UVC_HANDLE_ACTIVE) return 0; /* Check if the device already has a privileged handle. */ - mutex_lock(&uvc_driver.open_mutex); if (atomic_inc_return(&handle->stream->active) != 1) { atomic_dec(&handle->stream->active); - ret = -EBUSY; - goto done; + return -EBUSY; } handle->state = UVC_HANDLE_ACTIVE; - -done: - mutex_unlock(&uvc_driver.open_mutex); - return ret; + return 0; } static void uvc_dismiss_privileges(struct uvc_fh *handle) @@ -421,24 +414,20 @@ static int uvc_v4l2_open(struct file *file) int ret = 0; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); - mutex_lock(&uvc_driver.open_mutex); stream = video_drvdata(file); - if (stream->dev->state & UVC_DEV_DISCONNECTED) { - ret = -ENODEV; - goto done; - } + if (stream->dev->state & UVC_DEV_DISCONNECTED) + return -ENODEV; ret = usb_autopm_get_interface(stream->dev->intf); if (ret < 0) - goto done; + return ret; /* Create the device handle. */ handle = kzalloc(sizeof *handle, GFP_KERNEL); if (handle == NULL) { usb_autopm_put_interface(stream->dev->intf); - ret = -ENOMEM; - goto done; + return -ENOMEM; } if (atomic_inc_return(&stream->dev->users) == 1) { @@ -447,7 +436,7 @@ static int uvc_v4l2_open(struct file *file) usb_autopm_put_interface(stream->dev->intf); atomic_dec(&stream->dev->users); kfree(handle); - goto done; + return ret; } } @@ -456,11 +445,7 @@ static int uvc_v4l2_open(struct file *file) handle->state = UVC_HANDLE_PASSIVE; file->private_data = handle; - kref_get(&stream->dev->kref); - -done: - mutex_unlock(&uvc_driver.open_mutex); - return ret; + return 0; } static int uvc_v4l2_release(struct file *file) @@ -490,7 +475,6 @@ static int uvc_v4l2_release(struct file *file) uvc_status_stop(stream->dev); usb_autopm_put_interface(stream->dev->intf); - kref_put(&stream->dev->kref, uvc_delete); return 0; } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index f5c40c0f0b49..dae5f57523db 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -475,7 +475,6 @@ struct uvc_device { char name[32]; enum uvc_device_state state; - struct kref kref; struct list_head list; atomic_t users; @@ -488,6 +487,7 @@ struct uvc_device { /* Video Streaming interfaces */ struct list_head streams; + atomic_t nstreams; /* Status Interrupt Endpoint */ struct usb_host_endpoint *int_ep; @@ -511,8 +511,6 @@ struct uvc_fh { struct uvc_driver { struct usb_driver driver; - struct mutex open_mutex; /* protects from open/disconnect race */ - struct list_head devices; /* struct uvc_device list */ struct list_head controls; /* struct uvc_control_info list */ struct mutex ctrl_mutex; /* protects controls and devices @@ -572,7 +570,6 @@ extern unsigned int uvc_trace_param; /* Core driver */ 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, From fd1b6bbb4a54a232ae6a1e5e4a6fbe3507ed5142 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 27 Sep 2009 05:30:34 -0300 Subject: [PATCH 084/345] V4L/DVB (13153): uvcvideo: Fix uvc_alloc_urb_buffers() This patch sets stream->urb_size as psize*npackets before calling uvc_alloc_urb_buffers, which may fix a possible failure of usb_buffer_free in case usb_buffer_alloc returns NULL. The patch is based on the ideas below: 1,If usb_buffer_alloc can't allocate a buffer sucessfully, uvc_free_urb_buffers will be called to free the allocated buffers, and stream->urb_size is required to be passed to usb_buffer_free; 2,uvc_free_urb_buffers can reset stream->urb_size. This patch is against linux-v2.6.31-next-20090926. Signed-off-by: Ming Lei Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index bb9fed669363..3369200a91d7 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -770,8 +770,9 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, /* Retry allocations until one succeed. */ for (; npackets > 1; npackets /= 2) { for (i = 0; i < UVC_URBS; ++i) { + stream->urb_size = psize * npackets; stream->urb_buffer[i] = usb_buffer_alloc( - stream->dev->udev, psize * npackets, + stream->dev->udev, stream->urb_size, gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]); if (!stream->urb_buffer[i]) { uvc_free_urb_buffers(stream); @@ -780,7 +781,6 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, } if (i == UVC_URBS) { - stream->urb_size = psize * npackets; uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers " "of %ux%u bytes each.\n", UVC_URBS, npackets, psize); From c4ed8c66d79d707d89fe732ff5b97739edf1ba62 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 8 Oct 2009 19:38:10 -0300 Subject: [PATCH 085/345] V4L/DVB (13154): uvcvideo: Handle garbage at the end of streaming interface descriptors At least one 5986:0241 webcam model includes vendor-specific descriptors at the end of its streaming interface descriptors. Print an information UVC_TRACE_DESCR message and try to continue parsing the descriptors rather than bailing out with an error. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index ebddf006a4f4..307d3a6b7395 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -426,7 +426,8 @@ static int uvc_parse_format(struct uvc_device *dev, /* Parse the frame descriptors. Only uncompressed, MJPEG and frame * based formats have frame descriptors. */ - while (buflen > 2 && buffer[2] == ftype) { + while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && + buffer[2] == ftype) { frame = &format->frame[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) n = buflen > 25 ? buffer[25] : 0; @@ -503,12 +504,14 @@ static int uvc_parse_format(struct uvc_device *dev, buffer += buffer[0]; } - if (buflen > 2 && buffer[2] == UVC_VS_STILL_IMAGE_FRAME) { + if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && + buffer[2] == UVC_VS_STILL_IMAGE_FRAME) { buflen -= buffer[0]; buffer += buffer[0]; } - if (buflen > 2 && buffer[2] == UVC_VS_COLORFORMAT) { + if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && + buffer[2] == UVC_VS_COLORFORMAT) { if (buflen < 6) { uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d COLORFORMAT error\n", @@ -749,6 +752,11 @@ static int uvc_parse_streaming(struct uvc_device *dev, buffer += buffer[0]; } + if (buflen) + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " + "%d has %u bytes of trailing descriptor garbage.\n", + dev->udev->devnum, alts->desc.bInterfaceNumber, buflen); + /* Parse the alternate settings to find the maximum bandwidth. */ for (i = 0; i < intf->num_altsetting; ++i) { struct usb_host_endpoint *ep; From b232a012adfea9f535702e8296ea6b76e691f436 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 9 Oct 2009 20:55:23 -0300 Subject: [PATCH 086/345] V4L/DVB (13155): uvcvideo: Add a module parameter to set the streaming control timeout The default streaming control timeout was found by Ondrej Zary to be too low for some Logitech webcams. With kernel 2.6.22 and newer they would timeout during initialization unles the audio function was initialized before the video function. Add a module parameter to set the streaming control timeout and increase the default value from 1000ms to 3000ms to fix the above problem. Thanks to Ondrej Zary for investigating the issue and providing an initial patch. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 3 +++ drivers/media/video/uvc/uvc_video.c | 4 ++-- drivers/media/video/uvc/uvcvideo.h | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 307d3a6b7395..ab4a60102d08 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -46,6 +46,7 @@ unsigned int uvc_no_drop_param; static unsigned int uvc_quirks_param; unsigned int uvc_trace_param; +unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; /* ------------------------------------------------------------------------ * Video formats @@ -2195,6 +2196,8 @@ 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); MODULE_PARM_DESC(trace, "Trace level bitmask"); +module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 3369200a91d7..05139a4f14f6 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -135,7 +135,7 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, - size, UVC_CTRL_STREAMING_TIMEOUT); + size, uvc_timeout_param); if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) { /* Some cameras, mostly based on Bison Electronics chipsets, @@ -239,7 +239,7 @@ static int uvc_set_video_ctrl(struct uvc_streaming *stream, ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum, probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, - size, UVC_CTRL_STREAMING_TIMEOUT); + size, uvc_timeout_param); if (ret != size) { uvc_printk(KERN_ERR, "Failed to set UVC %s control : " "%d (exp. %u).\n", probe ? "probe" : "commit", diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index dae5f57523db..fb3342ae6d7c 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -148,7 +148,7 @@ struct uvc_xu_control { #define UVC_MAX_STATUS_SIZE 16 #define UVC_CTRL_CONTROL_TIMEOUT 300 -#define UVC_CTRL_STREAMING_TIMEOUT 1000 +#define UVC_CTRL_STREAMING_TIMEOUT 3000 /* Devices quirks */ #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 @@ -538,6 +538,7 @@ struct uvc_driver { extern unsigned int uvc_no_drop_param; extern unsigned int uvc_trace_param; +extern unsigned int uvc_timeout_param; #define uvc_trace(flag, msg...) \ do { \ From 06d3a396b26e48012ce0f2ee21b1fdff092d8d4a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 23 Oct 2009 20:09:42 -0300 Subject: [PATCH 087/345] V4L/DVB (13157): dvb_frontend: represent all DVBS2API commands via macro Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 159 ++++------------------ 1 file changed, 26 insertions(+), 133 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index e9ec8e911056..07461222a7f5 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -895,104 +895,27 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) } static struct dtv_cmds_h dtv_cmds[] = { - [DTV_TUNE] = { - .name = "DTV_TUNE", - .cmd = DTV_TUNE, - .set = 1, - }, - [DTV_CLEAR] = { - .name = "DTV_CLEAR", - .cmd = DTV_CLEAR, - .set = 1, - }, + _DTV_CMD(DTV_TUNE, 1, 0), + _DTV_CMD(DTV_CLEAR, 1, 0), /* Set */ - [DTV_FREQUENCY] = { - .name = "DTV_FREQUENCY", - .cmd = DTV_FREQUENCY, - .set = 1, - }, - [DTV_BANDWIDTH_HZ] = { - .name = "DTV_BANDWIDTH_HZ", - .cmd = DTV_BANDWIDTH_HZ, - .set = 1, - }, - [DTV_MODULATION] = { - .name = "DTV_MODULATION", - .cmd = DTV_MODULATION, - .set = 1, - }, - [DTV_INVERSION] = { - .name = "DTV_INVERSION", - .cmd = DTV_INVERSION, - .set = 1, - }, - [DTV_DISEQC_MASTER] = { - .name = "DTV_DISEQC_MASTER", - .cmd = DTV_DISEQC_MASTER, - .set = 1, - .buffer = 1, - }, - [DTV_SYMBOL_RATE] = { - .name = "DTV_SYMBOL_RATE", - .cmd = DTV_SYMBOL_RATE, - .set = 1, - }, - [DTV_INNER_FEC] = { - .name = "DTV_INNER_FEC", - .cmd = DTV_INNER_FEC, - .set = 1, - }, - [DTV_VOLTAGE] = { - .name = "DTV_VOLTAGE", - .cmd = DTV_VOLTAGE, - .set = 1, - }, - [DTV_TONE] = { - .name = "DTV_TONE", - .cmd = DTV_TONE, - .set = 1, - }, - [DTV_PILOT] = { - .name = "DTV_PILOT", - .cmd = DTV_PILOT, - .set = 1, - }, - [DTV_ROLLOFF] = { - .name = "DTV_ROLLOFF", - .cmd = DTV_ROLLOFF, - .set = 1, - }, - [DTV_DELIVERY_SYSTEM] = { - .name = "DTV_DELIVERY_SYSTEM", - .cmd = DTV_DELIVERY_SYSTEM, - .set = 1, - }, - [DTV_HIERARCHY] = { - .name = "DTV_HIERARCHY", - .cmd = DTV_HIERARCHY, - .set = 1, - }, - [DTV_CODE_RATE_HP] = { - .name = "DTV_CODE_RATE_HP", - .cmd = DTV_CODE_RATE_HP, - .set = 1, - }, - [DTV_CODE_RATE_LP] = { - .name = "DTV_CODE_RATE_LP", - .cmd = DTV_CODE_RATE_LP, - .set = 1, - }, - [DTV_GUARD_INTERVAL] = { - .name = "DTV_GUARD_INTERVAL", - .cmd = DTV_GUARD_INTERVAL, - .set = 1, - }, - [DTV_TRANSMISSION_MODE] = { - .name = "DTV_TRANSMISSION_MODE", - .cmd = DTV_TRANSMISSION_MODE, - .set = 1, - }, + _DTV_CMD(DTV_FREQUENCY, 1, 0), + _DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0), + _DTV_CMD(DTV_MODULATION, 1, 0), + _DTV_CMD(DTV_INVERSION, 1, 0), + _DTV_CMD(DTV_DISEQC_MASTER, 1, 1), + _DTV_CMD(DTV_SYMBOL_RATE, 1, 0), + _DTV_CMD(DTV_INNER_FEC, 1, 0), + _DTV_CMD(DTV_VOLTAGE, 1, 0), + _DTV_CMD(DTV_TONE, 1, 0), + _DTV_CMD(DTV_PILOT, 1, 0), + _DTV_CMD(DTV_ROLLOFF, 1, 0), + _DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0), + _DTV_CMD(DTV_HIERARCHY, 1, 0), + _DTV_CMD(DTV_CODE_RATE_HP, 1, 0), + _DTV_CMD(DTV_CODE_RATE_LP, 1, 0), + _DTV_CMD(DTV_GUARD_INTERVAL, 1, 0), + _DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0), _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0), _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0), @@ -1035,43 +958,13 @@ static struct dtv_cmds_h dtv_cmds[] = { _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), /* Get */ - [DTV_DISEQC_SLAVE_REPLY] = { - .name = "DTV_DISEQC_SLAVE_REPLY", - .cmd = DTV_DISEQC_SLAVE_REPLY, - .set = 0, - .buffer = 1, - }, - - [DTV_API_VERSION] = { - .name = "DTV_API_VERSION", - .cmd = DTV_API_VERSION, - .set = 0, - }, - [DTV_CODE_RATE_HP] = { - .name = "DTV_CODE_RATE_HP", - .cmd = DTV_CODE_RATE_HP, - .set = 0, - }, - [DTV_CODE_RATE_LP] = { - .name = "DTV_CODE_RATE_LP", - .cmd = DTV_CODE_RATE_LP, - .set = 0, - }, - [DTV_GUARD_INTERVAL] = { - .name = "DTV_GUARD_INTERVAL", - .cmd = DTV_GUARD_INTERVAL, - .set = 0, - }, - [DTV_TRANSMISSION_MODE] = { - .name = "DTV_TRANSMISSION_MODE", - .cmd = DTV_TRANSMISSION_MODE, - .set = 0, - }, - [DTV_HIERARCHY] = { - .name = "DTV_HIERARCHY", - .cmd = DTV_HIERARCHY, - .set = 0, - }, + _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), + _DTV_CMD(DTV_API_VERSION, 0, 0), + _DTV_CMD(DTV_CODE_RATE_HP, 0, 0), + _DTV_CMD(DTV_CODE_RATE_LP, 0, 0), + _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), + _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), + _DTV_CMD(DTV_HIERARCHY, 0, 0), }; static void dtv_property_dump(struct dtv_property *tvp) From 6dea3830d8a596345c9d498e346e2bde1546d0ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 24 Oct 2009 19:10:46 -0300 Subject: [PATCH 088/345] V4L/DVB (13159): DocBook/frontend: use cross references for ioctls Rename all sessions id's for frontend ioctls to match ioctl name and add the proper cross-link references for those ioctls. This also helps to identify what ioctls are missing specs. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/dvb/frontend.xml | 106 +++++++++++++------------ 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/Documentation/DocBook/dvb/frontend.xml b/Documentation/DocBook/dvb/frontend.xml index 9d89a7b94fd5..c8760ff94af5 100644 --- a/Documentation/DocBook/dvb/frontend.xml +++ b/Documentation/DocBook/dvb/frontend.xml @@ -73,7 +73,8 @@ a specific frontend type.
frontend information -Information about the frontend ca be queried with FE_GET_INFO. +Information about the frontend ca be queried with + FE_GET_INFO. struct dvb_frontend_info { @@ -338,7 +339,7 @@ modulation mode which can be one of the following: This system call opens a named frontend device (/dev/dvb/adapter0/frontend0) for subsequent use. Usually the first thing to do after a successful open is to - find out the frontend type with FE_GET_INFO. + find out the frontend type with FE_GET_INFO. The device can be opened in read-only mode, which only allows monitoring of device status and statistics, or read/write mode, which allows any kind of use (e.g. performing tuning operations.) @@ -478,7 +479,7 @@ modulation mode which can be one of the following:
-
+
FE_READ_STATUS DESCRIPTION @@ -492,7 +493,7 @@ modulation mode which can be one of the following: -int ioctl(int fd, int request = FE_READ_STATUS, +int ioctl(int fd, int request = FE_READ_STATUS, fe_status_t ⋆status); @@ -511,7 +512,7 @@ modulation mode which can be one of the following: int request -Equals FE_READ_STATUS for this command. +Equals FE_READ_STATUS for this command. @@ -542,7 +543,7 @@ modulation mode which can be one of the following:
-
+
FE_READ_BER DESCRIPTION @@ -557,7 +558,7 @@ modulation mode which can be one of the following: -int ioctl(int fd, int request = FE_READ_BER, +int ioctl(int fd, int request = FE_READ_BER, uint32_t ⋆ber); @@ -575,7 +576,7 @@ modulation mode which can be one of the following: int request -Equals FE_READ_BER for this command. +Equals FE_READ_BER for this command. @@ -619,7 +620,7 @@ modulation mode which can be one of the following:
-
+
FE_READ_SNR DESCRIPTION @@ -634,7 +635,7 @@ modulation mode which can be one of the following: -int ioctl(int fd, int request = FE_READ_SNR, int16_t +int ioctl(int fd, int request = FE_READ_SNR, int16_t ⋆snr); @@ -652,7 +653,7 @@ modulation mode which can be one of the following: int request -Equals FE_READ_SNR for this command. +Equals FE_READ_SNR for this command. @@ -697,7 +698,7 @@ modulation mode which can be one of the following:
-
+
FE_READ_SIGNAL_STRENGTH DESCRIPTION @@ -712,7 +713,7 @@ modulation mode which can be one of the following: int ioctl( int fd, int request = - FE_READ_SIGNAL_STRENGTH, int16_t ⋆strength); + FE_READ_SIGNAL_STRENGTH, int16_t ⋆strength); @@ -730,7 +731,7 @@ modulation mode which can be one of the following: int request -Equals FE_READ_SIGNAL_STRENGTH for this +Equals FE_READ_SIGNAL_STRENGTH for this command.
-
+
FE_READ_UNCORRECTED_BLOCKS DESCRIPTION @@ -797,7 +798,7 @@ modulation mode which can be one of the following: int ioctl( int fd, int request = - FE_READ_UNCORRECTED_BLOCKS, uint32_t ⋆ublocks); + FE_READ_UNCORRECTED_BLOCKS, uint32_t ⋆ublocks); PARAMETERS @@ -814,7 +815,7 @@ modulation mode which can be one of the following: int request -Equals FE_READ_UNCORRECTED_BLOCKS for this +Equals FE_READ_UNCORRECTED_BLOCKS for this command.
-
+
FE_SET_FRONTEND DESCRIPTION @@ -861,8 +862,8 @@ modulation mode which can be one of the following: This ioctl call starts a tuning operation using specified parameters. The result of this call will be successful if the parameters were valid and the tuning could be initiated. The result of the tuning operation in itself, however, will arrive - asynchronously as an event (see documentation for FE_GET_EVENT and - FrontendEvent.) If a new FE_SET_FRONTEND operation is initiated before + asynchronously as an event (see documentation for FE_GET_EVENT and + FrontendEvent.) If a new FE_SET_FRONTEND operation is initiated before the previous one was completed, the previous operation will be aborted in favor of the new one. This command requires read/write access to the device. @@ -872,7 +873,7 @@ modulation mode which can be one of the following: -int ioctl(int fd, int request = FE_SET_FRONTEND, +int ioctl(int fd, int request = FE_SET_FRONTEND, struct dvb_frontend_parameters ⋆p); @@ -890,7 +891,7 @@ modulation mode which can be one of the following: int request -Equals FE_SET_FRONTEND for this command. +Equals FE_SET_FRONTEND for this command. @@ -928,7 +929,7 @@ modulation mode which can be one of the following:
-
+
FE_GET_FRONTEND DESCRIPTION @@ -943,7 +944,7 @@ modulation mode which can be one of the following: -int ioctl(int fd, int request = FE_GET_FRONTEND, +int ioctl(int fd, int request = FE_GET_FRONTEND, struct dvb_frontend_parameters ⋆p); @@ -962,7 +963,7 @@ modulation mode which can be one of the following: int request -Equals FE_SET_FRONTEND for this command. +Equals FE_SET_FRONTEND for this command. @@ -1003,7 +1004,7 @@ modulation mode which can be one of the following:
-
+
FE_GET_EVENT DESCRIPTION @@ -1024,7 +1025,8 @@ modulation mode which can be one of the following: rather small (room for 8 events), the queue must be serviced regularly to avoid overflow. If an overflow happens, the oldest event is discarded from the queue, and an error (EOVERFLOW) occurs the next time the queue is read. After - reporting the error condition in this fashion, subsequent FE_GET_EVENT + reporting the error condition in this fashion, subsequent + FE_GET_EVENT calls will return events from the queue as usual. int request -Equals FE_GET_EVENT for this command. +Equals FE_GET_EVENT for this command. @@ -1115,7 +1117,7 @@ modulation mode which can be one of the following:
-
+
FE_GET_INFO DESCRIPTION @@ -1130,7 +1132,7 @@ modulation mode which can be one of the following: - int ioctl(int fd, int request = FE_GET_INFO, struct + int ioctl(int fd, int request = FE_GET_INFO, struct dvb_frontend_info ⋆info); @@ -1149,7 +1151,7 @@ modulation mode which can be one of the following: int request -Equals FE_GET_INFO for this command. +Equals FE_GET_INFO for this command. @@ -1181,7 +1183,7 @@ modulation mode which can be one of the following:
-
+
FE_DISEQC_RESET_OVERLOAD DESCRIPTION @@ -1199,7 +1201,7 @@ modulation mode which can be one of the following: int ioctl(int fd, int request = - FE_DISEQC_RESET_OVERLOAD); + FE_DISEQC_RESET_OVERLOAD); PARAMETERS @@ -1216,7 +1218,7 @@ modulation mode which can be one of the following: int request -Equals FE_DISEQC_RESET_OVERLOAD for this +Equals FE_DISEQC_RESET_OVERLOAD for this command. @@ -1247,7 +1249,7 @@ modulation mode which can be one of the following:
-
+
FE_DISEQC_SEND_MASTER_CMD DESCRIPTION @@ -1261,7 +1263,7 @@ modulation mode which can be one of the following: int ioctl(int fd, int request = - FE_DISEQC_SEND_MASTER_CMD, struct + FE_DISEQC_SEND_MASTER_CMD, struct dvb_diseqc_master_cmd ⋆cmd); @@ -1280,7 +1282,7 @@ modulation mode which can be one of the following: int request -Equals FE_DISEQC_SEND_MASTER_CMD for this +Equals FE_DISEQC_SEND_MASTER_CMD for this command.
-
+
FE_DISEQC_RECV_SLAVE_REPLY DESCRIPTION @@ -1350,7 +1352,7 @@ modulation mode which can be one of the following: int ioctl(int fd, int request = - FE_DISEQC_RECV_SLAVE_REPLY, struct + FE_DISEQC_RECV_SLAVE_REPLY, struct dvb_diseqc_slave_reply ⋆reply); @@ -1369,7 +1371,7 @@ modulation mode which can be one of the following: int request -Equals FE_DISEQC_RECV_SLAVE_REPLY for this +Equals FE_DISEQC_RECV_SLAVE_REPLY for this command.
-
+
FE_DISEQC_SEND_BURST DESCRIPTION @@ -1438,7 +1440,7 @@ modulation mode which can be one of the following: int ioctl(int fd, int request = - FE_DISEQC_SEND_BURST, fe_sec_mini_cmd_t burst); + FE_DISEQC_SEND_BURST, fe_sec_mini_cmd_t burst); @@ -1456,7 +1458,7 @@ modulation mode which can be one of the following: int request -Equals FE_DISEQC_SEND_BURST for this command. +Equals FE_DISEQC_SEND_BURST for this command. @@ -1509,7 +1511,7 @@ modulation mode which can be one of the following:
-
+
FE_SET_TONE DESCRIPTION @@ -1523,7 +1525,7 @@ modulation mode which can be one of the following: -int ioctl(int fd, int request = FE_SET_TONE, +int ioctl(int fd, int request = FE_SET_TONE, fe_sec_tone_mode_t tone); @@ -1541,7 +1543,7 @@ modulation mode which can be one of the following: int request -Equals FE_SET_TONE for this command. +Equals FE_SET_TONE for this command. @@ -1592,7 +1594,7 @@ modulation mode which can be one of the following:
-
+
FE_SET_VOLTAGE DESCRIPTION @@ -1606,7 +1608,7 @@ modulation mode which can be one of the following: -int ioctl(int fd, int request = FE_SET_VOLTAGE, +int ioctl(int fd, int request = FE_SET_VOLTAGE, fe_sec_voltage_t voltage); @@ -1625,7 +1627,7 @@ modulation mode which can be one of the following: int request -Equals FE_SET_VOLTAGE for this command. +Equals FE_SET_VOLTAGE for this command. @@ -1677,7 +1679,7 @@ modulation mode which can be one of the following:
-
+
FE_ENABLE_HIGH_LNB_VOLTAGE DESCRIPTION @@ -1694,7 +1696,7 @@ modulation mode which can be one of the following: int ioctl(int fd, int request = - FE_ENABLE_HIGH_LNB_VOLTAGE, int high); + FE_ENABLE_HIGH_LNB_VOLTAGE, int high); @@ -1712,7 +1714,7 @@ modulation mode which can be one of the following: int request -Equals FE_SET_VOLTAGE for this command. +Equals FE_SET_VOLTAGE for this command. From 9ca2bdaa765a88fa151172aa30a133b0745915ba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 24 Oct 2009 19:24:43 -0300 Subject: [PATCH 089/345] V4L/DVB (13160): DocBook/Makefile: add linux/dvb/frontend.h header file Adds linux/dvb/frontend.h header file at DocBook, and creates cross-references for the frontend ioctls. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/dvb/dvbapi.xml | 5 + Documentation/DocBook/dvb/frontend.h.xml | 415 ++++++++++++++++++++++ Documentation/DocBook/media-entities.tmpl | 1 + 3 files changed, 421 insertions(+) create mode 100644 Documentation/DocBook/dvb/frontend.h.xml diff --git a/Documentation/DocBook/dvb/dvbapi.xml b/Documentation/DocBook/dvb/dvbapi.xml index 4fc5b23470a3..a007f88c4024 100644 --- a/Documentation/DocBook/dvb/dvbapi.xml +++ b/Documentation/DocBook/dvb/dvbapi.xml @@ -85,3 +85,8 @@ Added ISDB-T test originally written by Patrick Boettcher &sub-examples; + + DVB Frontend Header File + &sub-frontend-h; + + diff --git a/Documentation/DocBook/dvb/frontend.h.xml b/Documentation/DocBook/dvb/frontend.h.xml new file mode 100644 index 000000000000..b99644f5340a --- /dev/null +++ b/Documentation/DocBook/dvb/frontend.h.xml @@ -0,0 +1,415 @@ + +/* + * frontend.h + * + * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de> + * Ralph Metzler <ralph@convergence.de> + * Holger Waechtler <holger@convergence.de> + * Andre Draszik <ad@convergence.de> + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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 _DVBFRONTEND_H_ +#define _DVBFRONTEND_H_ + +#include <linux/types.h> + +typedef enum fe_type { + FE_QPSK, + FE_QAM, + FE_OFDM, + FE_ATSC +} fe_type_t; + + +typedef enum fe_caps { + FE_IS_STUPID = 0, + FE_CAN_INVERSION_AUTO = 0x1, + FE_CAN_FEC_1_2 = 0x2, + FE_CAN_FEC_2_3 = 0x4, + FE_CAN_FEC_3_4 = 0x8, + FE_CAN_FEC_4_5 = 0x10, + FE_CAN_FEC_5_6 = 0x20, + FE_CAN_FEC_6_7 = 0x40, + FE_CAN_FEC_7_8 = 0x80, + FE_CAN_FEC_8_9 = 0x100, + FE_CAN_FEC_AUTO = 0x200, + FE_CAN_QPSK = 0x400, + FE_CAN_QAM_16 = 0x800, + FE_CAN_QAM_32 = 0x1000, + FE_CAN_QAM_64 = 0x2000, + FE_CAN_QAM_128 = 0x4000, + FE_CAN_QAM_256 = 0x8000, + FE_CAN_QAM_AUTO = 0x10000, + FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000, + FE_CAN_BANDWIDTH_AUTO = 0x40000, + FE_CAN_GUARD_INTERVAL_AUTO = 0x80000, + 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_caps_t; + + +struct dvb_frontend_info { + char name[128]; + fe_type_t type; + __u32 frequency_min; + __u32 frequency_max; + __u32 frequency_stepsize; + __u32 frequency_tolerance; + __u32 symbol_rate_min; + __u32 symbol_rate_max; + __u32 symbol_rate_tolerance; /* ppm */ + __u32 notifier_delay; /* DEPRECATED */ + fe_caps_t caps; +}; + + +/** + * Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for + * the meaning of this struct... + */ +struct dvb_diseqc_master_cmd { + __u8 msg [6]; /* { framing, address, command, data [3] } */ + __u8 msg_len; /* valid values are 3...6 */ +}; + + +struct dvb_diseqc_slave_reply { + __u8 msg [4]; /* { framing, data [3] } */ + __u8 msg_len; /* valid values are 0...4, 0 means no msg */ + int timeout; /* return from ioctl after timeout ms with */ +}; /* errorcode when no message was received */ + + +typedef enum fe_sec_voltage { + SEC_VOLTAGE_13, + SEC_VOLTAGE_18, + SEC_VOLTAGE_OFF +} fe_sec_voltage_t; + + +typedef enum fe_sec_tone_mode { + SEC_TONE_ON, + SEC_TONE_OFF +} fe_sec_tone_mode_t; + + +typedef enum fe_sec_mini_cmd { + SEC_MINI_A, + SEC_MINI_B +} fe_sec_mini_cmd_t; + + +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 */ + +typedef enum fe_spectral_inversion { + INVERSION_OFF, + INVERSION_ON, + INVERSION_AUTO +} fe_spectral_inversion_t; + + +typedef enum fe_code_rate { + FEC_NONE = 0, + FEC_1_2, + FEC_2_3, + FEC_3_4, + FEC_4_5, + FEC_5_6, + FEC_6_7, + FEC_7_8, + FEC_8_9, + FEC_AUTO, + FEC_3_5, + FEC_9_10, +} fe_code_rate_t; + + +typedef enum fe_modulation { + QPSK, + QAM_16, + QAM_32, + QAM_64, + QAM_128, + QAM_256, + QAM_AUTO, + VSB_8, + VSB_16, + PSK_8, + APSK_16, + APSK_32, + DQPSK, +} fe_modulation_t; + +typedef enum fe_transmit_mode { + TRANSMISSION_MODE_2K, + TRANSMISSION_MODE_8K, + TRANSMISSION_MODE_AUTO, + TRANSMISSION_MODE_4K +} fe_transmit_mode_t; + +typedef enum fe_bandwidth { + BANDWIDTH_8_MHZ, + BANDWIDTH_7_MHZ, + BANDWIDTH_6_MHZ, + BANDWIDTH_AUTO +} fe_bandwidth_t; + + +typedef enum fe_guard_interval { + GUARD_INTERVAL_1_32, + GUARD_INTERVAL_1_16, + GUARD_INTERVAL_1_8, + GUARD_INTERVAL_1_4, + GUARD_INTERVAL_AUTO +} fe_guard_interval_t; + + +typedef enum fe_hierarchy { + HIERARCHY_NONE, + HIERARCHY_1, + HIERARCHY_2, + HIERARCHY_4, + HIERARCHY_AUTO +} fe_hierarchy_t; + + +struct dvb_qpsk_parameters { + __u32 symbol_rate; /* symbol rate in Symbols per second */ + fe_code_rate_t fec_inner; /* forward error correction (see above) */ +}; + +struct dvb_qam_parameters { + __u32 symbol_rate; /* symbol rate in Symbols per second */ + fe_code_rate_t fec_inner; /* forward error correction (see above) */ + fe_modulation_t modulation; /* modulation type (see above) */ +}; + +struct dvb_vsb_parameters { + fe_modulation_t modulation; /* modulation type (see above) */ +}; + +struct dvb_ofdm_parameters { + fe_bandwidth_t bandwidth; + fe_code_rate_t code_rate_HP; /* high priority stream code rate */ + fe_code_rate_t code_rate_LP; /* low priority stream code rate */ + fe_modulation_t constellation; /* modulation type (see above) */ + fe_transmit_mode_t transmission_mode; + fe_guard_interval_t guard_interval; + fe_hierarchy_t hierarchy_information; +}; + + +struct dvb_frontend_parameters { + __u32 frequency; /* (absolute) frequency in Hz for QAM/OFDM/ATSC */ + /* intermediate frequency in kHz for QPSK */ + fe_spectral_inversion_t inversion; + union { + struct dvb_qpsk_parameters qpsk; + struct dvb_qam_parameters qam; + struct dvb_ofdm_parameters ofdm; + struct dvb_vsb_parameters vsb; + } u; +}; + + +struct dvb_frontend_event { + fe_status_t status; + struct dvb_frontend_parameters parameters; +}; + +/* S2API Commands */ +#define DTV_UNDEFINED 0 +#define DTV_TUNE 1 +#define DTV_CLEAR 2 +#define DTV_FREQUENCY 3 +#define DTV_MODULATION 4 +#define DTV_BANDWIDTH_HZ 5 +#define DTV_INVERSION 6 +#define DTV_DISEQC_MASTER 7 +#define DTV_SYMBOL_RATE 8 +#define DTV_INNER_FEC 9 +#define DTV_VOLTAGE 10 +#define DTV_TONE 11 +#define DTV_PILOT 12 +#define DTV_ROLLOFF 13 +#define DTV_DISEQC_SLAVE_REPLY 14 + +/* Basic enumeration set for querying unlimited capabilities */ +#define DTV_FE_CAPABILITY_COUNT 15 +#define DTV_FE_CAPABILITY 16 +#define DTV_DELIVERY_SYSTEM 17 + +/* ISDB-T and ISDB-Tsb */ +#define DTV_ISDBT_PARTIAL_RECEPTION 18 +#define DTV_ISDBT_SOUND_BROADCASTING 19 + +#define DTV_ISDBT_SB_SUBCHANNEL_ID 20 +#define DTV_ISDBT_SB_SEGMENT_IDX 21 +#define DTV_ISDBT_SB_SEGMENT_COUNT 22 + +#define DTV_ISDBT_LAYERA_FEC 23 +#define DTV_ISDBT_LAYERA_MODULATION 24 +#define DTV_ISDBT_LAYERA_SEGMENT_COUNT 25 +#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING 26 + +#define DTV_ISDBT_LAYERB_FEC 27 +#define DTV_ISDBT_LAYERB_MODULATION 28 +#define DTV_ISDBT_LAYERB_SEGMENT_COUNT 29 +#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING 30 + +#define DTV_ISDBT_LAYERC_FEC 31 +#define DTV_ISDBT_LAYERC_MODULATION 32 +#define DTV_ISDBT_LAYERC_SEGMENT_COUNT 33 +#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING 34 + +#define DTV_API_VERSION 35 + +#define DTV_CODE_RATE_HP 36 +#define DTV_CODE_RATE_LP 37 +#define DTV_GUARD_INTERVAL 38 +#define DTV_TRANSMISSION_MODE 39 +#define DTV_HIERARCHY 40 + +#define DTV_ISDBT_LAYER_ENABLED 41 + +#define DTV_ISDBS_TS_ID 42 + +#define DTV_MAX_COMMAND DTV_ISDBS_TS_ID + +typedef enum fe_pilot { + PILOT_ON, + PILOT_OFF, + PILOT_AUTO, +} fe_pilot_t; + +typedef enum fe_rolloff { + ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */ + ROLLOFF_20, + ROLLOFF_25, + ROLLOFF_AUTO, +} fe_rolloff_t; + +typedef enum fe_delivery_system { + SYS_UNDEFINED, + SYS_DVBC_ANNEX_AC, + SYS_DVBC_ANNEX_B, + SYS_DVBT, + SYS_DSS, + SYS_DVBS, + SYS_DVBS2, + SYS_DVBH, + SYS_ISDBT, + SYS_ISDBS, + SYS_ISDBC, + SYS_ATSC, + SYS_ATSCMH, + SYS_DMBTH, + SYS_CMMB, + SYS_DAB, +} fe_delivery_system_t; + +struct dtv_cmds_h { + char *name; /* A display name for debugging purposes */ + + __u32 cmd; /* A unique ID */ + + /* Flags */ + __u32 set:1; /* Either a set or get property */ + __u32 buffer:1; /* Does this property use the buffer? */ + __u32 reserved:30; /* Align */ +}; + +struct dtv_property { + __u32 cmd; + __u32 reserved[3]; + union { + __u32 data; + struct { + __u8 data[32]; + __u32 len; + __u32 reserved1[3]; + void *reserved2; + } buffer; + } u; + int result; +} __attribute__ ((packed)); + +/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */ +#define DTV_IOCTL_MAX_MSGS 64 + +struct dtv_properties { + __u32 num; + struct dtv_property *props; +}; + +#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties) +#define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties) + + +/** + * When set, this flag will disable any zigzagging or other "normal" tuning + * behaviour. Additionally, there will be no automatic monitoring of the lock + * status, and hence no frontend events will be generated. If a frontend device + * is closed, this flag will be automatically turned off when the device is + * reopened read-write. + */ +#define FE_TUNE_MODE_ONESHOT 0x01 + + +#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info) + +#define FE_DISEQC_RESET_OVERLOAD _IO('o', 62) +#define FE_DISEQC_SEND_MASTER_CMD _IOW('o', 63, struct dvb_diseqc_master_cmd) +#define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply) +#define FE_DISEQC_SEND_BURST _IO('o', 65) /* fe_sec_mini_cmd_t */ + +#define FE_SET_TONE _IO('o', 66) /* fe_sec_tone_mode_t */ +#define FE_SET_VOLTAGE _IO('o', 67) /* fe_sec_voltage_t */ +#define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68) /* int */ + +#define FE_READ_STATUS _IOR('o', 69, fe_status_t) +#define FE_READ_BER _IOR('o', 70, __u32) +#define FE_READ_SIGNAL_STRENGTH _IOR('o', 71, __u16) +#define FE_READ_SNR _IOR('o', 72, __u16) +#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32) + +#define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters) +#define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters) +#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81) /* unsigned int */ +#define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event) + +#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */ + +#endif /*_DVBFRONTEND_H_*/ + diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index 0eb43c1970bb..e3f3ad55d06e 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -288,6 +288,7 @@ + From f0964a770a2e180340fa6ab807c60ee970bb120b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 24 Oct 2009 19:55:24 -0300 Subject: [PATCH 090/345] V4L/DVB (13161): Add missing specs for FE_SET_FRONTEND_TUNE_MODE ioctl. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/dvb/dvbapi.xml | 8 ++++++ Documentation/DocBook/dvb/frontend.xml | 37 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/Documentation/DocBook/dvb/dvbapi.xml b/Documentation/DocBook/dvb/dvbapi.xml index a007f88c4024..fc1a237bba39 100644 --- a/Documentation/DocBook/dvb/dvbapi.xml +++ b/Documentation/DocBook/dvb/dvbapi.xml @@ -29,6 +29,14 @@ + + 2.0.2 + 2009-10-25 + mcc + + documents FE_SET_FRONTEND_TUNE_MODE ioctl + + 2.0.1 2009-09-16 diff --git a/Documentation/DocBook/dvb/frontend.xml b/Documentation/DocBook/dvb/frontend.xml index c8760ff94af5..21617c20fc43 100644 --- a/Documentation/DocBook/dvb/frontend.xml +++ b/Documentation/DocBook/dvb/frontend.xml @@ -1764,5 +1764,42 @@ modulation mode which can be one of the following:
+ +
+FE_SET_FRONTEND_TUNE_MODE +DESCRIPTION + + +Allow setting tuner mode flags to the frontend. + + + +SYNOPSIS + + +int ioctl(int fd, int request = +FE_SET_FRONTEND_TUNE_MODE, unsigned int flags); + + + +PARAMETERS + + + unsigned int flags + + + +FE_TUNE_MODE_ONESHOT When set, this flag will disable any zigzagging or other "normal" tuning behaviour. Additionally, there will be no automatic monitoring of the lock status, and hence no frontend events will be generated. If a frontend device is closed, this flag will be automatically turned off when the device is reopened read-write. + + + + +ERRORS + +EINVAL +Invalid argument. + + +
&sub-isdbt; From 603c0d80b4ff59487af33477e2ac7be113538161 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 24 Oct 2009 20:19:20 -0300 Subject: [PATCH 091/345] V4L/DVB (13162): Docbook/dvb: add missing specs for FE_DISHNETWORK_SEND_LEGACY_CMD ioctl While this ioctl should not be used, and is a good canditate for Documentation/feature-removal-schedule.txt, while it is on kernel, it needs to be documented. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/dvb/dvbapi.xml | 2 +- Documentation/DocBook/dvb/frontend.xml | 41 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Documentation/DocBook/dvb/dvbapi.xml b/Documentation/DocBook/dvb/dvbapi.xml index fc1a237bba39..63c528fee624 100644 --- a/Documentation/DocBook/dvb/dvbapi.xml +++ b/Documentation/DocBook/dvb/dvbapi.xml @@ -34,7 +34,7 @@ 2009-10-25 mcc - documents FE_SET_FRONTEND_TUNE_MODE ioctl + documents FE_SET_FRONTEND_TUNE_MODE and FE_DISHETWORK_SEND_LEGACY_CMD ioctls. diff --git a/Documentation/DocBook/dvb/frontend.xml b/Documentation/DocBook/dvb/frontend.xml index 21617c20fc43..958cbfa2553c 100644 --- a/Documentation/DocBook/dvb/frontend.xml +++ b/Documentation/DocBook/dvb/frontend.xml @@ -1799,7 +1799,48 @@ FE_TUNE_MODE_ONESHOT When set, this flag will disable any zigzagging or other "n EINVAL Invalid argument. +
+ +
+ FE_DISHNETWORK_SEND_LEGACY_CMD +DESCRIPTION + + +WARNING: This is a very obscure legacy command, used only at stv0299 driver. Should not be used on newer drivers. +It provides a non-standard method for selecting Diseqc voltage on the frontend, for Dish Network legacy switches. +As support for this ioctl were added in 2004, this means that such dishes were already legacy in 2004. + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISHNETWORK_SEND_LEGACY_CMD, unsigned long cmd); + + + +PARAMETERS + + + unsigned long cmd + + + +sends the specified raw cmd to the dish via DISEqC. + + + + +ERRORS + + + There are no errors in use for this call + +
+ +
&sub-isdbt; From b832104c7acac4d5469a031773847ec3b6fbd147 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 24 Oct 2009 21:01:22 -0300 Subject: [PATCH 092/345] V4L/DVB (13163): Docbook/dvb: Rename isdbt.xml to dvbproperty.xml We'll need to add the documentation for FE_[GET|SET]_PROPERTY that is not specific to isdb-t. Instead of doing it at frontend.xml, it is better to have a separate session for it. Also, isdbt.xml assumes that those ioctls were already introduced, and documents several exisiting properties. So, better to just rename it and add the documentation for it, together with each existing property there. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/dvb/{isdbt.xml => dvbproperty.xml} | 0 Documentation/DocBook/dvb/frontend.xml | 5 ++--- Documentation/DocBook/media-entities.tmpl | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) rename Documentation/DocBook/dvb/{isdbt.xml => dvbproperty.xml} (100%) diff --git a/Documentation/DocBook/dvb/isdbt.xml b/Documentation/DocBook/dvb/dvbproperty.xml similarity index 100% rename from Documentation/DocBook/dvb/isdbt.xml rename to Documentation/DocBook/dvb/dvbproperty.xml diff --git a/Documentation/DocBook/dvb/frontend.xml b/Documentation/DocBook/dvb/frontend.xml index 958cbfa2553c..300ba1f04177 100644 --- a/Documentation/DocBook/dvb/frontend.xml +++ b/Documentation/DocBook/dvb/frontend.xml @@ -1838,9 +1838,8 @@ sends the specified raw cmd to the dish via DISEqC. There are no errors in use for this call +
- -
-&sub-isdbt; +&sub-dvbproperty; diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index e3f3ad55d06e..bb5ab741220e 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -280,7 +280,7 @@ - + From 131db3a1acbd947a9c3257b95ee860a58ce0dffa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 24 Oct 2009 21:18:46 -0300 Subject: [PATCH 093/345] V4L/DVB (13164): DocBook/dvb: Starts documenting DVBS2API ioctls DVBS2API introduced two new ioctls that allows changing/getting details about newer video standards like DVB-S2 and ISDB-T. There are lots of thing to do in this chapter, but, for now, just add a session there, in order to allow make to not complain about undefined symbol. With this patch, all ioctls at the frontend.h API were somehow documented. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/dvb/dvbproperty.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/DocBook/dvb/dvbproperty.xml b/Documentation/DocBook/dvb/dvbproperty.xml index 92855222fccb..5f57c7ccd4ba 100644 --- a/Documentation/DocBook/dvb/dvbproperty.xml +++ b/Documentation/DocBook/dvb/dvbproperty.xml @@ -1,3 +1,6 @@ +
+FE_GET_PROPERTY/FE_SET_PROPERTY +
ISDB-T frontend This section describes shortly what are the possible parameters in the Linux @@ -312,3 +315,4 @@
+
From 7cbefad085c9112d0b1814db18423e5da072f5c8 Mon Sep 17 00:00:00 2001 From: Tuukka Toivonen Date: Thu, 23 Jul 2009 10:56:25 -0300 Subject: [PATCH 094/345] V4L/DVB (13165): videobuf do not force buffer size to be multiple of PAGE_SIZE When the image size (bytesperline*height) is not multiple of PAGE_SIZE, v4l2 rounded the required buffer size to be multiple of PAGE_SIZE. This prevented user space to store images directly into userptr buffers which were not multiple of PAGE_SIZE. This constraint is removed. The start address is still assumed to be required page-aligned, ie., when v4l2 allocates mmap buffers, the offset between different buffers is page-aligned. Signed-off-by: Tuukka Toivonen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 7 +++---- drivers/media/video/videobuf-dma-sg.c | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 8e93c6f25c83..a96b08d3df5a 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -360,7 +360,7 @@ int __videobuf_mmap_setup(struct videobuf_queue *q, q->bufs[i]->bsize = bsize; switch (memory) { case V4L2_MEMORY_MMAP: - q->bufs[i]->boff = bsize * i; + q->bufs[i]->boff = PAGE_ALIGN(bsize) * i; break; case V4L2_MEMORY_USERPTR: case V4L2_MEMORY_OVERLAY: @@ -430,9 +430,8 @@ int videobuf_reqbufs(struct videobuf_queue *q, count = VIDEO_MAX_FRAME; size = 0; q->ops->buf_setup(q, &count, &size); - size = PAGE_ALIGN(size); dprintk(1, "reqbufs: bufs=%d, size=0x%x [%d pages total]\n", - count, size, (count*size)>>PAGE_SHIFT); + count, size, (count*PAGE_ALIGN(size))>>PAGE_SHIFT); retval = __videobuf_mmap_setup(q, count, size, req->memory); if (retval < 0) { @@ -1099,7 +1098,7 @@ int videobuf_cgmbuf(struct videobuf_queue *q, mbuf->size = 0; for (i = 0; i < mbuf->frames; i++) { mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += q->bufs[i]->bsize; + mbuf->size += PAGE_ALIGN(q->bufs[i]->bsize); } return 0; diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 032ebae0134a..a583d394696e 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -588,7 +588,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, retval = -EBUSY; goto done; } - size += q->bufs[last]->bsize; + size += PAGE_ALIGN(q->bufs[last]->bsize); if (size == (vma->vm_end - vma->vm_start)) break; } @@ -610,7 +610,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, continue; q->bufs[i]->map = map; q->bufs[i]->baddr = vma->vm_start + size; - size += q->bufs[i]->bsize; + size += PAGE_ALIGN(q->bufs[i]->bsize); } map->count = 1; From e6a1a08f00689b0006bef2376ac30daa467901e9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 19 Sep 2009 16:48:17 -0300 Subject: [PATCH 095/345] V4L/DVB (13166): remove duplicate structure field initialization The definition of tvaudio_tuner_ops initializes the s_tuner field twice. It appears that the second case should initialize the g_tuner field. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ identifier I, s, fld; position p0,p; expression E; @@ struct I s =@p0 { ... .fld@p = E, ...}; @s@ identifier I, s, r.fld; position r.p0,p; expression E; @@ struct I s =@p0 { ... .fld@p = E, ...}; @script:python@ p0 << r.p0; fld << r.fld; ps << s.p; pr << r.p; @@ if int(ps[0].line)!=int(pr[0].line) or int(ps[0].column)!=int(pr[0].column): cocci.print_main(fld,p0) // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 0869bafc2b56..800fc1b111ef 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1919,7 +1919,7 @@ static const struct v4l2_subdev_tuner_ops tvaudio_tuner_ops = { .s_radio = tvaudio_s_radio, .s_frequency = tvaudio_s_frequency, .s_tuner = tvaudio_s_tuner, - .s_tuner = tvaudio_g_tuner, + .g_tuner = tvaudio_g_tuner, }; static const struct v4l2_subdev_audio_ops tvaudio_audio_ops = { From e3c6e1aaa5db7822524f5b1355960fd732910068 Mon Sep 17 00:00:00 2001 From: Danny Wood Date: Sun, 20 Sep 2009 12:14:21 -0300 Subject: [PATCH 096/345] V4L/DVB (13168): Add support for Asus Europa Hybrid DVB-T card (SAA7134 SubVendor ID: 0x1043 Device ID: 0x4847) Adds the device IDs and driver linking to allow the Asus Europa DVB-T card to operate with these drivers. The device has a SAA7134 chipset with a TD1316 Hybrid Tuner. All inputs work on the card including switching between DVB-T and Analogue TV, there is also no IR with this card. [mchehab@redhat.com: CodingStyle fixes] Signed-off-by: Danny Wood Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 31 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 1 + drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 34 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 2620d60341ee..94e255a76f79 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -172,3 +172,4 @@ 171 -> Beholder BeholdTV X7 [5ace:7595] 172 -> RoverMedia TV Link Pro FM [19d1:0138] 173 -> Zolid Hybrid TV Tuner PCI [1131:2004] +174 -> Asus Europa Hybrid OEM [1043:4847] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 7de7f1f0adda..bdb613851362 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5280,6 +5280,30 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, }, }, + [SAA7134_BOARD_ASUS_EUROPA_HYBRID] = { + .name = "Asus Europa Hybrid OEM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TD1316, + .radio_type = UNSET, + .tuner_addr = 0x61, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, + .mpeg = SAA7134_MPEG_DVB, + .inputs = { { + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 4, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + }, }; @@ -6418,6 +6442,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = PCI_VENDOR_ID_PHILIPS, .subdevice = 0x2004, .driver_data = SAA7134_BOARD_ZOLID_HYBRID_PCI, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1043, + .subdevice = 0x4847, + .driver_data = SAA7134_BOARD_ASUS_EUROPA_HYBRID, }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -7080,6 +7110,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) /* break intentionally omitted */ case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: + case SAA7134_BOARD_ASUS_EUROPA_HYBRID: { /* The Philips EUROPA based hybrid boards have the tuner diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 96d3668f4691..cd31284faf7c 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1131,6 +1131,7 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_PHILIPS_EUROPA: case SAA7134_BOARD_VIDEOMATE_DVBT_300: + case SAA7134_BOARD_ASUS_EUROPA_HYBRID: fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_europa_config, &dev->i2c_adap); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f8697d46ff5f..94e1a3be3317 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -297,6 +297,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_X7 171 #define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172 #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 +#define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 From d31242943a73aba0e5cfd0ea674b5e694b4a39e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 22 Sep 2009 06:05:42 -0300 Subject: [PATCH 097/345] V4L/DVB (13173): adv7180: Support for getting input status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support to the ADV7180 driver to check the input status. Since the status is held in the same register as the input standard a small restructuring of the code is done to reuse the code for reading the register Signed-off-by: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7180.c | 66 ++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c index 1b3cbd02a7fd..f3fce398020a 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/video/adv7180.c @@ -30,14 +30,31 @@ #define DRIVER_NAME "adv7180" -#define ADV7180_INPUT_CONTROL_REG 0x00 -#define ADV7180_INPUT_CONTROL_PAL_BG_NTSC_J_SECAM 0x00 +#define ADV7180_INPUT_CONTROL_REG 0x00 +#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 +#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10 +#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM 0x20 +#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_M_SECAM 0x30 +#define ADV7180_INPUT_CONTROL_NTSC_J 0x40 +#define ADV7180_INPUT_CONTROL_NTSC_M 0x50 +#define ADV7180_INPUT_CONTROL_PAL60 0x60 +#define ADV7180_INPUT_CONTROL_NTSC_443 0x70 +#define ADV7180_INPUT_CONTROL_PAL_BG 0x80 +#define ADV7180_INPUT_CONTROL_PAL_N 0x90 +#define ADV7180_INPUT_CONTROL_PAL_M 0xa0 +#define ADV7180_INPUT_CONTROL_PAL_M_PED 0xb0 +#define ADV7180_INPUT_CONTROL_PAL_COMB_N 0xc0 +#define ADV7180_INPUT_CONTROL_PAL_COMB_N_PED 0xd0 +#define ADV7180_INPUT_CONTROL_PAL_SECAM 0xe0 +#define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0 + #define ADV7180_AUTODETECT_ENABLE_REG 0x07 #define ADV7180_AUTODETECT_DEFAULT 0x7f -#define ADV7180_STATUS1_REG 0x10 -#define ADV7180_STATUS1_AUTOD_MASK 0x70 +#define ADV7180_STATUS1_REG 0x10 +#define ADV7180_STATUS1_IN_LOCK 0x01 +#define ADV7180_STATUS1_AUTOD_MASK 0x70 #define ADV7180_STATUS1_AUTOD_NTSM_M_J 0x00 #define ADV7180_STATUS1_AUTOD_NTSC_4_43 0x10 #define ADV7180_STATUS1_AUTOD_PAL_M 0x20 @@ -55,13 +72,11 @@ struct adv7180_state { struct v4l2_subdev sd; }; -static v4l2_std_id determine_norm(struct i2c_client *client) +static v4l2_std_id adv7180_std_to_v4l2(u8 status1) { - u8 status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG); - switch (status1 & ADV7180_STATUS1_AUTOD_MASK) { case ADV7180_STATUS1_AUTOD_NTSM_M_J: - return V4L2_STD_NTSC_M_JP; + return V4L2_STD_NTSC; case ADV7180_STATUS1_AUTOD_NTSC_4_43: return V4L2_STD_NTSC_443; case ADV7180_STATUS1_AUTOD_PAL_M: @@ -81,6 +96,30 @@ static v4l2_std_id determine_norm(struct i2c_client *client) } } +static u32 adv7180_status_to_v4l2(u8 status1) +{ + if (!(status1 & ADV7180_STATUS1_IN_LOCK)) + return V4L2_IN_ST_NO_SIGNAL; + + return 0; +} + +static int __adv7180_status(struct i2c_client *client, u32 *status, + v4l2_std_id *std) +{ + int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG); + + if (status1 < 0) + return status1; + + if (status) + *status = adv7180_status_to_v4l2(status1); + if (std) + *std = adv7180_std_to_v4l2(status1); + + return 0; +} + static inline struct adv7180_state *to_state(struct v4l2_subdev *sd) { return container_of(sd, struct adv7180_state, sd); @@ -88,10 +127,12 @@ static inline struct adv7180_state *to_state(struct v4l2_subdev *sd) static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { - struct i2c_client *client = v4l2_get_subdevdata(sd); + return __adv7180_status(v4l2_get_subdevdata(sd), NULL, std); +} - *std = determine_norm(client); - return 0; +static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + return __adv7180_status(v4l2_get_subdevdata(sd), status, NULL); } static int adv7180_g_chip_ident(struct v4l2_subdev *sd, @@ -104,6 +145,7 @@ static int adv7180_g_chip_ident(struct v4l2_subdev *sd, static const struct v4l2_subdev_video_ops adv7180_video_ops = { .querystd = adv7180_querystd, + .g_input_status = adv7180_g_input_status, }; static const struct v4l2_subdev_core_ops adv7180_core_ops = { @@ -143,7 +185,7 @@ static int adv7180_probe(struct i2c_client *client, /* Initialize adv7180 */ /* enable autodetection */ ret = i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, - ADV7180_INPUT_CONTROL_PAL_BG_NTSC_J_SECAM); + ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM); if (ret > 0) ret = i2c_smbus_write_byte_data(client, ADV7180_AUTODETECT_ENABLE_REG, From c277b60a08fe9e201656528b3f5cd35b554e24af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 22 Sep 2009 06:06:34 -0300 Subject: [PATCH 098/345] V4L/DVB (13174): adv7180: Support for setting input status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for settings the input standard of the ADV7180. When the input standard is set there is no use to ask the chip for standard, therefore it is cached in the driver. Signed-off-by: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7180.c | 72 ++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c index f3fce398020a..8b199a86a3a9 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/video/adv7180.c @@ -69,7 +69,9 @@ struct adv7180_state { - struct v4l2_subdev sd; + struct v4l2_subdev sd; + v4l2_std_id curr_norm; + bool autodetect; }; static v4l2_std_id adv7180_std_to_v4l2(u8 status1) @@ -96,6 +98,29 @@ static v4l2_std_id adv7180_std_to_v4l2(u8 status1) } } +static int v4l2_std_to_adv7180(v4l2_std_id std) +{ + if (std == V4L2_STD_PAL_60) + return ADV7180_INPUT_CONTROL_PAL60; + if (std == V4L2_STD_NTSC_443) + return ADV7180_INPUT_CONTROL_NTSC_443; + if (std == V4L2_STD_PAL_N) + return ADV7180_INPUT_CONTROL_PAL_N; + if (std == V4L2_STD_PAL_M) + return ADV7180_INPUT_CONTROL_PAL_M; + if (std == V4L2_STD_PAL_Nc) + return ADV7180_INPUT_CONTROL_PAL_COMB_N; + + if (std & V4L2_STD_PAL) + return ADV7180_INPUT_CONTROL_PAL_BG; + if (std & V4L2_STD_NTSC) + return ADV7180_INPUT_CONTROL_NTSC_M; + if (std & V4L2_STD_SECAM) + return ADV7180_INPUT_CONTROL_PAL_SECAM; + + return -EINVAL; +} + static u32 adv7180_status_to_v4l2(u8 status1) { if (!(status1 & ADV7180_STATUS1_IN_LOCK)) @@ -127,7 +152,15 @@ static inline struct adv7180_state *to_state(struct v4l2_subdev *sd) static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { - return __adv7180_status(v4l2_get_subdevdata(sd), NULL, std); + struct adv7180_state *state = to_state(sd); + int err = 0; + + if (!state->autodetect) + *std = state->curr_norm; + else + err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std); + + return err; } static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) @@ -143,6 +176,39 @@ static int adv7180_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0); } +static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct adv7180_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + /* all standards -> autodetect */ + if (std == V4L2_STD_ALL) { + ret = i2c_smbus_write_byte_data(client, + ADV7180_INPUT_CONTROL_REG, + ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM); + if (ret < 0) + goto out; + + state->autodetect = true; + } else { + ret = v4l2_std_to_adv7180(std); + if (ret < 0) + goto out; + + ret = i2c_smbus_write_byte_data(client, + ADV7180_INPUT_CONTROL_REG, ret); + if (ret < 0) + goto out; + + state->curr_norm = std; + state->autodetect = false; + } + ret = 0; +out: + return ret; +} + static const struct v4l2_subdev_video_ops adv7180_video_ops = { .querystd = adv7180_querystd, .g_input_status = adv7180_g_input_status, @@ -150,6 +216,7 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { static const struct v4l2_subdev_core_ops adv7180_core_ops = { .g_chip_ident = adv7180_g_chip_ident, + .s_std = adv7180_s_std, }; static const struct v4l2_subdev_ops adv7180_ops = { @@ -179,6 +246,7 @@ static int adv7180_probe(struct i2c_client *client, state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL); if (state == NULL) return -ENOMEM; + state->autodetect = true; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); From 527aebf29c64a56557f9b44d2852ccb99f91ac3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 22 Sep 2009 06:07:34 -0300 Subject: [PATCH 099/345] V4L/DVB (13175): adv7180: Use __devinit and __devexit macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch defines the probe and remove function as __devinit and __devexit. Signed-off-by: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7180.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c index 8b199a86a3a9..77eada64cf74 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/video/adv7180.c @@ -229,7 +229,7 @@ static const struct v4l2_subdev_ops adv7180_ops = { * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ -static int adv7180_probe(struct i2c_client *client, +static __devinit int adv7180_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct adv7180_state *state; @@ -267,7 +267,7 @@ static int adv7180_probe(struct i2c_client *client, return 0; } -static int adv7180_remove(struct i2c_client *client) +static __devexit int adv7180_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); @@ -289,7 +289,7 @@ static struct i2c_driver adv7180_driver = { .name = DRIVER_NAME, }, .probe = adv7180_probe, - .remove = adv7180_remove, + .remove = __devexit_p(adv7180_remove), .id_table = adv7180_id, }; From 42752f7a3f4afbabb513d5769c590e9abe2d0cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 22 Sep 2009 06:07:06 -0300 Subject: [PATCH 100/345] V4L/DVB (13176): adv7180: Support checking standard via interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the I2C device provides an interrupt it is registered and the standard is updated via interrupts rather than polling. Since I2C communication is needed, the interrupt handler fires off a work which will check the new standard, and store it in the internal structure. To handle mutual exclusion a mutex is introduced. Signed-off-by: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7180.c | 185 ++++++++++++++++++++++++++++++---- 1 file changed, 168 insertions(+), 17 deletions(-) diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c index 77eada64cf74..0826f0dabc17 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/video/adv7180.c @@ -27,6 +27,7 @@ #include #include #include +#include #define DRIVER_NAME "adv7180" @@ -48,9 +49,14 @@ #define ADV7180_INPUT_CONTROL_PAL_SECAM 0xe0 #define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0 -#define ADV7180_AUTODETECT_ENABLE_REG 0x07 -#define ADV7180_AUTODETECT_DEFAULT 0x7f +#define ADV7180_EXTENDED_OUTPUT_CONTROL_REG 0x04 +#define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5 +#define ADV7180_AUTODETECT_ENABLE_REG 0x07 +#define ADV7180_AUTODETECT_DEFAULT 0x7f + +#define ADV7180_ADI_CTRL_REG 0x0e +#define ADV7180_ADI_CTRL_IRQ_SPACE 0x20 #define ADV7180_STATUS1_REG 0x10 #define ADV7180_STATUS1_IN_LOCK 0x01 @@ -67,9 +73,28 @@ #define ADV7180_IDENT_REG 0x11 #define ADV7180_ID_7180 0x18 +#define ADV7180_ICONF1_ADI 0x40 +#define ADV7180_ICONF1_ACTIVE_LOW 0x01 +#define ADV7180_ICONF1_PSYNC_ONLY 0x10 +#define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0 + +#define ADV7180_IRQ1_LOCK 0x01 +#define ADV7180_IRQ1_UNLOCK 0x02 +#define ADV7180_ISR1_ADI 0x42 +#define ADV7180_ICR1_ADI 0x43 +#define ADV7180_IMR1_ADI 0x44 +#define ADV7180_IMR2_ADI 0x48 +#define ADV7180_IRQ3_AD_CHANGE 0x08 +#define ADV7180_ISR3_ADI 0x4A +#define ADV7180_ICR3_ADI 0x4B +#define ADV7180_IMR3_ADI 0x4C +#define ADV7180_IMR4_ADI 0x50 struct adv7180_state { struct v4l2_subdev sd; + struct work_struct work; + struct mutex mutex; /* mutual excl. when accessing chip */ + int irq; v4l2_std_id curr_norm; bool autodetect; }; @@ -153,19 +178,30 @@ static inline struct adv7180_state *to_state(struct v4l2_subdev *sd) static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { struct adv7180_state *state = to_state(sd); - int err = 0; + int err = mutex_lock_interruptible(&state->mutex); + if (err) + return err; - if (!state->autodetect) + /* when we are interrupt driven we know the state */ + if (!state->autodetect || state->irq > 0) *std = state->curr_norm; else err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std); + mutex_unlock(&state->mutex); return err; } static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) { - return __adv7180_status(v4l2_get_subdevdata(sd), status, NULL); + struct adv7180_state *state = to_state(sd); + int ret = mutex_lock_interruptible(&state->mutex); + if (ret) + return ret; + + ret = __adv7180_status(v4l2_get_subdevdata(sd), status, NULL); + mutex_unlock(&state->mutex); + return ret; } static int adv7180_g_chip_ident(struct v4l2_subdev *sd, @@ -180,7 +216,9 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) { struct adv7180_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret; + int ret = mutex_lock_interruptible(&state->mutex); + if (ret) + return ret; /* all standards -> autodetect */ if (std == V4L2_STD_ALL) { @@ -190,6 +228,7 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) if (ret < 0) goto out; + __adv7180_status(client, NULL, &state->curr_norm); state->autodetect = true; } else { ret = v4l2_std_to_adv7180(std); @@ -206,6 +245,7 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) } ret = 0; out: + mutex_unlock(&state->mutex); return ret; } @@ -224,6 +264,39 @@ static const struct v4l2_subdev_ops adv7180_ops = { .video = &adv7180_video_ops, }; +static void adv7180_work(struct work_struct *work) +{ + struct adv7180_state *state = container_of(work, struct adv7180_state, + work); + struct i2c_client *client = v4l2_get_subdevdata(&state->sd); + u8 isr3; + + mutex_lock(&state->mutex); + i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, + ADV7180_ADI_CTRL_IRQ_SPACE); + isr3 = i2c_smbus_read_byte_data(client, ADV7180_ISR3_ADI); + /* clear */ + i2c_smbus_write_byte_data(client, ADV7180_ICR3_ADI, isr3); + i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 0); + + if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) + __adv7180_status(client, NULL, &state->curr_norm); + mutex_unlock(&state->mutex); + + enable_irq(state->irq); +} + +static irqreturn_t adv7180_irq(int irq, void *devid) +{ + struct adv7180_state *state = devid; + + schedule_work(&state->work); + + disable_irq_nosync(state->irq); + + return IRQ_HANDLED; +} + /* * Generic i2c probe * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' @@ -244,33 +317,111 @@ static __devinit int adv7180_probe(struct i2c_client *client, client->addr << 1, client->adapter->name); state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL); - if (state == NULL) - return -ENOMEM; + if (state == NULL) { + ret = -ENOMEM; + goto err; + } + + state->irq = client->irq; + INIT_WORK(&state->work, adv7180_work); + mutex_init(&state->mutex); state->autodetect = true; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); /* Initialize adv7180 */ - /* enable autodetection */ + /* Enable autodetection */ ret = i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM); - if (ret > 0) - ret = i2c_smbus_write_byte_data(client, - ADV7180_AUTODETECT_ENABLE_REG, - ADV7180_AUTODETECT_DEFAULT); - if (ret < 0) { - printk(KERN_ERR DRIVER_NAME - ": Failed to communicate to chip: %d\n", ret); - return ret; + if (ret < 0) + goto err_unreg_subdev; + + ret = i2c_smbus_write_byte_data(client, ADV7180_AUTODETECT_ENABLE_REG, + ADV7180_AUTODETECT_DEFAULT); + if (ret < 0) + goto err_unreg_subdev; + + /* ITU-R BT.656-4 compatible */ + ret = i2c_smbus_write_byte_data(client, + ADV7180_EXTENDED_OUTPUT_CONTROL_REG, + ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS); + if (ret < 0) + goto err_unreg_subdev; + + /* read current norm */ + __adv7180_status(client, NULL, &state->curr_norm); + + /* register for interrupts */ + if (state->irq > 0) { + ret = request_irq(state->irq, adv7180_irq, 0, DRIVER_NAME, + state); + if (ret) + goto err_unreg_subdev; + + ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, + ADV7180_ADI_CTRL_IRQ_SPACE); + if (ret < 0) + goto err_unreg_subdev; + + /* config the Interrupt pin to be active low */ + ret = i2c_smbus_write_byte_data(client, ADV7180_ICONF1_ADI, + ADV7180_ICONF1_ACTIVE_LOW | ADV7180_ICONF1_PSYNC_ONLY); + if (ret < 0) + goto err_unreg_subdev; + + ret = i2c_smbus_write_byte_data(client, ADV7180_IMR1_ADI, 0); + if (ret < 0) + goto err_unreg_subdev; + + ret = i2c_smbus_write_byte_data(client, ADV7180_IMR2_ADI, 0); + if (ret < 0) + goto err_unreg_subdev; + + /* enable AD change interrupts interrupts */ + ret = i2c_smbus_write_byte_data(client, ADV7180_IMR3_ADI, + ADV7180_IRQ3_AD_CHANGE); + if (ret < 0) + goto err_unreg_subdev; + + ret = i2c_smbus_write_byte_data(client, ADV7180_IMR4_ADI, 0); + if (ret < 0) + goto err_unreg_subdev; + + ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, + 0); + if (ret < 0) + goto err_unreg_subdev; } return 0; + +err_unreg_subdev: + mutex_destroy(&state->mutex); + v4l2_device_unregister_subdev(sd); + kfree(state); +err: + printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", ret); + return ret; } static __devexit int adv7180_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct adv7180_state *state = to_state(sd); + if (state->irq > 0) { + free_irq(client->irq, state); + if (cancel_work_sync(&state->work)) { + /* + * Work was pending, therefore we need to enable + * IRQ here to balance the disable_irq() done in the + * interrupt handler. + */ + enable_irq(state->irq); + } + } + + mutex_destroy(&state->mutex); v4l2_device_unregister_subdev(sd); kfree(to_state(sd)); return 0; From eea85b0a629970d462481a80e1d45f4d71fe797f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 22 Sep 2009 10:14:39 -0300 Subject: [PATCH 101/345] V4L/DVB (13177): radio: Add support for TEF6862 tuner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for TEF6862 Car Radio Enhanced Selectivity Tuner. It's implemented as a subdev, supporting checking signal strength and setting and getting frequency. Signed-off-by: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/Kconfig | 12 ++ drivers/media/radio/Makefile | 1 + drivers/media/radio/tef6862.c | 232 ++++++++++++++++++++++++++++++++ include/media/v4l2-chip-ident.h | 3 + 4 files changed, 248 insertions(+) create mode 100644 drivers/media/radio/tef6862.c diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index a87a477c87f2..931b8b370b50 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -401,4 +401,16 @@ config RADIO_TEA5764_XTAL Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N here if TEA5764 reference frequency is connected in FREQIN. +config RADIO_TEF6862 + tristate "TEF6862 Car Radio Enhanced Selectivity Tuner" + depends on I2C && VIDEO_V4L2 + ---help--- + Say Y here if you want to use the TEF6862 Car Radio Enhanced + Selectivity Tuner, found for instance on the Russellville development + board. On the russellville the device is connected to internal + timberdale I2C bus. + + To compile this driver as a module, choose M here: the + module will be called TEF6862. + endif # RADIO_ADAPTERS diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 2a1be3bf4f7c..a4bdca08a94d 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -22,5 +22,6 @@ obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_RADIO_SI470X) += si470x/ obj-$(CONFIG_USB_MR800) += radio-mr800.o obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o +obj-$(CONFIG_RADIO_TEF6862) += tef6862.o EXTRA_CFLAGS += -Isound diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c new file mode 100644 index 000000000000..6e607ff0c169 --- /dev/null +++ b/drivers/media/radio/tef6862.c @@ -0,0 +1,232 @@ +/* + * tef6862.c Philips TEF6862 Car Radio Enhanced Selectivity Tuner + * Copyright (c) 2009 Intel Corporation + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "tef6862" + +#define FREQ_MUL 16000 + +#define TEF6862_LO_FREQ (875 * FREQ_MUL / 10) +#define TEF6862_HI_FREQ (108 * FREQ_MUL) + +/* Write mode sub addresses */ +#define WM_SUB_BANDWIDTH 0x0 +#define WM_SUB_PLLM 0x1 +#define WM_SUB_PLLL 0x2 +#define WM_SUB_DAA 0x3 +#define WM_SUB_AGC 0x4 +#define WM_SUB_BAND 0x5 +#define WM_SUB_CONTROL 0x6 +#define WM_SUB_LEVEL 0x7 +#define WM_SUB_IFCF 0x8 +#define WM_SUB_IFCAP 0x9 +#define WM_SUB_ACD 0xA +#define WM_SUB_TEST 0xF + +/* Different modes of the MSA register */ +#define MODE_BUFFER 0x0 +#define MODE_PRESET 0x1 +#define MODE_SEARCH 0x2 +#define MODE_AF_UPDATE 0x3 +#define MODE_JUMP 0x4 +#define MODE_CHECK 0x5 +#define MODE_LOAD 0x6 +#define MODE_END 0x7 +#define MODE_SHIFT 5 + +struct tef6862_state { + struct v4l2_subdev sd; + unsigned long freq; +}; + +static inline struct tef6862_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct tef6862_state, sd); +} + +static u16 tef6862_sigstr(struct i2c_client *client) +{ + u8 buf[4]; + int err = i2c_master_recv(client, buf, sizeof(buf)); + if (err == sizeof(buf)) + return buf[3] << 8; + return 0; +} + +static int tef6862_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) +{ + if (v->index > 0) + return -EINVAL; + + /* only support FM for now */ + strlcpy(v->name, "FM", sizeof(v->name)); + v->type = V4L2_TUNER_RADIO; + v->rangelow = TEF6862_LO_FREQ; + v->rangehigh = TEF6862_HI_FREQ; + v->rxsubchans = V4L2_TUNER_SUB_MONO; + v->capability = V4L2_TUNER_CAP_LOW; + v->audmode = V4L2_TUNER_MODE_STEREO; + v->signal = tef6862_sigstr(v4l2_get_subdevdata(sd)); + + return 0; +} + +static int tef6862_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) +{ + return v->index ? -EINVAL : 0; +} + +static int tef6862_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) +{ + struct tef6862_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + u16 pll; + u8 i2cmsg[3]; + int err; + + if (f->tuner != 0) + return -EINVAL; + + pll = 1964 + ((f->frequency - TEF6862_LO_FREQ) * 20) / FREQ_MUL; + i2cmsg[0] = (MODE_PRESET << MODE_SHIFT) | WM_SUB_PLLM; + i2cmsg[1] = (pll >> 8) & 0xff; + i2cmsg[2] = pll & 0xff; + + err = i2c_master_send(client, i2cmsg, sizeof(i2cmsg)); + if (!err) + state->freq = f->frequency; + return err; +} + +static int tef6862_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) +{ + struct tef6862_state *state = to_state(sd); + + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; + f->frequency = state->freq; + return 0; +} + +static int tef6862_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEF6862, 0); +} + +static const struct v4l2_subdev_tuner_ops tef6862_tuner_ops = { + .g_tuner = tef6862_g_tuner, + .s_tuner = tef6862_s_tuner, + .s_frequency = tef6862_s_frequency, + .g_frequency = tef6862_g_frequency, +}; + +static const struct v4l2_subdev_core_ops tef6862_core_ops = { + .g_chip_ident = tef6862_g_chip_ident, +}; + +static const struct v4l2_subdev_ops tef6862_ops = { + .core = &tef6862_core_ops, + .tuner = &tef6862_tuner_ops, +}; + +/* + * Generic i2c probe + * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' + */ + +static int __devinit tef6862_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tef6862_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%02x (%s)\n", + client->addr << 1, client->adapter->name); + + state = kmalloc(sizeof(struct tef6862_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + state->freq = TEF6862_LO_FREQ; + + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &tef6862_ops); + + return 0; +} + +static int __devexit tef6862_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); + return 0; +} + +static const struct i2c_device_id tef6862_id[] = { + {DRIVER_NAME, 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, tef6862_id); + +static struct i2c_driver tef6862_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME, + }, + .probe = tef6862_probe, + .remove = tef6862_remove, + .id_table = tef6862_id, +}; + +static __init int tef6862_init(void) +{ + return i2c_add_driver(&tef6862_driver); +} + +static __exit void tef6862_exit(void) +{ + i2c_del_driver(&tef6862_driver); +} + +module_init(tef6862_init); +module_exit(tef6862_exit); + +MODULE_DESCRIPTION("TEF6862 Car Radio Enhanced Selectivity Tuner"); +MODULE_AUTHOR("Mocean Laboratories"); +MODULE_LICENSE("GPL v2"); + diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 43cf26ea6734..91942dbe64e3 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -131,6 +131,9 @@ enum { V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, + /* modules tef6862: just ident 6862 */ + V4L2_IDENT_TEF6862 = 6862, + /* module adv7170: just ident 7170 */ V4L2_IDENT_ADV7170 = 7170, From a511ba947600ae263f8c29c86020ba66a901d3e5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 Oct 2009 07:13:07 -0300 Subject: [PATCH 102/345] V4L/DVB (13178): gspca: Add support for Winbond W9967CF and W9968CF camera's This patch adds support to gspca for the Winbond W9967CF and W9968CF camera's. This is mostly a port of the existing v4l1 driver to gspca (making it v4l2). But this also features fixes to the bitbanging i2c code (send a nack not an ack after reading the last byte of a transfer), which gets rid of the weird errors which were being seen there, and of the smbus_refresh() hack to get around these errors. Also the vstart settings have been tweaked to work with different frequency filter settings. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 11 +- drivers/media/video/gspca/Kconfig | 5 +- drivers/media/video/gspca/gspca.c | 22 +- drivers/media/video/gspca/gspca.h | 1 + drivers/media/video/gspca/ov519.c | 115 +++++- drivers/media/video/gspca/w996Xcf.c | 589 ++++++++++++++++++++++++++++ 6 files changed, 713 insertions(+), 30 deletions(-) create mode 100644 drivers/media/video/gspca/w996Xcf.c diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 0ab7ccd8729b..c69f858c9278 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -951,9 +951,13 @@ source "drivers/media/video/usbvideo/Kconfig" source "drivers/media/video/et61x251/Kconfig" config VIDEO_OVCAMCHIP - tristate "OmniVision Camera Chip support" + tristate "OmniVision Camera Chip support (DEPRECATED)" depends on I2C && VIDEO_V4L1 ---help--- + This driver is DEPRECATED please use the gspca ov519 module + instead. Note that for the ov511 / ov518 support of the gspca module + you need atleast version 0.6.0 of libv4l. + Support for the OmniVision OV6xxx and OV7xxx series of camera chips. This driver is intended to be used with the ov511 and w9968cf USB camera drivers. @@ -962,9 +966,12 @@ config VIDEO_OVCAMCHIP module will be called ovcamchip. config USB_W9968CF - tristate "USB W996[87]CF JPEG Dual Mode Camera support" + tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)" depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP ---help--- + This driver is DEPRECATED please use the gspca ov519 module + instead. + Say Y here if you want support for cameras based on OV681 or Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index fe2e490ebc52..cbc2367719f0 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -76,10 +76,11 @@ config USB_GSPCA_MR97310A module will be called gspca_mr97310a. config USB_GSPCA_OV519 - tristate "OV519 USB Camera Driver" + tristate "OV51x / OVFX2 / W996xCF USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the OV519 chip. + Say Y here if you want support for cameras based on one of these: + OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF To compile this driver as a module, choose M here: the module will be called gspca_ov519. diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 179cbc14ee51..ebaa2425fb50 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -475,10 +475,18 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK : USB_ENDPOINT_XFER_ISOC; i = gspca_dev->alt; /* previous alt setting */ - while (--i >= 0) { - ep = alt_xfer(&intf->altsetting[i], xfer); - if (ep) - break; + if (gspca_dev->cam.reverse_alts) { + while (++i < gspca_dev->nbalt) { + ep = alt_xfer(&intf->altsetting[i], xfer); + if (ep) + break; + } + } else { + while (--i >= 0) { + ep = alt_xfer(&intf->altsetting[i], xfer); + if (ep) + break; + } } if (ep == NULL) { err("no transfer endpoint found"); @@ -599,7 +607,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) /* set the higher alternate setting and * loop until urb submit succeeds */ - gspca_dev->alt = gspca_dev->nbalt; + if (gspca_dev->cam.reverse_alts) + gspca_dev->alt = 0; + else + gspca_dev->alt = gspca_dev->nbalt; + if (gspca_dev->sd_desc->isoc_init) { ret = gspca_dev->sd_desc->isoc_init(gspca_dev); if (ret < 0) diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 70b1fd830876..1d761d7cefc6 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -58,6 +58,7 @@ struct cam { u8 npkt; /* number of packets in an ISOC message * 0 is the default value: 32 packets */ u32 input_flags; /* value for ENUM_INPUT status flags */ + char reverse_alts; /* Alt settings are in high to low order */ }; struct gspca_dev; diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 4d6a762a6f3d..994a5e927d2d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -64,6 +64,7 @@ struct sd { #define BRIDGE_OV518PLUS 3 #define BRIDGE_OV519 4 #define BRIDGE_OVFX2 5 +#define BRIDGE_W9968CF 6 #define BRIDGE_MASK 7 char invert_led; @@ -98,8 +99,17 @@ struct sd { #define SEN_OV7670 9 #define SEN_OV76BE 10 #define SEN_OV8610 11 + + u8 sensor_addr; + int sensor_width; + int sensor_height; }; +/* Note this is a bit of a hack, but the w9968cf driver needs the code for all + the ov sensors which is already present here. When we have the time we + really should move the sensor drivers to v4l2 sub drivers. */ +#include "w996Xcf.c" + /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); @@ -1471,6 +1481,7 @@ static const struct ov_i2c_regvals norm_7610[] = { }; static const struct ov_i2c_regvals norm_7620[] = { + { 0x12, 0x80 }, /* reset */ { 0x00, 0x00 }, /* gain */ { 0x01, 0x80 }, /* blue gain */ { 0x02, 0x80 }, /* red gain */ @@ -1835,10 +1846,9 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) } /* Write a OV519 register */ -static int reg_w(struct sd *sd, __u16 index, __u8 value) +static int reg_w(struct sd *sd, __u16 index, __u16 value) { - int ret; - int req; + int ret, req = 0; switch (sd->bridge) { case BRIDGE_OV511: @@ -1846,11 +1856,14 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) req = 2; break; case BRIDGE_OVFX2: + req = 0x0a; + /* fall through */ + case BRIDGE_W9968CF: ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), - 0x0a, + req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (__u16)value, index, NULL, 0, 500); + value, index, NULL, 0, 500); goto leave; default: req = 1; @@ -1864,12 +1877,17 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) 0, index, sd->gspca_dev.usb_buf, 1, 500); leave: - if (ret < 0) - PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value); - return ret; + if (ret < 0) { + PDEBUG(D_ERR, "Write reg 0x%04x -> [0x%02x] failed", + value, index); + return ret; + } + + PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index); + return 0; } -/* Read from a OV519 register */ +/* Read from a OV519 register, note not valid for the w9968cf!! */ /* returns: negative is error, pos or zero is data */ static int reg_r(struct sd *sd, __u16 index) { @@ -1894,10 +1912,12 @@ static int reg_r(struct sd *sd, __u16 index) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, sd->gspca_dev.usb_buf, 1, 500); - if (ret >= 0) + if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - else + PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret); + } else PDEBUG(D_ERR, "Read reg [0x%02x] failed", index); + return ret; } @@ -1917,6 +1937,7 @@ static int reg_r8(struct sd *sd, ret = sd->gspca_dev.usb_buf[0]; else PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index); + return ret; } @@ -1962,9 +1983,12 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, sd->gspca_dev.usb_buf, n, 500); - if (ret < 0) + if (ret < 0) { PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value); - return ret; + return ret; + } + + return 0; } static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) @@ -2156,12 +2180,13 @@ static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, (__u16)value, (__u16)reg, NULL, 0, 500); - if (ret >= 0) - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); - else + if (ret < 0) { PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); + return ret; + } - return ret; + PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + return 0; } static int ovfx2_i2c_r(struct sd *sd, __u8 reg) @@ -2195,6 +2220,8 @@ static int i2c_w(struct sd *sd, __u8 reg, __u8 value) return ov518_i2c_w(sd, reg, value); case BRIDGE_OVFX2: return ovfx2_i2c_w(sd, reg, value); + case BRIDGE_W9968CF: + return w9968cf_i2c_w(sd, reg, value); } return -1; /* Should never happen */ } @@ -2211,6 +2238,8 @@ static int i2c_r(struct sd *sd, __u8 reg) return ov518_i2c_r(sd, reg); case BRIDGE_OVFX2: return ovfx2_i2c_r(sd, reg); + case BRIDGE_W9968CF: + return w9968cf_i2c_r(sd, reg); } return -1; /* Should never happen */ } @@ -2241,6 +2270,8 @@ static int i2c_w_mask(struct sd *sd, * registers while the camera is streaming */ static inline int ov51x_stop(struct sd *sd) { + int ret; + PDEBUG(D_STREAM, "stopping"); sd->stopped = 1; switch (sd->bridge) { @@ -2254,6 +2285,11 @@ static inline int ov51x_stop(struct sd *sd) return reg_w(sd, OV519_SYS_RESET1, 0x0f); case BRIDGE_OVFX2: return reg_w_mask(sd, 0x0f, 0x00, 0x02); + case BRIDGE_W9968CF: + ret = reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ + ret += reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ + ret += reg_w(sd, 0x16, 0x0000); /* stop video capture */ + return ret; } return 0; @@ -2285,6 +2321,8 @@ static inline int ov51x_restart(struct sd *sd) return reg_w(sd, OV519_SYS_RESET1, 0x00); case BRIDGE_OVFX2: return reg_w_mask(sd, 0x0f, 0x02, 0x02); + case BRIDGE_W9968CF: + return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ } return 0; @@ -2338,8 +2376,13 @@ static int ov51x_set_slave_ids(struct sd *sd, { int rc; - if (sd->bridge == BRIDGE_OVFX2) + switch (sd->bridge) { + case BRIDGE_OVFX2: return reg_w(sd, OVFX2_I2C_ADDR, slave); + case BRIDGE_W9968CF: + sd->sensor_addr = slave; + return 0; + } rc = reg_w(sd, R51x_I2C_W_SID, slave); if (rc < 0) @@ -2920,6 +2963,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->bulk_nurbs = MAX_NURBS; cam->bulk = 1; break; + case BRIDGE_W9968CF: + ret = w9968cf_configure(sd); + cam->reverse_alts = 1; + break; } if (ret) @@ -3005,6 +3052,16 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = ARRAY_SIZE(ov519_sif_mode); } break; + case BRIDGE_W9968CF: + cam->cam_mode = w9968cf_vga_mode; + cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); + /* if (sd->sif) + cam->nmodes--; */ + + /* w9968cf needs initialisation once the sensor is known */ + if (w9968cf_init(sd) < 0) + goto error; + break; } sd->brightness = BRIGHTNESS_DEF; if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) @@ -3753,9 +3810,9 @@ static int set_ov_sensor_window(struct sd *sd) return ret; i2c_w(sd, 0x17, hwsbase); - i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); + i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); i2c_w(sd, 0x19, vwsbase); - i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); + i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); return 0; } @@ -3766,6 +3823,10 @@ static int sd_start(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int ret = 0; + /* Default for most bridges, allow bridge_mode_init_regs to override */ + sd->sensor_width = sd->gspca_dev.width; + sd->sensor_height = sd->gspca_dev.height; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -3779,6 +3840,9 @@ static int sd_start(struct gspca_dev *gspca_dev) ret = ov519_mode_init_regs(sd); break; /* case BRIDGE_OVFX2: nothing to do */ + case BRIDGE_W9968CF: + ret = w9968cf_mode_init_regs(sd); + break; } if (ret < 0) goto out; @@ -3980,6 +4044,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, case BRIDGE_OVFX2: ovfx2_pkt_scan(gspca_dev, frame, data, len); break; + case BRIDGE_W9968CF: + w9968cf_pkt_scan(gspca_dev, frame, data, len); + break; } } @@ -4275,8 +4342,12 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->freq = val; - if (gspca_dev->streaming) + if (gspca_dev->streaming) { setfreq(sd); + /* Ugly but necessary */ + if (sd->bridge == BRIDGE_W9968CF) + w9968cf_set_crop_window(sd); + } return 0; } @@ -4332,6 +4403,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF }, {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, @@ -4356,6 +4428,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, + {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, {} }; diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c new file mode 100644 index 000000000000..ba3a28d4f87f --- /dev/null +++ b/drivers/media/video/gspca/w996Xcf.c @@ -0,0 +1,589 @@ +/** + * + * GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip. + * + * Copyright (C) 2009 Hans de Goede + * + * This module is adapted from the in kernel v4l1 w9968cf driver: + * + * Copyright (C) 2002-2004 by Luca Risolia + * + * 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 + * 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 + * + */ + +/* Note this is not a stand alone driver, it gets included in ov519.c, this + is a bit of a hack, but it needs the driver code for a lot of different + ov sensors which is already present in ov519.c (the old v4l1 driver used + the ovchipcam framework). When we have the time we really should move + the sensor drivers to v4l2 sub drivers, and properly split of this + driver from ov519.c */ + +#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ + +/* FIXME make this runtime configurable */ +/* Comment/uncomment this for high/low quality of compressed video */ +#define W9968CF_DEC_FAST_LOWQUALITY_VIDEO + +#ifdef W9968CF_DEC_FAST_LOWQUALITY_VIDEO +static const unsigned char Y_QUANTABLE[64] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +static const unsigned char UV_QUANTABLE[64] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; +#else +static const unsigned char Y_QUANTABLE[64] = { + 8, 5, 5, 8, 12, 20, 25, 30, + 6, 6, 7, 9, 13, 29, 30, 27, + 7, 6, 8, 12, 20, 28, 34, 28, + 7, 8, 11, 14, 25, 43, 40, 31, + 9, 11, 18, 28, 34, 54, 51, 38, + 12, 17, 27, 32, 40, 52, 56, 46, + 24, 32, 39, 43, 51, 60, 60, 50, + 36, 46, 47, 49, 56, 50, 51, 49 +}; + +static const unsigned char UV_QUANTABLE[64] = { + 8, 9, 12, 23, 49, 49, 49, 49, + 9, 10, 13, 33, 49, 49, 49, 49, + 12, 13, 28, 49, 49, 49, 49, 49, + 23, 33, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49 +}; +#endif + +static const struct v4l2_pix_format w9968cf_vga_mode[] = { + {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, + .bytesperline = 160 * 2, + .sizeimage = 160 * 120 * 2, + .colorspace = V4L2_COLORSPACE_JPEG}, + {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, + .bytesperline = 176 * 2, + .sizeimage = 176 * 144 * 2, + .colorspace = V4L2_COLORSPACE_JPEG}, + {320, 240, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, + .bytesperline = 320 * 2, + .sizeimage = 320 * 240 * 2, + .colorspace = V4L2_COLORSPACE_JPEG}, + {352, 288, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, + .bytesperline = 352 * 2, + .sizeimage = 352 * 288 * 2, + .colorspace = V4L2_COLORSPACE_JPEG}, +/* {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, + .bytesperline = 640 * 2, + .sizeimage = 640 * 480 * 2, + .colorspace = V4L2_COLORSPACE_JPEG}, */ +}; + +static int reg_w(struct sd *sd, __u16 index, __u16 value); + +/*-------------------------------------------------------------------------- + Write 64-bit data to the fast serial bus registers. + Return 0 on success, -1 otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_write_fsb(struct sd *sd, u16* data) +{ + struct usb_device* udev = sd->gspca_dev.dev; + u16 value; + int ret; + + value = *data++; + memcpy(sd->gspca_dev.usb_buf, data, 6); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, + USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + value, 0x06, sd->gspca_dev.usb_buf, 6, 500); + if (ret < 0) { + PDEBUG(D_ERR, "Write FSB registers failed (%d)", ret); + return ret; + } + + return 0; +} + +/*-------------------------------------------------------------------------- + Write data to the serial bus control register. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_write_sb(struct sd *sd, u16 value) +{ + int ret; + + /* We don't use reg_w here, as that would cause all writes when + bitbanging i2c to be logged, making the logs impossible to read */ + ret = usb_control_msg(sd->gspca_dev.dev, + usb_sndctrlpipe(sd->gspca_dev.dev, 0), + 0, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, 0x01, NULL, 0, 500); + + udelay(W9968CF_I2C_BUS_DELAY); + + if (ret < 0) { + PDEBUG(D_ERR, "Write SB reg [01] %04x failed", value); + return ret; + } + + return 0; +} + +/*-------------------------------------------------------------------------- + Read data from the serial bus control register. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_read_sb(struct sd *sd) +{ + int ret; + + /* We don't use reg_r here, as the w9968cf is special and has 16 + bit registers instead of 8 bit */ + ret = usb_control_msg(sd->gspca_dev.dev, + usb_rcvctrlpipe(sd->gspca_dev.dev, 0), + 1, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); + if (ret >= 0) + ret = sd->gspca_dev.usb_buf[0] | + (sd->gspca_dev.usb_buf[1] << 8); + else + PDEBUG(D_ERR, "Read SB reg [01] failed"); + + udelay(W9968CF_I2C_BUS_DELAY); + + return ret; +} + +/*-------------------------------------------------------------------------- + Upload quantization tables for the JPEG compression. + This function is called by w9968cf_start_transfer(). + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_upload_quantizationtables(struct sd *sd) +{ + u16 a, b; + int ret = 0, i, j; + + ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ + + for (i = 0, j = 0; i < 32; i++, j += 2) { + a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); + b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); + ret += reg_w(sd, 0x40+i, a); + ret += reg_w(sd, 0x60+i, b); + } + ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ + + return ret; +} + +/**************************************************************************** + * Low-level I2C I/O functions. * + * The adapter supports the following I2C transfer functions: * + * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * + * i2c_adap_read_byte_data() * + * i2c_adap_read_byte() * + ****************************************************************************/ + +static int w9968cf_smbus_start(struct sd *sd) +{ + int ret = 0; + + ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ + + return ret; +} + +static int w9968cf_smbus_stop(struct sd *sd) +{ + int ret = 0; + + ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ + ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + + return ret; +} + +static int w9968cf_smbus_write_byte(struct sd *sd, u8 v) +{ + u8 bit; + int ret = 0, sda; + + for (bit = 0 ; bit < 8 ; bit++) { + sda = (v & 0x80) ? 2 : 0; + v <<= 1; + /* SDE=1, SDA=sda, SCL=0 */ + ret += w9968cf_write_sb(sd, 0x10 | sda); + /* SDE=1, SDA=sda, SCL=1 */ + ret += w9968cf_write_sb(sd, 0x11 | sda); + /* SDE=1, SDA=sda, SCL=0 */ + ret += w9968cf_write_sb(sd, 0x10 | sda); + } + + return ret; +} + +static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) +{ + u8 bit; + int ret = 0; + + /* No need to ensure SDA is high as we are always called after + read_ack which ends with SDA high */ + *v = 0; + for (bit = 0 ; bit < 8 ; bit++) { + *v <<= 1; + /* SDE=1, SDA=1, SCL=1 */ + ret += w9968cf_write_sb(sd, 0x0013); + *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; + /* SDE=1, SDA=1, SCL=0 */ + ret += w9968cf_write_sb(sd, 0x0012); + } + + return ret; +} + +static int w9968cf_smbus_write_nack(struct sd *sd) +{ + int ret = 0; + + /* No need to ensure SDA is high as we are always called after + read_byte which ends with SDA high */ + ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + + return ret; +} + +static int w9968cf_smbus_read_ack(struct sd *sd) +{ + int ret = 0, sda; + + /* Ensure SDA is high before raising clock to avoid a spurious stop */ + ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + sda = w9968cf_read_sb(sd); + ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + if (sda < 0) + ret += sda; + else if (sda & 0x08) { + PDEBUG(D_USBI, "Did not receive i2c ACK"); + ret += -1; + } + + return ret; +} + +/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ +static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) +{ + u16* data = (u16 *)sd->gspca_dev.usb_buf; + int ret = 0; + + data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); + data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; + data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0); + data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0; + data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0; + data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0); + data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0; + data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0; + data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); + data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; + + ret += w9968cf_write_fsb(sd, data); + + data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); + data[0] |= (reg & 0x40) ? 0x0540 : 0x0; + data[0] |= (reg & 0x20) ? 0x5000 : 0x0; + data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0); + data[1] |= (reg & 0x10) ? 0x0054 : 0x0; + data[1] |= (reg & 0x08) ? 0x1500 : 0x0; + data[1] |= (reg & 0x04) ? 0x4000 : 0x0; + data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0); + data[2] |= (reg & 0x02) ? 0x0150 : 0x0; + data[2] |= (reg & 0x01) ? 0x5400 : 0x0; + data[3] = 0x001d; + + ret += w9968cf_write_fsb(sd, data); + + data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); + data[0] |= (value & 0x40) ? 0x0540 : 0x0; + data[0] |= (value & 0x20) ? 0x5000 : 0x0; + data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); + data[1] |= (value & 0x10) ? 0x0054 : 0x0; + data[1] |= (value & 0x08) ? 0x1500 : 0x0; + data[1] |= (value & 0x04) ? 0x4000 : 0x0; + data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); + data[2] |= (value & 0x02) ? 0x0150 : 0x0; + data[2] |= (value & 0x01) ? 0x5400 : 0x0; + data[3] = 0xfe1d; + + ret += w9968cf_write_fsb(sd, data); + + if (!ret) + PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + else + PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); + + return ret; +} + +/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ +static int w9968cf_i2c_r(struct sd *sd, u8 reg) +{ + int ret = 0; + u8 value; + + /* Fast serial bus data control disable */ + ret += w9968cf_write_sb(sd, 0x0013); /* don't change ! */ + + ret += w9968cf_smbus_start(sd); + ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr); + ret += w9968cf_smbus_read_ack(sd); + ret += w9968cf_smbus_write_byte(sd, reg); + ret += w9968cf_smbus_read_ack(sd); + ret += w9968cf_smbus_stop(sd); + ret += w9968cf_smbus_start(sd); + ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); + ret += w9968cf_smbus_read_ack(sd); + ret += w9968cf_smbus_read_byte(sd, &value); + /* signal we don't want to read anymore, the v4l1 driver used to + send an ack here which is very wrong! (and then fixed + the issues this gave by retrying reads) */ + ret += w9968cf_smbus_write_nack(sd); + ret += w9968cf_smbus_stop(sd); + + /* Fast serial bus data control re-enable */ + ret += w9968cf_write_sb(sd, 0x0030); + + if (!ret) { + ret = value; + PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); + } else + PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg); + + return ret; +} + + +/*-------------------------------------------------------------------------- + Turn on the LED on some webcams. A beep should be heard too. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_configure(struct sd *sd) +{ + int ret = 0; + + ret += reg_w(sd, 0x00, 0xff00); /* power-down */ + ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ + ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ + ret += reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ + ret += reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ + ret += reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ + ret += reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ + + if (ret) + PDEBUG(D_ERR, "Couldn't turn on the LED"); + + sd->stopped = 1; + + return ret; +} + +static int w9968cf_init(struct sd *sd) +{ + int ret = 0; + unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), + y0 = 0x0000, + u0 = y0 + hw_bufsize/2, + v0 = u0 + hw_bufsize/4, + y1 = v0 + hw_bufsize/4, + u1 = y1 + hw_bufsize/2, + v1 = u1 + hw_bufsize/4; + + ret += reg_w(sd, 0x00, 0xff00); /* power off */ + ret += reg_w(sd, 0x00, 0xbf10); /* power on */ + + ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */ + ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ + + ret += reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ + ret += reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ + ret += reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ + ret += reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ + ret += reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ + ret += reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ + + ret += reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ + ret += reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ + ret += reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ + ret += reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ + ret += reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ + ret += reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ + + ret += reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ + ret += reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ + + ret += reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ + ret += reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ + + ret += reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ + ret += reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ + ret += reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ + ret += reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ + + return ret; +} + +static int w9968cf_set_crop_window(struct sd *sd) +{ + int ret = 0, start_cropx, start_cropy, x, y, fw, fh, cw, ch, + max_width, max_height; + + if (sd->sif) { + max_width = 352; + max_height = 288; + } else { + max_width = 640; + max_height = 480; + } + + if (sd->sensor == SEN_OV7620) { + /* Sigh, this is dependend on the clock / framerate changes + made by the frequency control, sick. */ + if (sd->freq == 1) { + start_cropx = 279; + start_cropy = 35; + } else { + start_cropx = 103; + start_cropy = 35; + } + } else { + start_cropx = 320; + start_cropy = 35; + } + + /* Work around to avoid FP arithmetics */ + #define SC(x) ((x) << 10) + + /* Scaling factors */ + fw = SC(sd->gspca_dev.width) / max_width; + fh = SC(sd->gspca_dev.height) / max_height; + + cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width)/fh; + ch = (fw >= fh) ? SC(sd->gspca_dev.height)/fw : max_height; + + sd->sensor_width = max_width; + sd->sensor_height = max_height; + + x = (max_width - cw) / 2; + y = (max_height - ch) / 2; + + ret += reg_w(sd, 0x10, start_cropx + x); + ret += reg_w(sd, 0x11, start_cropy + y); + ret += reg_w(sd, 0x12, start_cropx + x + cw); + ret += reg_w(sd, 0x13, start_cropy + y + ch); + + return ret; +} + +static int w9968cf_mode_init_regs(struct sd *sd) +{ + int ret = 0, val, vs_polarity, hs_polarity; + + ret += w9968cf_set_crop_window(sd); + + ret += reg_w(sd, 0x14, sd->gspca_dev.width); + ret += reg_w(sd, 0x15, sd->gspca_dev.height); + + /* JPEG width & height */ + ret += reg_w(sd, 0x30, sd->gspca_dev.width); + ret += reg_w(sd, 0x31, sd->gspca_dev.height); + + /* Y & UV frame buffer strides (in WORD) */ + ret += reg_w(sd, 0x2c, sd->gspca_dev.width); + + ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ + ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ + + /* Transfer size */ + /* FIXME JPEG * 4 ?? */ + val = sd->gspca_dev.width * sd->gspca_dev.height; + ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ + ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ + + /* Video Capture Control Register */ + if (sd->sensor == SEN_OV7620) { + /* Seems to work around a bug in the image sensor */ + vs_polarity = 1; + hs_polarity = 1; + } else { + vs_polarity = 1; + hs_polarity = 0; + } + + val = (vs_polarity << 12) | (hs_polarity << 11); + + val |= 0x0080; /* Enable HW double buffering */ + + /* val |= 0x0020; enable clamping */ + /* val |= 0x0008; enable (1-2-1) filter */ + /* val |= 0x000c; enable (2-3-6-3-2) filter */ + + val |= 0x8000; /* capt. enable */ + + ret += reg_w(sd, 0x16, val); + + sd->gspca_dev.empty_packet = 0; + + return ret; +} + +static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + /* An empty packet signals EOF */ + if (gspca_dev->empty_packet) { + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + NULL, 0); + gspca_dev->empty_packet = 0; + } + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); +} From fb1f9020609ead93fcec4b0dd02511a46294c147 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 Oct 2009 07:42:53 -0300 Subject: [PATCH 103/345] V4L/DVB (13179): gspca_ov519: cache sensor regs to avoid unnecessary slow i2c reads / writes Cache sensor regs to avoid unnecessary slow i2c reads / writes, this speeds up sd_start a bit with most bridges and a lot (from 5 seconds down to 0.3 seconds) with W996xCF cams, as this avoids very slow bit bang IO over USB i2c reads. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 53 +++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 994a5e927d2d..91e9b23a3a01 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -103,6 +103,7 @@ struct sd { u8 sensor_addr; int sensor_width; int sensor_height; + int sensor_reg_cache[256]; }; /* Note this is a bit of a hack, but the w9968cf driver needs the code for all @@ -2210,38 +2211,70 @@ static int ovfx2_i2c_r(struct sd *sd, __u8 reg) static int i2c_w(struct sd *sd, __u8 reg, __u8 value) { + int ret = -1; + + if (sd->sensor_reg_cache[reg] == value) + return 0; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - return ov511_i2c_w(sd, reg, value); + ret = ov511_i2c_w(sd, reg, value); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: case BRIDGE_OV519: - return ov518_i2c_w(sd, reg, value); + ret = ov518_i2c_w(sd, reg, value); + break; case BRIDGE_OVFX2: - return ovfx2_i2c_w(sd, reg, value); + ret = ovfx2_i2c_w(sd, reg, value); + break; case BRIDGE_W9968CF: - return w9968cf_i2c_w(sd, reg, value); + ret = w9968cf_i2c_w(sd, reg, value); + break; } - return -1; /* Should never happen */ + + if (ret >= 0) { + /* Up on sensor reset empty the register cache */ + if (reg == 0x12 && (value & 0x80)) + memset(sd->sensor_reg_cache, -1, + sizeof(sd->sensor_reg_cache)); + else + sd->sensor_reg_cache[reg] = value; + } + + return ret; } static int i2c_r(struct sd *sd, __u8 reg) { + int ret; + + if (sd->sensor_reg_cache[reg] != -1) + return sd->sensor_reg_cache[reg]; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - return ov511_i2c_r(sd, reg); + ret = ov511_i2c_r(sd, reg); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: case BRIDGE_OV519: - return ov518_i2c_r(sd, reg); + ret = ov518_i2c_r(sd, reg); + break; case BRIDGE_OVFX2: - return ovfx2_i2c_r(sd, reg); + ret = ovfx2_i2c_r(sd, reg); + break; case BRIDGE_W9968CF: - return w9968cf_i2c_r(sd, reg); + ret = w9968cf_i2c_r(sd, reg); + break; } - return -1; /* Should never happen */ + + if (ret >= 0) + sd->sensor_reg_cache[reg] = ret; + + return ret; } /* Writes bits at positions specified by mask to an I2C reg. Bits that are in From 8394bcf3fc0293aa5cd07e2a1a3c6bf4e1a5b835 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 Oct 2009 11:26:22 -0300 Subject: [PATCH 104/345] V4L/DVB (13180): gspca-w9968cf: Don't add an extra packet to the buffer after the EOF gspca-w9968cf: Don't add an extra packet to the buffer after the EOF, this makes the frame data size bigger then it should be which makes gstreamer discard it. This patch also fixes an unrelated compiler warning. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 2 +- drivers/media/video/gspca/w996Xcf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 91e9b23a3a01..ef88e244df17 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2248,7 +2248,7 @@ static int i2c_w(struct sd *sd, __u8 reg, __u8 value) static int i2c_r(struct sd *sd, __u8 reg) { - int ret; + int ret = -1; if (sd->sensor_reg_cache[reg] != -1) return sd->sensor_reg_cache[reg]; diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index ba3a28d4f87f..3bdc6b405e27 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -580,7 +580,7 @@ static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, /* An empty packet signals EOF */ if (gspca_dev->empty_packet) { frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, len); + NULL, 0); gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); gspca_dev->empty_packet = 0; From 79b359025d57969decb465973f7c0ea195009007 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 19 Oct 2009 06:08:01 -0300 Subject: [PATCH 105/345] V4L/DVB (13181): gspca w9968cf: Add support for JPEG compression gspca w9968cf: Add support for JPEG compression, this enables much higher framerates at 320x240 / 352x288 and also allows for 640x480 mode for cams which can do this. The w9968cf uses planar JPEG, which libv4l until now did not support, so this requires atleast version 0.6.3 of libv4l. And something important I forgot to mention in my earlier w9968cf commits: Many thanks to Hans Verkuil for giving me a w9968cf based cam, which has allowed me to develop the gspca w9968cf support. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 6 +- drivers/media/video/gspca/ov519.c | 68 +++++++++++-- drivers/media/video/gspca/w996Xcf.c | 143 ++++++++++++++++------------ 3 files changed, 146 insertions(+), 71 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index c69f858c9278..7ecae636e6ad 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -956,7 +956,8 @@ config VIDEO_OVCAMCHIP ---help--- This driver is DEPRECATED please use the gspca ov519 module instead. Note that for the ov511 / ov518 support of the gspca module - you need atleast version 0.6.0 of libv4l. + you need atleast version 0.6.0 of libv4l and for the w9968cf + atleast version 0.6.3 of libv4l. Support for the OmniVision OV6xxx and OV7xxx series of camera chips. This driver is intended to be used with the ov511 and w9968cf USB @@ -970,7 +971,8 @@ config USB_W9968CF depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP ---help--- This driver is DEPRECATED please use the gspca ov519 module - instead. + instead. Note that for the w9968cf support of the gspca module + you need atleast version 0.6.3 of libv4l. Say Y here if you want support for cameras based on OV681 or Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index ef88e244df17..a63cb75aa7f1 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -80,6 +80,10 @@ struct sd { __u8 vflip; __u8 autobrightness; __u8 freq; + __u8 quality; +#define QUALITY_MIN 50 +#define QUALITY_MAX 70 +#define QUALITY_DEF 50 __u8 stopped; /* Streaming is temporarily paused */ @@ -104,6 +108,8 @@ struct sd { int sensor_width; int sensor_height; int sensor_reg_cache[256]; + + u8 *jpeg_hdr; }; /* Note this is a bit of a hack, but the w9968cf driver needs the code for all @@ -2303,8 +2309,6 @@ static int i2c_w_mask(struct sd *sd, * registers while the camera is streaming */ static inline int ov51x_stop(struct sd *sd) { - int ret; - PDEBUG(D_STREAM, "stopping"); sd->stopped = 1; switch (sd->bridge) { @@ -2319,10 +2323,7 @@ static inline int ov51x_stop(struct sd *sd) case BRIDGE_OVFX2: return reg_w_mask(sd, 0x0f, 0x00, 0x02); case BRIDGE_W9968CF: - ret = reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ - ret += reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ - ret += reg_w(sd, 0x16, 0x0000); /* stop video capture */ - return ret; + return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ } return 0; @@ -3088,8 +3089,8 @@ static int sd_config(struct gspca_dev *gspca_dev, case BRIDGE_W9968CF: cam->cam_mode = w9968cf_vga_mode; cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); - /* if (sd->sif) - cam->nmodes--; */ + if (sd->sif) + cam->nmodes--; /* w9968cf needs initialisation once the sensor is known */ if (w9968cf_init(sd) < 0) @@ -3113,6 +3114,7 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << OV7670_FREQ_IDX); } + sd->quality = QUALITY_DEF; if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; /* OV8610 Frequency filter control should work but needs testing */ @@ -3909,6 +3911,14 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ov51x_led_control(sd, 0); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->bridge == BRIDGE_W9968CF) + w9968cf_stop0(sd); +} + static void ov511_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *in, /* isoc packet */ @@ -4421,6 +4431,45 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, return -EINVAL; } +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->bridge != BRIDGE_W9968CF) + return -EINVAL; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT | + V4L2_JPEG_MARKER_DRI; + return 0; +} + +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->bridge != BRIDGE_W9968CF) + return -EINVAL; + + if (gspca_dev->streaming) + return -EBUSY; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + + /* Return resulting jcomp params to app */ + sd_get_jcomp(gspca_dev, jcomp); + + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -4430,8 +4479,11 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 3bdc6b405e27..7378f0495082 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -31,57 +31,14 @@ the sensor drivers to v4l2 sub drivers, and properly split of this driver from ov519.c */ +/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */ +#define CONEX_CAM +#include "jpeg.h" + #define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ -/* FIXME make this runtime configurable */ -/* Comment/uncomment this for high/low quality of compressed video */ -#define W9968CF_DEC_FAST_LOWQUALITY_VIDEO - -#ifdef W9968CF_DEC_FAST_LOWQUALITY_VIDEO -static const unsigned char Y_QUANTABLE[64] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 -}; - -static const unsigned char UV_QUANTABLE[64] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 -}; -#else -static const unsigned char Y_QUANTABLE[64] = { - 8, 5, 5, 8, 12, 20, 25, 30, - 6, 6, 7, 9, 13, 29, 30, 27, - 7, 6, 8, 12, 20, 28, 34, 28, - 7, 8, 11, 14, 25, 43, 40, 31, - 9, 11, 18, 28, 34, 54, 51, 38, - 12, 17, 27, 32, 40, 52, 56, 46, - 24, 32, 39, 43, 51, 60, 60, 50, - 36, 46, 47, 49, 56, 50, 51, 49 -}; - -static const unsigned char UV_QUANTABLE[64] = { - 8, 9, 12, 23, 49, 49, 49, 49, - 9, 10, 13, 33, 49, 49, 49, 49, - 12, 13, 28, 49, 49, 49, 49, 49, - 23, 33, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49 -}; -#endif +#define Y_QUANTABLE (sd->jpeg_hdr + JPEG_QT0_OFFSET) +#define UV_QUANTABLE (sd->jpeg_hdr + JPEG_QT1_OFFSET) static const struct v4l2_pix_format w9968cf_vga_mode[] = { {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, @@ -92,18 +49,18 @@ static const struct v4l2_pix_format w9968cf_vga_mode[] = { .bytesperline = 176 * 2, .sizeimage = 176 * 144 * 2, .colorspace = V4L2_COLORSPACE_JPEG}, - {320, 240, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320 * 2, .sizeimage = 320 * 240 * 2, .colorspace = V4L2_COLORSPACE_JPEG}, - {352, 288, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, + {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 352 * 2, .sizeimage = 352 * 288 * 2, .colorspace = V4L2_COLORSPACE_JPEG}, -/* {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, + {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640 * 2, .sizeimage = 640 * 480 * 2, - .colorspace = V4L2_COLORSPACE_JPEG}, */ + .colorspace = V4L2_COLORSPACE_JPEG}, }; static int reg_w(struct sd *sd, __u16 index, __u16 value); @@ -534,17 +491,35 @@ static int w9968cf_mode_init_regs(struct sd *sd) ret += reg_w(sd, 0x31, sd->gspca_dev.height); /* Y & UV frame buffer strides (in WORD) */ + if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == + V4L2_PIX_FMT_JPEG) { + ret += reg_w(sd, 0x2c, sd->gspca_dev.width/2); + ret += reg_w(sd, 0x2d, sd->gspca_dev.width/4); + } else ret += reg_w(sd, 0x2c, sd->gspca_dev.width); ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ - /* Transfer size */ - /* FIXME JPEG * 4 ?? */ + /* Transfer size in WORDS (for UYVY format only) */ val = sd->gspca_dev.width * sd->gspca_dev.height; ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ + if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == + V4L2_PIX_FMT_JPEG) { + /* We may get called multiple times (usb isoc bw negotiat.) */ + if (!sd->jpeg_hdr) + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (!sd->jpeg_hdr) + return -ENOMEM; + + jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, + sd->gspca_dev.width, 0x22); /* JPEG 420 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + ret += w9968cf_upload_quantizationtables(sd); + } + /* Video Capture Control Register */ if (sd->sensor == SEN_OV7620) { /* Seems to work around a bug in the image sensor */ @@ -557,6 +532,15 @@ static int w9968cf_mode_init_regs(struct sd *sd) val = (vs_polarity << 12) | (hs_polarity << 11); + /* NOTE: We may not have enough memory to do double buffering while + doing compression (amount of memory differs per model cam). + So we use the second image buffer also as jpeg stream buffer + (see w9968cf_init), and disable double buffering. */ + if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == + V4L2_PIX_FMT_JPEG) { + /* val |= 0x0002; YUV422P */ + val |= 0x0003; /* YUV420P */ + } else val |= 0x0080; /* Enable HW double buffering */ /* val |= 0x0020; enable clamping */ @@ -572,18 +556,55 @@ static int w9968cf_mode_init_regs(struct sd *sd) return ret; } +static void w9968cf_stop0(struct sd *sd) +{ + if (sd->gspca_dev.present) { + reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ + reg_w(sd, 0x16, 0x0000); /* stop video capture */ + } + + kfree(sd->jpeg_hdr); + sd->jpeg_hdr = NULL; +} + +/* The w9968cf docs say that a 0 sized packet means EOF (and also SOF + for the next frame). This seems to simply not be true when operating + in JPEG mode, in this case there may be empty packets within the + frame. So in JPEG mode use the JPEG SOI marker to detect SOF. + + Note to make things even more interesting the w9968cf sends *PLANAR* jpeg, + to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS, + V-data, EOI. */ static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */ { - /* An empty packet signals EOF */ - if (gspca_dev->empty_packet) { - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + struct sd *sd = (struct sd *) gspca_dev; + + if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat == + V4L2_PIX_FMT_JPEG) { + if (len >= 2 && + data[0] == 0xff && + data[1] == 0xd8) { + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - NULL, 0); - gspca_dev->empty_packet = 0; + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); + /* Strip the ff d8, our own header (which adds + huffman and quantization tables) already has this */ + len -= 2; + data += 2; + } + } else { + /* In UYVY mode an empty packet signals EOF */ + if (gspca_dev->empty_packet) { + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + NULL, 0); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + NULL, 0); + gspca_dev->empty_packet = 0; + } } gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } From 73997870c64d604f521e85a57511f36a2dc22ed0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 19 Oct 2009 06:47:03 -0300 Subject: [PATCH 106/345] V4L/DVB (13182): gspca w9968cf: slight tweak to vstart and hstart gspca w9968cf: slight tweak to vstart and hstart to get rid of black borders in 640x480 mode. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/w996Xcf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 7378f0495082..4f9add79ce13 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -442,11 +442,11 @@ static int w9968cf_set_crop_window(struct sd *sd) /* Sigh, this is dependend on the clock / framerate changes made by the frequency control, sick. */ if (sd->freq == 1) { - start_cropx = 279; - start_cropy = 35; + start_cropx = 277; + start_cropy = 37; } else { - start_cropx = 103; - start_cropy = 35; + start_cropx = 105; + start_cropy = 37; } } else { start_cropx = 320; From 21f1b932dbcc5ed18444e6995aeb856e583804ae Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 23 Oct 2009 06:50:12 -0300 Subject: [PATCH 107/345] V4L/DVB (13183): gspca: add stv0680 subdriver This patch adds a new subdriver to gspca supporting cams with the stv0680 bridge (replacing the old in kernel v4l1 driver). Many thanks to Hans Verkuil for providing me with one of the 2 cams used in testing this new sub driver. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 6 +- drivers/media/video/gspca/Kconfig | 9 + drivers/media/video/gspca/Makefile | 2 + drivers/media/video/gspca/stv0680.c | 365 ++++++++++++++++++++++++++++ include/linux/videodev2.h | 1 + 5 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 drivers/media/video/gspca/stv0680.c diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 7ecae636e6ad..82ae85c975f5 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -1016,9 +1016,13 @@ config USB_SE401 source "drivers/media/video/sn9c102/Kconfig" config USB_STV680 - tristate "USB STV680 (Pencam) Camera support" + tristate "USB STV680 (Pencam) Camera support (DEPRECATED)" depends on VIDEO_V4L1 ---help--- + This driver is DEPRECATED please use the gspca stv0680 module + instead. Note that for the gspca stv0680 module you need + atleast version 0.6.3 of libv4l. + Say Y here if you want to connect this type of camera to your computer's USB port. This includes the Pencam line of cameras. See for more information diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index cbc2367719f0..568edbbb8948 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -230,6 +230,15 @@ config USB_GSPCA_STK014 To compile this driver as a module, choose M here: the module will be called gspca_stk014. +config USB_GSPCA_STV0680 + tristate "STV0680 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the STV0680 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_stv0680. + config USB_GSPCA_SUNPLUS tristate "SUNPLUS USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index b7420818037e..770b01387e99 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o +obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o @@ -50,6 +51,7 @@ gspca_spca561-objs := spca561.o gspca_sq905-objs := sq905.o gspca_sq905c-objs := sq905c.o gspca_stk014-objs := stk014.o +gspca_stv0680-objs := stv0680.o gspca_sunplus-objs := sunplus.o gspca_t613-objs := t613.o gspca_tv8532-objs := tv8532.o diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c new file mode 100644 index 000000000000..0981ce14235d --- /dev/null +++ b/drivers/media/video/gspca/stv0680.c @@ -0,0 +1,365 @@ +/* + * STV0680 USB Camera Driver + * + * Copyright (C) 2009 Hans de Goede + * + * This module is adapted from the in kernel v4l1 stv680 driver: + * + * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net) + * + * Thanks to STMicroelectronics for information on the usb commands, and + * to Steve Miller at STM for his help and encouragement while I was + * writing this driver. + * + * 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 + * + */ + +#define MODULE_NAME "stv0680" + +#include "gspca.h" + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("STV0680 USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* specific webcam descriptor */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + struct v4l2_pix_format mode; + u8 orig_mode; + u8 video_mode; + u8 current_mode; +}; + +/* V4L2 controls supported by the driver */ +static struct ctrl sd_ctrls[] = { +}; + +static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, + int size) +{ + int ret = -1; + u8 req_type = 0; + + switch (set) { + case 0: /* 0xc1 */ + req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; + break; + case 1: /* 0x41 */ + req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; + break; + case 2: /* 0x80 */ + req_type = USB_DIR_IN | USB_RECIP_DEVICE; + break; + case 3: /* 0x40 */ + req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + break; + } + + ret = usb_control_msg(gspca_dev->dev, + usb_rcvctrlpipe(gspca_dev->dev, 0), + req, req_type, + val, 0, gspca_dev->usb_buf, size, 500); + + if ((ret < 0) && (req != 0x0a)) + PDEBUG(D_ERR, + "usb_control_msg error %i, request = 0x%x, error = %i", + set, req, ret); + + return ret; +} + +static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret) +{ + stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */ + PDEBUG(D_ERR, "last error: %i, command = 0x%x", + gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); + return ret; +} + +static int stv0680_get_video_mode(struct gspca_dev *gspca_dev) +{ + /* Note not sure if this init of usb_buf is really necessary */ + memset(gspca_dev->usb_buf, 0, 8); + gspca_dev->usb_buf[0] = 0x0f; + + if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) { + PDEBUG(D_ERR, "Get_Camera_Mode failed"); + return stv0680_handle_error(gspca_dev, -EIO); + } + + return gspca_dev->usb_buf[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */ +} + +static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->current_mode == mode) + return 0; + + memset(gspca_dev->usb_buf, 0, 8); + gspca_dev->usb_buf[0] = mode; + + if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) { + PDEBUG(D_ERR, "Set_Camera_Mode failed"); + return stv0680_handle_error(gspca_dev, -EIO); + } + + /* Verify we got what we've asked for */ + if (stv0680_get_video_mode(gspca_dev) != mode) { + PDEBUG(D_ERR, "Error setting camera video mode!"); + return -EIO; + } + + sd->current_mode = mode; + + return 0; +} + +/* this function is called at probe time */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + int ret; + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; + + /* ping camera to be sure STV0680 is present */ + if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 || + gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) { + PDEBUG(D_ERR, "STV(e): camera ping failed!!"); + return stv0680_handle_error(gspca_dev, -ENODEV); + } + + /* get camera descriptor */ + if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x09) != 0x09) + return stv0680_handle_error(gspca_dev, -ENODEV); + + if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 || + gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) { + PDEBUG(D_ERR, "Could not get descriptor 0200."); + return stv0680_handle_error(gspca_dev, -ENODEV); + } + if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02) + return stv0680_handle_error(gspca_dev, -ENODEV); + if (stv_sndctrl(gspca_dev, 0, 0x8b, 0, 0x24) != 0x24) + return stv0680_handle_error(gspca_dev, -ENODEV); + if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10) + return stv0680_handle_error(gspca_dev, -ENODEV); + + if (!(gspca_dev->usb_buf[7] & 0x09)) { + PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode"); + return -ENODEV; + } + if (gspca_dev->usb_buf[7] & 0x01) + PDEBUG(D_PROBE, "Camera supports CIF mode"); + if (gspca_dev->usb_buf[7] & 0x02) + PDEBUG(D_PROBE, "Camera supports VGA mode"); + if (gspca_dev->usb_buf[7] & 0x08) + PDEBUG(D_PROBE, "Camera supports QVGA mode"); + + if (gspca_dev->usb_buf[7] & 0x01) + sd->video_mode = 0x00; /* CIF */ + else + sd->video_mode = 0x03; /* QVGA */ + + /* FW rev, ASIC rev, sensor ID */ + PDEBUG(D_PROBE, "Firmware rev is %i.%i", + gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); + PDEBUG(D_PROBE, "ASIC rev is %i.%i", + gspca_dev->usb_buf[2], gspca_dev->usb_buf[3]); + PDEBUG(D_PROBE, "Sensor ID is %i", + (gspca_dev->usb_buf[4]*16) + (gspca_dev->usb_buf[5]>>4)); + + + ret = stv0680_get_video_mode(gspca_dev); + if (ret < 0) + return ret; + sd->current_mode = sd->orig_mode = ret; + + ret = stv0680_set_video_mode(gspca_dev, sd->video_mode); + if (ret < 0) + return ret; + + /* Get mode details */ + if (stv_sndctrl(gspca_dev, 0, 0x8f, 0, 0x10) != 0x10) + return stv0680_handle_error(gspca_dev, -EIO); + + cam->bulk = 1; + cam->bulk_nurbs = 1; /* The cam cannot handle more */ + cam->bulk_size = (gspca_dev->usb_buf[0] << 24) | + (gspca_dev->usb_buf[1] << 16) | + (gspca_dev->usb_buf[2] << 8) | + (gspca_dev->usb_buf[3]); + sd->mode.width = (gspca_dev->usb_buf[4] << 8) | + (gspca_dev->usb_buf[5]); /* 322, 356, 644 */ + sd->mode.height = (gspca_dev->usb_buf[6] << 8) | + (gspca_dev->usb_buf[7]); /* 242, 292, 484 */ + sd->mode.pixelformat = V4L2_PIX_FMT_STV0680; + sd->mode.field = V4L2_FIELD_NONE; + sd->mode.bytesperline = sd->mode.width; + sd->mode.sizeimage = cam->bulk_size; + sd->mode.colorspace = V4L2_COLORSPACE_SRGB; + + /* origGain = gspca_dev->usb_buf[12]; */ + + cam->cam_mode = &sd->mode; + cam->nmodes = 1; + + + ret = stv0680_set_video_mode(gspca_dev, sd->orig_mode); + if (ret < 0) + return ret; + + if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 || + gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) { + PDEBUG(D_ERR, "Could not get descriptor 0100."); + return stv0680_handle_error(gspca_dev, -EIO); + } + + return 0; +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + return 0; +} + +/* -- start the camera -- */ +static int sd_start(struct gspca_dev *gspca_dev) +{ + int ret; + struct sd *sd = (struct sd *) gspca_dev; + + ret = stv0680_set_video_mode(gspca_dev, sd->video_mode); + if (ret < 0) + return ret; + + if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10) + return stv0680_handle_error(gspca_dev, -EIO); + + /* Start stream at: + 0x0000 = CIF (352x288) + 0x0100 = VGA (640x480) + 0x0300 = QVGA (320x240) */ + if (stv_sndctrl(gspca_dev, 1, 0x09, sd->video_mode << 8, 0x0) != 0x0) + return stv0680_handle_error(gspca_dev, -EIO); + + return 0; +} + +static void sd_stopN(struct gspca_dev *gspca_dev) +{ + /* This is a high priority command; it stops all lower order cmds */ + if (stv_sndctrl(gspca_dev, 1, 0x04, 0x0000, 0x0) != 0x0) + stv0680_handle_error(gspca_dev, -EIO); +} + +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (!sd->gspca_dev.present) + return; + + stv0680_set_video_mode(gspca_dev, sd->orig_mode); +} + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, + __u8 *data, + int len) +{ + struct sd *sd = (struct sd *) gspca_dev; + + /* Every now and then the camera sends a 16 byte packet, no idea + what it contains, but it is not image data, when this + happens the frame received before this packet is corrupt, + so discard it. */ + if (len != sd->mode.sizeimage) { + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } + + /* Finish the previous frame, we do this upon reception of the next + packet, even though it is already complete so that the strange 16 + byte packets send after a corrupt frame can discard it. */ + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, NULL, 0); + + /* Store the just received frame */ + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); +} + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stopN = sd_stopN, + .stop0 = sd_stop0, + .pkt_scan = sd_pkt_scan, +}; + +/* -- module initialisation -- */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x0553, 0x0202)}, + {USB_DEVICE(0x041e, 0x4007)}, + {} +}; +MODULE_DEVICE_TABLE(usb, device_table); + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + 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); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index b59e78c57161..b9a799a35763 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -361,6 +361,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ #define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */ #define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ +#define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */ /* * F O R M A T E N U M E R A T I O N From bf926adfbbb36876396511f1bdc78f73dc596e21 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 23 Oct 2009 06:56:06 -0300 Subject: [PATCH 108/345] V4L/DVB (13184): gspca: Don't forget to resubmit URB's in case of an error The gscpa core was not resubmitting URB's when the URB status was an error, this means we will loose URB's (potentially all stopping the stream) in case of sporadic USB issues. I've seen this with an Aiptek stv0680 based PenCam connected through an USB 2.0 hub. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ebaa2425fb50..3298e33c7822 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -138,7 +138,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, if (!gspca_dev->frozen) #endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); - return; + goto resubmit; } pkt_scan = gspca_dev->sd_desc->pkt_scan; for (i = 0; i < urb->number_of_packets; i++) { @@ -174,6 +174,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, pkt_scan(gspca_dev, frame, data, len); } +resubmit: /* resubmit the URB */ st = usb_submit_urb(urb, GFP_ATOMIC); if (st < 0) @@ -220,7 +221,7 @@ static void bulk_irq(struct urb *urb) if (!gspca_dev->frozen) #endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); - return; + goto resubmit; } /* check the availability of the frame buffer */ @@ -235,6 +236,7 @@ static void bulk_irq(struct urb *urb) urb->actual_length); } +resubmit: /* resubmit the URB */ if (gspca_dev->cam.bulk_nurbs != 0) { st = usb_submit_urb(urb, GFP_ATOMIC); From 6a540bdf0134fc7198dd053a352b4c414a5e7e19 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 24 Oct 2009 15:02:14 -0300 Subject: [PATCH 109/345] V4L/DVB (13185): gspca: Don't resubmit error status URB's when suspending gspca: Don't resubmit error status URB's when suspending Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 3298e33c7822..eb166048540d 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -135,9 +135,10 @@ static void fill_frame(struct gspca_dev *gspca_dev, if (urb->status == -ESHUTDOWN) return; /* disconnection */ #ifdef CONFIG_PM - if (!gspca_dev->frozen) + if (gspca_dev->frozen) + return; #endif - PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); + PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); goto resubmit; } pkt_scan = gspca_dev->sd_desc->pkt_scan; @@ -218,9 +219,10 @@ static void bulk_irq(struct urb *urb) break; default: #ifdef CONFIG_PM - if (!gspca_dev->frozen) + if (gspca_dev->frozen) + return; #endif - PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); + PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); goto resubmit; } From 36a91879d85396ea6470d3a5bde8287e40b5a0e9 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 13 Oct 2009 23:32:29 -0300 Subject: [PATCH 110/345] V4L/DVB (13187): au8522: add support for saturation and hue controls Add support for saturation/hue controls, prompted by errors showing up in the mythbackend log. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522_decoder.c | 22 ++++++++++++++++++-- drivers/media/dvb/frontends/au8522_priv.h | 2 ++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 74981ee923c8..dee609cdd77a 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -23,7 +23,6 @@ /* Developer notes: * * VBI support is not yet working - * Saturation and hue setting are not yet working * Enough is implemented here for CVBS and S-Video inputs, but the actual * analog demodulator code isn't implemented (not needed for xc5000 since it * has its own demodulator and outputs CVBS) @@ -236,8 +235,10 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode) state->contrast = 0x79; au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80); au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80); + state->saturation = 0x80; au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00); au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00); + state->hue = 0x00; /* Other decoder registers */ au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00); @@ -504,7 +505,19 @@ static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ctrl->value); break; case V4L2_CID_SATURATION: + state->saturation = ctrl->value; + au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, + ctrl->value); + au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, + ctrl->value); + break; case V4L2_CID_HUE: + state->hue = ctrl->value; + au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, + ctrl->value >> 8); + au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, + ctrl->value & 0xFF); + break; case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: @@ -534,7 +547,11 @@ static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ctrl->value = state->contrast; break; case V4L2_CID_SATURATION: + ctrl->value = state->saturation; + break; case V4L2_CID_HUE: + ctrl->value = state->hue; + break; case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: @@ -632,8 +649,9 @@ static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) case V4L2_CID_BRIGHTNESS: return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_HUE: - /* Not yet implemented */ + return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0); default: break; } diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h index f328f2b3ad3d..c74c4e72fe91 100644 --- a/drivers/media/dvb/frontends/au8522_priv.h +++ b/drivers/media/dvb/frontends/au8522_priv.h @@ -62,6 +62,8 @@ struct au8522_state { u32 rev; u8 brightness; u8 contrast; + u8 saturation; + s16 hue; }; /* These are routines shared by both the VSB/QAM demodulator and the analog From 760c466c66db40cde5953e93b94ae20c7610fb20 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 13 Oct 2009 23:44:14 -0300 Subject: [PATCH 111/345] V4L/DVB (13188): xc5000: return an error on tuning attempts if firmware not loaded Xc5000 tuning attempts shouldn't return zero in the case where the firmware did not load successfully. Thanks to Michael Krufky for pointing out this issue. Cc: Michael Krufky Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index d33bf831e76c..432003dded7c 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -633,8 +633,12 @@ static int xc5000_set_params(struct dvb_frontend *fe, struct xc5000_priv *priv = fe->tuner_priv; int ret; - if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) - xc_load_fw_and_init_tuner(fe); + if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { + if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { + dprintk(1, "Unable to load firmware and init tuner\n"); + return -EINVAL; + } + } dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); @@ -884,8 +888,12 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, if (priv->i2c_props.adap == NULL) return -EINVAL; - if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) - xc_load_fw_and_init_tuner(fe); + if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { + if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { + dprintk(1, "Unable to load firmware and init tuner\n"); + return -EINVAL; + } + } switch (params->mode) { case V4L2_TUNER_RADIO: From e0d49e2d3ae3cd887b7999c4227c04008d2a02c4 Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Mon, 5 Oct 2009 05:41:30 -0300 Subject: [PATCH 112/345] V4L/DVB (13192): gspca - pac_common: redesign function for finding Start Of Frame The original implementation of pac_find_sof() does not always find the Start Of Frame (SOF) marker. Replace it with a state machine based design. Acked-by: Hans de Goede Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac_common.h | 84 ++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h index 34d4b1494cd5..d3006539fb82 100644 --- a/drivers/media/video/gspca/pac_common.h +++ b/drivers/media/video/gspca/pac_common.h @@ -33,6 +33,45 @@ static const unsigned char pac_sof_marker[5] = { 0xff, 0xff, 0x00, 0xff, 0x96 }; +/* + The following state machine finds the SOF marker sequence + 0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream. + + +----------+ + | 0: START |<---------------\ + +----------+<-\ | + | \---/otherwise | + v 0xff | + +----------+ otherwise | + | 1 |--------------->* + | | ^ + +----------+ | + | | + v 0xff | + +----------+<-\0xff | + /->| |--/ | + | | 2 |--------------->* + | | | otherwise ^ + | +----------+ | + | | | + | v 0x00 | + | +----------+ | + | | 3 | | + | | |--------------->* + | +----------+ otherwise ^ + | | | + 0xff | v 0xff | + | +----------+ | + \--| 4 | | + | |----------------/ + +----------+ otherwise + | + v 0x96 + +----------+ + | FOUND | + +----------+ +*/ + static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, unsigned char *m, int len) { @@ -41,17 +80,54 @@ static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, /* Search for the SOF marker (fixed part) in the header */ for (i = 0; i < len; i++) { - if (m[i] == pac_sof_marker[sd->sof_read]) { - sd->sof_read++; - if (sd->sof_read == sizeof(pac_sof_marker)) { + switch (sd->sof_read) { + case 0: + if (m[i] == 0xff) + sd->sof_read = 1; + break; + case 1: + if (m[i] == 0xff) + sd->sof_read = 2; + else + sd->sof_read = 0; + break; + case 2: + switch (m[i]) { + case 0x00: + sd->sof_read = 3; + break; + case 0xff: + /* stay in this state */ + break; + default: + sd->sof_read = 0; + } + break; + case 3: + if (m[i] == 0xff) + sd->sof_read = 4; + else + sd->sof_read = 0; + break; + case 4: + switch (m[i]) { + case 0x96: + /* Pattern found */ PDEBUG(D_FRAM, "SOF found, bytes to analyze: %u." " Frame starts at byte #%u", len, i + 1); sd->sof_read = 0; return m + i + 1; + break; + case 0xff: + sd->sof_read = 2; + break; + default: + sd->sof_read = 0; } - } else { + break; + default: sd->sof_read = 0; } } From 013db7575bdfb57d295e9a27186f52c7547ef2d2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 7 Oct 2009 05:24:19 -0300 Subject: [PATCH 113/345] V4L/DVB (13193): gspca - zc3xx.c: Change init sequences of sensor tas5130c. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 228 +++++++++--------------------- 1 file changed, 69 insertions(+), 159 deletions(-) diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index e544630757c8..0aa87d2958a0 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -5481,7 +5481,7 @@ static const struct usb_action tas5130CK_InitialScale[] = { {} }; -static const struct usb_action tas5130cxx_Initial[] = { +static const struct usb_action tas5130cxx_InitialScale[] = { /* 320x240 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, @@ -5510,74 +5510,19 @@ static const struct usb_action tas5130cxx_Initial[] = { {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x68, ZC3XX_R18D_YTARGET}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, + {0xa0, 0x95, ZC3XX_R18D_YTARGET}, + {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, {0xa0, 0x00, 0x01ad}, {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - - {0xa0, 0x68, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xec, ZC3XX_R10B_RGB01}, - {0xa0, 0xec, ZC3XX_R10C_RGB02}, - {0xa0, 0xec, ZC3XX_R10D_RGB10}, - {0xa0, 0x68, ZC3XX_R10E_RGB11}, - {0xa0, 0xec, ZC3XX_R10F_RGB12}, - {0xa0, 0xec, ZC3XX_R110_RGB20}, - {0xa0, 0xec, ZC3XX_R111_RGB21}, - {0xa0, 0x68, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x018d}, - {0xa0, 0x90, ZC3XX_R18D_YTARGET}, /* 90 */ - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - - {0xaa, 0xa3, 0x0001}, - {0xaa, 0xa4, 0x0077}, - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, - {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, - - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 00 */ - {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 03 */ - {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* e8 */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 0 */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 0 */ - {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 7d */ - - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 08 */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 24 */ - {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, - {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 50 */ - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, {} }; -static const struct usb_action tas5130cxx_InitialScale[] = { -/*?? {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, */ +static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT}, {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING}, @@ -5601,63 +5546,13 @@ static const struct usb_action tas5130cxx_InitialScale[] = { {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x68, ZC3XX_R18D_YTARGET}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, + {0xa0, 0x95, ZC3XX_R18D_YTARGET}, + {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, {0xa0, 0x00, 0x01ad}, {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa1, 0x01, 0x0008}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - - {0xa0, 0x68, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xec, ZC3XX_R10B_RGB01}, - {0xa0, 0xec, ZC3XX_R10C_RGB02}, - {0xa0, 0xec, ZC3XX_R10D_RGB10}, - {0xa0, 0x68, ZC3XX_R10E_RGB11}, - {0xa0, 0xec, ZC3XX_R10F_RGB12}, - {0xa0, 0xec, ZC3XX_R110_RGB20}, - {0xa0, 0xec, ZC3XX_R111_RGB21}, - {0xa0, 0x68, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x018d}, - {0xa0, 0x90, ZC3XX_R18D_YTARGET}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0xa3, 0x0001}, - {0xaa, 0xa4, 0x0063}, - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, - {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x38, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, - {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, {} }; static const struct usb_action tas5130cxx_50HZ[] = { @@ -5667,20 +5562,22 @@ static const struct usb_action tas5130cxx_50HZ[] = { {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */ - {0xa0, 0x38, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,38,cc */ + {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW}, {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ + {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */ {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */ {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */ {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ + {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW}, + {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, {} }; static const struct usb_action tas5130cxx_50HZScale[] = { @@ -5690,20 +5587,22 @@ static const struct usb_action tas5130cxx_50HZScale[] = { {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */ - {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e8,cc */ + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xd0, ZC3XX_R192_EXPOSURELIMITLOW}, {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */ - {0xa0, 0x14, ZC3XX_R18C_AEFREEZE}, /* 01,8c,14,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ + {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */ {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */ {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */ {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ + {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW}, + {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, {} }; static const struct usb_action tas5130cxx_60HZ[] = { @@ -5713,20 +5612,22 @@ static const struct usb_action tas5130cxx_60HZ[] = { {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,01,cc */ - {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ + {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ + {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */ {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ + {0xa0, 0x28, ZC3XX_R0A0_MAXXLOW}, + {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, {} }; static const struct usb_action tas5130cxx_60HZScale[] = { @@ -5736,20 +5637,22 @@ static const struct usb_action tas5130cxx_60HZScale[] = { {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */ - {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e8,cc */ + {0xa0, 0x09, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x47, ZC3XX_R192_EXPOSURELIMITLOW}, {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */ - {0xa0, 0x14, ZC3XX_R18C_AEFREEZE}, /* 01,8c,14,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ + {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */ {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ + {0xa0, 0x20, ZC3XX_R0A0_MAXXLOW}, + {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, {} }; static const struct usb_action tas5130cxx_NoFliker[] = { @@ -5759,13 +5662,13 @@ static const struct usb_action tas5130cxx_NoFliker[] = { {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,01,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, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ + {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */ @@ -5773,6 +5676,8 @@ static const struct usb_action tas5130cxx_NoFliker[] = { {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */ + {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW}, + {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, {} }; @@ -5783,13 +5688,13 @@ static const struct usb_action tas5130cxx_NoFlikerScale[] = { {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,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, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ + {0xa0, 0x0a, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */ @@ -5797,6 +5702,8 @@ static const struct usb_action tas5130cxx_NoFlikerScale[] = { {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */ + {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW}, + {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, {} }; @@ -6206,6 +6113,8 @@ static void setmatrix(struct gspca_dev *gspca_dev) {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 tas5130c_matrix[9] = + {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; static const __u8 vf0250_matrix[9] = {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; static const __u8 *matrix_tb[SENSOR_MAX] = { @@ -6225,7 +6134,7 @@ static void setmatrix(struct gspca_dev *gspca_dev) NULL, /* SENSOR_PB0330 13 */ po2030_matrix, /* SENSOR_PO2030 14 */ NULL, /* SENSOR_TAS5130CK 15 */ - NULL, /* SENSOR_TAS5130CXX 16 */ + tas5130c_matrix, /* SENSOR_TAS5130CXX 16 */ vf0250_matrix, /* SENSOR_TAS5130C_VF0250 17 */ }; @@ -6491,13 +6400,13 @@ static int setlightfreq(struct gspca_dev *gspca_dev) PO2030_50HZ, PO2030_50HZ, PO2030_60HZ, PO2030_60HZ}, /* SENSOR_TAS5130CK 15 */ - {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, - tas5130cxx_50HZ, tas5130cxx_50HZScale, - tas5130cxx_60HZ, tas5130cxx_60HZScale}, + {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, + tas5130cxx_50HZScale, tas5130cxx_50HZ, + tas5130cxx_60HZScale, tas5130cxx_60HZ}, /* SENSOR_TAS5130CXX 16 */ - {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, - tas5130cxx_50HZ, tas5130cxx_50HZScale, - tas5130cxx_60HZ, tas5130cxx_60HZScale}, + {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, + tas5130cxx_50HZScale, tas5130cxx_50HZ, + tas5130cxx_60HZScale, tas5130cxx_60HZ}, /* SENSOR_TAS5130C_VF0250 17 */ {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, @@ -6689,6 +6598,7 @@ struct sensor_by_chipset_revision { __u8 internal_sensor_id; }; static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { + {0xc000, 0x12}, /* TAS5130C */ {0xc001, 0x13}, /* MI0360 */ {0xe001, 0x13}, {0x8001, 0x13}, @@ -6866,7 +6776,7 @@ static int sd_config(struct gspca_dev *gspca_dev, 4, /* SENSOR_PB0330 13 */ 4, /* SENSOR_PO2030 14 */ 4, /* SENSOR_TAS5130CK 15 */ - 4, /* SENSOR_TAS5130CXX 16 */ + 3, /* SENSOR_TAS5130CXX 16 */ 3, /* SENSOR_TAS5130C_VF0250 17 */ }; @@ -6929,7 +6839,7 @@ static int sd_config(struct gspca_dev *gspca_dev, break; case 0x10: case 0x12: - PDEBUG(D_PROBE, "Find Sensor TAS5130"); + PDEBUG(D_PROBE, "Find Sensor TAS5130C"); sd->sensor = SENSOR_TAS5130CXX; break; case 0x11: @@ -7062,7 +6972,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* or {pb03303x_InitialScale, pb03303x_Initial}, */ {PO2030_mode0, PO2030_mode1}, /* 14 */ {tas5130CK_InitialScale, tas5130CK_Initial}, /* 15 */ - {tas5130cxx_InitialScale, tas5130cxx_Initial}, /* 16 */ + {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 16 */ {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial}, /* 17 */ }; From 216f05aa2a704ab8dfbfb3ca36da1e04d2a9ee67 Mon Sep 17 00:00:00 2001 From: Olivier Lorin Date: Thu, 15 Oct 2009 04:12:46 -0300 Subject: [PATCH 114/345] V4L/DVB (13194): gspca - gl860: improvement of the main driver part - fix for warning compilation about sd_ctrls - trace improvement while probing the sensor Signed-off-by: Olivier Lorin Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gl860/gl860.c | 43 ++++++++++++------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index 6ef59ac7f502..1c3ec0242c32 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c @@ -23,8 +23,8 @@ #include "gspca.h" #include "gl860.h" -MODULE_AUTHOR("Olivier Lorin "); -MODULE_DESCRIPTION("GSPCA/Genesys Logic GL860 USB Camera Driver"); +MODULE_AUTHOR("Olivier Lorin "); +MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver"); MODULE_LICENSE("GPL"); /*======================== static function declarations ====================*/ @@ -53,7 +53,7 @@ MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)"); static char sensor[7]; module_param_string(sensor, sensor, sizeof(sensor), 0644); MODULE_PARM_DESC(sensor, - " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640'/'')"); + " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')"); /*============================ webcam controls =============================*/ @@ -156,7 +156,7 @@ static int gl860_build_control_table(struct gspca_dev *gspca_dev) SET_MY_CTRL(V4L2_CID_VFLIP, V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip) SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CTRL_TYPE_BOOLEAN, "50Hz", AC50Hz) + V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz) return nCtrls; } @@ -702,6 +702,7 @@ static int gl860_guess_sensor(struct gspca_dev *gspca_dev, ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL); msleep(56); + PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX"); nOV = 0; for (ntry = 0; ntry < 4; ntry++) { ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); @@ -711,14 +712,14 @@ static int gl860_guess_sensor(struct gspca_dev *gspca_dev, ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL); msleep(10); ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe); - PDEBUG(D_PROBE, "1st probe=%02x", probe); + PDEBUG(D_PROBE, "probe=0x%02x", probe); if (probe == 0xff) nOV++; } if (nOV) { - PDEBUG(D_PROBE, "0xff -> sensor OVXXXX"); - PDEBUG(D_PROBE, "Probing for sensor OV2640 or OV9655"); + PDEBUG(D_PROBE, "0xff -> OVXXXX"); + PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655"); nb26 = nb96 = 0; for (ntry = 0; ntry < 4; ntry++) { @@ -728,40 +729,38 @@ static int gl860_guess_sensor(struct gspca_dev *gspca_dev, ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a, 0, NULL); msleep(10); + /* Wait for 26(OV2640) or 96(OV9655) */ ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a, 1, &probe); - PDEBUG(D_PROBE, "2nd probe=%02x", probe); - if (probe == 0x00) - nb26++; if (probe == 0x26 || probe == 0x40) { + PDEBUG(D_PROBE, + "probe=0x%02x -> OV2640", + probe); sd->sensor = ID_OV2640; nb26 += 4; break; } if (probe == 0x96 || probe == 0x55) { + PDEBUG(D_PROBE, + "probe=0x%02x -> OV9655", + probe); sd->sensor = ID_OV9655; nb96 += 4; break; } + PDEBUG(D_PROBE, "probe=0x%02x", probe); + if (probe == 0x00) + nb26++; if (probe == 0xff) nb96++; msleep(3); } - if (nb26 < 4 && nb96 < 4) { - PDEBUG(D_PROBE, "No relevant answer "); - PDEBUG(D_PROBE, "* 1.3Mpixels -> use OV9655"); - PDEBUG(D_PROBE, "* 2.0Mpixels -> use OV2640"); - PDEBUG(D_PROBE, - "To force a sensor, add that line to " - "/etc/modprobe.d/options.conf:"); - PDEBUG(D_PROBE, "options gspca_gl860 " - "sensor=\"OV2640\" or \"OV9655\""); + if (nb26 < 4 && nb96 < 4) return -1; - } - } else { /* probe = 0 */ - PDEBUG(D_PROBE, "No 0xff -> sensor MI2020"); + } else { + PDEBUG(D_PROBE, "Not any 0xff -> MI2020"); sd->sensor = ID_MI2020; } } From be9904bdde05137085af1df98de98a49ddce9ad8 Mon Sep 17 00:00:00 2001 From: Olivier Lorin Date: Thu, 15 Oct 2009 04:13:45 -0300 Subject: [PATCH 115/345] V4L/DVB (13195): gspca - gl860: comment changes and naming scheme egalization - small changes in comments - unified naming scheme for subdriver variables Signed-off-by: Olivier Lorin Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- .../media/video/gspca/gl860/gl860-mi1320.c | 55 ++++++++------- .../media/video/gspca/gl860/gl860-mi2020.c | 69 +++++++++---------- .../media/video/gspca/gl860/gl860-ov2640.c | 57 +++++++-------- .../media/video/gspca/gl860/gl860-ov9655.c | 43 ++++++------ drivers/media/video/gspca/gl860/gl860.c | 8 +-- drivers/media/video/gspca/gl860/gl860.h | 7 +- 6 files changed, 118 insertions(+), 121 deletions(-) diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c index 39f6261c1a0c..1355e526ee84 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi1320.c +++ b/drivers/media/video/gspca/gl860/gl860-mi1320.c @@ -1,6 +1,5 @@ -/* @file gl860-mi1320.c - * @author Olivier LORIN from my logs - * @date 2009-08-27 +/* Subdriver for the GL860 chip with the MI1320 sensor + * Author Olivier LORIN from own logs * * 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 @@ -127,49 +126,49 @@ static u8 dat_wbalBL[] = static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00}; -static u8 s000[] = +static u8 dat_common00[] = "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42" "\xd8\x04\x58\x00\x04\x02"; -static u8 s001[] = +static u8 dat_common01[] = "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d" "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0"; -static u8 s002[] = +static u8 dat_common02[] = "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e" "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00" "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff"; -static u8 s003[] = +static u8 dat_common03[] = "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda" "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c" "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c"; -static u8 s004[] = +static u8 dat_common04[] = "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43"; -static u8 s005[] = +static u8 dat_common05[] = "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68" "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82" "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b"; -static u8 s006[] = +static u8 dat_common06[] = "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06" "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4" "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f"; -static u8 s007[] = +static u8 dat_common07[] = "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72" "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03" "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea" "\xe1\xff\xf1\x00"; -static u8 s008[] = +static u8 dat_common08[] = "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7" "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06" "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a"; -static u8 s009[] = +static u8 dat_common09[] = "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03" "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa" "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14"; -static u8 s010[] = +static u8 dat_common10[] = "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00" "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f" "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01" "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10"; -static u8 s011[] = +static u8 dat_common11[] = "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10" "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00" "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81"; @@ -222,26 +221,26 @@ void mi1320_init_settings(struct gspca_dev *gspca_dev) static void common(struct gspca_dev *gspca_dev) { - s32 n; /* reserved for FETCH macros */ + s32 n; /* reserved for FETCH functions */ - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, s000); + ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00); ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, s001); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01); n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common)); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s002); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s003); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, s004); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s005); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, s006); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06); keep_on_fetching_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common), n); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, s007); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s008); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s009); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, s010); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10); keep_on_fetching_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common), n); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, s011); + ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11); keep_on_fetching_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common), n); } diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c index ffb09fed3e8c..80cb3f1b36f7 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi2020.c +++ b/drivers/media/video/gspca/gl860/gl860-mi2020.c @@ -1,7 +1,6 @@ -/* @file gl860-mi2020.c - * @author Olivier LORIN, from Ice/Soro2005's logs(A), Fret_saw/Hulkie's +/* Subdriver for the GL860 chip with the MI2020 sensor + * Author Olivier LORIN, from Ice/Soro2005's logs(A), Fret_saw/Hulkie's * logs(B) and Tricid"s logs(C). With the help of Kytrix/BUGabundo/Blazercist. - * @date 2009-08-27 * * 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 @@ -41,7 +40,7 @@ static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 }; static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 }; static u8 dat_multi6[] = { 0x90, 0x00, 0x05 }; -static struct validx tbl_common_a[] = { +static struct validx tbl_common1[] = { {0x0000, 0x0000}, {1, 0xffff}, /* msleep(35); */ {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d}, {0x0000, 0x00c0}, @@ -49,7 +48,7 @@ static struct validx tbl_common_a[] = { {0x0000, 0x0058}, {0x0002, 0x0004}, {0x0041, 0x0000}, }; -static struct validx tbl_common_b[] = { +static struct validx tbl_common2[] = { {0x006a, 0x0007}, {35, 0xffff}, {0x00ef, 0x0006}, @@ -60,7 +59,7 @@ static struct validx tbl_common_b[] = { {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000}, }; -static struct idxdata tbl_common_c[] = { +static struct idxdata tbl_common3[] = { {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"}, {6, "\xff\xff\xff"}, /* 12 */ {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, @@ -109,7 +108,7 @@ static struct idxdata tbl_common_c[] = { {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, }; -static struct idxdata tbl_common_d[] = { +static struct idxdata tbl_common4[] = { {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"}, {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"}, @@ -118,7 +117,7 @@ static struct idxdata tbl_common_d[] = { {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\xc0"}, }; -static struct idxdata tbl_common_e[] = { +static struct idxdata tbl_common5[] = { {0x33, "\x8c\xa4\x04"}, {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0c"}, {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, @@ -180,7 +179,7 @@ static struct validx tbl_init_at_startup[] = { {53, 0xffff}, }; -static struct idxdata tbl_init_post_alt_low_a[] = { +static struct idxdata tbl_init_post_alt_low1[] = { {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"}, @@ -189,7 +188,7 @@ static struct idxdata tbl_init_post_alt_low_a[] = { {0x33, "\x90\x00\x9b"}, }; -static struct idxdata tbl_init_post_alt_low_b[] = { +static struct idxdata tbl_init_post_alt_low2[] = { {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, {2, "\xff\xff\xff"}, @@ -197,7 +196,7 @@ static struct idxdata tbl_init_post_alt_low_b[] = { {2, "\xff\xff\xff"}, }; -static struct idxdata tbl_init_post_alt_low_c[] = { +static struct idxdata tbl_init_post_alt_low3[] = { {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, {2, "\xff\xff\xff"}, {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"}, @@ -221,7 +220,7 @@ static struct idxdata tbl_init_post_alt_low_c[] = { {1, "\xff\xff\xff"}, }; -static struct idxdata tbl_init_post_alt_low_d[] = { +static struct idxdata tbl_init_post_alt_low4[] = { {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, @@ -267,7 +266,7 @@ static struct idxdata tbl_init_post_alt_low_d[] = { {0x32, "\x6c\x14\x08"}, }; -static struct idxdata tbl_init_post_alt_big_a[] = { +static struct idxdata tbl_init_post_alt_big1[] = { {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, {2, "\xff\xff\xff"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, @@ -288,7 +287,7 @@ static struct idxdata tbl_init_post_alt_big_a[] = { {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, }; -static struct idxdata tbl_init_post_alt_big_b[] = { +static struct idxdata tbl_init_post_alt_big2[] = { {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, @@ -317,7 +316,7 @@ static struct idxdata tbl_init_post_alt_big_b[] = { {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, }; -static struct idxdata tbl_init_post_alt_big_c[] = { +static struct idxdata tbl_init_post_alt_big3[] = { {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa1\x02"}, @@ -388,14 +387,14 @@ static void common(struct gspca_dev *gspca_dev) s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; if (_MI2020b_) { - fetch_validx(gspca_dev, tbl_common_a, ARRAY_SIZE(tbl_common_a)); + fetch_validx(gspca_dev, tbl_common1, ARRAY_SIZE(tbl_common1)); } else { if (_MI2020_) ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x0004, 0, NULL); else ctrl_out(gspca_dev, 0x40, 1, 0x0002, 0x0004, 0, NULL); msleep(35); - fetch_validx(gspca_dev, tbl_common_b, ARRAY_SIZE(tbl_common_b)); + fetch_validx(gspca_dev, tbl_common2, ARRAY_SIZE(tbl_common2)); } ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x86\x25\x01"); ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x86\x25\x00"); @@ -403,13 +402,13 @@ static void common(struct gspca_dev *gspca_dev) ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0030, 3, "\x1a\x0a\xcc"); if (reso == IMAGE_1600) msleep(2); /* 1600 */ - fetch_idxdata(gspca_dev, tbl_common_c, ARRAY_SIZE(tbl_common_c)); + fetch_idxdata(gspca_dev, tbl_common3, ARRAY_SIZE(tbl_common3)); if (_MI2020b_ || _MI2020_) - fetch_idxdata(gspca_dev, tbl_common_d, - ARRAY_SIZE(tbl_common_d)); + fetch_idxdata(gspca_dev, tbl_common4, + ARRAY_SIZE(tbl_common4)); - fetch_idxdata(gspca_dev, tbl_common_e, ARRAY_SIZE(tbl_common_e)); + fetch_idxdata(gspca_dev, tbl_common5, ARRAY_SIZE(tbl_common5)); if (_MI2020b_ || _MI2020_) { /* Different from fret */ ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x78"); @@ -525,15 +524,15 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) 12, dat_800); if (_MI2020c_) - fetch_idxdata(gspca_dev, tbl_init_post_alt_low_a, - ARRAY_SIZE(tbl_init_post_alt_low_a)); + fetch_idxdata(gspca_dev, tbl_init_post_alt_low1, + ARRAY_SIZE(tbl_init_post_alt_low1)); if (reso == IMAGE_800) - fetch_idxdata(gspca_dev, tbl_init_post_alt_low_b, - ARRAY_SIZE(tbl_init_post_alt_low_b)); + fetch_idxdata(gspca_dev, tbl_init_post_alt_low2, + ARRAY_SIZE(tbl_init_post_alt_low2)); - fetch_idxdata(gspca_dev, tbl_init_post_alt_low_c, - ARRAY_SIZE(tbl_init_post_alt_low_c)); + fetch_idxdata(gspca_dev, tbl_init_post_alt_low3, + ARRAY_SIZE(tbl_init_post_alt_low3)); if (_MI2020b_) { ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); @@ -574,8 +573,8 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) msleep(5);/* " */ if (_MI2020c_) { - fetch_idxdata(gspca_dev, tbl_init_post_alt_low_d, - ARRAY_SIZE(tbl_init_post_alt_low_d)); + fetch_idxdata(gspca_dev, tbl_init_post_alt_low4, + ARRAY_SIZE(tbl_init_post_alt_low4)); } else { ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c); msleep(14); /* 0xd8 */ @@ -644,8 +643,8 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) 3, "\x90\x04\xb0"); } - fetch_idxdata(gspca_dev, tbl_init_post_alt_big_a, - ARRAY_SIZE(tbl_init_post_alt_big_a)); + fetch_idxdata(gspca_dev, tbl_init_post_alt_big1, + ARRAY_SIZE(tbl_init_post_alt_big1)); if (reso == IMAGE_1600) msleep(13); /* 1600 */ @@ -708,8 +707,8 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) msleep(14); if (_MI2020c_) - fetch_idxdata(gspca_dev, tbl_init_post_alt_big_b, - ARRAY_SIZE(tbl_init_post_alt_big_b)); + fetch_idxdata(gspca_dev, tbl_init_post_alt_big2, + ARRAY_SIZE(tbl_init_post_alt_big2)); /* flip/mirror */ ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); @@ -738,8 +737,8 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) sd->nbIm = 0; if (_MI2020c_) - fetch_idxdata(gspca_dev, tbl_init_post_alt_big_c, - ARRAY_SIZE(tbl_init_post_alt_big_c)); + fetch_idxdata(gspca_dev, tbl_init_post_alt_big3, + ARRAY_SIZE(tbl_init_post_alt_big3)); } sd->vold.mirror = mirror; diff --git a/drivers/media/video/gspca/gl860/gl860-ov2640.c b/drivers/media/video/gspca/gl860/gl860-ov2640.c index 14b9c373f9f7..e0837432d394 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov2640.c +++ b/drivers/media/video/gspca/gl860/gl860-ov2640.c @@ -1,6 +1,5 @@ -/* @file gl860-ov2640.c - * @author Olivier LORIN, from Malmostoso's logs - * @date 2009-08-27 +/* Subdriver for the GL860 chip with the OV2640 sensor + * Author Olivier LORIN, from Malmostoso's logs * * 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 @@ -92,7 +91,7 @@ static struct validx tbl_common[] = { {0x6000, 0x0010}, }; -static struct validx tbl_sensor_settings_common_a[] = { +static struct validx tbl_sensor_settings_common1[] = { {0x0041, 0x0000}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d}, {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2}, {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0041, 0x0000}, @@ -104,7 +103,7 @@ static struct validx tbl_sensor_settings_common_a[] = { {0x0040, 0x0000}, }; -static struct validx tbl_sensor_settings_common_b[] = { +static struct validx tbl_sensor_settings_common2[] = { {0x6001, 0x00ff}, {0x6038, 0x000c}, {10, 0xffff}, {0x6000, 0x0011}, @@ -166,7 +165,7 @@ static struct validx tbl_800[] = { {0x60ff, 0x00dd}, {0x6020, 0x008c}, {0x6001, 0x00ff}, {0x6044, 0x0018}, }; -static struct validx tbl_big_a[] = { +static struct validx tbl_big1[] = { {0x0002, 0x00c1}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010}, {0x6000, 0x0011}, {0x6011, 0x0017}, {0x6075, 0x0018}, @@ -176,14 +175,14 @@ static struct validx tbl_big_a[] = { {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, }; -static struct validx tbl_big_b[] = { +static struct validx tbl_big2[] = { {0x603d, 0x0086}, {0x6000, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, {0x6000, 0x0053}, {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, {0x6040, 0x005a}, {0x60f0, 0x005b}, {0x6001, 0x005c}, {0x6082, 0x00d3}, {0x6000, 0x008e}, }; -static struct validx tbl_big_c[] = { +static struct validx tbl_big3[] = { {0x6004, 0x00da}, {0x6000, 0x00e0}, {0x6067, 0x00e1}, {0x60ff, 0x00dd}, {0x6001, 0x00ff}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6001, 0x00ff}, {0x6000, 0x0011}, {0x6000, 0x00ff}, {0x6010, 0x00c7}, @@ -275,6 +274,8 @@ static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + sd->mirrorMask = 0; + sd->vold.backlight = -1; sd->vold.brightness = -1; sd->vold.sharpness = -1; @@ -292,16 +293,16 @@ static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) { s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - s32 n; /* reserved for FETCH macros */ + s32 n; /* reserved for FETCH functions */ ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); - n = fetch_validx(gspca_dev, tbl_sensor_settings_common_a, - ARRAY_SIZE(tbl_sensor_settings_common_a)); + n = fetch_validx(gspca_dev, tbl_sensor_settings_common1, + ARRAY_SIZE(tbl_sensor_settings_common1)); ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_post); common(gspca_dev); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_a, - ARRAY_SIZE(tbl_sensor_settings_common_a), n); + keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common1, + ARRAY_SIZE(tbl_sensor_settings_common1), n); switch (reso) { case IMAGE_640: @@ -316,18 +317,18 @@ static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) case IMAGE_1600: case IMAGE_1280: - n = fetch_validx(gspca_dev, tbl_big_a, ARRAY_SIZE(tbl_big_a)); + n = fetch_validx(gspca_dev, tbl_big1, ARRAY_SIZE(tbl_big1)); if (reso == IMAGE_1280) { - n = fetch_validx(gspca_dev, tbl_big_b, - ARRAY_SIZE(tbl_big_b)); + n = fetch_validx(gspca_dev, tbl_big2, + ARRAY_SIZE(tbl_big2)); } else { ctrl_out(gspca_dev, 0x40, 1, 0x601d, 0x0086, 0, NULL); ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00d7, 0, NULL); ctrl_out(gspca_dev, 0x40, 1, 0x6082, 0x00d3, 0, NULL); } - n = fetch_validx(gspca_dev, tbl_big_c, ARRAY_SIZE(tbl_big_c)); + n = fetch_validx(gspca_dev, tbl_big3, ARRAY_SIZE(tbl_big3)); if (reso == IMAGE_1280) { ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); @@ -343,20 +344,20 @@ static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) break; } - n = fetch_validx(gspca_dev, tbl_sensor_settings_common_b, - ARRAY_SIZE(tbl_sensor_settings_common_b)); + n = fetch_validx(gspca_dev, tbl_sensor_settings_common2, + ARRAY_SIZE(tbl_sensor_settings_common2)); ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_b, - ARRAY_SIZE(tbl_sensor_settings_common_b), n); + keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, + ARRAY_SIZE(tbl_sensor_settings_common2), n); ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_b, - ARRAY_SIZE(tbl_sensor_settings_common_b), n); + keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, + ARRAY_SIZE(tbl_sensor_settings_common2), n); ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_b, - ARRAY_SIZE(tbl_sensor_settings_common_b), n); + keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, + ARRAY_SIZE(tbl_sensor_settings_common2), n); ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_b, - ARRAY_SIZE(tbl_sensor_settings_common_b), n); + keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, + ARRAY_SIZE(tbl_sensor_settings_common2), n); ov2640_camera_settings(gspca_dev); @@ -395,6 +396,7 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) s32 wbal = sd->vcur.whitebal; if (backlight != sd->vold.backlight) { + /* No sd->vold.backlight=backlight; (to be done again later) */ if (backlight < 0 || backlight > sd->vmax.backlight) backlight = 0; @@ -404,7 +406,6 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) 0, NULL); ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight - 10, 0x0025, 0, NULL); - /* No sd->vold.backlight=backlight; (to be done again later) */ } if (bright != sd->vold.brightness) { diff --git a/drivers/media/video/gspca/gl860/gl860-ov9655.c b/drivers/media/video/gspca/gl860/gl860-ov9655.c index eda3346f939c..d412694c50af 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov9655.c +++ b/drivers/media/video/gspca/gl860/gl860-ov9655.c @@ -1,7 +1,6 @@ -/* @file gl860-ov9655.c - * @author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt +/* Subdriver for the GL860 chip with the OV9655 sensor + * Author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt * on dsd's weblog - * @date 2009-08-27 * * 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 @@ -104,14 +103,14 @@ static u8 *tbl_800[] = { }; static u8 c04[] = {0x04}; -static u8 dat_post_1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02"; -static u8 dat_post_2[] = "\x10\x10\xc1\x02"; -static u8 dat_post_3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04"; -static u8 dat_post_4[] = "\x10\x02\xc1\x06"; -static u8 dat_post_5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08"; -static u8 dat_post_6[] = "\x10\x10\xc1\x05"; -static u8 dat_post_7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08"; -static u8 dat_post_8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09"; +static u8 dat_post1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02"; +static u8 dat_post2[] = "\x10\x10\xc1\x02"; +static u8 dat_post3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04"; +static u8 dat_post4[] = "\x10\x02\xc1\x06"; +static u8 dat_post5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08"; +static u8 dat_post6[] = "\x10\x10\xc1\x05"; +static u8 dat_post7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08"; +static u8 dat_post8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09"; static struct validx tbl_init_post_alt[] = { {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x603c, 0x00ff}, @@ -212,7 +211,7 @@ static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev) static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) { s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - s32 n; /* reserved for FETCH macros */ + s32 n; /* reserved for FETCH functions */ s32 i; u8 **tbl; @@ -243,7 +242,7 @@ static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1); + ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, ARRAY_SIZE(tbl_init_post_alt), n); @@ -259,7 +258,7 @@ static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1); + ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, ARRAY_SIZE(tbl_init_post_alt), n); @@ -270,18 +269,18 @@ static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1); + ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_2); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_3); + ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post2); + ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post3); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_4); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_5); + ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post4); + ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post5); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_6); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_7); + ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post6); + ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post7); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_8); + ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post8); ov9655_camera_settings(gspca_dev); diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index 1c3ec0242c32..a2108dd71053 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c @@ -1,9 +1,7 @@ -/* @file gl860.c - * @date 2009-08-27 +/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip + * Subdriver core * - * Genesys Logic webcam with gl860 subdrivers - * - * Driver by Olivier Lorin + * 2009/09/24 Olivier Lorin * GSPCA by Jean-Francois Moine * Thanks BUGabundo and Malmostoso for your amazing help! * diff --git a/drivers/media/video/gspca/gl860/gl860.h b/drivers/media/video/gspca/gl860/gl860.h index cef4e24c1e61..305061ff8387 100644 --- a/drivers/media/video/gspca/gl860/gl860.h +++ b/drivers/media/video/gspca/gl860/gl860.h @@ -1,6 +1,7 @@ -/* @file gl860.h - * @author Olivier LORIN, tiré du pilote Syntek par Nicolas VIVIEN - * @date 2009-08-27 +/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip + * Subdriver declarations + * + * 2009/10/14 Olivier LORIN * * 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 From fdd1dd1d246e14dacd8fb0bf842828b03bed2481 Mon Sep 17 00:00:00 2001 From: Olivier Lorin Date: Thu, 15 Oct 2009 04:20:54 -0300 Subject: [PATCH 116/345] V4L/DVB (13196): gspca - gl860: add flip/mirror for OV2640 - add flip/mirror support for OV2640 - fix for backlight value range - fix for red-blue inversion hue mode with V4L1 applications Signed-off-by: Olivier Lorin Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- .../media/video/gspca/gl860/gl860-ov2640.c | 99 ++++++++----------- 1 file changed, 41 insertions(+), 58 deletions(-) diff --git a/drivers/media/video/gspca/gl860/gl860-ov2640.c b/drivers/media/video/gspca/gl860/gl860-ov2640.c index e0837432d394..768cac5cd72b 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov2640.c +++ b/drivers/media/video/gspca/gl860/gl860-ov2640.c @@ -20,8 +20,12 @@ #include "gl860.h" static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01"; -static u8 dat_init2[] = {0x61}; /* expected */ -static u8 dat_init3[] = {0x51}; /* expected */ + +static u8 c61[] = {0x61}; /* expected */ +static u8 c51[] = {0x51}; /* expected */ +static u8 c50[] = {0x50}; /* expected */ +static u8 c28[] = {0x28}; /* expected */ +static u8 ca8[] = {0xa8}; /* expected */ static u8 dat_post[] = "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01"; @@ -31,10 +35,6 @@ static u8 dat_800[] = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21"; static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01"; static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41"; -static u8 c50[] = {0x50}; /* expected */ -static u8 c28[] = {0x28}; /* expected */ -static u8 ca8[] = {0xa8}; /* expected */ - static struct validx tbl_init_at_startup[] = { {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, @@ -107,36 +107,6 @@ static struct validx tbl_sensor_settings_common2[] = { {0x6001, 0x00ff}, {0x6038, 0x000c}, {10, 0xffff}, {0x6000, 0x0011}, - /* backlight=31/64 */ - {0x6001, 0x00ff}, {0x603e, 0x0024}, {0x6034, 0x0025}, - /* bright=0/256 */ - {0x6000, 0x00ff}, {0x6009, 0x007c}, {0x6000, 0x007d}, - /* wbal=64/128 */ - {0x6000, 0x00ff}, {0x6003, 0x007c}, {0x6040, 0x007d}, - /* cntr=0/256 */ - {0x6000, 0x00ff}, {0x6007, 0x007c}, {0x6000, 0x007d}, - /* sat=128/256 */ - {0x6000, 0x00ff}, {0x6001, 0x007c}, {0x6080, 0x007d}, - /* sharpness=0/32 */ - {0x6000, 0x00ff}, {0x6001, 0x0092}, {0x60c0, 0x0093}, - /* hue=0/256 */ - {0x6000, 0x00ff}, {0x6002, 0x007c}, {0x6000, 0x007d}, - /* gam=32/64 */ - {0x6000, 0x00ff}, {0x6008, 0x007c}, {0x6020, 0x007d}, - /* image right up */ - {0xffff, 0xffff}, - {15, 0xffff}, - {0x6001, 0x00ff}, {0x6000, 0x8004}, - {0xffff, 0xffff}, - {0x60a8, 0x0004}, - {15, 0xffff}, - {0x6001, 0x00ff}, {0x6000, 0x8004}, - {0xffff, 0xffff}, - {0x60f8, 0x0004}, - /* image right up */ - {0xffff, 0xffff}, - /* backlight=31/64 */ - {0x6001, 0x00ff}, {0x603e, 0x0024}, {0x6034, 0x0025}, }; static struct validx tbl_640[] = { @@ -222,17 +192,19 @@ void ov2640_init_settings(struct gspca_dev *gspca_dev) sd->vcur.hue = 0; sd->vcur.saturation = 128; sd->vcur.whitebal = 64; + sd->vcur.mirror = 0; + sd->vcur.flip = 0; sd->vmax.backlight = 64; sd->vmax.brightness = 255; sd->vmax.sharpness = 31; sd->vmax.contrast = 255; sd->vmax.gamma = 64; - sd->vmax.hue = 255 + 1; + sd->vmax.hue = 254 + 2; sd->vmax.saturation = 255; sd->vmax.whitebal = 128; - sd->vmax.mirror = 0; - sd->vmax.flip = 0; + sd->vmax.mirror = 1; + sd->vmax.flip = 1; sd->vmax.AC50Hz = 0; sd->dev_camera_settings = ov2640_camera_settings; @@ -258,11 +230,11 @@ static int ov2640_init_at_startup(struct gspca_dev *gspca_dev) common(gspca_dev); - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, dat_init2); + ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, c61); ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL); - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, dat_init3); + ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c51); ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL); /* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ @@ -284,6 +256,8 @@ static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) sd->vold.gamma = -1; sd->vold.hue = -1; sd->vold.whitebal = -1; + sd->vold.mirror = -1; + sd->vold.flip = -1; ov2640_init_post_alt(gspca_dev); @@ -346,18 +320,6 @@ static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) n = fetch_validx(gspca_dev, tbl_sensor_settings_common2, ARRAY_SIZE(tbl_sensor_settings_common2)); - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, - ARRAY_SIZE(tbl_sensor_settings_common2), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, - ARRAY_SIZE(tbl_sensor_settings_common2), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, - ARRAY_SIZE(tbl_sensor_settings_common2), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, - ARRAY_SIZE(tbl_sensor_settings_common2), n); ov2640_camera_settings(gspca_dev); @@ -394,6 +356,8 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) s32 sat = sd->vcur.saturation; s32 hue = sd->vcur.hue; s32 wbal = sd->vcur.whitebal; + s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0); + s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) == 0); if (backlight != sd->vold.backlight) { /* No sd->vold.backlight=backlight; (to be done again later) */ @@ -402,9 +366,9 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight , 0x0024, + ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight - 10, 0x0025, + ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, 0, NULL); } @@ -467,7 +431,7 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) ctrl_out(gspca_dev, 0x40, 1, 0x6002 , 0x007c, 0, NULL); ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d, 0, NULL); - if (hue >= sd->vmax.hue) + if (hue >= 255) sd->swapRB = 1; else sd->swapRB = 0; @@ -483,14 +447,33 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL); } + if (mirror != sd->vold.mirror || flip != sd->vold.flip) { + sd->vold.mirror = mirror; + sd->vold.flip = flip; + + mirror = 0x80 * mirror; + ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); + ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); + ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); + ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL); + + flip = 0x50 * flip + mirror; + ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); + ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); + ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); + ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL); + + ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); + } + if (backlight != sd->vold.backlight) { sd->vold.backlight = backlight; ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight , 0x0024, + ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight - 10, 0x0025, + ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, 0, NULL); } From 46b4f2ab5858de905a20389c32105fcee833e0d3 Mon Sep 17 00:00:00 2001 From: Amauri Magagna Date: Sat, 17 Oct 2009 07:21:29 -0300 Subject: [PATCH 117/345] V4L/DVB (13197): gspca - sonixj: Adjust colors and autogain for sensor om6802. - set correct colors at startup time - autogain was too slow (4-5 mn - now 15-30 s)) Signed-off-by: Amauri Magagna Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 33f4d0a1f6fd..82604f328dc4 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -346,7 +346,7 @@ static const u8 sn_mt9v111[0x1c] = { static const u8 sn_om6802[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20, + 0x00, 0x23, 0x72, 0x00, 0x1a, 0x20, 0x20, 0x19, /* reg8 reg9 rega regb regc regd rege regf */ 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ @@ -1987,11 +1987,19 @@ static void do_autogain(struct gspca_dev *gspca_dev) sd->exposure = setexposure(gspca_dev, (unsigned int) (expotimes << 8)); break; + case SENSOR_OM6802: + expotimes = sd->exposure; + expotimes += (luma_mean - delta) >> 2; + if (expotimes < 0) + expotimes = 0; + sd->exposure = setexposure(gspca_dev, + (unsigned int) expotimes); + setredblue(gspca_dev); + break; default: /* case SENSOR_MO4000: */ /* case SENSOR_MI0360: */ /* case SENSOR_MT9V111: */ -/* case SENSOR_OM6802: */ expotimes = sd->exposure; expotimes += (luma_mean - delta) >> 6; if (expotimes < 0) From 5f78a9f96bc1954e9bd51458af8658b1eda603be Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 19 Oct 2009 07:40:33 -0300 Subject: [PATCH 118/345] V4L/DVB (13198): gspca - ov519: Bad frame pointer in ovfx2 packet scan. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index a63cb75aa7f1..f88a526e216f 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -4058,7 +4058,7 @@ static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, { /* A short read signals EOF */ if (len < OVFX2_BULK_SIZE) { - gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, len); + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, len); gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); return; } From bc809ab37e4a8f6eeea0afae76bb1bc6cc52fe98 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 28 Sep 2009 16:44:52 -0300 Subject: [PATCH 119/345] V4L/DVB (13201): saa7164: disable tda18271 slave tuner output on slave in standby mode Enable the standby mode optimization to disable the tda18271 slave tuner output / loop thru options when in low power mode on the slave tuner, only. The master tuner must always leave slave tuner output / loop thru enabled. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7164/saa7164-dvb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/saa7164/saa7164-dvb.c b/drivers/media/video/saa7164/saa7164-dvb.c index 6a2d847d6a88..cf099c59b38e 100644 --- a/drivers/media/video/saa7164/saa7164-dvb.c +++ b/drivers/media/video/saa7164/saa7164-dvb.c @@ -68,6 +68,7 @@ static struct tda18271_config hauppauge_hvr22x0s_tuner_config = { .std_map = &hauppauge_tda18271_std_map, .gate = TDA18271_GATE_ANALOG, .role = TDA18271_SLAVE, + .output_opt = TDA18271_OUTPUT_LT_OFF, .rf_cal_on_startup = 1 }; From 184e769f93e734ced24c948ea02e3d541c45c766 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 5 Jun 2009 04:28:28 -0300 Subject: [PATCH 120/345] V4L/DVB (13204): saa7134: add support for the Leadtek DTV1000S Thanks to Terry Wu for finding the GPIOs required for svideo / composite input Cc: Terry Wu Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 6 ++++ drivers/media/video/saa7134/saa7134-dvb.c | 39 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 47 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 94e255a76f79..fce1e7eb0474 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -173,3 +173,4 @@ 172 -> RoverMedia TV Link Pro FM [19d1:0138] 173 -> Zolid Hybrid TV Tuner PCI [1131:2004] 174 -> Asus Europa Hybrid OEM [1043:4847] +175 -> Leadtek Winfast DTV1000S [107d:6655] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index bdb613851362..9481379edec9 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -6448,6 +6448,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1043, .subdevice = 0x4847, .driver_data = SAA7134_BOARD_ASUS_EUROPA_HYBRID, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x107d, + .subdevice = 0x6655, + .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S, }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index cd31284faf7c..73739d2a63dd 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1045,6 +1045,32 @@ static struct tda18271_config zolid_tda18271_config = { .gate = TDA18271_GATE_ANALOG, }; +static struct tda10048_config dtv1000s_tda10048_config = { + .demod_address = 0x10 >> 1, + .output_mode = TDA10048_PARALLEL_OUTPUT, + .fwbulkwritelen = TDA10048_BULKWRITE_200, + .inversion = TDA10048_INVERSION_ON, + .dtv6_if_freq_khz = TDA10048_IF_3300, + .dtv7_if_freq_khz = TDA10048_IF_3800, + .dtv8_if_freq_khz = TDA10048_IF_4300, + .clk_freq_khz = TDA10048_CLK_16000, + .disable_gate_access = 1, +}; + +static struct tda18271_std_map dtv1000s_tda18271_std_map = { + .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x37, }, + .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x37, }, + .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, + .if_lvl = 1, .rfagc_top = 0x37, }, +}; + +static struct tda18271_config dtv1000s_tda18271_config = { + .std_map = &dtv1000s_tda18271_std_map, + .gate = TDA18271_GATE_ANALOG, +}; + /* ================================================================== * Core code */ @@ -1543,6 +1569,19 @@ static int dvb_init(struct saa7134_dev *dev) &zolid_tda18271_config); } break; + case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: + fe0->dvb.frontend = dvb_attach(tda10048_attach, + &dtv1000s_tda10048_config, + &dev->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, + &dev->i2c_adap, 0x4b, + &tda829x_no_probe); + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_adap, + &dtv1000s_tda18271_config); + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 94e1a3be3317..13a861bedc36 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -298,6 +298,7 @@ struct saa7134_format { #define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172 #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 +#define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 From fb29ab96982baba57b03636e2a894c0d0acd197e Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Tue, 20 Oct 2009 12:13:39 -0300 Subject: [PATCH 121/345] V4L/DVB (13206): cx25840: add component support Signed-off-by: David T.L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 36 ++++++++++++++-------- include/media/cx25840.h | 1 + 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 904e9a5a9065..9702a9334b4a 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -703,6 +703,10 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp struct cx25840_state *state = to_state(i2c_get_clientdata(client)); u8 is_composite = (vid_input >= CX25840_COMPOSITE1 && vid_input <= CX25840_COMPOSITE8); + u8 is_component = (vid_input & CX25840_COMPONENT_ON) == + CX25840_COMPONENT_ON; + int luma = vid_input & 0xf0; + int chroma = vid_input & 0xf00; u8 reg; v4l_dbg(1, cx25840_debug, client, @@ -715,18 +719,14 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp reg = vid_input & 0xff; if ((vid_input & CX25840_SVIDEO_ON) == CX25840_SVIDEO_ON) is_composite = 0; - else + else if ((vid_input & CX25840_COMPONENT_ON) == 0) is_composite = 1; v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n", reg, is_composite); - } else - if (is_composite) { + } else if (is_composite) { reg = 0xf0 + (vid_input - CX25840_COMPOSITE1); } else { - int luma = vid_input & 0xf0; - int chroma = vid_input & 0xf00; - if ((vid_input & ~0xff0) || luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA8 || chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { @@ -768,8 +768,11 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp cx25840_write(client, 0x103, reg); - /* Set INPUT_MODE to Composite (0) or S-Video (1) */ - cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); + /* Set INPUT_MODE to Composite, S-Video or Component */ + if (is_component) + cx25840_and_or(client, 0x401, ~0x6, 0x6); + else + cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); if (!is_cx2388x(state) && !is_cx231xx(state)) { /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ @@ -780,12 +783,21 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp else cx25840_and_or(client, 0x102, ~0x4, 0); } else { - if (is_composite) + /* Set DUAL_MODE_ADC2 to 1 if component*/ + cx25840_and_or(client, 0x102, ~0x4, is_component ? 0x4 : 0x0); + if (is_composite) { /* ADC2 input select channel 2 */ cx25840_and_or(client, 0x102, ~0x2, 0); - else - /* ADC2 input select channel 3 */ - cx25840_and_or(client, 0x102, ~0x2, 2); + } else if (!is_component) { + /* S-Video */ + if (chroma >= CX25840_SVIDEO_CHROMA7) { + /* ADC2 input select channel 3 */ + cx25840_and_or(client, 0x102, ~0x2, 2); + } else { + /* ADC2 input select channel 2 */ + cx25840_and_or(client, 0x102, ~0x2, 0); + } + } } state->vid_input = vid_input; diff --git a/include/media/cx25840.h b/include/media/cx25840.h index 2c3fbaa33f74..0b0cb1776796 100644 --- a/include/media/cx25840.h +++ b/include/media/cx25840.h @@ -84,6 +84,7 @@ enum cx25840_video_input { CX25840_NONE0_CH3 = 0x80000080, CX25840_NONE1_CH3 = 0x800000c0, CX25840_SVIDEO_ON = 0x80000100, + CX25840_COMPONENT_ON = 0x80000200, }; enum cx25840_audio_input { From dac65fa169ebf9fb1bd488385c62b5dd0c71771c Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Wed, 21 Oct 2009 11:07:24 -0300 Subject: [PATCH 122/345] V4L/DVB (13207): cx23885: add component input type Signed-off-by: David T. L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-video.c | 1 + drivers/media/video/cx23885/cx23885.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 3f1d07e6490a..eebd52eb3dcd 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1145,6 +1145,7 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) [CX23885_VMUX_COMPOSITE3] = "Composite3", [CX23885_VMUX_COMPOSITE4] = "Composite4", [CX23885_VMUX_SVIDEO] = "S-Video", + [CX23885_VMUX_COMPONENT] = "Component", [CX23885_VMUX_TELEVISION] = "Television", [CX23885_VMUX_CABLE] = "Cable TV", [CX23885_VMUX_DVB] = "DVB", diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index d2fbc6807ce9..813eaf7c5e94 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -157,6 +157,7 @@ enum cx23885_itype { CX23885_VMUX_COMPOSITE3, CX23885_VMUX_COMPOSITE4, CX23885_VMUX_SVIDEO, + CX23885_VMUX_COMPONENT, CX23885_VMUX_TELEVISION, CX23885_VMUX_CABLE, CX23885_VMUX_DVB, From fd705e7cd8ef61efc443b90f94afed42beabeacd Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Wed, 21 Oct 2009 11:08:30 -0300 Subject: [PATCH 123/345] V4L/DVB (13208): cx23885: fix uninitialized member bug Signed-off-by: David T. L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index eebd52eb3dcd..e14cb39d8412 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1504,6 +1504,7 @@ int cx23885_video_register(struct cx23885_dev *dev) if (sd) { struct tuner_setup tun_setup; + memset(&tun_setup, 0, sizeof(tun_setup)); tun_setup.mode_mask = T_ANALOG_TV; tun_setup.type = dev->tuner_type; tun_setup.addr = v4l2_i2c_subdev_addr(sd); From bc1548adbee02899c7db5cd045bb0d799b220dce Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Wed, 21 Oct 2009 11:09:28 -0300 Subject: [PATCH 124/345] V4L/DVB (13209): cx23885: card mygica x8506 add analog video input support Signed-off-by: David T. L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 42 +++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index c0e2409f3cbd..7438e79a8efd 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -200,11 +200,51 @@ struct cx23885_board cx23885_boards[] = { }, [CX23885_BOARD_MYGICA_X8506] = { .name = "Mygica X8506 DMB-TH", + .tuner_type = TUNER_ABSENT, + .porta = CX23885_ANALOG_VIDEO, .portb = CX23885_MPEG_DVB, + .input = { + { + .type = CX23885_VMUX_COMPOSITE1, + .vmux = CX25840_COMPOSITE8, + }, + { + .type = CX23885_VMUX_SVIDEO, + .vmux = CX25840_SVIDEO_LUMA3 | + CX25840_SVIDEO_CHROMA4, + }, + { + .type = CX23885_VMUX_COMPONENT, + .vmux = CX25840_COMPONENT_ON | + CX25840_VIN1_CH1 | + CX25840_VIN6_CH2 | + CX25840_VIN7_CH3, + }, + }, }, [CX23885_BOARD_MAGICPRO_PROHDTVE2] = { .name = "Magic-Pro ProHDTV Extreme 2", + .tuner_type = TUNER_ABSENT, + .porta = CX23885_ANALOG_VIDEO, .portb = CX23885_MPEG_DVB, + .input = { + { + .type = CX23885_VMUX_COMPOSITE1, + .vmux = CX25840_COMPOSITE8, + }, + { + .type = CX23885_VMUX_SVIDEO, + .vmux = CX25840_SVIDEO_LUMA3 | + CX25840_SVIDEO_CHROMA4, + }, + { + .type = CX23885_VMUX_COMPONENT, + .vmux = CX25840_COMPONENT_ON | + CX25840_VIN1_CH1 | + CX25840_VIN6_CH2 | + CX25840_VIN7_CH3, + }, + }, }, [CX23885_BOARD_HAUPPAUGE_HVR1850] = { .name = "Hauppauge WinTV-HVR1850", @@ -970,6 +1010,8 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_MYGICA_X8506: + case CX23885_BOARD_MAGICPRO_PROHDTVE2: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, "cx25840", "cx25840", 0x88 >> 1, NULL); From 8e069bb9aeb4250dd062bb136f4b3db5c4c530ff Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Wed, 21 Oct 2009 12:29:11 -0300 Subject: [PATCH 125/345] V4L/DVB (13210): cx23885: card Mygica X8506 better GPIO setup Signed-off-by: David T.L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 7438e79a8efd..a2ba09e0aef0 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -799,12 +799,13 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) break; case CX23885_BOARD_MYGICA_X8506: case CX23885_BOARD_MAGICPRO_PROHDTVE2: + /* GPIO-0 (0)Analog / (1)Digital TV */ /* GPIO-1 reset XC5000 */ /* GPIO-2 reset LGS8GL5 / LGS8G75 */ - cx_set(GP0_IO, 0x00060000); - cx_clear(GP0_IO, 0x00000006); + cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1); + cx23885_gpio_clear(dev, GPIO_1 | GPIO_2); mdelay(100); - cx_set(GP0_IO, 0x00060006); + cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2); mdelay(100); break; case CX23885_BOARD_HAUPPAUGE_HVR1850: From 6f0d8c020ecff4acb959627109d3b81ded211b70 Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Wed, 21 Oct 2009 13:15:30 -0300 Subject: [PATCH 126/345] V4L/DVB (13211): cx23885: card Mygica X8506 analog TV support Signed-off-by: David T.L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 14 ++++++++++++-- drivers/media/video/cx23885/cx23885-dvb.c | 5 +++++ drivers/media/video/cx23885/cx23885-video.c | 8 ++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index a2ba09e0aef0..2cbac93866be 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -200,10 +200,15 @@ struct cx23885_board cx23885_boards[] = { }, [CX23885_BOARD_MYGICA_X8506] = { .name = "Mygica X8506 DMB-TH", - .tuner_type = TUNER_ABSENT, + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, .porta = CX23885_ANALOG_VIDEO, .portb = CX23885_MPEG_DVB, .input = { + { + .type = CX23885_VMUX_TELEVISION, + .vmux = CX25840_COMPOSITE2, + }, { .type = CX23885_VMUX_COMPOSITE1, .vmux = CX25840_COMPOSITE8, @@ -224,10 +229,15 @@ struct cx23885_board cx23885_boards[] = { }, [CX23885_BOARD_MAGICPRO_PROHDTVE2] = { .name = "Magic-Pro ProHDTV Extreme 2", - .tuner_type = TUNER_ABSENT, + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, .porta = CX23885_ANALOG_VIDEO, .portb = CX23885_MPEG_DVB, .input = { + { + .type = CX23885_VMUX_TELEVISION, + .vmux = CX25840_COMPOSITE2, + }, { .type = CX23885_VMUX_COMPOSITE1, .vmux = CX25840_COMPOSITE8, diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 875597640d74..4d439f2c4abc 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -486,6 +486,11 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, break; } break; + case CX23885_BOARD_MYGICA_X8506: + case CX23885_BOARD_MAGICPRO_PROHDTVE2: + /* Select Digital TV */ + cx23885_gpio_set(dev, GPIO_0); + break; } return 0; } diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index e14cb39d8412..8b372b4f0de2 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -402,6 +402,13 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) INPUT(input)->gpio2, INPUT(input)->gpio3); dev->input = input; + if (dev->board == CX23885_BOARD_MYGICA_X8506 || + dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2) { + /* Select Analog TV */ + if (INPUT(input)->type == CX23885_VMUX_TELEVISION) + cx23885_gpio_clear(dev, GPIO_0); + } + /* Tell the internal A/V decoder */ v4l2_subdev_call(dev->sd_cx25840, video, s_routing, INPUT(input)->vmux, 0, 0); @@ -1508,6 +1515,7 @@ int cx23885_video_register(struct cx23885_dev *dev) tun_setup.mode_mask = T_ANALOG_TV; tun_setup.type = dev->tuner_type; tun_setup.addr = v4l2_i2c_subdev_addr(sd); + tun_setup.tuner_callback = cx23885_tuner_callback; v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); } From e29cd96715ab8b9315fb50096df4677a23d7d6a7 Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Mon, 26 Oct 2009 08:25:52 -0300 Subject: [PATCH 127/345] V4L/DVB (13212): fix gcc-4.3.3 compilation error at dib7000p_pid_filter(): missing parameter name Signed-off-by: David T.L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib7000p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 3a769df3c86f..805dd13a97ee 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -97,7 +97,7 @@ static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap) printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -static inline int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff) +static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; From 1724c8fa7eb33d68898e060a08a8e6a88348b62f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 23 Oct 2009 02:47:49 -0300 Subject: [PATCH 128/345] V4L/DVB (13214): tda18271: allow for i2c buses that cant send 16 bytes at once There is already an option for sending 16 byte chunks rather that writing 39 bytes all at once during the tuner's initialization. Some i2c buses can't send 16 bytes at once, so create an option for sending 8 byte chunks. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-common.c | 16 ++++++++++++++-- drivers/media/common/tuners/tda18271-fe.c | 3 ++- drivers/media/common/tuners/tda18271-priv.h | 2 +- drivers/media/common/tuners/tda18271.h | 12 +++++++++--- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c index 155c93eb75da..e1f678281a58 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/common/tuners/tda18271-common.c @@ -326,12 +326,24 @@ int tda18271_init_regs(struct dvb_frontend *fe) regs[R_EB22] = 0x48; regs[R_EB23] = 0xb0; - if (priv->small_i2c) { + switch (priv->small_i2c) { + case TDA18271_08_BYTE_CHUNK_INIT: + tda18271_write_regs(fe, 0x00, 0x08); + tda18271_write_regs(fe, 0x08, 0x08); + tda18271_write_regs(fe, 0x10, 0x08); + tda18271_write_regs(fe, 0x18, 0x08); + tda18271_write_regs(fe, 0x20, 0x07); + break; + case TDA18271_16_BYTE_CHUNK_INIT: tda18271_write_regs(fe, 0x00, 0x10); tda18271_write_regs(fe, 0x10, 0x10); tda18271_write_regs(fe, 0x20, 0x07); - } else + break; + case TDA18271_39_BYTE_CHUNK_INIT: + default: tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); + break; + } /* setup agc1 gain */ regs[R_EB17] = 0x00; diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index e0fd9f5d5944..eb7724158861 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1224,7 +1224,8 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; priv->role = (cfg) ? cfg->role : TDA18271_MASTER; priv->config = (cfg) ? cfg->config : 0; - priv->small_i2c = (cfg) ? cfg->small_i2c : 0; + priv->small_i2c = (cfg) ? + cfg->small_i2c : TDA18271_39_BYTE_CHUNK_INIT; priv->output_opt = (cfg) ? cfg->output_opt : TDA18271_OUTPUT_LT_XT_ON; diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h index 7047680cdbd1..9589ab0576d2 100644 --- a/drivers/media/common/tuners/tda18271-priv.h +++ b/drivers/media/common/tuners/tda18271-priv.h @@ -109,10 +109,10 @@ struct tda18271_priv { enum tda18271_i2c_gate gate; enum tda18271_ver id; enum tda18271_output_options output_opt; + enum tda18271_small_i2c small_i2c; unsigned int config; /* interface to saa713x / tda829x */ unsigned int cal_initialized:1; - unsigned int small_i2c:1; u8 tm_rfcal; diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h index 323f2912128d..d7fcc36dc6e6 100644 --- a/drivers/media/common/tuners/tda18271.h +++ b/drivers/media/common/tuners/tda18271.h @@ -78,6 +78,12 @@ enum tda18271_output_options { TDA18271_OUTPUT_XT_OFF = 2, }; +enum tda18271_small_i2c { + TDA18271_39_BYTE_CHUNK_INIT = 0, + TDA18271_16_BYTE_CHUNK_INIT = 1, + TDA18271_08_BYTE_CHUNK_INIT = 2, +}; + struct tda18271_config { /* override default if freq / std settings (optional) */ struct tda18271_std_map *std_map; @@ -91,12 +97,12 @@ struct tda18271_config { /* output options that can be disabled */ enum tda18271_output_options output_opt; + /* some i2c providers cant write all 39 registers at once */ + enum tda18271_small_i2c small_i2c; + /* force rf tracking filter calibration on startup */ unsigned int rf_cal_on_startup:1; - /* some i2c providers cant write all 39 registers at once */ - unsigned int small_i2c:1; - /* interface to saa713x / tda829x */ unsigned int config; }; From 42f9a03ed3ddcccc5372bf4774afc8c4273c6c3a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 23 Oct 2009 03:20:45 -0300 Subject: [PATCH 129/345] V4L/DVB (13215): tda18271: add support for the set_config method Add the set_config method to allow drivers to configure the tda18271 driver options after attach. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 39 +++++++++++++++-------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index eb7724158861..ecb65802725f 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1185,6 +1185,26 @@ static int tda18271_get_id(struct dvb_frontend *fe) return ret; } +static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg) +{ + struct tda18271_priv *priv = fe->tuner_priv; + struct tda18271_config *cfg = (struct tda18271_config *) priv_cfg; + + priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; + priv->role = (cfg) ? cfg->role : TDA18271_MASTER; + priv->config = (cfg) ? cfg->config : 0; + priv->small_i2c = (cfg) ? + cfg->small_i2c : TDA18271_39_BYTE_CHUNK_INIT; + priv->output_opt = (cfg) ? + cfg->output_opt : TDA18271_OUTPUT_LT_XT_ON; + + /* override default std map with values in config struct */ + if ((cfg) && (cfg->std_map)) + tda18271_update_std_map(fe, cfg->std_map); + + return 0; +} + static struct dvb_tuner_ops tda18271_tuner_ops = { .info = { .name = "NXP TDA18271HD", @@ -1197,6 +1217,7 @@ static struct dvb_tuner_ops tda18271_tuner_ops = { .set_params = tda18271_set_params, .set_analog_params = tda18271_set_analog_params, .release = tda18271_release, + .set_config = tda18271_set_config, .get_frequency = tda18271_get_frequency, .get_bandwidth = tda18271_get_bandwidth, }; @@ -1221,13 +1242,9 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, /* new tuner instance */ int rf_cal_on_startup; - priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; - priv->role = (cfg) ? cfg->role : TDA18271_MASTER; - priv->config = (cfg) ? cfg->config : 0; - priv->small_i2c = (cfg) ? - cfg->small_i2c : TDA18271_39_BYTE_CHUNK_INIT; - priv->output_opt = (cfg) ? - cfg->output_opt : TDA18271_OUTPUT_LT_XT_ON; + fe->tuner_priv = priv; + + tda18271_set_config(fe, cfg); /* tda18271_cal_on_startup == -1 when cal * module option is unset */ @@ -1243,8 +1260,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, priv->cal_initialized = false; mutex_init(&priv->lock); - fe->tuner_priv = priv; - if (tda_fail(tda18271_get_id(fe))) goto fail; @@ -1276,14 +1291,12 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, priv->small_i2c = cfg->small_i2c; if (cfg->output_opt) priv->output_opt = cfg->output_opt; + if (cfg->std_map) + tda18271_update_std_map(fe, cfg->std_map); } break; } - /* override default std map with values in config struct */ - if ((cfg) && (cfg->std_map)) - tda18271_update_std_map(fe, cfg->std_map); - mutex_unlock(&tda18271_list_mutex); memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, From c54e1dde586ea0e930d6c443ca60a9b9d0310de3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 24 Oct 2009 17:47:49 -0300 Subject: [PATCH 130/345] V4L/DVB (13216): tda18271: initialize tuner during set_config if rf_cal_on_startup is set If rf_cal_on_startup is enabled in the structure passed into tda18271_set_config, and the cal module option isn't disabled, then we should run the initialization and calibration procedures during the tda18271_set_config function call. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 28 ++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index ecb65802725f..24f1d38081e6 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1185,10 +1185,10 @@ static int tda18271_get_id(struct dvb_frontend *fe) return ret; } -static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg) +static int tda18271_setup_configuration(struct dvb_frontend *fe, + struct tda18271_config *cfg) { struct tda18271_priv *priv = fe->tuner_priv; - struct tda18271_config *cfg = (struct tda18271_config *) priv_cfg; priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; priv->role = (cfg) ? cfg->role : TDA18271_MASTER; @@ -1205,6 +1205,28 @@ static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg) return 0; } +static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg) +{ + struct tda18271_config *cfg = (struct tda18271_config *) priv_cfg; + int rf_cal_on_startup; + + tda18271_setup_configuration(fe, cfg); + + /* tda18271_cal_on_startup == -1 when cal module option is unset */ + if (tda18271_cal_on_startup == -1) { + /* honor configuration setting */ + rf_cal_on_startup = + ((cfg) && (cfg->rf_cal_on_startup)) ? 1 : 0; + } else { + /* module option overrides configuration setting */ + rf_cal_on_startup = tda18271_cal_on_startup; + } + if (rf_cal_on_startup) + tda18271_init(fe); + + return 0; +} + static struct dvb_tuner_ops tda18271_tuner_ops = { .info = { .name = "NXP TDA18271HD", @@ -1244,7 +1266,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, fe->tuner_priv = priv; - tda18271_set_config(fe, cfg); + tda18271_setup_configuration(fe, cfg); /* tda18271_cal_on_startup == -1 when cal * module option is unset */ From 188ea058ff2e671270273a1f5d13f46ca75b8a35 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 24 Oct 2009 18:18:03 -0300 Subject: [PATCH 131/345] V4L/DVB (13217): tda18271: handle rf_cal_on_startup properly during attach If rf_cal_on_startup is enabled in the structure passed into tda18271_attach, and the cal module option isn't disabled, then we should run the initialization and calibration procedures during the tda18271_attach function call, regardless of how many instances of the driver have been attached. If the device is already calibrated, the driver will detect that and will only calibrate again if necessary. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 24f1d38081e6..8b934f48b6f3 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1249,7 +1249,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, struct tda18271_config *cfg) { struct tda18271_priv *priv = NULL; - int instance; + int instance, rf_cal_on_startup = 0; mutex_lock(&tda18271_list_mutex); @@ -1262,8 +1262,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, case 1: { /* new tuner instance */ - int rf_cal_on_startup; - fe->tuner_priv = priv; tda18271_setup_configuration(fe, cfg); @@ -1315,7 +1313,20 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, priv->output_opt = cfg->output_opt; if (cfg->std_map) tda18271_update_std_map(fe, cfg->std_map); + + /* tda18271_cal_on_startup == -1 when cal + * module option is unset */ + if (tda18271_cal_on_startup == -1) { + /* honor attach-time configuration */ + rf_cal_on_startup = + (cfg->rf_cal_on_startup) ? 1 : 0; + } else { + /* module option overrides attach config */ + rf_cal_on_startup = tda18271_cal_on_startup; + } } + if (rf_cal_on_startup) + tda18271_init(fe); break; } From 5881ecfca058d731758c76018205b5b3dff9291f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 24 Oct 2009 18:37:22 -0300 Subject: [PATCH 132/345] V4L/DVB (13218): tda18271: consolidate common code for calibration on startup determination consolidate common code used to determine if calibration on startup is needed Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 51 +++++++---------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 8b934f48b6f3..cae0df1748f1 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1205,23 +1205,23 @@ static int tda18271_setup_configuration(struct dvb_frontend *fe, return 0; } +static inline int tda18271_need_cal_on_startup(struct tda18271_config *cfg) +{ + /* tda18271_cal_on_startup == -1 when cal module option is unset */ + return ((tda18271_cal_on_startup == -1) ? + /* honor configuration setting */ + ((cfg) && (cfg->rf_cal_on_startup)) : + /* module option overrides configuration setting */ + (tda18271_cal_on_startup)) ? 1 : 0; +} + static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg) { struct tda18271_config *cfg = (struct tda18271_config *) priv_cfg; - int rf_cal_on_startup; tda18271_setup_configuration(fe, cfg); - /* tda18271_cal_on_startup == -1 when cal module option is unset */ - if (tda18271_cal_on_startup == -1) { - /* honor configuration setting */ - rf_cal_on_startup = - ((cfg) && (cfg->rf_cal_on_startup)) ? 1 : 0; - } else { - /* module option overrides configuration setting */ - rf_cal_on_startup = tda18271_cal_on_startup; - } - if (rf_cal_on_startup) + if (tda18271_need_cal_on_startup(cfg)) tda18271_init(fe); return 0; @@ -1249,7 +1249,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, struct tda18271_config *cfg) { struct tda18271_priv *priv = NULL; - int instance, rf_cal_on_startup = 0; + int instance; mutex_lock(&tda18271_list_mutex); @@ -1266,17 +1266,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, tda18271_setup_configuration(fe, cfg); - /* tda18271_cal_on_startup == -1 when cal - * module option is unset */ - if (tda18271_cal_on_startup == -1) { - /* honor attach-time configuration */ - rf_cal_on_startup = - ((cfg) && (cfg->rf_cal_on_startup)) ? 1 : 0; - } else { - /* module option overrides attach configuration */ - rf_cal_on_startup = tda18271_cal_on_startup; - } - priv->cal_initialized = false; mutex_init(&priv->lock); @@ -1289,7 +1278,8 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, mutex_lock(&priv->lock); tda18271_init_regs(fe); - if ((rf_cal_on_startup) && (priv->id == TDA18271HDC2)) + if ((tda18271_need_cal_on_startup(cfg)) && + (priv->id == TDA18271HDC2)) tda18271c2_rf_cal_init(fe); mutex_unlock(&priv->lock); @@ -1313,19 +1303,8 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, priv->output_opt = cfg->output_opt; if (cfg->std_map) tda18271_update_std_map(fe, cfg->std_map); - - /* tda18271_cal_on_startup == -1 when cal - * module option is unset */ - if (tda18271_cal_on_startup == -1) { - /* honor attach-time configuration */ - rf_cal_on_startup = - (cfg->rf_cal_on_startup) ? 1 : 0; - } else { - /* module option overrides attach config */ - rf_cal_on_startup = tda18271_cal_on_startup; - } } - if (rf_cal_on_startup) + if (tda18271_need_cal_on_startup(cfg)) tda18271_init(fe); break; } From 712bc0b30fa72edd1b3910250dcaf52894871714 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 25 Oct 2009 12:36:26 -0300 Subject: [PATCH 133/345] V4L/DVB (13219): tda18271: remove unneeded braces in switch..case block Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index cae0df1748f1..9199e362279c 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1260,7 +1260,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, case 0: goto fail; case 1: - { /* new tuner instance */ fe->tuner_priv = priv; @@ -1284,7 +1283,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, mutex_unlock(&priv->lock); break; - } default: /* existing tuner instance */ fe->tuner_priv = priv; From 5abaa530bfe10e2a446679442b283f865a444a32 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 25 Oct 2009 10:43:30 -0300 Subject: [PATCH 134/345] V4L/DVB (13220): tda18271: increment module version minor Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 9199e362279c..07d6e1c159ca 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1326,7 +1326,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach); MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.3"); +MODULE_VERSION("0.4"); /* * Overrides for Emacs so that we follow Linus's tabbing style. From 4a89baa2e140fd4a12be55e03f8ebe1acabb1328 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 12 Oct 2009 00:13:28 -0300 Subject: [PATCH 135/345] V4L/DVB (13222): pvrusb2: Make more info available to udev pvrusb2: Associate V4L device node in sysfs with the underlying USB device. This opens the door to device information tracking in udev Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 2d8825e5b1be..6aa48e0ae731 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -913,6 +913,15 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) } +static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip) +{ + if (!dip) return; + if (!dip->devbase.parent) return; + dip->devbase.parent = NULL; + device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE); +} + + static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) { if (vp->dev_video) { @@ -943,6 +952,8 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) struct pvr2_v4l2 *vp; vp = container_of(chp,struct pvr2_v4l2,channel); if (!vp->channel.mc_head->disconnect_flag) return; + pvr2_v4l2_dev_disassociate_parent(vp->dev_video); + pvr2_v4l2_dev_disassociate_parent(vp->dev_radio); if (vp->vfirst) return; pvr2_v4l2_destroy_no_lock(vp); } @@ -1250,12 +1261,13 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, struct pvr2_v4l2 *vp, int v4l_type) { + struct usb_device *usbdev; int mindevnum; int unit_number; int *nr_ptr = NULL; dip->v4lp = vp; - + usbdev = pvr2_hdw_get_dev(vp->channel.mc_head->hdw); dip->v4l_type = v4l_type; switch (v4l_type) { case VFL_TYPE_GRABBER: @@ -1296,6 +1308,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) { mindevnum = nr_ptr[unit_number]; } + dip->devbase.parent = &usbdev->dev; if ((video_register_device(&dip->devbase, dip->v4l_type, mindevnum) < 0) && (video_register_device(&dip->devbase, From 1b33185f5d944092576fc6562a842c603a2570d6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 12 Oct 2009 00:18:13 -0300 Subject: [PATCH 136/345] V4L/DVB (13223): pvrusb2: Soften encoder warning message pvrusb2: Encoder failures are mostly recoverable by the driver. While it would sure be nice not to have the failure happen in the first place, this has been going on for years and I doubt that a real solution will ever present itself. I think that part's firmware is just slightly flakey and we have to deal with it. The driver does deal with it just fine, but the warning message going into the kernel log is probably a little more alarming than it should be. So try to soften up the warning somewhat. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-encoder.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 54ac5349dee2..e046fdaec5ae 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -294,7 +294,10 @@ static int pvr2_encoder_cmd(void *ctxt, pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Giving up on command." - " This is normally recovered by the driver."); + " This is normally recovered via a firmware" + " reload and re-initialization; concern" + " is only warranted if this happens repeatedly" + " and rapidly."); break; } wrData[0] = 0x7; From 271081475427f7d1acf5f8cdc51fc70afe662b17 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 12 Oct 2009 00:21:20 -0300 Subject: [PATCH 137/345] V4L/DVB (13224): pvrusb2: Improve diagnostic info on driver initialization failure It used to be that the only real detectable reason for the driver to fail during initialization would be that if the hardware is simply jammed. However with the advent of the sub-device mechanism in V4L it is possible now to detect if a sub-device module fails to load successfully. The pvrusb2 driver does in fact react to this by also (correctly) failing, however the original diagnostic message "hardware is jammed" was still being reported. This misleads the user because in fact it might not actually be a hardware failure. This change adds logic to tell the difference and then report a more appropriate message to the kernel log. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- .../video/pvrusb2/pvrusb2-hdw-internal.h | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 5b152ff20bd0..9098494ae59c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -270,6 +270,7 @@ struct pvr2_hdw { int force_dirty; /* consider all controls dirty if true */ int flag_ok; /* device in known good state */ + int flag_modulefail; /* true if at least one module failed to load */ int flag_disconnected; /* flag_ok == 0 due to disconnect */ int flag_init_ok; /* true if structure is fully initialized */ int fw1_state; /* current situation with fw1 */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 13639b302700..33ea950abb4f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2030,7 +2030,8 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; if (!fname) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u for device %s has no name", + "Module ID %u for device %s has no name?" + " The driver might have a configuration problem.", mid, hdw->hdw_desc->description); return -EINVAL; @@ -2058,7 +2059,8 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, if (!i2ccnt) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Module ID %u (%s) for device %s:" - " No i2c addresses", + " No i2c addresses." + " The driver might have a configuration problem.", mid, fname, hdw->hdw_desc->description); return -EINVAL; } @@ -2090,7 +2092,9 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, if (!sd) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u (%s) for device %s failed to load", + "Module ID %u (%s) for device %s failed to load." + " Possible missing sub-device kernel module or" + " initialization failure within module.", mid, fname, hdw->hdw_desc->description); return -EIO; } @@ -2132,7 +2136,10 @@ static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) for (idx = 0; idx < ct->cnt; idx++) { if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0; } - if (!okFl) pvr2_hdw_render_useless(hdw); + if (!okFl) { + hdw->flag_modulefail = !0; + pvr2_hdw_render_useless(hdw); + } } @@ -2334,6 +2341,19 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw) break; } } + if (hdw->flag_modulefail) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "***WARNING*** pvrusb2 driver initialization" + " failed due to the failure of one or more" + " sub-device kernel modules."); + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "You need to resolve the failing condition" + " before this driver can function. There" + " should be some earlier messages giving more" + " information about the problem."); + } if (procreload) { pvr2_trace( PVR2_TRACE_ERROR_LEGS, From 00970beb9b51dd1b25c0d91a3f5fe11dd29e38e2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 12 Oct 2009 00:23:37 -0300 Subject: [PATCH 138/345] V4L/DVB (13225): pvrusb2: Report hardware description to kernel log upon initialization The driver also contains a piece of configuration data that produces a one line description of the specific hardware being driver (e.g. "Hauppauge 24xxx", "OnAir", etc). This change generates an informational message to the kernel log reporting the hardware type being driven. This is a very useful thing to know when diagnosing problems. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 33ea950abb4f..1bfa9b9d7aa0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2439,6 +2439,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", hdw,hdw_desc->description); + pvr2_trace(PVR2_TRACE_INFO, "Hardware description attached: %s", + hdw_desc->description); if (!hdw) goto fail; init_timer(&hdw->quiescent_timer); From aa976ca1dfb2e5b3fb67eeaf1ca44182ef3efcdb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 12 Oct 2009 00:25:09 -0300 Subject: [PATCH 139/345] V4L/DVB (13226): pvrusb2: Add hardware description to debuginfo output Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-debugifc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index fbe3856bdca6..010018bc8383 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -142,6 +142,9 @@ int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) { int bcnt = 0; int ccnt; + ccnt = scnprintf(buf, acnt, "Driver hardware description: %s\n", + pvr2_hdw_get_desc(hdw)); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; ccnt = scnprintf(buf,acnt,"Driver state info:\n"); bcnt += ccnt; acnt -= ccnt; buf += ccnt; ccnt = pvr2_hdw_state_report(hdw,buf,acnt); From 515ebf79e579d423d60aea4334d61007328c5114 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 12 Oct 2009 00:27:38 -0300 Subject: [PATCH 140/345] V4L/DVB (13227): pvrusb2: Fix redundant message on driver initialization failure (missing break) After detecting failure due to module initialization error, get out. Don't report jammed hardware. Problem due to a missing break statement. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1bfa9b9d7aa0..4a464ff3bb00 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2353,6 +2353,7 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw) " before this driver can function. There" " should be some earlier messages giving more" " information about the problem."); + break; } if (procreload) { pvr2_trace( From e67e376b1e50b60238410893971c5e6c4dd19ef1 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 12 Oct 2009 00:28:19 -0300 Subject: [PATCH 141/345] V4L/DVB (13228): pvrusb2: Cosmetic kernel log tweak Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 4a464ff3bb00..4c1a2a534427 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2440,7 +2440,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", hdw,hdw_desc->description); - pvr2_trace(PVR2_TRACE_INFO, "Hardware description attached: %s", + pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s", hdw_desc->description); if (!hdw) goto fail; From 2d8d7762d75d36a08a4a5c3d3f1c301f76cb8f56 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 24 Sep 2009 07:58:09 -0300 Subject: [PATCH 142/345] V4L/DVB (13231): pwc: Use kernel's simple_strtol() Change own implementation of pwc_atoi() by simple_strtol(x, NULL, 10). Signed-off-by: Andy Shevchenko Acked-by: Pekka Enberg Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/pwc-if.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index f976df452a34..89b620f6db7b 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -68,6 +68,7 @@ #endif #include #include +#include /* simple_strtol() */ #include "pwc.h" #include "pwc-kiara.h" @@ -1916,19 +1917,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf) unlock_kernel(); } -/* *grunt* We have to do atoi ourselves :-( */ -static int pwc_atoi(const char *s) -{ - int k = 0; - - k = 0; - while (*s != '\0' && *s >= '0' && *s <= '9') { - k = 10 * k + (*s - '0'); - s++; - } - return k; -} - /* * Initialization code & module stuff @@ -2078,13 +2066,16 @@ static int __init usb_pwc_init(void) } else { /* No type or serial number specified, just a number. */ - device_hint[i].device_node = pwc_atoi(s); + device_hint[i].device_node = + simple_strtol(s, NULL, 10); } } else { /* There's a colon, so we have at least a type and a device node */ - device_hint[i].type = pwc_atoi(s); - device_hint[i].device_node = pwc_atoi(colon + 1); + device_hint[i].type = + simple_strtol(s, NULL, 10); + device_hint[i].device_node = + simple_strtol(colon + 1, NULL, 10); if (*dot != '\0') { /* There's a serial number as well */ int k; From 3c3099d5edd719aebfccf63b628b6f11afa59bfe Mon Sep 17 00:00:00 2001 From: "Aleksandr V. Piskunov" Date: Fri, 25 Sep 2009 18:16:21 -0300 Subject: [PATCH 143/345] V4L/DVB (13232): cx25840 6.5MHz carrier detection fixes cx25840: Disable 6.5MHz carrier autodetection for PAL, always assume its DK. Only try to autodetect 6.5MHz carrier for SECAM if user accepts both system DK and L. Signed-off-by: Aleksandr V. Piskunov Reviewed-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 9702a9334b4a..385ecd58f1c0 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -685,13 +685,30 @@ static void input_change(struct i2c_client *client) } cx25840_write(client, 0x80b, 0x00); } else if (std & V4L2_STD_PAL) { - /* Follow tuner change procedure for PAL */ + /* Autodetect audio standard and audio system */ cx25840_write(client, 0x808, 0xff); - cx25840_write(client, 0x80b, 0x10); + /* Since system PAL-L is pretty much non-existant and + not used by any public broadcast network, force + 6.5 MHz carrier to be interpreted as System DK, + this avoids DK audio detection instability */ + cx25840_write(client, 0x80b, 0x00); } else if (std & V4L2_STD_SECAM) { - /* Select autodetect for SECAM */ + /* Autodetect audio standard and audio system */ cx25840_write(client, 0x808, 0xff); - cx25840_write(client, 0x80b, 0x10); + /* If only one of SECAM-DK / SECAM-L is required, then force + 6.5MHz carrier, else autodetect it */ + if ((std & V4L2_STD_SECAM_DK) && + !(std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) { + /* 6.5 MHz carrier to be interpreted as System DK */ + cx25840_write(client, 0x80b, 0x00); + } else if (!(std & V4L2_STD_SECAM_DK) && + (std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) { + /* 6.5 MHz carrier to be interpreted as System L */ + cx25840_write(client, 0x80b, 0x08); + } else { + /* 6.5 MHz carrier to be autodetected */ + cx25840_write(client, 0x80b, 0x10); + } } cx25840_and_or(client, 0x810, ~0x01, 0); From 43e16ea241cab1f4d4206307b2f6eacbaf4dc335 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 2 Oct 2009 05:47:08 -0300 Subject: [PATCH 144/345] V4L/DVB (13233): i2c_board_info can be local Recent fixes to the em28xx and saa7134 drivers have been overzealous. While the ir-kbd-i2c platform data indeed needs to be persistent, the struct i2c_board_info doesn't, as it is only used by i2c_new_device(). So revert a part of the original fixes, to save some memory. Signed-off-by: Jean Delvare Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 9 +++++---- drivers/media/video/em28xx/em28xx.h | 1 - drivers/media/video/saa7134/saa7134-input.c | 21 +++++++++++---------- drivers/media/video/saa7134/saa7134.h | 1 - 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 7ccac2095b75..6c7cbbc59e1c 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2234,6 +2234,7 @@ static int em28xx_hint_board(struct em28xx *dev) /* ----------------------------------------------------------------------- */ void em28xx_register_i2c_ir(struct em28xx *dev) { + struct i2c_board_info info; const unsigned short addr_list[] = { 0x30, 0x47, I2C_CLIENT_END }; @@ -2241,9 +2242,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) if (disable_ir) return; - memset(&dev->info, 0, sizeof(&dev->info)); + memset(&info, 0, sizeof(struct i2c_board_info)); memset(&dev->init_data, 0, sizeof(dev->init_data)); - strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); /* detect & configure */ switch (dev->model) { @@ -2266,8 +2267,8 @@ void em28xx_register_i2c_ir(struct em28xx *dev) } if (dev->init_data.name) - dev->info.platform_data = &dev->init_data; - i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); + info.platform_data = &dev->init_data; + i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); } void em28xx_card_setup(struct em28xx *dev) diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 0a73e8bf0d6e..a476f7bb7bf8 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -615,7 +615,6 @@ struct em28xx { struct em28xx_dvb *dvb; /* I2C keyboard data */ - struct i2c_board_info info; struct IR_i2c_init_data init_data; }; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index a0e8c62e6ae1..bcb65e93edca 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -695,6 +695,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { + struct i2c_board_info info; const unsigned short addr_list[] = { 0x7a, 0x47, 0x71, 0x2d, I2C_CLIENT_END @@ -714,9 +715,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) return; } - memset(&dev->info, 0, sizeof(dev->info)); + memset(&info, 0, sizeof(struct i2c_board_info)); memset(&dev->init_data, 0, sizeof(dev->init_data)); - strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: @@ -725,11 +726,11 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) if (pinnacle_remote == 0) { dev->init_data.get_key = get_key_pinnacle_color; dev->init_data.ir_codes = &ir_codes_pinnacle_color_table; - dev->info.addr = 0x47; + info.addr = 0x47; } else { dev->init_data.get_key = get_key_pinnacle_grey; dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; - dev->info.addr = 0x47; + info.addr = 0x47; } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: @@ -741,7 +742,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "MSI TV@nywhere Plus"; dev->init_data.get_key = get_key_msi_tvanywhere_plus; dev->init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; - dev->info.addr = 0x30; + info.addr = 0x30; /* MSI TV@nywhere Plus controller doesn't seem to respond to probes unless we read something from an existing device. Weird... @@ -775,20 +776,20 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: - dev->info.addr = 0x40; + info.addr = 0x40; break; } if (dev->init_data.name) - dev->info.platform_data = &dev->init_data; + info.platform_data = &dev->init_data; /* No need to probe if address is known */ - if (dev->info.addr) { - i2c_new_device(&dev->i2c_adap, &dev->info); + if (info.addr) { + i2c_new_device(&dev->i2c_adap, &info); return; } /* Address not known, fallback to probing */ - i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); + i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); } static int saa7134_rc5_irq(struct saa7134_dev *dev) diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 13a861bedc36..53b7e0b8a2fb 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -594,7 +594,6 @@ struct saa7134_dev { unsigned int insuspend; /* I2C keyboard data */ - struct i2c_board_info info; struct IR_i2c_init_data init_data; /* SAA7134_MPEG_* */ From aef02aa1e2593b39f808b2b8ae928699087b96dc Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 2 Oct 2009 08:47:22 -0300 Subject: [PATCH 145/345] V4L/DVB (13234): IR device at I2C address 0x7a The i2c core prevents us from probing I2C address 0x7a because it's not a valid 7-bit address (reserved for 10-bit addressing.) So we must stop probing this address, and explicitly list all adapters which use it. Under the assumption that only the Upmost Purple TV adapter uses this invalid address, this fix should do the trick. Signed-off-by: Jean Delvare Acked-by: hermann pitton Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-input.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index bcb65e93edca..c3b5cfa13b60 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -697,7 +697,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { struct i2c_board_info info; const unsigned short addr_list[] = { - 0x7a, 0x47, 0x71, 0x2d, + 0x47, 0x71, 0x2d, I2C_CLIENT_END }; @@ -737,6 +737,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "Purple TV"; dev->init_data.get_key = get_key_purpletv; dev->init_data.ir_codes = &ir_codes_purpletv_table; + info.addr = 0x7a; break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: dev->init_data.name = "MSI TV@nywhere Plus"; From 30093e8bf90217deef07299bae45d95ddc5fdb8a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 2 Oct 2009 09:48:04 -0300 Subject: [PATCH 146/345] V4L/DVB (13235): saa7134: Complete the IR address list Google is pretty clear that the HVR 1110 IR chip is always at address 0x71 and the BeholdTV IR chip is always at address 0x2d. This completes the list of IR device addresses for the SAA7134-based adapters, and we no longer need to probe any of them. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-input.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index c3b5cfa13b60..8f9203e7d3b8 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -696,10 +696,6 @@ void saa7134_input_fini(struct saa7134_dev *dev) void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { struct i2c_board_info info; - const unsigned short addr_list[] = { - 0x47, 0x71, 0x2d, - I2C_CLIENT_END - }; struct i2c_msg msg_msi = { .addr = 0x50, @@ -757,6 +753,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "HVR 1110"; dev->init_data.get_key = get_key_hvr1110; dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; + info.addr = 0x71; break; case SAA7134_BOARD_BEHOLD_607FM_MK3: case SAA7134_BOARD_BEHOLD_607FM_MK5: @@ -774,23 +771,20 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "BeholdTV"; dev->init_data.get_key = get_key_beholdm6xx; dev->init_data.ir_codes = &ir_codes_behold_table; + info.addr = 0x2d; break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: info.addr = 0x40; break; + default: + dprintk("No I2C IR support for board %x\n", dev->board); + return; } if (dev->init_data.name) info.platform_data = &dev->init_data; - /* No need to probe if address is known */ - if (info.addr) { - i2c_new_device(&dev->i2c_adap, &info); - return; - } - - /* Address not known, fallback to probing */ - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + i2c_new_device(&dev->i2c_adap, &info); } static int saa7134_rc5_irq(struct saa7134_dev *dev) From 7ef68e60d9435eb604a346babccb48000b94bc76 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 2 Oct 2009 10:27:42 -0300 Subject: [PATCH 147/345] V4L/DVB (13236): ir-kbd-i2c: Don't reject unknown I2C addresses I do not think it makes sense any longer for ir-kbd-i2c to reject devices at unknown I2C addresses. The caller can provide all the details about how the device should be handled. Having to add new addresses to ir-kbd-i2c so that they aren't rejected is a pain we don't need. Unsupported devices will be spotted a few lines later anyway. This already lets us unlist 2 addresses (0x7a and 0x2d) for which handling details are always provided by the caller (saa7134-input). Hopefully we can remove more in the future. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ir-kbd-i2c.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 247d3115a9b7..aec36660987d 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -299,7 +299,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ir_scancode_table *ir_codes = NULL; const char *name = NULL; - int ir_type; + int ir_type = 0; struct IR_i2c *ir; struct input_dev *input_dev; struct i2c_adapter *adap = client->adapter; @@ -353,10 +353,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir_type = IR_TYPE_RC5; ir_codes = &ir_codes_fusionhdtv_mce_table; break; - case 0x7a: case 0x47: case 0x71: - case 0x2d: if (adap->id == I2C_HW_B_CX2388x || adap->id == I2C_HW_B_CX2341X) { /* Handled by cx88-input */ @@ -381,10 +379,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir_type = IR_TYPE_OTHER; ir_codes = &ir_codes_avermedia_cardbus_table; break; - default: - dprintk(1, DEVNAME ": Unsupported i2c address 0x%02x\n", addr); - err = -ENODEV; - goto err_out_free; } /* Let the caller override settings */ @@ -427,7 +421,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) } /* Make sure we are all setup before going on */ - if (!name || !ir->get_key || !ir_codes) { + if (!name || !ir->get_key || !ir_type || !ir_codes) { dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n", addr); err = -ENODEV; From 622b828ab795580903e79acb33fb44f5c9ce7b0f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 5 Oct 2009 10:48:17 -0300 Subject: [PATCH 148/345] V4L/DVB (13238): v4l2_subdev: rename tuner s_standby operation to core s_power Upcoming I2C v4l2_subdev drivers need a way to control the subdevice power state from the core. This use case is already partially covered by the tuner s_standby operation, but no way to explicitly come back from the standby state is available. Rename the tuner s_standby operation to core s_power, and fix tuner drivers accordingly. The tuner core will call s_power(0) instead of s_standby(). No explicit call to s_power(1) is required for tuners as they are supposed to wake up from standby automatically. [mchehab@redhat.com: CodingStyle fix] Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 2 +- drivers/media/video/cx231xx/cx231xx-video.c | 2 +- drivers/media/video/cx23885/cx23885-core.c | 2 +- drivers/media/video/cx23885/cx23885-dvb.c | 2 +- drivers/media/video/cx88/cx88-cards.c | 2 +- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/cx88/cx88-video.c | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/em28xx/em28xx-video.c | 2 +- drivers/media/video/saa7134/saa7134-core.c | 2 +- drivers/media/video/saa7134/saa7134-video.c | 2 +- drivers/media/video/tuner-core.c | 9 ++++++--- include/media/v4l2-subdev.h | 7 ++++--- 13 files changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 51527d7b55a7..1485aee18d58 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -830,7 +830,7 @@ static int au0828_v4l2_close(struct file *filp) au0828_uninit_isoc(dev); /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); /* When close the device, set the usb intf0 into alt0 to free USB bandwidth */ diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 36503725d973..d095aa0d6d19 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -2106,7 +2106,7 @@ static int cx231xx_v4l2_close(struct file *filp) } /* Save some power by putting tuner to sleep */ - call_all(dev, tuner, s_standby); + call_all(dev, core, s_power, 0); /* do this before setting alternate! */ cx231xx_uninit_isoc(dev); diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index d6e41db500ef..e34a4ec4a2cd 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -919,7 +919,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_i2c_register(&dev->i2c_bus[1]); cx23885_i2c_register(&dev->i2c_bus[2]); cx23885_card_setup(dev); - call_all(dev, tuner, s_standby); + call_all(dev, core, s_power, 0); cx23885_ir_init(dev); if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 4d439f2c4abc..f4f046cd81a5 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -920,7 +920,7 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ - call_all(dev, tuner, s_standby); + call_all(dev, core, s_power, 0); if (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 33be6369871a..7330a2d70439 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -3267,7 +3267,7 @@ static void cx88_card_setup(struct cx88_core *core) ctl.fname); call_all(core, tuner, s_config, &xc2028_cfg); } - call_all(core, tuner, s_standby); + call_all(core, core, s_power, 0); } /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index d9e402b25b56..9df71d0244a8 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -1170,7 +1170,7 @@ static int dvb_register(struct cx8802_dev *dev) fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ - call_all(core, tuner, s_standby); + call_all(core, core, s_power, 0); /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 57e6b1241090..d7e8fcee559c 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -935,7 +935,7 @@ static int video_release(struct file *file) mutex_lock(&dev->core->lock); if(atomic_dec_and_test(&dev->core->users)) - call_all(dev->core, tuner, s_standby); + call_all(dev->core, core, s_power, 0); mutex_unlock(&dev->core->lock); return 0; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 6c7cbbc59e1c..1e1937070738 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2658,7 +2658,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_init_extension(dev); /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); return 0; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 3a1dfb7726f8..fbe536f092f9 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2225,7 +2225,7 @@ static int em28xx_v4l2_close(struct file *filp) } /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); /* do this before setting alternate! */ em28xx_uninit_isoc(dev); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index f87757fccc72..9a5df930885b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -1032,7 +1032,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, saa7134_irq_video_signalchange(dev); if (TUNER_ABSENT != dev->tuner_type) - saa_call_all(dev, tuner, s_standby); + saa_call_all(dev, core, s_power, 0); /* register v4l devices */ if (saa7134_no_overlay > 0) diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index da26f476a302..35f8daa3a359 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1499,7 +1499,7 @@ static int video_release(struct file *file) saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0); saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); - saa_call_all(dev, tuner, s_standby); + saa_call_all(dev, core, s_power, 0); if (fh->radio) saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd); diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index aba92e2313d8..50f6db5cd50b 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -752,14 +752,17 @@ static int tuner_s_radio(struct v4l2_subdev *sd) return 0; } -static int tuner_s_standby(struct v4l2_subdev *sd) +static int tuner_s_power(struct v4l2_subdev *sd, int on) { struct tuner *t = to_tuner(sd); struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; + if (on) + return 0; + tuner_dbg("Putting tuner to sleep\n"); - if (check_mode(t, "s_standby") == -EINVAL) + if (check_mode(t, "s_power") == -EINVAL) return 0; t->mode = T_STANDBY; if (analog_ops->standby) @@ -961,6 +964,7 @@ static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg) static const struct v4l2_subdev_core_ops tuner_core_ops = { .log_status = tuner_log_status, .s_std = tuner_s_std, + .s_power = tuner_s_power, }; static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { @@ -971,7 +975,6 @@ static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { .g_frequency = tuner_g_frequency, .s_type_addr = tuner_s_type_addr, .s_config = tuner_s_config, - .s_standby = tuner_s_standby, }; static const struct v4l2_subdev_ops tuner_ops = { diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index ecc2818938b3..88c13d6f7912 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -106,6 +106,9 @@ struct v4l2_decode_vbi_line { s_gpio: set GPIO pins. Very simple right now, might need to be extended with a direction argument if needed. + + s_power: puts subdevice in power saving mode (on == 0) or normal operation + mode (on == 1). */ struct v4l2_subdev_core_ops { int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); @@ -128,6 +131,7 @@ struct v4l2_subdev_core_ops { 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 + int (*s_power)(struct v4l2_subdev *sd, int on); }; /* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio. @@ -137,8 +141,6 @@ struct v4l2_subdev_core_ops { s_type_addr: sets tuner type and its I2C addr. s_config: sets tda9887 specific stuff, like port1, port2 and qss - - s_standby: puts tuner on powersaving state, disabling it, except for i2c. */ struct v4l2_subdev_tuner_ops { int (*s_mode)(struct v4l2_subdev *sd, enum v4l2_tuner_type); @@ -151,7 +153,6 @@ struct v4l2_subdev_tuner_ops { int (*s_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm); 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); - int (*s_standby)(struct v4l2_subdev *sd); }; /* s_clock_freq: set the frequency (in Hz) of the audio clock output. From 311c70e1f906b7411b30f526ef15deb62cb37e7a Mon Sep 17 00:00:00 2001 From: Johann Friedrichs Date: Wed, 7 Oct 2009 04:41:37 -0300 Subject: [PATCH 149/345] V4L/DVB (13239): saa7146: fix memory leakage in pagetable-handling In buffer_release() the previously allocated pagetables are not freed, which might result in a memory leak in certain application use-cases, where the frame format is changed from planar format to non-planar format. The fix explicitely frees the page tables when a format change is done and when buffer_release() is called. Signed-off-by: Johann Friedrichs Signed-off-by: Michael Hunold Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_video.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 552dab442d78..becbaadb3b77 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1205,6 +1205,13 @@ static int buffer_activate (struct saa7146_dev *dev, return 0; } +static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf) +{ + saa7146_pgtable_free(dev->pci, &buf->pt[0]); + saa7146_pgtable_free(dev->pci, &buf->pt[1]); + saa7146_pgtable_free(dev->pci, &buf->pt[2]); +} + static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { @@ -1257,16 +1264,12 @@ static int buffer_prepare(struct videobuf_queue *q, sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); + release_all_pagetables(dev, buf); if( 0 != IS_PLANAR(sfmt->trans)) { - saa7146_pgtable_free(dev->pci, &buf->pt[0]); - saa7146_pgtable_free(dev->pci, &buf->pt[1]); - saa7146_pgtable_free(dev->pci, &buf->pt[2]); - saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); saa7146_pgtable_alloc(dev->pci, &buf->pt[1]); saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); } else { - saa7146_pgtable_free(dev->pci, &buf->pt[0]); saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); } @@ -1329,6 +1332,9 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) struct saa7146_buf *buf = (struct saa7146_buf *)vb; DEB_CAP(("vbuf:%p\n",vb)); + + release_all_pagetables(dev, buf); + saa7146_dma_free(dev,q,buf); } From f14a2972e40dbfbe7077ec7ab21cc2729f7e7d6d Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 23 Oct 2009 07:59:42 -0300 Subject: [PATCH 150/345] V4L/DVB (13241): Cleanup redundant tests on unsigned The variables are unsigned so the test `>= 0' is always true, the `< 0' test always fails. In these cases the other part of the test catches wrapped values. Signed-off-by: Roel Kluin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda9887.c | 2 +- drivers/media/dvb/siano/smscoreapi.c | 2 +- drivers/media/video/bt819.c | 2 +- drivers/media/video/hexium_gemini.c | 2 +- drivers/media/video/hexium_orion.c | 2 +- drivers/media/video/mxb.c | 2 +- drivers/media/video/s2255drv.c | 2 +- drivers/media/video/saa7110.c | 2 +- drivers/media/video/saa717x.c | 2 +- drivers/media/video/tuner-core.c | 2 +- drivers/media/video/usbvision/usbvision-video.c | 2 +- drivers/media/video/vpx3220.c | 2 +- drivers/media/video/zoran/zoran_driver.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/common/tuners/tda9887.c index 544cdbe88a6c..a71c100c95df 100644 --- a/drivers/media/common/tuners/tda9887.c +++ b/drivers/media/common/tuners/tda9887.c @@ -463,7 +463,7 @@ static int tda9887_set_insmod(struct dvb_frontend *fe) buf[1] &= ~cQSS; } - if (adjust >= 0x00 && adjust < 0x20) { + if (adjust < 0x20) { buf[2] &= ~cTopMask; buf[2] |= adjust; } diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index fa6a62369a78..ca758bcb48c9 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c @@ -1373,7 +1373,7 @@ static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum, *pGroupCfg = 1; - if (PinNum >= 0 && PinNum <= 1) { + if (PinNum <= 1) { *pTranslatedPinNum = 0; *pGroupNum = 9; *pGroupCfg = 2; diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index f9330e3529c3..5bb0f9e71583 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -299,7 +299,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, v4l2_dbg(1, debug, sd, "set input %x\n", input); - if (input < 0 || input > 7) + if (input > 7) return -EINVAL; if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index 71c211402eb5..60d992ee2589 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -251,7 +251,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); - if (input < 0 || input >= HEXIUM_INPUTS) + if (input >= HEXIUM_INPUTS) return -EINVAL; hexium->cur_input = input; diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 39d65ca41c62..938a1f8f880a 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -350,7 +350,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct hexium *hexium = (struct hexium *) dev->ext_priv; - if (input < 0 || input >= HEXIUM_INPUTS) + if (input >= HEXIUM_INPUTS) return -EINVAL; hexium->cur_input = input; diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 3454070e63f0..c1fc6dc776f5 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -478,7 +478,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); - if (input < 0 || input >= MXB_INPUTS) + if (input >= MXB_INPUTS) return -EINVAL; mxb->cur_input = input; diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 2c0bb06cab3b..d0824f3c734f 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1958,7 +1958,7 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) if (pdword[1] >= MAX_CHANNELS) break; cc = G_chnmap[pdword[1]]; - if (!(cc >= 0 && cc < MAX_CHANNELS)) + if (cc >= MAX_CHANNELS) break; switch (pdword[2]) { case S2255_RESPONSE_SETMODE: diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 5c24c993ac16..3bca744e43af 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -304,7 +304,7 @@ static int saa7110_s_routing(struct v4l2_subdev *sd, { struct saa7110 *decoder = to_saa7110(sd); - if (input < 0 || input >= SAA7110_MAX_INPUT) { + if (input >= SAA7110_MAX_INPUT) { v4l2_dbg(1, debug, sd, "input=%d not available\n", input); return -EINVAL; } diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index b15c40908e84..ad6cd37311fa 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c @@ -1115,7 +1115,7 @@ static int saa717x_s_video_routing(struct v4l2_subdev *sd, v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input); /* inputs from 0-9 are available*/ /* saa717x have mode0-mode9 but mode5 is reserved. */ - if (input < 0 || input > 9 || input == 5) + if (input > 9 || input == 5) return -EINVAL; if (decoder->input != input) { diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 50f6db5cd50b..a9c9703113c2 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -328,7 +328,7 @@ static void set_type(struct i2c_client *c, unsigned int type, t->type = type; /* prevent invalid config values */ - t->config = ((new_config >= 0) && (new_config < 256)) ? new_config : 0; + t->config = new_config < 256 ? new_config : 0; if (tuner_callback != NULL) { tuner_dbg("defining GPIO callback\n"); t->fe.callback = tuner_callback; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index a2a50d608a3f..c07b0ac452ab 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -601,7 +601,7 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input) { struct usb_usbvision *usbvision = video_drvdata(file); - if ((input >= usbvision->video_inputs) || (input < 0) ) + if (input >= usbvision->video_inputs) return -EINVAL; mutex_lock(&usbvision->lock); diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 97e0ce28ff18..33205d7537d8 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -391,7 +391,7 @@ static int vpx3220_s_routing(struct v4l2_subdev *sd, {0x0e, 1} }; - if (input < 0 || input > 2) + if (input > 2) return -EINVAL; v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[input]); diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 47137deafcfd..e9f72ca458f1 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2764,7 +2764,7 @@ static int zoran_enum_input(struct file *file, void *__fh, struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - if (inp->index < 0 || inp->index >= zr->card.inputs) + if (inp->index >= zr->card.inputs) return -EINVAL; else { int id = inp->index; From 065b6f7a34ec5628e0b1243bfc4214cb5f53d429 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 29 Oct 2009 07:42:30 -0300 Subject: [PATCH 151/345] V4L/DVB (13242): gspca_mr97310a: Add minimum clock divider control When "shooting" certain (quite rare) scenes, the mr97310's compression is not effective and it cannot keep up with the data stream. This patch adds a minimum clock divider control, which influences the maximum framerate, libv4l will automatically increase this minimum clockdiv control when it detect the cam cannot keep up. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 57 +++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index f282f8000701..63050f0ebfad 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -55,6 +55,10 @@ #define MR97310A_GAIN_MAX 31 #define MR97310A_GAIN_DEFAULT 25 +#define MR97310A_MIN_CLOCKDIV_MIN 3 +#define MR97310A_MIN_CLOCKDIV_MAX 8 +#define MR97310A_MIN_CLOCKDIV_DEFAULT 3 + MODULE_AUTHOR("Kyle Guinn ," "Theodore Kilgore "); MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); @@ -76,6 +80,7 @@ struct sd { int brightness; u16 exposure; u8 gain; + u8 min_clockdiv; }; struct sensor_w_data { @@ -92,6 +97,8 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); static void setbrightness(struct gspca_dev *gspca_dev); static void setexposure(struct gspca_dev *gspca_dev); static void setgain(struct gspca_dev *gspca_dev); @@ -160,6 +167,21 @@ static struct ctrl sd_ctrls[] = { .set = sd_setgain, .get = sd_getgain, }, + { +#define MIN_CLOCKDIV_IDX 4 + { + .id = V4L2_CID_PRIVATE_BASE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Minimum Clock Divider", + .minimum = MR97310A_MIN_CLOCKDIV_MIN, + .maximum = MR97310A_MIN_CLOCKDIV_MAX, + .step = 1, + .default_value = MR97310A_MIN_CLOCKDIV_DEFAULT, + .flags = 0, + }, + .set = sd_setmin_clockdiv, + .get = sd_getmin_clockdiv, + }, }; static const struct v4l2_pix_format vga_mode[] = { @@ -544,14 +566,16 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << ARGUS_QC_BRIGHTNESS_IDX); else - gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); + gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | + (1 << MIN_CLOCKDIV_IDX); } else { /* All controls need to be disabled if VGA sensor_type is 0 */ if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << EXPOSURE_IDX) | - (1 << GAIN_IDX); + (1 << GAIN_IDX) | + (1 << MIN_CLOCKDIV_IDX); else if (sd->do_lcd_stop) /* Argus QuickClix has different brightness limits */ gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); @@ -562,6 +586,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; sd->exposure = MR97310A_EXPOSURE_DEFAULT; sd->gain = MR97310A_GAIN_DEFAULT; + sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; return 0; } @@ -837,6 +862,7 @@ static void setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int exposure; + u8 buf[2]; if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) return; @@ -858,8 +884,8 @@ static void setexposure(struct gspca_dev *gspca_dev) u8 clockdiv = (60 * sd->exposure + 7999) / 8000; /* Limit framerate to not exceed usb bandwidth */ - if (clockdiv < 3 && gspca_dev->width >= 320) - clockdiv = 3; + if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320) + clockdiv = sd->min_clockdiv; else if (clockdiv < 2) clockdiv = 2; @@ -875,9 +901,10 @@ static void setexposure(struct gspca_dev *gspca_dev) /* exposure register value is reversed! */ exposure = 511 - exposure; + buf[0] = exposure & 0xff; + buf[1] = exposure >> 8; + sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2); sensor_write1(gspca_dev, 0x02, clockdiv); - sensor_write1(gspca_dev, 0x0e, exposure & 0xff); - sensor_write1(gspca_dev, 0x0f, exposure >> 8); } } @@ -949,6 +976,24 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->min_clockdiv = val; + if (gspca_dev->streaming) + setexposure(gspca_dev); + return 0; +} + +static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->min_clockdiv; + return 0; +} + /* Include pac common sof detection functions */ #include "pac_common.h" From 8ac246cb8fc880cb8f438ab7ded454207cc8170d Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Thu, 29 Oct 2009 07:45:24 -0300 Subject: [PATCH 152/345] V4L/DVB (13243): gscpa_mr97310a: Add Trust Spyc@m 100 USB ID gscpa_mr97310a: Add Trust Spyc@m 100 USB ID Signed-off-by: Aurelien Jacobs Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/mr97310a.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 90e85a8a8817..2bd1d165042f 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -203,6 +203,7 @@ spca500 084d:0003 D-Link DSC-350 spca500 08ca:0103 Aiptek PocketDV sunplus 08ca:0104 Aiptek PocketDVII 1.3 sunplus 08ca:0106 Aiptek Pocket DV3100+ +mr97310a 08ca:0110 Trust Spyc@m 100 mr97310a 08ca:0111 Aiptek PenCam VGA+ sunplus 08ca:2008 Aiptek Mini PenCam 2 M sunplus 08ca:2010 Aiptek PocketCam 3M diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 63050f0ebfad..d316b56e396e 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -457,7 +457,7 @@ static int sd_config(struct gspca_dev *gspca_dev, if (err_code < 0) return err_code; - if (id->idProduct == 0x010e) { + if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { sd->cam_type = CAM_TYPE_CIF; cam->nmodes--; err_code = cam_get_response16(gspca_dev, 0x06, 1); @@ -1039,6 +1039,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */ {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */ From 1160a3818ec387ddadfd173b3bceea654a474b74 Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Fri, 30 Oct 2009 04:29:56 -0300 Subject: [PATCH 153/345] V4L/DVB (13244): gspca_mr97310a: Fix / update some comments gspca_mr97310a: Fix / update some comments Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index d316b56e396e..b66169256dc4 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -18,7 +18,9 @@ * Several previously unsupported cameras are owned and have been tested by * Hans de Goede and * Thomas Kaiser and - * Theodore Kilgore + * Theodore Kilgore and + * Edmond Rodriguez and + * Aurelien Jacobs * * The MR97311A support in gspca/mars.c has been helpful in understanding some * of the registers in these cameras. @@ -105,8 +107,8 @@ static void setgain(struct gspca_dev *gspca_dev); /* V4L2 controls supported by the driver */ static struct ctrl sd_ctrls[] = { -/* Seprate brightness control description for Argus QuickClix as it has - different limits from to other mr97310a camera's */ +/* Separate brightness control description for Argus QuickClix as it has + different limits from the other mr97310a cameras */ { #define NORM_BRIGHTNESS_IDX 0 { @@ -428,7 +430,7 @@ static int isoc_enable(struct gspca_dev *gspca_dev) return mr_write(gspca_dev, 2); } -/* this function is called at probe time */ +/* This function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { @@ -441,11 +443,11 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = ARRAY_SIZE(vga_mode); sd->do_lcd_stop = 0; - /* Now, logical layout of the driver must fall sacrifice to the - * realities of the hardware supported. We have to sort out several - * cameras which share the USB ID but are in fact different inside. - * We need to start the initialization process for the cameras in - * order to classify them. Some of the supported cameras require the + /* Several of the supported CIF cameras share the same USB ID but + * require different initializations and different control settings. + * The same is true of the VGA cameras. Therefore, we are forced + * to start the initialization process in order to determine which + * camera is present. Some of the supported cameras require the * memory pointer to be set to 0 as the very first item of business * or else they will not stream. So we do that immediately. */ @@ -464,9 +466,10 @@ static int sd_config(struct gspca_dev *gspca_dev, if (err_code < 0) return err_code; /* - * The various CIF cameras share the same USB ID but use - * different init routines and different controls. We need to - * detect which one is connected! + * All but one of the known CIF cameras share the same USB ID, + * but two different init routines are in use, and the control + * settings are different, too. We need to detect which camera + * of the two known varieties is connected! * * A list of known CIF cameras follows. They all report either * 0002 for type 0 or 0003 for type 1. @@ -481,6 +484,7 @@ static int sd_config(struct gspca_dev *gspca_dev, * Vivitar Mini 1 T. Kilgore * Elta-Media 8212dc 1 T. Kaiser * Philips dig. keych. 1 T. Kilgore + * Trust Spyc@m 100 1 A. Jacobs */ switch (gspca_dev->usb_buf[1]) { case 2: From 64f4d9a367b4fe329ba78e3171d1abb1338a951f Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Fri, 30 Oct 2009 04:43:39 -0300 Subject: [PATCH 154/345] V4L/DVB (13245): gspca_mr97310a: Change blue gain setting for Sakar Digital VGA camera gspca_mr97310a: Change blue gain setting for Sakar Digital VGA camera Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 32 ++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index b66169256dc4..a97061a9e44a 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -78,6 +78,7 @@ struct sd { u8 cam_type; /* 0 is CIF and 1 is VGA */ u8 sensor_type; /* We use 0 and 1 here, too. */ u8 do_lcd_stop; + u8 adj_colors; int brightness; u16 exposure; @@ -525,6 +526,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor_type = 1; sd->do_lcd_stop = 0; + sd->adj_colors = 0; if ((gspca_dev->usb_buf[0] != 0x03) && (gspca_dev->usb_buf[0] != 0x04)) { PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", @@ -532,6 +534,10 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_ERR, "Defaults assumed, may not work"); PDEBUG(D_ERR, "Please report this"); } + /* Sakar Digital color needs to be adjusted. */ + if ((gspca_dev->usb_buf[0] == 0x03) && + (gspca_dev->usb_buf[1] == 0x50)) + sd->adj_colors = 1; if (gspca_dev->usb_buf[0] == 0x04) { sd->do_lcd_stop = 1; switch (gspca_dev->usb_buf[1]) { @@ -759,9 +765,20 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, ARRAY_SIZE(vga_sensor0_init_data)); } else { /* sd->sensor_type = 1 */ - const struct sensor_w_data vga_sensor1_init_data[] = { + const struct sensor_w_data color_adj[] = { {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, - 0x07, 0x00, 0x01}, 8}, + /* adjusted blue, green, red gain correct + too much blue from the Sakar Digital */ + 0x05, 0x01, 0x05}, 8} + }; + + const struct sensor_w_data color_no_adj[] = { + {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, + /* default blue, green, red gain settings */ + 0x07, 0x00, 0x01}, 8} + }; + + const struct sensor_w_data vga_sensor1_init_data[] = { {0x11, 0x04, {0x01}, 1}, /*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */ {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, @@ -771,6 +788,17 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) {0x11, 0x04, {0x01}, 1}, {0, 0, {0}, 0} }; + + if (sd->adj_colors) + err_code = sensor_write_regs(gspca_dev, color_adj, + ARRAY_SIZE(color_adj)); + else + err_code = sensor_write_regs(gspca_dev, color_no_adj, + ARRAY_SIZE(color_no_adj)); + + if (err_code < 0) + return err_code; + err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, ARRAY_SIZE(vga_sensor1_init_data)); } From d6eef4947858ebebaf05d79bce7b8be0d4c036ba Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 24 Oct 2009 16:42:16 -0300 Subject: [PATCH 155/345] V4L/DVB (13247): tuner-core: dont force every tuner to set frequency at startup Setting the tuner frequency at the same time as initializing the other devices on the i2c bus can cause problems on devices that require firmware download or extensive calibration proceduces during initialization. This change allows us to prevent the tune at startup for devices that perform better without it. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index a9c9703113c2..5b3eaa16afd2 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -320,6 +320,7 @@ static void set_type(struct i2c_client *c, unsigned int type, 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]; + int tune_now = 1; if (type == UNSET || type == TUNER_ABSENT) { tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr); @@ -404,6 +405,7 @@ static void set_type(struct i2c_client *c, unsigned int type, }; if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) goto attach_failed; + tune_now = 0; break; } case TUNER_TDA9887: @@ -419,6 +421,7 @@ static void set_type(struct i2c_client *c, unsigned int type, if (!dvb_attach(xc5000_attach, &t->fe, t->i2c->adapter, &xc5000_cfg)) goto attach_failed; + tune_now = 0; break; } case TUNER_NXP_TDA18271: @@ -430,6 +433,7 @@ static void set_type(struct i2c_client *c, unsigned int type, if (!dvb_attach(tda18271_attach, &t->fe, t->i2c->addr, t->i2c->adapter, &cfg)) goto attach_failed; + tune_now = 0; break; } default: @@ -458,12 +462,13 @@ static void set_type(struct i2c_client *c, unsigned int type, if (t->mode_mask == T_UNINITIALIZED) t->mode_mask = new_mode_mask; - /* xc2028/3028 and xc5000 requires a firmware to be set-up later + /* Some tuners require more initialization setup before use, + such as firmware download or device calibration. trying to set a frequency here will just fail FIXME: better to move set_freq to the tuner code. This is needed on analog tuners for PLL to properly work */ - if (t->type != TUNER_XC2028 && t->type != TUNER_XC5000) + if (tune_now) set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq); From 56e93ed9cff06e258cff8815fde31cd61d0a6d5a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 20 Oct 2009 04:34:11 -0300 Subject: [PATCH 156/345] V4L/DVB (13249): gspca - pac7311: Webcam 093a:2628 added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/pac7311.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 2bd1d165042f..a87a8ceb6246 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -241,6 +241,7 @@ pac7311 093a:2621 PAC731x pac7311 093a:2622 Genius Eye 312 pac7311 093a:2624 PAC7302 pac7311 093a:2626 Labtec 2200 +pac7311 093a:2628 Genius iLook 300 pac7311 093a:2629 Genious iSlim 300 pac7311 093a:262a Webcam 300k pac7311 093a:262c Philips SPC 230 NC diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index f954900c451b..a3fbd307bb76 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -1092,6 +1092,7 @@ static __devinitdata struct usb_device_id device_table[] = { {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, 0x2628), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2629), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302}, From 721ecbcbea61df76490b3ba03c7dded7134e628c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 20 Oct 2009 05:25:16 -0300 Subject: [PATCH 157/345] V4L/DVB (13250): gspca - zc3xx: Add some delays and warn on i2c errors. This patch fixes the kernel bug 14195 (random errors - bad images - with the webcam 10fd:8050 - sensor tas5130cxx). Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 0aa87d2958a0..e57f9dd68a48 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6036,8 +6036,10 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev, reg_w_i(gspca_dev->dev, reg, 0x0092); reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ - msleep(25); + msleep(20); retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ + if (retbyte != 0x00) + err("i2c_r status error %02x", retbyte); retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", @@ -6056,8 +6058,10 @@ 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(15); + msleep(1); retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ + if (retbyte != 0x00) + err("i2c_w status error %02x", retbyte); PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", reg, valH, valL, retbyte); return retbyte; @@ -6092,7 +6096,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, break; } action++; -/* msleep(1); */ + msleep(1); } } @@ -6555,7 +6559,7 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) start_2wr_probe(dev, 0x0e); /* PAS202BCB */ reg_w(dev, 0x08, 0x008d); i2c_write(gspca_dev, 0x03, 0xaa, 0x00); - msleep(500); + msleep(50); retword = i2c_read(gspca_dev, 0x03); if (retword != 0) return 0x0e; /* PAS202BCB */ @@ -6699,7 +6703,6 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) reg_w(dev, 0x01, 0x0001); reg_w(dev, 0xee, 0x008b); reg_w(dev, 0x03, 0x0012); -/* msleep(150); */ reg_w(dev, 0x01, 0x0012); reg_w(dev, 0x05, 0x0012); retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */ @@ -7100,7 +7103,7 @@ static int sd_start(struct gspca_dev *gspca_dev) setautogain(gspca_dev); switch (sd->sensor) { case SENSOR_PO2030: - msleep(500); + msleep(50); reg_r(gspca_dev, 0x0008); reg_r(gspca_dev, 0x0007); /*fall thru*/ From 7fb101ae2525ea5e8bad43a3fc228e87c5f047c6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 22 Oct 2009 06:27:14 -0300 Subject: [PATCH 158/345] V4L/DVB (13251): gspca - sonixj: Cleanup code and change some comments. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 38 +++++++++++++----------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 82604f328dc4..22209945698e 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -455,7 +455,7 @@ static const u8 hv7131r_sensor_init[][8] = { {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10}, @@ -1014,7 +1014,7 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) reg_r(gspca_dev, 0x0a, 5); } -static int hv7131r_probe(struct gspca_dev *gspca_dev) +static void hv7131r_probe(struct gspca_dev *gspca_dev) { i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ msleep(10); @@ -1026,14 +1026,12 @@ static int hv7131r_probe(struct gspca_dev *gspca_dev) && gspca_dev->usb_buf[2] == 0x01 && gspca_dev->usb_buf[3] == 0x00 && gspca_dev->usb_buf[4] == 0x00) { - PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R"); - return 0; + PDEBUG(D_PROBE, "Sensor sn9c102P HV7131R found"); + return; } - PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x", + PDEBUG(D_PROBE, "Sensor 0x%02x 0x%02x 0x%02x - sn9c102P not found", gspca_dev->usb_buf[0], gspca_dev->usb_buf[1], gspca_dev->usb_buf[2]); - PDEBUG(D_PROBE, "Sensor sn9c102P Not found"); - return -ENODEV; } static void mi0360_probe(struct gspca_dev *gspca_dev) @@ -1086,7 +1084,7 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) } } -static int configure_gpio(struct gspca_dev *gspca_dev, +static void configure_gpio(struct gspca_dev *gspca_dev, const u8 *sn9c1xx) { struct sd *sd = (struct sd *) gspca_dev; @@ -1160,13 +1158,10 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0x61); reg_w1(gspca_dev, 0x01, 0x42); - if (sd->sensor == SENSOR_HV7131R) { - if (hv7131r_probe(gspca_dev) < 0) - return -ENODEV; - } + if (sd->sensor == SENSOR_HV7131R) + hv7131r_probe(gspca_dev); break; } - return 0; } static void hv7131R_InitSensor(struct gspca_dev *gspca_dev) @@ -2319,31 +2314,32 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)}, {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x06f8, 0x3008), BSI(SN9C105, OV7660, 0x21)}, +/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x21)}, */ {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)}, -/* bw600.inf: - {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */ -/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */ -/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x21)}, */ +/* {USB_DEVICE(0x0c45, 0x607b), BSI(SN9C102P, OV7660, 0x21)}, */ {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, -/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x21)}, */ {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, -/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x60c2), BSI(SN9C105, P1030xC, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x21)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ -/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x21)}, */ {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, #endif {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ -/* {USB_DEVICE(0x0c45, 0x6102), BSI(SN9C120, PO2030N, ??)}, */ +/* {USB_DEVICE(0x0c45, 0x6102), BSI(SN9C120, P1030xC, ??)}, */ /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6802, 0x21)}, */ {USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610e), BSI(SN9C120, OV7630, 0x21)}, /*sn9c128*/ +/* {USB_DEVICE(0x0c45, 0x610f), BSI(SN9C120, S5K53BEB, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/ From 928213aad76e0036290901d244d614c01cac7278 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 29 Oct 2009 22:24:34 -0300 Subject: [PATCH 159/345] V4L/DVB (13253): cx23885: CodingStyle fix Add whitespace around binary operators in cx23888-ir.c Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23888-ir.c | 37 ++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index e8d949ae06b9..3ccc8afeccf3 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -108,7 +108,7 @@ MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]"); #define CX23888_IR_LEARN_REG 0x170044 #define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */ -#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ/2) +#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2) #define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32)) #define CX23888_IR_TX_KFIFO_SIZE (512 * sizeof(u32)) @@ -171,7 +171,7 @@ static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr, */ static inline u16 count_to_clock_divider(unsigned int d) { - if (d > RXCLK_RCD+1) + if (d > RXCLK_RCD + 1) d = RXCLK_RCD; else if (d < 2) d = 1; @@ -183,14 +183,14 @@ static inline u16 count_to_clock_divider(unsigned int d) static inline u16 ns_to_clock_divider(unsigned int ns) { return count_to_clock_divider( - DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ/1000000 * ns, 1000)); + DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000)); } static inline unsigned int clock_divider_to_ns(unsigned int divider) { /* Period of the Rx or Tx clock in ns */ return DIV_ROUND_CLOSEST((divider + 1) * 1000, - CX23888_IR_REFCLK_FREQ/1000000); + CX23888_IR_REFCLK_FREQ / 1000000); } static inline u16 carrier_freq_to_clock_divider(unsigned int freq) @@ -237,19 +237,20 @@ static inline u16 count_to_lpf_count(unsigned int d) static inline u16 ns_to_lpf_count(unsigned int ns) { return count_to_lpf_count( - DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ/1000000 * ns, 1000)); + DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000)); } static inline unsigned int lpf_count_to_ns(unsigned int count) { /* Duration of the Low Pass Filter rejection window in ns */ - return DIV_ROUND_CLOSEST(count * 1000, CX23888_IR_REFCLK_FREQ/1000000); + return DIV_ROUND_CLOSEST(count * 1000, + CX23888_IR_REFCLK_FREQ / 1000000); } static inline unsigned int lpf_count_to_us(unsigned int count) { /* Duration of the Low Pass Filter rejection window in us */ - return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ/1000000); + return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ / 1000000); } /* @@ -263,7 +264,7 @@ static u32 clock_divider_to_resolution(u16 divider) * not readable, hence the << 2. This function returns ns. */ return DIV_ROUND_CLOSEST((1 << 2) * ((u32) divider + 1) * 1000, - CX23888_IR_REFCLK_FREQ/1000000); + CX23888_IR_REFCLK_FREQ / 1000000); } static u64 pulse_width_count_to_ns(u16 count, u16 divider) @@ -276,8 +277,8 @@ static u64 pulse_width_count_to_ns(u16 count, u16 divider) * the (count << 2) | 0x3 */ n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */ - rem = do_div(n, CX23888_IR_REFCLK_FREQ/1000000); /* / MHz => ns */ - if (rem >= CX23888_IR_REFCLK_FREQ/1000000/2) + rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => ns */ + if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2) n++; return n; } @@ -291,9 +292,9 @@ static unsigned int pulse_width_count_to_us(u16 count, u16 divider) * The 2 lsb's of the pulse width timer count are not readable, hence * the (count << 2) | 0x3 */ - n = (((u64) count << 2) | 0x3) * (divider + 1); /* cycles */ - rem = do_div(n, CX23888_IR_REFCLK_FREQ/1000000); /* / MHz => us */ - if (rem >= CX23888_IR_REFCLK_FREQ/1000000/2) + n = (((u64) count << 2) | 0x3) * (divider + 1); /* cycles */ + rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => us */ + if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2) n++; return (unsigned int) n; } @@ -310,9 +311,9 @@ static u64 ns_to_pulse_clocks(u32 ns) { u64 clocks; u32 rem; - clocks = CX23888_IR_REFCLK_FREQ/1000000 * (u64) ns; /* millicycles */ + clocks = CX23888_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles */ rem = do_div(clocks, 1000); /* /1000 = cycles */ - if (rem >= 1000/2) + if (rem >= 1000 / 2) clocks++; return clocks; } @@ -324,7 +325,7 @@ static u16 pulse_clocks_to_clock_divider(u64 count) rem = do_div(count, (FIFO_RXTX << 2) | 0x3); /* net result needs to be rounded down and decremented by 1 */ - if (count > RXCLK_RCD+1) + if (count > RXCLK_RCD + 1) count = RXCLK_RCD; else if (count < 2) count = 1; @@ -484,7 +485,7 @@ static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev, if (n > 15) n = 15; cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n); - return DIV_ROUND_CLOSEST((n+1) * 100, 16); + return DIV_ROUND_CLOSEST((n + 1) * 100, 16); } /* @@ -630,7 +631,7 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl); *handled = true; } - if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE/2) + if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; if (events) From 53c8ec5e0e93f1ab600f91203ede43b83b3361ba Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 31 Oct 2009 13:46:08 -0300 Subject: [PATCH 160/345] V4L/DVB (13259): saa7134: fix badly merged DTV1000S patch As pointed out by Hermann Pitton, it turns out that the DTV1000S card's analog entry made it into the #if 0 flyvideo tweaks in saa7134-cards.c and is not valid there. This patch fixes the problem. Cc: hermann pitton Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 9481379edec9..e737ddf94140 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5304,6 +5304,22 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, } }, }, + [SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S] = { + .name = "Leadtek Winfast DTV1000S", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = { { + .name = name_comp1, + .vmux = 3, + }, { + .name = name_svideo, + .vmux = 8, + } }, + }, }; From 0700adec9efec3136fa44d90f064c9227817f37b Mon Sep 17 00:00:00 2001 From: Michael Obst Date: Sat, 31 Oct 2009 14:05:42 -0300 Subject: [PATCH 161/345] V4L/DVB (13260): saa7134: add support for Leadtek Winfast DTV-1000S remote control Signed-off-by: Michael Obst Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 1 + drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-input.c | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 32f765e6e5fd..e353dffe696a 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -1705,6 +1705,7 @@ static struct ir_scancode ir_codes_winfast[] = { { 0x37, KEY_RADIO }, /* FM */ { 0x38, KEY_DVD }, + { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e737ddf94140..7e40d6d99dd0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -6801,6 +6801,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: + case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 8f9203e7d3b8..83206cfb7b8c 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -616,6 +616,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keycode = 0x003f00; mask_keydown = 0x040000; break; + case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: + ir_codes = &ir_codes_winfast_table; + mask_keycode = 0x5f00; + mask_keyup = 0x020000; + polling = 50; // ms + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", From 972aacc2989506d9c67f8b710021ff98041363d5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 1 Nov 2009 02:52:01 -0300 Subject: [PATCH 162/345] V4L/DVB (13262): tda18271: fix regression preventing std map override from taking effect In the changeset entitled, "tda18271: add support for the set_config method", the initialization order was changed such that the standard map overrides were being applied before loading the default standard map, based on the stepping of the silicon. This changeset restores the proper order by processing the standard map overrides both within the tda18271_set_config() and the tda18271_attach() functions, after we read the id register of the tuner. Thanks to Michael Obst for his testing, helping me to identify the regression. Signed-off-by: Michael Krufky Signed-off-by: Michael Obst Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 07d6e1c159ca..b2e15456d5f3 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1198,10 +1198,6 @@ static int tda18271_setup_configuration(struct dvb_frontend *fe, priv->output_opt = (cfg) ? cfg->output_opt : TDA18271_OUTPUT_LT_XT_ON; - /* override default std map with values in config struct */ - if ((cfg) && (cfg->std_map)) - tda18271_update_std_map(fe, cfg->std_map); - return 0; } @@ -1224,6 +1220,10 @@ static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg) if (tda18271_need_cal_on_startup(cfg)) tda18271_init(fe); + /* override default std map with values in config struct */ + if ((cfg) && (cfg->std_map)) + tda18271_update_std_map(fe, cfg->std_map); + return 0; } @@ -1307,6 +1307,10 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, break; } + /* override default std map with values in config struct */ + if ((cfg) && (cfg->std_map)) + tda18271_update_std_map(fe, cfg->std_map); + mutex_unlock(&tda18271_list_mutex); memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, From b31210d737f383c14a02b20ab68e1a5770818f2d Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Sun, 1 Nov 2009 13:02:59 -0300 Subject: [PATCH 163/345] V4L/DVB (13265): gspca_mr97310a: Partly back off red gain change for Sakar Digital VGA camera gspca_mr97310a: Partly back off red gain change for Sakar Digital VGA camera Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index a97061a9e44a..57ea1c772214 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -769,7 +769,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, /* adjusted blue, green, red gain correct too much blue from the Sakar Digital */ - 0x05, 0x01, 0x05}, 8} + 0x05, 0x01, 0x04}, 8} }; const struct sensor_w_data color_no_adj[] = { From b4b84deede5edb1e5492533a04f24ea16d1fae0a Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Sun, 1 Nov 2009 13:07:08 -0300 Subject: [PATCH 164/345] V4L/DVB (13266): gspca_mr97310a: Fix / update some comments gspca_mr97310a: Fix / update some comments Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 57ea1c772214..d2bfdec1c907 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -814,9 +814,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* Some of the VGA cameras require the memory pointer * to be set to 0 again. We have been forced to start the - * stream somewhere else to detect the hardware, and closed it, - * and now since we are restarting the stream we need to do a - * completely fresh and clean start. */ + * stream in sd_config() to detect the hardware, and closed it. + * Thus, we need here to do a completely fresh and clean start. */ err_code = zero_the_pointer(gspca_dev); if (err_code < 0) return err_code; @@ -875,7 +874,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) value_reg += 4; } - /* Note register 7 is also seen as 0x8x or 0xCx in dumps */ + /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ if (sd->brightness > 0) { sensor_write1(gspca_dev, sign_reg, 0x00); val = sd->brightness; @@ -900,7 +899,7 @@ static void setexposure(struct gspca_dev *gspca_dev) return; if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { - /* This cam does not like exposure settings > 300, + /* This cam does not like exposure settings < 300, so scale 0 - 4095 to 300 - 4095 */ exposure = (sd->exposure * 9267) / 10000 + 300; sensor_write1(gspca_dev, 3, exposure >> 4); @@ -908,7 +907,7 @@ static void setexposure(struct gspca_dev *gspca_dev) } else { /* We have both a clock divider and an exposure register. We first calculate the clock divider, as that determines - the maximum exposure and then we calculayte the exposure + the maximum exposure and then we calculate the exposure register setting (which goes from 0 - 511). Note our 0 - 4095 exposure is mapped to 0 - 511 From 542821d8d064d04e898a3c473b742b4e512de09d Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Sun, 1 Nov 2009 13:09:15 -0300 Subject: [PATCH 165/345] V4L/DVB (13267): gspca_mr97310a: Change brightness for VGA type 1 cameras downward gspca_mr97310a: Change brightness for VGA type 1 cameras downward Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index d2bfdec1c907..442bf1ec5eda 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -780,8 +780,9 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) const struct sensor_w_data vga_sensor1_init_data[] = { {0x11, 0x04, {0x01}, 1}, - /*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */ - {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, + {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, + /* These settings may be better for some cameras */ + /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */ 0x00, 0x0a}, 7}, {0x11, 0x04, {0x01}, 1}, {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6}, From 117e1348f8b0cd91834873bb21faff827798bd8b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 1 Nov 2009 11:16:10 -0300 Subject: [PATCH 166/345] V4L/DVB (13269): saa7134: codingstyle: use /* style comments */ instead of // Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 83206cfb7b8c..f658f2513992 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -620,7 +620,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir_codes = &ir_codes_winfast_table; mask_keycode = 0x5f00; mask_keyup = 0x020000; - polling = 50; // ms + polling = 50; /* ms */ break; } if (NULL == ir_codes) { From 26b9d6c0b0e91c84b4713da5abd16baef3963d33 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Sun, 1 Nov 2009 18:46:53 -0300 Subject: [PATCH 167/345] V4L/DVB (13271): TS speed check. Logging transport stream speed in Kbits per second [mchehab@redhat.com: add asm/div64.h and allocate vars only if dvb_demux_speedcheck specified] Signed-off-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_demux.c | 39 ++++++++++++++++++++++++++ drivers/media/dvb/dvb-core/dvb_demux.h | 5 ++++ 2 files changed, 44 insertions(+) diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 91c537bca8ad..b78cfb7d1897 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "dvb_demux.h" @@ -44,6 +45,11 @@ module_param(dvb_demux_tscheck, int, 0644); MODULE_PARM_DESC(dvb_demux_tscheck, "enable transport stream continuity and TEI check"); +static int dvb_demux_speedcheck; +module_param(dvb_demux_speedcheck, int, 0644); +MODULE_PARM_DESC(dvb_demux_speedcheck, + "enable transport stream speed check"); + #define dprintk_tscheck(x...) do { \ if (dvb_demux_tscheck && printk_ratelimit()) \ printk(x); \ @@ -387,6 +393,39 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) u16 pid = ts_pid(buf); int dvr_done = 0; + if (dvb_demux_speedcheck) { + struct timespec cur_time, delta_time; + u64 speed_bytes, speed_timedelta; + + demux->speed_pkts_cnt++; + + /* show speed every SPEED_PKTS_INTERVAL packets */ + if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) { + cur_time = current_kernel_time(); + + if (demux->speed_last_time.tv_sec != 0 && + demux->speed_last_time.tv_nsec != 0) { + delta_time = timespec_sub(cur_time, + demux->speed_last_time); + speed_bytes = (u64)demux->speed_pkts_cnt + * 188 * 8; + /* convert to 1024 basis */ + speed_bytes = 1000 * div64_u64(speed_bytes, + 1024); + speed_timedelta = + (u64)timespec_to_ns(&delta_time); + speed_timedelta = div64_u64(speed_timedelta, + 1000000); /* nsec -> usec */ + printk(KERN_INFO "TS speed %llu Kbits/sec \n", + div64_u64(speed_bytes, + speed_timedelta)); + }; + + demux->speed_last_time = cur_time; + demux->speed_pkts_cnt = 0; + }; + }; + if (dvb_demux_tscheck) { if (!demux->cnt_storage) demux->cnt_storage = vmalloc(MAX_PID + 1); diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h index 2fe05d03240d..a7d876fd02dd 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.h +++ b/drivers/media/dvb/dvb-core/dvb_demux.h @@ -44,6 +44,8 @@ #define MAX_PID 0x1fff +#define SPEED_PKTS_INTERVAL 50000 + struct dvb_demux_filter { struct dmx_section_filter filter; u8 maskandmode[DMX_MAX_FILTER_SIZE]; @@ -131,6 +133,9 @@ struct dvb_demux { spinlock_t lock; uint8_t *cnt_storage; /* for TS continuity check */ + + struct timespec speed_last_time; /* for TS speed check */ + uint32_t speed_pkts_cnt; /* for TS speed check */ }; int dvb_dmx_init(struct dvb_demux *dvbdemux); From 648732fcefa73932ae8caa8bcfd262863904dd66 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 4 Nov 2009 12:11:43 -0200 Subject: [PATCH 168/345] V4L/DVB (13271a): Fix a badly solved merge conflict Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 1ec1a4cb0472..c8034d5c817c 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -2135,10 +2135,6 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 1, .adapter = { { - .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .pid_filter_count = 32, - .pid_filter = stk70x0p_pid_filter, - .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, .pid_filter = stk70x0p_pid_filter, @@ -2210,6 +2206,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_adapters = 1, .adapter = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, .frontend_attach = stk7070p_frontend_attach, .tuner_attach = dib7070p_tuner_attach, From 0b66cf90371dcd28c6eb98904adb694ae98eb20f Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 4 Nov 2009 14:16:25 -0300 Subject: [PATCH 169/345] V4L/DVB (13285): vpfe_capture: keep index within bound in vpfe_cropcap() If vpfe_dev->std_index equals ARRAY_SIZE(vpfe_standards), that is one too large. Signed-off-by: Roel Kluin Acked-by: Muralidharan Karicheri Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 402ce43ef38e..6b31e59f47f3 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1577,7 +1577,7 @@ static int vpfe_cropcap(struct file *file, void *priv, v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n"); - if (vpfe_dev->std_index > ARRAY_SIZE(vpfe_standards)) + if (vpfe_dev->std_index >= ARRAY_SIZE(vpfe_standards)) return -EINVAL; memset(crop, 0, sizeof(struct v4l2_cropcap)); From 9710e7a77a0a0564a393250d86b8cb3d560bb69f Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Wed, 4 Nov 2009 15:28:33 -0300 Subject: [PATCH 170/345] V4L/DVB (13288): adding __init/__exit macros to various drivers Trivial patch which adds the __init/__exit macros to the module_init/ module_exit functions of the following drivers in media video: drivers/media/video/ivtv/ivtv-driver.c drivers/media/video/cx18/cx18-driver.c drivers/media/video/davinci/dm355_ccdc.c drivers/media/video/davinci/dm644x_ccdc.c drivers/media/video/saa7164/saa7164-core.c drivers/media/video/saa7134/saa7134-core.c drivers/media/video/cx23885/cx23885-core.c Cc: Hermann Pitton Acked-by: Steven Toth Signed-off-by: Peter Huewe Acked-by: Andy Walls Acked-by: Laurent Pinchart Acked-by: Muralidharan Karicheri Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 4 ++-- drivers/media/video/cx23885/cx23885-core.c | 4 ++-- drivers/media/video/davinci/dm355_ccdc.c | 4 ++-- drivers/media/video/davinci/dm644x_ccdc.c | 4 ++-- drivers/media/video/ivtv/ivtv-driver.c | 4 ++-- drivers/media/video/saa7134/saa7134-core.c | 4 ++-- drivers/media/video/saa7164/saa7164-core.c | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 6dd51e27582c..e12082b8a08d 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -1200,7 +1200,7 @@ static struct pci_driver cx18_pci_driver = { .remove = cx18_remove, }; -static int module_start(void) +static int __init module_start(void) { printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION); @@ -1224,7 +1224,7 @@ static int module_start(void) return 0; } -static void module_cleanup(void) +static void __exit module_cleanup(void) { pci_unregister_driver(&cx18_pci_driver); } diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index e34a4ec4a2cd..e8eb4ec0c30a 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -2026,7 +2026,7 @@ static struct pci_driver cx23885_pci_driver = { .resume = NULL, }; -static int cx23885_init(void) +static int __init cx23885_init(void) { printk(KERN_INFO "cx23885 driver version %d.%d.%d loaded\n", (CX23885_VERSION_CODE >> 16) & 0xff, @@ -2039,7 +2039,7 @@ static int cx23885_init(void) return pci_register_driver(&cx23885_pci_driver); } -static void cx23885_fini(void) +static void __exit cx23885_fini(void) { pci_unregister_driver(&cx23885_pci_driver); } diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c index 4629cabe3f28..56fbefe036ae 100644 --- a/drivers/media/video/davinci/dm355_ccdc.c +++ b/drivers/media/video/davinci/dm355_ccdc.c @@ -959,7 +959,7 @@ static struct ccdc_hw_device ccdc_hw_dev = { }, }; -static int dm355_ccdc_init(void) +static int __init dm355_ccdc_init(void) { printk(KERN_NOTICE "dm355_ccdc_init\n"); if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0) @@ -969,7 +969,7 @@ static int dm355_ccdc_init(void) return 0; } -static void dm355_ccdc_exit(void) +static void __exit dm355_ccdc_exit(void) { vpfe_unregister_ccdc_device(&ccdc_hw_dev); } diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index 2f19a919f477..d5fa193f32d2 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c @@ -859,7 +859,7 @@ static struct ccdc_hw_device ccdc_hw_dev = { }, }; -static int dm644x_ccdc_init(void) +static int __init dm644x_ccdc_init(void) { printk(KERN_NOTICE "dm644x_ccdc_init\n"); if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0) @@ -869,7 +869,7 @@ static int dm644x_ccdc_init(void) return 0; } -static void dm644x_ccdc_exit(void) +static void __exit dm644x_ccdc_exit(void) { vpfe_unregister_ccdc_device(&ccdc_hw_dev); } diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 463ec3457d7b..7cdbc1a8f218 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1361,7 +1361,7 @@ static struct pci_driver ivtv_pci_driver = { .remove = ivtv_remove, }; -static int module_start(void) +static int __init module_start(void) { printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION); @@ -1385,7 +1385,7 @@ static int module_start(void) return 0; } -static void module_cleanup(void) +static void __exit module_cleanup(void) { pci_unregister_driver(&ivtv_pci_driver); } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 9a5df930885b..0ba7f5af0fc3 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -1319,7 +1319,7 @@ static struct pci_driver saa7134_pci_driver = { #endif }; -static int saa7134_init(void) +static int __init saa7134_init(void) { INIT_LIST_HEAD(&saa7134_devlist); printk(KERN_INFO "saa7130/34: v4l2 driver version %d.%d.%d loaded\n", @@ -1333,7 +1333,7 @@ static int saa7134_init(void) return pci_register_driver(&saa7134_pci_driver); } -static void saa7134_fini(void) +static void __exit saa7134_fini(void) { pci_unregister_driver(&saa7134_pci_driver); } diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c index 709affc31042..e6aa0fbd1e91 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/video/saa7164/saa7164-core.c @@ -724,13 +724,13 @@ static struct pci_driver saa7164_pci_driver = { .resume = NULL, }; -static int saa7164_init(void) +static int __init saa7164_init(void) { printk(KERN_INFO "saa7164 driver loaded\n"); return pci_register_driver(&saa7164_pci_driver); } -static void saa7164_fini(void) +static void __exit saa7164_fini(void) { pci_unregister_driver(&saa7164_pci_driver); } From 0bc23083cfa0e4bee3a89254c0af7dc6a16513bb Mon Sep 17 00:00:00 2001 From: Filipe Rosset Date: Wed, 4 Nov 2009 15:31:25 -0300 Subject: [PATCH 171/345] V4L/DVB (13289): em28xx-audio: Convert printks to em28xx_err Convert printks to em28xx_err. Signed-off-by: Filipe Rosset Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index ac947aecb9c3..bd783387b37d 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -293,7 +293,7 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) dprintk("opening device and trying to acquire exclusive lock\n"); if (!dev) { - printk(KERN_ERR "BUG: em28xx can't find device struct." + em28xx_err("BUG: em28xx can't find device struct." " Can't proceed with open\n"); return -ENODEV; } @@ -325,7 +325,7 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) return 0; err: - printk(KERN_ERR "Error while configuring em28xx mixer\n"); + em28xx_err("Error while configuring em28xx mixer\n"); return ret; } From 480be1851aebcb0b9c5b0fb9acefe5da97cc702a Mon Sep 17 00:00:00 2001 From: Filipe Rosset Date: Wed, 4 Nov 2009 15:32:37 -0300 Subject: [PATCH 172/345] V4L/DVB (13290): em28xx-dvb: Convert printks to em28xx_err and em28xx_info Convert printks to em28xx_err and em28xx_info Signed-off-by: Filipe Rosset Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-dvb.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 19f5156f653e..cc0505eb900f 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -313,22 +313,20 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) cfg.i2c_addr = addr; if (!dev->dvb->frontend) { - printk(KERN_ERR "%s/2: dvb frontend not attached. " - "Can't attach xc3028\n", - dev->name); + em28xx_errdev("/2: dvb frontend not attached. " + "Can't attach xc3028\n"); return -EINVAL; } fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); if (!fe) { - printk(KERN_ERR "%s/2: xc3028 attach failed\n", - dev->name); + em28xx_errdev("/2: xc3028 attach failed\n"); dvb_frontend_detach(dev->dvb->frontend); dev->dvb->frontend = NULL; return -EINVAL; } - printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name); + em28xx_info("%s/2: xc3028 attached\n", dev->name); return 0; } @@ -463,7 +461,7 @@ static int dvb_init(struct em28xx *dev) dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); if (dvb == NULL) { - printk(KERN_INFO "em28xx_dvb: memory allocation failed\n"); + em28xx_info("em28xx_dvb: memory allocation failed\n"); return -ENOMEM; } dev->dvb = dvb; @@ -570,15 +568,12 @@ static int dvb_init(struct em28xx *dev) } break; default: - printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" - " isn't supported yet\n", - dev->name); + em28xx_errdev("/2: The frontend of your DVB/ATSC card" + " isn't supported yet\n"); break; } if (NULL == dvb->frontend) { - printk(KERN_ERR - "%s/2: frontend initialization failed\n", - dev->name); + em28xx_errdev("/2: frontend initialization failed\n"); result = -EINVAL; goto out_free; } @@ -592,7 +587,7 @@ static int dvb_init(struct em28xx *dev) goto out_free; em28xx_set_mode(dev, EM28XX_SUSPEND); - printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); + em28xx_info("Successfully loaded em28xx-dvb\n"); return 0; out_free: From 6f901a991991fd3c9ac51bc7234a6706ef17ddfe Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 4 Nov 2009 15:35:09 -0300 Subject: [PATCH 173/345] V4L/DVB (13292): tvp514x: recognize the error case in tvp514x_read_reg() i2c_smbus_read_byte_data() returns a negative value on error. It is very likely to be != -1 (-EPERM). Signed-off-by: Sebastian Andrzej Siewior Acked-by: Vaibhav Hiremath Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp514x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index 244372627df2..26b4e718cd6d 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -272,7 +272,7 @@ static int tvp514x_read_reg(struct v4l2_subdev *sd, u8 reg) read_again: err = i2c_smbus_read_byte_data(client, reg); - if (err == -1) { + if (err < 0) { if (retry <= I2C_RETRY_COUNT) { v4l2_warn(sd, "Read: retry ... %d\n", retry); retry++; From ad12f07bf21e8d98e6042c8ed795d2d041e26934 Mon Sep 17 00:00:00 2001 From: Akihiro Tsukada Date: Wed, 4 Nov 2009 15:39:31 -0300 Subject: [PATCH 174/345] V4L/DVB (13293): dvb-usb-friio: return the correct DTV_DELIVERY_SYSTEM This patch makes the driver return the correct DTV_DELIVERY_SYSTEM. The driver previously returned SYS_UNDEFINED for DTV_DELIVERY_SYSTEM property, as it lacked any driver specific S2API support. Signed-off-by: Akihiro Tsukada Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/friio-fe.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c index c4dfe25cf60d..8b489d11eb37 100644 --- a/drivers/media/dvb/dvb-usb/friio-fe.c +++ b/drivers/media/dvb/dvb-usb/friio-fe.c @@ -286,6 +286,27 @@ static int jdvbt90502_get_tune_settings(struct dvb_frontend *fe, return 0; } +/* filter out un-supported properties to notify users */ +static int jdvbt90502_set_property(struct dvb_frontend *fe, + struct dtv_property *tvp) +{ + int r = 0; + + switch (tvp->cmd) { + case DTV_DELIVERY_SYSTEM: + if (tvp->u.data != SYS_ISDBT) + r = -EINVAL; + break; + case DTV_CLEAR: + case DTV_TUNE: + case DTV_FREQUENCY: + break; + default: + r = -EINVAL; + } + return r; +} + static int jdvbt90502_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { @@ -314,6 +335,9 @@ static int jdvbt90502_set_frontend(struct dvb_frontend *fe, deb_fe("%s: Freq:%d\n", __func__, p->frequency); + /* for recovery from DTV_CLEAN */ + fe->dtv_property_cache.delivery_system = SYS_ISDBT; + ret = jdvbt90502_pll_set_freq(state, p->frequency); if (ret) { deb_fe("%s:ret == %d\n", __func__, ret); @@ -394,6 +418,7 @@ static int jdvbt90502_init(struct dvb_frontend *fe) if (ret != 1) goto error; } + fe->dtv_property_cache.delivery_system = SYS_ISDBT; msleep(100); return 0; @@ -471,6 +496,8 @@ static struct dvb_frontend_ops jdvbt90502_ops = { .sleep = jdvbt90502_sleep, .write = _jdvbt90502_write, + .set_property = jdvbt90502_set_property, + .set_frontend = jdvbt90502_set_frontend, .get_frontend = jdvbt90502_get_frontend, .get_tune_settings = jdvbt90502_get_tune_settings, From 9ebef973b4a3b9af5c71ef5c266efac8be3e17e0 Mon Sep 17 00:00:00 2001 From: Akihiro Tsukada Date: Wed, 4 Nov 2009 15:40:36 -0300 Subject: [PATCH 175/345] V4L/DVB (13294): dvb-usb-friio: cleaning up unnecessary functions This patch removes some fe->ops.X() functions which do nothing more useful than the default. Signed-off-by: Akihiro Tsukada Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/friio-fe.c | 38 ---------------------------- 1 file changed, 38 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c index 8b489d11eb37..9cbbe42ca44b 100644 --- a/drivers/media/dvb/dvb-usb/friio-fe.c +++ b/drivers/media/dvb/dvb-usb/friio-fe.c @@ -232,12 +232,6 @@ static int jdvbt90502_read_status(struct dvb_frontend *fe, fe_status_t *state) return 0; } -static int jdvbt90502_read_ber(struct dvb_frontend *fe, u32 *ber) -{ - *ber = 0; - return 0; -} - static int jdvbt90502_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { @@ -264,27 +258,6 @@ static int jdvbt90502_read_signal_strength(struct dvb_frontend *fe, return 0; } -static int jdvbt90502_read_snr(struct dvb_frontend *fe, u16 *snr) -{ - *snr = 0x0101; - return 0; -} - -static int jdvbt90502_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -{ - *ucblocks = 0; - return 0; -} - -static int jdvbt90502_get_tune_settings(struct dvb_frontend *fe, - struct dvb_frontend_tune_settings *fs) -{ - fs->min_delay_ms = 500; - fs->step_size = 0; - fs->max_drift = 0; - - return 0; -} /* filter out un-supported properties to notify users */ static int jdvbt90502_set_property(struct dvb_frontend *fe, @@ -347,12 +320,6 @@ static int jdvbt90502_set_frontend(struct dvb_frontend *fe, return 0; } -static int jdvbt90502_sleep(struct dvb_frontend *fe) -{ - deb_fe("%s called.\n", __func__); - return 0; -} - /** * (reg, val) commad list to initialize this module. @@ -493,18 +460,13 @@ static struct dvb_frontend_ops jdvbt90502_ops = { .release = jdvbt90502_release, .init = jdvbt90502_init, - .sleep = jdvbt90502_sleep, .write = _jdvbt90502_write, .set_property = jdvbt90502_set_property, .set_frontend = jdvbt90502_set_frontend, .get_frontend = jdvbt90502_get_frontend, - .get_tune_settings = jdvbt90502_get_tune_settings, .read_status = jdvbt90502_read_status, - .read_ber = jdvbt90502_read_ber, .read_signal_strength = jdvbt90502_read_signal_strength, - .read_snr = jdvbt90502_read_snr, - .read_ucblocks = jdvbt90502_read_ucblocks, }; From 7dee9d1c057a24f5b1cd97b0bf37d05766906222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Piel?= Date: Wed, 4 Nov 2009 15:46:11 -0300 Subject: [PATCH 176/345] V4L/DVB (13295): sms1xxx: load smsdvb also for the hauppauge tiger cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit load smsdvb also for the hauppauge tiger cards [dougsland@redhat.com: fixed rejects due changes in sms-cards.c] Signed-off-by: Éric Piel Acked-by: Michael Krufky Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/sms-cards.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index 0420e2885e75..e21638969cd3 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c @@ -294,6 +294,8 @@ int sms_board_load_modules(int id) case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A: case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B: case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: request_module("smsdvb"); break; default: From c86c82b74f800486ede57fdd5a4fa77d86368861 Mon Sep 17 00:00:00 2001 From: Sergio C Fortier Date: Wed, 4 Nov 2009 15:55:09 -0300 Subject: [PATCH 177/345] V4L/DVB (13297): dib0700_devices: EvolutePC TvWay+ USB ISDB-Tb remote control support Patch for EvolutePC TvWay+ USB ISDB-Tb remote control support. [dougsland@redhat.com: fixed malformed patch] Cc: Patrick Boettcher Signed-off-by: Sergio C Fortier Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_devices.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index c8034d5c817c..684146f98eb7 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -917,6 +917,18 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { { 0x8618, KEY_RECORD }, { 0x861a, KEY_STOP }, + + /* Key codes for the EvolutePC TVWay+ remote (proto NEC) */ + { 0x7a00, KEY_MENU }, + { 0x7a01, KEY_RECORD }, + { 0x7a02, KEY_PLAY }, + { 0x7a03, KEY_STOP }, + { 0x7a10, KEY_CHANNELUP }, + { 0x7a11, KEY_CHANNELDOWN }, + { 0x7a12, KEY_VOLUMEUP }, + { 0x7a13, KEY_VOLUMEDOWN }, + { 0x7a40, KEY_POWER }, + { 0x7a41, KEY_MUTE }, }; /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ From a6b69e409a41144c24dcbecdc174a5c847631de2 Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Mon, 2 Nov 2009 08:05:51 -0300 Subject: [PATCH 178/345] V4L/DVB (13298): gspca - pac207/pac7311/mr97310a: Simplify pac_find_sof. Remove struct sd dependency from pac_find_sof() function implementation. This step prepares separation of pac7302 and pac7311 specific parts of struct sd. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 3 ++- drivers/media/video/gspca/pac207.c | 2 +- drivers/media/video/gspca/pac7311.c | 2 +- drivers/media/video/gspca/pac_common.h | 27 +++++++++++++------------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 442bf1ec5eda..ffb5e6d62c0b 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -1034,9 +1034,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; unsigned char *sof; - sof = pac_find_sof(gspca_dev, data, len); + sof = pac_find_sof(&sd->sof_read, data, len); if (sof) { int n; diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 96659433d248..57e13e2d550c 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -344,7 +344,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; unsigned char *sof; - sof = pac_find_sof(gspca_dev, data, len); + sof = pac_find_sof(&sd->sof_read, data, len); if (sof) { int n; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index a3fbd307bb76..329f867612d4 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -838,7 +838,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; unsigned char *sof; - sof = pac_find_sof(gspca_dev, data, len); + sof = pac_find_sof(&sd->sof_read, data, len); if (sof) { unsigned char tmpbuf[4]; int n, lum_offset, footer_length; diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h index d3006539fb82..20f67d9b8c06 100644 --- a/drivers/media/video/gspca/pac_common.h +++ b/drivers/media/video/gspca/pac_common.h @@ -72,42 +72,41 @@ static const unsigned char pac_sof_marker[5] = +----------+ */ -static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, +static unsigned char *pac_find_sof(u8 *sof_read, unsigned char *m, int len) { - struct sd *sd = (struct sd *) gspca_dev; int i; /* Search for the SOF marker (fixed part) in the header */ for (i = 0; i < len; i++) { - switch (sd->sof_read) { + switch (*sof_read) { case 0: if (m[i] == 0xff) - sd->sof_read = 1; + *sof_read = 1; break; case 1: if (m[i] == 0xff) - sd->sof_read = 2; + *sof_read = 2; else - sd->sof_read = 0; + *sof_read = 0; break; case 2: switch (m[i]) { case 0x00: - sd->sof_read = 3; + *sof_read = 3; break; case 0xff: /* stay in this state */ break; default: - sd->sof_read = 0; + *sof_read = 0; } break; case 3: if (m[i] == 0xff) - sd->sof_read = 4; + *sof_read = 4; else - sd->sof_read = 0; + *sof_read = 0; break; case 4: switch (m[i]) { @@ -117,18 +116,18 @@ static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, "SOF found, bytes to analyze: %u." " Frame starts at byte #%u", len, i + 1); - sd->sof_read = 0; + *sof_read = 0; return m + i + 1; break; case 0xff: - sd->sof_read = 2; + *sof_read = 2; break; default: - sd->sof_read = 0; + *sof_read = 0; } break; default: - sd->sof_read = 0; + *sof_read = 0; } } From cc409c0efb40a4c99cf023ec12ba7d67c67f666b Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Mon, 2 Nov 2009 08:09:34 -0300 Subject: [PATCH 179/345] V4L/DVB (13299): gspca - pac7311: Extract pac_start_frame. Creating the start of the frame is done in the same way for pac7302 and for pac7311. Extract this common part to the pac_start_frame() function. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7311.c | 42 ++++++++++++++++++----------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 329f867612d4..8d3e4eb53d7b 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -802,7 +802,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) } /* JPEG header, part 1 */ -static const unsigned char pac7311_jpeg_header1[] = { +static const unsigned char pac_jpeg_header1[] = { 0xff, 0xd8, /* SOI: Start of Image */ 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ @@ -813,7 +813,7 @@ static const unsigned char pac7311_jpeg_header1[] = { }; /* JPEG header, continued */ -static const unsigned char pac7311_jpeg_header2[] = { +static const unsigned char pac_jpeg_header2[] = { 0x03, /* Number of image components: 3 */ 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ @@ -829,6 +829,26 @@ static const unsigned char pac7311_jpeg_header2[] = { 0x00 /* Successive approximation: 0 */ }; +static void pac_start_frame(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, + __u16 lines, __u16 samples_per_line) +{ + unsigned char tmpbuf[4]; + + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + pac_jpeg_header1, sizeof(pac_jpeg_header1)); + + tmpbuf[0] = lines >> 8; + tmpbuf[1] = lines & 0xff; + tmpbuf[2] = samples_per_line >> 8; + tmpbuf[3] = samples_per_line & 0xff; + + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + tmpbuf, sizeof(tmpbuf)); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + pac_jpeg_header2, sizeof(pac_jpeg_header2)); +} + /* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ @@ -840,7 +860,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, sof = pac_find_sof(&sd->sof_read, data, len); if (sof) { - unsigned char tmpbuf[4]; int n, lum_offset, footer_length; if (sd->sensor == SENSOR_PAC7302) { @@ -882,23 +901,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, atomic_set(&sd->avg_lum, -1); /* Start the new frame with the jpeg header */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1)); if (sd->sensor == SENSOR_PAC7302) { /* The PAC7302 has the image rotated 90 degrees */ - tmpbuf[0] = gspca_dev->width >> 8; - tmpbuf[1] = gspca_dev->width & 0xff; - tmpbuf[2] = gspca_dev->height >> 8; - tmpbuf[3] = gspca_dev->height & 0xff; + pac_start_frame(gspca_dev, frame, + gspca_dev->width, gspca_dev->height); } else { - tmpbuf[0] = gspca_dev->height >> 8; - tmpbuf[1] = gspca_dev->height & 0xff; - tmpbuf[2] = gspca_dev->width >> 8; - tmpbuf[3] = gspca_dev->width & 0xff; + pac_start_frame(gspca_dev, frame, + gspca_dev->height, gspca_dev->width); } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2)); } gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } From 1408b8472910e894b290205b4baed5b14b8f45af Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Mon, 2 Nov 2009 08:13:21 -0300 Subject: [PATCH 180/345] V4L/DVB (13300): gspca - pac7302/pac7311: Separate the two subdrivers. All PAC7311 specific functions remain in pac7311.c. All PAC7302 specific functions are moved to pac7302.c. The USB device table is also divided into two parts. This makes it possible to remove the sensor specific decisions from different functions and also remove sensor infromation from the USB device table. The common functions are just copied to both subdrivers. These common functions can be separated later to a common file or helper module. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 9 + drivers/media/video/gspca/Makefile | 2 + drivers/media/video/gspca/pac7302.c | 962 ++++++++++++++++++++++++++++ drivers/media/video/gspca/pac7311.c | 440 ++----------- 4 files changed, 1033 insertions(+), 380 deletions(-) create mode 100644 drivers/media/video/gspca/pac7302.c diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 568edbbb8948..609d65b0b10d 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -104,6 +104,15 @@ config USB_GSPCA_PAC207 To compile this driver as a module, choose M here: the module will be called gspca_pac207. +config USB_GSPCA_PAC7302 + tristate "Pixart PAC7302 USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the PAC7302 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_pac7302. + config USB_GSPCA_PAC7311 tristate "Pixart PAC7311 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index 770b01387e99..ff2c7279d82e 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o +obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o @@ -38,6 +39,7 @@ gspca_mr97310a-objs := mr97310a.o gspca_ov519-objs := ov519.o gspca_ov534-objs := ov534.o gspca_pac207-objs := pac207.o +gspca_pac7302-objs := pac7302.o gspca_pac7311-objs := pac7311.o gspca_sn9c20x-objs := sn9c20x.o gspca_sonixb-objs := sonixb.o diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c new file mode 100644 index 000000000000..228b414709f7 --- /dev/null +++ b/drivers/media/video/gspca/pac7302.c @@ -0,0 +1,962 @@ +/* + * Pixart PAC7302 library + * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li + * + * V4L2 by Jean-Francois Moine + * + * Separated from Pixart PAC7311 library by Márton Németh + * + * 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 + * 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 + */ + +/* Some documentation about various registers as determined by trial and error. + When the register addresses differ between the 7202 and the 7311 the 2 + different addresses are written as 7302addr/7311addr, when one of the 2 + addresses is a - sign that register description is not valid for the + matching IC. + + Register page 1: + + Address Description + -/0x08 Unknown compressor related, must always be 8 except when not + in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! + -/0x1b Auto white balance related, bit 0 is AWB enable (inverted) + bits 345 seem to toggle per color gains on/off (inverted) + 0x78 Global control, bit 6 controls the LED (inverted) + -/0x80 JPEG compression ratio ? Best not touched + + Register page 3/4: + + Address Description + 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on + the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? + -/0x0f Master gain 1-245, low value = high gain + 0x10/- Master gain 0-31 + -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) + 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused + -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to + completely disable the analog amplification block. Set to 0x68 + for max gain, 0x14 for minimal gain. +*/ + +#define MODULE_NAME "pac7302" + +#include "gspca.h" + +MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); +MODULE_DESCRIPTION("Pixart PAC7302"); +MODULE_LICENSE("GPL"); + +/* specific webcam descriptor for pac7302 */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + + unsigned char brightness; + unsigned char contrast; + unsigned char colors; + unsigned char gain; + unsigned char exposure; + unsigned char autogain; + __u8 hflip; + __u8 vflip; + + u8 sof_read; + u8 autogain_ignore_frames; + + atomic_t avg_lum; +}; + +/* V4L2 controls supported by the driver */ +static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); +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_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_setgain(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); + +static struct ctrl sd_ctrls[] = { +/* This control is pac7302 only */ + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, +#define BRIGHTNESS_MAX 0x20 + .maximum = BRIGHTNESS_MAX, + .step = 1, +#define BRIGHTNESS_DEF 0x10 + .default_value = BRIGHTNESS_DEF, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, +/* This control is for both the 7302 and the 7311 */ + { + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, +#define CONTRAST_MAX 255 + .maximum = CONTRAST_MAX, + .step = 1, +#define CONTRAST_DEF 127 + .default_value = CONTRAST_DEF, + }, + .set = sd_setcontrast, + .get = sd_getcontrast, + }, +/* This control is pac7302 only */ + { + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, +#define COLOR_MAX 255 + .maximum = COLOR_MAX, + .step = 1, +#define COLOR_DEF 127 + .default_value = COLOR_DEF, + }, + .set = sd_setcolors, + .get = sd_getcolors, + }, +/* All controls below are for both the 7302 and the 7311 */ + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, +#define GAIN_MAX 255 + .maximum = GAIN_MAX, + .step = 1, +#define GAIN_DEF 127 +#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ + .default_value = GAIN_DEF, + }, + .set = sd_setgain, + .get = sd_getgain, + }, + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, +#define EXPOSURE_MAX 255 + .maximum = EXPOSURE_MAX, + .step = 1, +#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ +#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ + .default_value = EXPOSURE_DEF, + }, + .set = sd_setexposure, + .get = sd_getexposure, + }, + { + { + .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, + }, + { + { + .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, + }, + { + { + .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, + }, +}; + +static const struct v4l2_pix_format vga_mode[] = { + {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0}, +}; + +#define LOAD_PAGE3 255 +#define LOAD_PAGE4 254 +#define END_OF_SEQUENCE 0 + +/* pac 7302 */ +static const __u8 init_7302[] = { +/* index,value */ + 0xff, 0x01, /* page 1 */ + 0x78, 0x00, /* deactivate */ + 0xff, 0x01, + 0x78, 0x40, /* led off */ +}; +static const __u8 start_7302[] = { +/* index, len, [value]* */ + 0xff, 1, 0x00, /* page 0 */ + 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, + 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, + 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, + 0x26, 2, 0xaa, 0xaa, + 0x2e, 1, 0x31, + 0x38, 1, 0x01, + 0x3a, 3, 0x14, 0xff, 0x5a, + 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, + 0x00, 0x54, 0x11, + 0x55, 1, 0x00, + 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, + 0x6b, 1, 0x00, + 0x6e, 3, 0x08, 0x06, 0x00, + 0x72, 3, 0x00, 0xff, 0x00, + 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, + 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, + 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, + 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, + 0xd2, 0xeb, + 0xaf, 1, 0x02, + 0xb5, 2, 0x08, 0x08, + 0xb8, 2, 0x08, 0x88, + 0xc4, 4, 0xae, 0x01, 0x04, 0x01, + 0xcc, 1, 0x00, + 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, + 0xc1, 0xd7, 0xec, + 0xdc, 1, 0x01, + 0xff, 1, 0x01, /* page 1 */ + 0x12, 3, 0x02, 0x00, 0x01, + 0x3e, 2, 0x00, 0x00, + 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, + 0x7c, 1, 0x00, + 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, + 0x02, 0x00, + 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, + 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, + 0xd8, 1, 0x01, + 0xdb, 2, 0x00, 0x01, + 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, + 0xe6, 4, 0x00, 0x00, 0x00, 0x01, + 0xeb, 1, 0x00, + 0xff, 1, 0x02, /* page 2 */ + 0x22, 1, 0x00, + 0xff, 1, 0x03, /* page 3 */ + 0, LOAD_PAGE3, /* load the page 3 */ + 0x11, 1, 0x01, + 0xff, 1, 0x02, /* page 2 */ + 0x13, 1, 0x00, + 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, + 0x27, 2, 0x14, 0x0c, + 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, + 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, + 0x6e, 1, 0x08, + 0xff, 1, 0x01, /* page 1 */ + 0x78, 1, 0x00, + 0, END_OF_SEQUENCE /* end of sequence */ +}; + +#define SKIP 0xaa +/* page 3 - the value SKIP says skip the index - see reg_w_page() */ +static const __u8 page3_7302[] = { + 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, + 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, + 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, + 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, + 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, + 0x00 +}; + +static void reg_w_buf(struct gspca_dev *gspca_dev, + __u8 index, + const char *buffer, int len) +{ + memcpy(gspca_dev->usb_buf, buffer, len); + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 1, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, /* value */ + index, gspca_dev->usb_buf, len, + 500); +} + + +static void reg_w(struct gspca_dev *gspca_dev, + __u8 index, + __u8 value) +{ + gspca_dev->usb_buf[0] = value; + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, index, gspca_dev->usb_buf, 1, + 500); +} + +static void reg_w_seq(struct gspca_dev *gspca_dev, + const __u8 *seq, int len) +{ + while (--len >= 0) { + reg_w(gspca_dev, seq[0], seq[1]); + seq += 2; + } +} + +/* load the beginning of a page */ +static void reg_w_page(struct gspca_dev *gspca_dev, + const __u8 *page, int len) +{ + int index; + + for (index = 0; index < len; index++) { + if (page[index] == SKIP) /* skip this index */ + continue; + gspca_dev->usb_buf[0] = page[index]; + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, index, gspca_dev->usb_buf, 1, + 500); + } +} + +/* output a variable sequence */ +static void reg_w_var(struct gspca_dev *gspca_dev, + const __u8 *seq, + const __u8 *page3, unsigned int page3_len, + const __u8 *page4, unsigned int page4_len) +{ + int index, len; + + for (;;) { + index = *seq++; + len = *seq++; + switch (len) { + case END_OF_SEQUENCE: + return; + case LOAD_PAGE4: + reg_w_page(gspca_dev, page4, page4_len); + break; + case LOAD_PAGE3: + reg_w_page(gspca_dev, page3, page3_len); + break; + default: + if (len > USB_BUF_SZ) { + PDEBUG(D_ERR|D_STREAM, + "Incorrect variable sequence"); + return; + } + while (len > 0) { + if (len < 8) { + reg_w_buf(gspca_dev, index, seq, len); + seq += len; + break; + } + reg_w_buf(gspca_dev, index, seq, 8); + seq += 8; + index += 8; + len -= 8; + } + } + } + /* not reached */ +} + +/* this function is called at probe time for pac7302 */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam; + + cam = &gspca_dev->cam; + + PDEBUG(D_CONF, "Find Sensor PAC7302"); + cam->cam_mode = vga_mode; /* only 640x480 */ + cam->nmodes = ARRAY_SIZE(vga_mode); + + sd->brightness = BRIGHTNESS_DEF; + sd->contrast = CONTRAST_DEF; + sd->colors = COLOR_DEF; + sd->gain = GAIN_DEF; + sd->exposure = EXPOSURE_DEF; + sd->autogain = AUTOGAIN_DEF; + sd->hflip = HFLIP_DEF; + sd->vflip = VFLIP_DEF; + return 0; +} + +/* This function is used by pac7302 only */ +static void setbrightcont(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i, v; + static const __u8 max[10] = + {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, + 0xd4, 0xec}; + static const __u8 delta[10] = + {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, + 0x11, 0x0b}; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 10; i++) { + v = max[i]; + v += (sd->brightness - BRIGHTNESS_MAX) + * 150 / BRIGHTNESS_MAX; /* 200 ? */ + v -= delta[i] * sd->contrast / CONTRAST_MAX; + if (v < 0) + v = 0; + else if (v > 0xff) + v = 0xff; + reg_w(gspca_dev, 0xa2 + i, v); + } + reg_w(gspca_dev, 0xdc, 0x01); +} + +/* This function is used by pac7302 only */ +static void setcolors(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i, v; + static const int a[9] = + {217, -212, 0, -101, 170, -67, -38, -315, 355}; + static const int b[9] = + {19, 106, 0, 19, 106, 1, 19, 106, 1}; + + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + reg_w(gspca_dev, 0x11, 0x01); + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 9; i++) { + v = a[i] * sd->colors / COLOR_MAX + b[i]; + reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); + reg_w(gspca_dev, 0x0f + 2 * i + 1, v); + } + reg_w(gspca_dev, 0xdc, 0x01); + PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); +} + +static void setgain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + reg_w(gspca_dev, 0x10, sd->gain >> 3); + + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); +} + +static void setexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 reg; + + /* register 2 of frame 3/4 contains the clock divider configuring the + no fps according to the formula: 60 / reg. sd->exposure is the + desired exposure time in ms. */ + reg = 120 * sd->exposure / 1000; + if (reg < 2) + reg = 2; + else if (reg > 63) + reg = 63; + + /* On the pac7302 reg2 MUST be a multiple of 3, so round it to + the nearest multiple of 3, except when between 6 and 12? */ + if (reg < 6 || reg > 12) + reg = ((reg + 1) / 3) * 3; + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + reg_w(gspca_dev, 0x02, reg); + + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); +} + +static void sethvflip(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 data; + + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00); + reg_w(gspca_dev, 0x21, data); + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); +} + +/* this function is called at probe and resume time for pac7302 */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + reg_w_seq(gspca_dev, init_7302, sizeof init_7302); + + return 0; +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->sof_read = 0; + + reg_w_var(gspca_dev, start_7302, + page3_7302, sizeof(page3_7302), + NULL, 0); + setbrightcont(gspca_dev); + setcolors(gspca_dev); + setgain(gspca_dev); + setexposure(gspca_dev); + sethvflip(gspca_dev); + + /* only resolution 640x480 is supported for pac7302 */ + + sd->sof_read = 0; + sd->autogain_ignore_frames = 0; + atomic_set(&sd->avg_lum, -1); + + /* start stream */ + reg_w(gspca_dev, 0xff, 0x01); + reg_w(gspca_dev, 0x78, 0x01); + + return 0; +} + +static void sd_stopN(struct gspca_dev *gspca_dev) +{ + reg_w(gspca_dev, 0xff, 0x01); + reg_w(gspca_dev, 0x78, 0x00); + reg_w(gspca_dev, 0x78, 0x00); +} + +/* called on streamoff with alt 0 and on disconnect for pac7302 */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + if (!gspca_dev->present) + return; + reg_w(gspca_dev, 0xff, 0x01); + reg_w(gspca_dev, 0x78, 0x40); +} + +/* Include pac common sof detection functions */ +#include "pac_common.h" + +static void do_autogain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int avg_lum = atomic_read(&sd->avg_lum); + int desired_lum, deadzone; + + if (avg_lum == -1) + return; + + desired_lum = 270 + sd->brightness * 4; + /* Hack hack, with the 7202 the first exposure step is + pretty large, so if we're about to make the first + exposure increase make the deadzone large to avoid + oscilating */ + if (desired_lum > avg_lum && sd->gain == GAIN_DEF && + sd->exposure > EXPOSURE_DEF && + sd->exposure < 42) + deadzone = 90; + else + deadzone = 30; + + if (sd->autogain_ignore_frames > 0) + sd->autogain_ignore_frames--; + else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, + deadzone, GAIN_KNEE, EXPOSURE_KNEE)) + sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; +} + +/* JPEG header, part 1 */ +static const unsigned char pac_jpeg_header1[] = { + 0xff, 0xd8, /* SOI: Start of Image */ + + 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ + 0x00, 0x11, /* length = 17 bytes (including this length field) */ + 0x08 /* Precision: 8 */ + /* 2 bytes is placed here: number of image lines */ + /* 2 bytes is placed here: samples per line */ +}; + +/* JPEG header, continued */ +static const unsigned char pac_jpeg_header2[] = { + 0x03, /* Number of image components: 3 */ + 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ + 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ + 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ + + 0xff, 0xda, /* SOS: Start Of Scan */ + 0x00, 0x0c, /* length = 12 bytes (including this length field) */ + 0x03, /* number of components: 3 */ + 0x01, 0x00, /* selector 1, table 0x00 */ + 0x02, 0x11, /* selector 2, table 0x11 */ + 0x03, 0x11, /* selector 3, table 0x11 */ + 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ + 0x00 /* Successive approximation: 0 */ +}; + +static void pac_start_frame(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, + __u16 lines, __u16 samples_per_line) +{ + unsigned char tmpbuf[4]; + + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + pac_jpeg_header1, sizeof(pac_jpeg_header1)); + + tmpbuf[0] = lines >> 8; + tmpbuf[1] = lines & 0xff; + tmpbuf[2] = samples_per_line >> 8; + tmpbuf[3] = samples_per_line & 0xff; + + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + tmpbuf, sizeof(tmpbuf)); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + pac_jpeg_header2, sizeof(pac_jpeg_header2)); +} + +/* this function is run at interrupt level */ +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + struct sd *sd = (struct sd *) gspca_dev; + unsigned char *sof; + + sof = pac_find_sof(&sd->sof_read, data, len); + if (sof) { + int n, lum_offset, footer_length; + + /* 6 bytes after the FF D9 EOF marker a number of lumination + bytes are send corresponding to different parts of the + image, the 14th and 15th byte after the EOF seem to + correspond to the center of the image */ + lum_offset = 61 + sizeof pac_sof_marker; + footer_length = 74; + + /* Finish decoding current frame */ + n = (sof - data) - (footer_length + sizeof pac_sof_marker); + if (n < 0) { + frame->data_end += n; + n = 0; + } + frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, n); + if (gspca_dev->last_packet_type != DISCARD_PACKET && + frame->data_end[-2] == 0xff && + frame->data_end[-1] == 0xd9) + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + NULL, 0); + + n = sof - data; + len -= n; + data = sof; + + /* Get average lumination */ + if (gspca_dev->last_packet_type == LAST_PACKET && + n >= lum_offset) + atomic_set(&sd->avg_lum, data[-lum_offset] + + data[-lum_offset + 1]); + else + atomic_set(&sd->avg_lum, -1); + + /* Start the new frame with the jpeg header */ + /* The PAC7302 has the image rotated 90 degrees */ + pac_start_frame(gspca_dev, frame, + gspca_dev->width, gspca_dev->height); + } + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); +} + +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) + setbrightcont(gspca_dev); + return 0; +} + +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->brightness; + return 0; +} + +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) { + setbrightcont(gspca_dev); + } + return 0; +} + +static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->contrast; + return 0; +} + +static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->colors = val; + if (gspca_dev->streaming) + setcolors(gspca_dev); + return 0; +} + +static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->colors; + return 0; +} + +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gain = val; + if (gspca_dev->streaming) + setgain(gspca_dev); + return 0; +} + +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->gain; + return 0; +} + +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->exposure = val; + if (gspca_dev->streaming) + setexposure(gspca_dev); + return 0; +} + +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->exposure; + return 0; +} + +static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->autogain = val; + /* when switching to autogain set defaults to make sure + we are on a valid point of the autogain gain / + exposure knee graph, and give this change time to + take effect before doing autogain. */ + if (sd->autogain) { + sd->exposure = EXPOSURE_DEF; + sd->gain = GAIN_DEF; + if (gspca_dev->streaming) { + sd->autogain_ignore_frames = + PAC_AUTOGAIN_IGNORE_FRAMES; + setexposure(gspca_dev); + setgain(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; + + 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; +} + +/* sub-driver description for pac7302 */ +static struct sd_desc sd_desc = { + .name = MODULE_NAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stopN = sd_stopN, + .stop0 = sd_stop0, + .pkt_scan = sd_pkt_scan, + .dq_callback = do_autogain, +}; + +/* -- module initialisation -- */ +static __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x06f8, 0x3009)}, + {USB_DEVICE(0x093a, 0x2620)}, + {USB_DEVICE(0x093a, 0x2621)}, + {USB_DEVICE(0x093a, 0x2622)}, + {USB_DEVICE(0x093a, 0x2624)}, + {USB_DEVICE(0x093a, 0x2626)}, + {USB_DEVICE(0x093a, 0x2628)}, + {USB_DEVICE(0x093a, 0x2629)}, + {USB_DEVICE(0x093a, 0x262a)}, + {USB_DEVICE(0x093a, 0x262c)}, + {} +}; +MODULE_DEVICE_TABLE(usb, device_table); + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + 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); diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 8d3e4eb53d7b..a2f788468ec0 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -57,23 +57,17 @@ MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); MODULE_DESCRIPTION("Pixart PAC7311"); MODULE_LICENSE("GPL"); -/* specific webcam descriptor */ +/* specific webcam descriptor for pac7311 */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned char brightness; unsigned char contrast; - unsigned char colors; unsigned char gain; unsigned char exposure; unsigned char autogain; __u8 hflip; __u8 vflip; - __u8 sensor; -#define SENSOR_PAC7302 0 -#define SENSOR_PAC7311 1 - u8 sof_read; u8 autogain_ignore_frames; @@ -81,12 +75,8 @@ struct sd { }; /* V4L2 controls supported by the driver */ -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 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_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); @@ -99,23 +89,6 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { -/* This control is pac7302 only */ -#define BRIGHTNESS_IDX 0 - { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, -#define BRIGHTNESS_MAX 0x20 - .maximum = BRIGHTNESS_MAX, - .step = 1, -#define BRIGHTNESS_DEF 0x10 - .default_value = BRIGHTNESS_DEF, - }, - .set = sd_setbrightness, - .get = sd_getbrightness, - }, /* This control is for both the 7302 and the 7311 */ { { @@ -132,23 +105,6 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcontrast, .get = sd_getcontrast, }, -/* This control is pac7302 only */ -#define SATURATION_IDX 2 - { - { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, -#define COLOR_MAX 255 - .maximum = COLOR_MAX, - .step = 1, -#define COLOR_DEF 127 - .default_value = COLOR_DEF, - }, - .set = sd_setcolors, - .get = sd_getcolors, - }, /* All controls below are for both the 7302 and the 7311 */ { { @@ -248,103 +204,6 @@ static const struct v4l2_pix_format vga_mode[] = { #define LOAD_PAGE4 254 #define END_OF_SEQUENCE 0 -/* pac 7302 */ -static const __u8 init_7302[] = { -/* index,value */ - 0xff, 0x01, /* page 1 */ - 0x78, 0x00, /* deactivate */ - 0xff, 0x01, - 0x78, 0x40, /* led off */ -}; -static const __u8 start_7302[] = { -/* index, len, [value]* */ - 0xff, 1, 0x00, /* page 0 */ - 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, - 0x00, 0x00, 0x00, 0x00, - 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, - 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, - 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, - 0x26, 2, 0xaa, 0xaa, - 0x2e, 1, 0x31, - 0x38, 1, 0x01, - 0x3a, 3, 0x14, 0xff, 0x5a, - 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, - 0x00, 0x54, 0x11, - 0x55, 1, 0x00, - 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, - 0x6b, 1, 0x00, - 0x6e, 3, 0x08, 0x06, 0x00, - 0x72, 3, 0x00, 0xff, 0x00, - 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, - 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, - 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, - 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, - 0xd2, 0xeb, - 0xaf, 1, 0x02, - 0xb5, 2, 0x08, 0x08, - 0xb8, 2, 0x08, 0x88, - 0xc4, 4, 0xae, 0x01, 0x04, 0x01, - 0xcc, 1, 0x00, - 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, - 0xc1, 0xd7, 0xec, - 0xdc, 1, 0x01, - 0xff, 1, 0x01, /* page 1 */ - 0x12, 3, 0x02, 0x00, 0x01, - 0x3e, 2, 0x00, 0x00, - 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, - 0x7c, 1, 0x00, - 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, - 0x02, 0x00, - 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, - 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, - 0xd8, 1, 0x01, - 0xdb, 2, 0x00, 0x01, - 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, - 0xe6, 4, 0x00, 0x00, 0x00, 0x01, - 0xeb, 1, 0x00, - 0xff, 1, 0x02, /* page 2 */ - 0x22, 1, 0x00, - 0xff, 1, 0x03, /* page 3 */ - 0, LOAD_PAGE3, /* load the page 3 */ - 0x11, 1, 0x01, - 0xff, 1, 0x02, /* page 2 */ - 0x13, 1, 0x00, - 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, - 0x27, 2, 0x14, 0x0c, - 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, - 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, - 0x6e, 1, 0x08, - 0xff, 1, 0x01, /* page 1 */ - 0x78, 1, 0x00, - 0, END_OF_SEQUENCE /* end of sequence */ -}; - -#define SKIP 0xaa -/* page 3 - the value SKIP says skip the index - see reg_w_page() */ -static const __u8 page3_7302[] = { - 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, - 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, - 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, - 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, - 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, - 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, - 0x00 -}; - /* pac 7311 */ static const __u8 init_7311[] = { 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ @@ -388,6 +247,7 @@ static const __u8 start_7311[] = { 0, END_OF_SEQUENCE /* end of sequence */ }; +#define SKIP 0xaa /* page 4 - the value SKIP says skip the index - see reg_w_page() */ static const __u8 page4_7311[] = { SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, @@ -457,7 +317,9 @@ static void reg_w_page(struct gspca_dev *gspca_dev, /* output a variable sequence */ static void reg_w_var(struct gspca_dev *gspca_dev, - const __u8 *seq) + const __u8 *seq, + const __u8 *page3, unsigned int page3_len, + const __u8 *page4, unsigned int page4_len) { int index, len; @@ -468,10 +330,10 @@ static void reg_w_var(struct gspca_dev *gspca_dev, case END_OF_SEQUENCE: return; case LOAD_PAGE4: - reg_w_page(gspca_dev, page4_7311, sizeof page4_7311); + reg_w_page(gspca_dev, page4, page4_len); break; case LOAD_PAGE3: - reg_w_page(gspca_dev, page3_7302, sizeof page3_7302); + reg_w_page(gspca_dev, page3, page3_len); break; default: if (len > USB_BUF_SZ) { @@ -495,7 +357,7 @@ static void reg_w_var(struct gspca_dev *gspca_dev, /* not reached */ } -/* this function is called at probe time */ +/* this function is called at probe time for pac7311 */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { @@ -504,22 +366,11 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; - sd->sensor = id->driver_info; - if (sd->sensor == SENSOR_PAC7302) { - PDEBUG(D_CONF, "Find Sensor PAC7302"); - cam->cam_mode = &vga_mode[2]; /* only 640x480 */ - cam->nmodes = 1; - } else { - PDEBUG(D_CONF, "Find Sensor PAC7311"); - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) - | (1 << SATURATION_IDX); - } + PDEBUG(D_CONF, "Find Sensor PAC7311"); + cam->cam_mode = vga_mode; + cam->nmodes = ARRAY_SIZE(vga_mode); - sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; - sd->colors = COLOR_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; sd->autogain = AUTOGAIN_DEF; @@ -528,33 +379,6 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* This function is used by pac7302 only */ -static void setbrightcont(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, v; - static const __u8 max[10] = - {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, - 0xd4, 0xec}; - static const __u8 delta[10] = - {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, - 0x11, 0x0b}; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - for (i = 0; i < 10; i++) { - v = max[i]; - v += (sd->brightness - BRIGHTNESS_MAX) - * 150 / BRIGHTNESS_MAX; /* 200 ? */ - v -= delta[i] * sd->contrast / CONTRAST_MAX; - if (v < 0) - v = 0; - else if (v > 0xff) - v = 0xff; - reg_w(gspca_dev, 0xa2 + i, v); - } - reg_w(gspca_dev, 0xdc, 0x01); -} - /* This function is used by pac7311 only */ static void setcontrast(struct gspca_dev *gspca_dev) { @@ -566,45 +390,19 @@ static void setcontrast(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x11, 0x01); } -/* This function is used by pac7302 only */ -static void setcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, v; - static const int a[9] = - {217, -212, 0, -101, 170, -67, -38, -315, 355}; - static const int b[9] = - {19, 106, 0, 19, 106, 1, 19, 106, 1}; - - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x11, 0x01); - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - for (i = 0; i < 9; i++) { - v = a[i] * sd->colors / COLOR_MAX + b[i]; - reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); - reg_w(gspca_dev, 0x0f + 2 * i + 1, v); - } - reg_w(gspca_dev, 0xdc, 0x01); - PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); -} - static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int gain = GAIN_MAX - sd->gain; + + if (gain < 1) + gain = 1; + else if (gain > 245) + gain = 245; + reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ + reg_w(gspca_dev, 0x0e, 0x00); + reg_w(gspca_dev, 0x0f, gain); - if (sd->sensor == SENSOR_PAC7302) { - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x10, sd->gain >> 3); - } else { - int gain = GAIN_MAX - sd->gain; - if (gain < 1) - gain = 1; - else if (gain > 245) - gain = 245; - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ - reg_w(gspca_dev, 0x0e, 0x00); - reg_w(gspca_dev, 0x0f, gain); - } /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); } @@ -623,25 +421,17 @@ static void setexposure(struct gspca_dev *gspca_dev) else if (reg > 63) reg = 63; - if (sd->sensor == SENSOR_PAC7302) { - /* On the pac7302 reg2 MUST be a multiple of 3, so round it to - the nearest multiple of 3, except when between 6 and 12? */ - if (reg < 6 || reg > 12) - reg = ((reg + 1) / 3) * 3; - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x02, reg); - } else { - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ - reg_w(gspca_dev, 0x02, reg); - /* Page 1 register 8 must always be 0x08 except when not in - 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ - reg_w(gspca_dev, 0xff, 0x01); - if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && - reg <= 3) - reg_w(gspca_dev, 0x08, 0x09); - else - reg_w(gspca_dev, 0x08, 0x08); - } + reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ + reg_w(gspca_dev, 0x02, reg); + /* Page 1 register 8 must always be 0x08 except when not in + 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ + reg_w(gspca_dev, 0xff, 0x01); + if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && + reg <= 3) + reg_w(gspca_dev, 0x08, 0x09); + else + reg_w(gspca_dev, 0x08, 0x08); + /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); } @@ -651,29 +441,17 @@ static void sethvflip(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; __u8 data; - if (sd->sensor == SENSOR_PAC7302) { - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - data = (sd->hflip ? 0x08 : 0x00) - | (sd->vflip ? 0x04 : 0x00); - } else { - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ - data = (sd->hflip ? 0x04 : 0x00) - | (sd->vflip ? 0x08 : 0x00); - } + reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ + data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); reg_w(gspca_dev, 0x21, data); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); } -/* this function is called at probe and resume time */ +/* this function is called at probe and resume time for pac7311 */ static int sd_init(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PAC7302) - reg_w_seq(gspca_dev, init_7302, sizeof init_7302); - else - reg_w_seq(gspca_dev, init_7311, sizeof init_7311); + reg_w_seq(gspca_dev, init_7311, sizeof init_7311); return 0; } @@ -684,14 +462,10 @@ static int sd_start(struct gspca_dev *gspca_dev) sd->sof_read = 0; - if (sd->sensor == SENSOR_PAC7302) { - reg_w_var(gspca_dev, start_7302); - setbrightcont(gspca_dev); - setcolors(gspca_dev); - } else { - reg_w_var(gspca_dev, start_7311); - setcontrast(gspca_dev); - } + reg_w_var(gspca_dev, start_7311, + NULL, 0, + page4_7311, sizeof(page4_7311)); + setcontrast(gspca_dev); setgain(gspca_dev); setexposure(gspca_dev); sethvflip(gspca_dev); @@ -709,8 +483,6 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x87, 0x11); break; case 0: /* 640x480 */ - if (sd->sensor == SENSOR_PAC7302) - break; reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x17, 0x00); reg_w(gspca_dev, 0x87, 0x12); @@ -723,23 +495,13 @@ static int sd_start(struct gspca_dev *gspca_dev) /* start stream */ reg_w(gspca_dev, 0xff, 0x01); - if (sd->sensor == SENSOR_PAC7302) - reg_w(gspca_dev, 0x78, 0x01); - else - reg_w(gspca_dev, 0x78, 0x05); + reg_w(gspca_dev, 0x78, 0x05); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PAC7302) { - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x00); - reg_w(gspca_dev, 0x78, 0x00); - return; - } reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x27, 0x80); reg_w(gspca_dev, 0x28, 0xca); @@ -752,17 +514,9 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ } -/* called on streamoff with alt 0 and on disconnect */ +/* called on streamoff with alt 0 and on disconnect for 7311 */ static void sd_stop0(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; - - if (!gspca_dev->present) - return; - if (sd->sensor == SENSOR_PAC7302) { - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x40); - } } /* Include pac common sof detection functions */ @@ -777,22 +531,8 @@ static void do_autogain(struct gspca_dev *gspca_dev) if (avg_lum == -1) return; - if (sd->sensor == SENSOR_PAC7302) { - desired_lum = 270 + sd->brightness * 4; - /* Hack hack, with the 7202 the first exposure step is - pretty large, so if we're about to make the first - exposure increase make the deadzone large to avoid - oscilating */ - if (desired_lum > avg_lum && sd->gain == GAIN_DEF && - sd->exposure > EXPOSURE_DEF && - sd->exposure < 42) - deadzone = 90; - else - deadzone = 30; - } else { - desired_lum = 200; - deadzone = 20; - } + desired_lum = 200; + deadzone = 20; if (sd->autogain_ignore_frames > 0) sd->autogain_ignore_frames--; @@ -862,17 +602,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (sof) { int n, lum_offset, footer_length; - if (sd->sensor == SENSOR_PAC7302) { - /* 6 bytes after the FF D9 EOF marker a number of lumination - bytes are send corresponding to different parts of the - image, the 14th and 15th byte after the EOF seem to - correspond to the center of the image */ - lum_offset = 61 + sizeof pac_sof_marker; - footer_length = 74; - } else { - lum_offset = 24 + sizeof pac_sof_marker; - footer_length = 26; - } + /* 6 bytes after the FF D9 EOF marker a number of lumination + bytes are send corresponding to different parts of the + image, the 14th and 15th byte after the EOF seem to + correspond to the center of the image */ + lum_offset = 24 + sizeof pac_sof_marker; + footer_length = 26; /* Finish decoding current frame */ n = (sof - data) - (footer_length + sizeof pac_sof_marker); @@ -901,46 +636,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, atomic_set(&sd->avg_lum, -1); /* Start the new frame with the jpeg header */ - if (sd->sensor == SENSOR_PAC7302) { - /* The PAC7302 has the image rotated 90 degrees */ - pac_start_frame(gspca_dev, frame, - gspca_dev->width, gspca_dev->height); - } else { - pac_start_frame(gspca_dev, frame, - gspca_dev->height, gspca_dev->width); - } + pac_start_frame(gspca_dev, frame, + gspca_dev->height, gspca_dev->width); } gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -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) - setbrightcont(gspca_dev); - return 0; -} - -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->brightness; - return 0; -} - 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) { - if (sd->sensor == SENSOR_PAC7302) - setbrightcont(gspca_dev); - else - setcontrast(gspca_dev); + setcontrast(gspca_dev); } return 0; } @@ -953,24 +661,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->colors = val; - if (gspca_dev->streaming) - setcolors(gspca_dev); - return 0; -} - -static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->colors; - return 0; -} - static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1074,7 +764,7 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -/* sub-driver description */ +/* sub-driver description for pac7311 */ static struct sd_desc sd_desc = { .name = MODULE_NAME, .ctrls = sd_ctrls, @@ -1090,22 +780,12 @@ static struct sd_desc sd_desc = { /* -- module initialisation -- */ static __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x06f8, 0x3009), .driver_info = SENSOR_PAC7302}, - {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311}, - {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311}, - {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311}, - {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}, - {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302}, - {USB_DEVICE(0x093a, 0x2628), .driver_info = SENSOR_PAC7302}, - {USB_DEVICE(0x093a, 0x2629), .driver_info = SENSOR_PAC7302}, - {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302}, - {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302}, + {USB_DEVICE(0x093a, 0x2600)}, + {USB_DEVICE(0x093a, 0x2601)}, + {USB_DEVICE(0x093a, 0x2603)}, + {USB_DEVICE(0x093a, 0x2608)}, + {USB_DEVICE(0x093a, 0x260e)}, + {USB_DEVICE(0x093a, 0x260f)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); From 23a98274cc348880ecb6803307c254448084953a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Nov 2009 09:10:25 -0300 Subject: [PATCH 181/345] V4L/DVB (13301): gspca - sonixj: Simplify the sensor init exchanges. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 174 ++++++----------------------- 1 file changed, 34 insertions(+), 140 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 22209945698e..63371bbe3da9 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -464,6 +464,8 @@ static const u8 hv7131r_sensor_init[][8] = { {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10}, + /* set sensor clock */ {} }; static const u8 mi0360_sensor_init[][8] = { @@ -545,7 +547,7 @@ static const u8 mo4000_sensor_init[][8] = { }; static const u8 mt9v111_sensor_init[][8] = { {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */ - /* delay 20 ms */ + {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */ {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */ @@ -622,10 +624,10 @@ static const u8 om6802_sensor_init[][8] = { static const u8 ov7630_sensor_init[][8] = { {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, -/* win: delay 20ms */ + {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, -/* win: delay 20ms */ + {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, /* win: i2c_r from 00 to 80 */ {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, @@ -677,6 +679,7 @@ static const u8 ov7630_sensor_init[][8] = { static const u8 ov7648_sensor_init[][8] = { {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */ + {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10}, {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10}, @@ -723,7 +726,7 @@ static const u8 ov7648_sensor_init[][8] = { static const u8 ov7660_sensor_init[][8] = { {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */ -/* (delay 20ms) */ + {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10}, /* Outformat = rawRGB */ {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */ @@ -894,6 +897,18 @@ static const u8 sp80708_sensor_init[][8] = { {} }; +static const u8 (*sensor_init[9])[8] = { + hv7131r_sensor_init, /* HV7131R 0 */ + mi0360_sensor_init, /* MI0360 1 */ + mo4000_sensor_init, /* MO4000 2 */ + mt9v111_sensor_init, /* MT9V111 3 */ + om6802_sensor_init, /* OM6802 4 */ + ov7630_sensor_init, /* OV7630 5 */ + ov7648_sensor_init, /* OV7648 6 */ + ov7660_sensor_init, /* OV7660 7 */ + sp80708_sensor_init, /* SP80708 8 */ +}; + /* read bytes to gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, u16 value, int len) @@ -1014,6 +1029,18 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) reg_r(gspca_dev, 0x0a, 5); } +static void i2c_w_seq(struct gspca_dev *gspca_dev, + const u8 (*data)[8]) +{ + while ((*data)[0] != 0) { + if ((*data)[0] != 0xdd) + i2c_w8(gspca_dev, *data); + else + msleep((*data)[1]); + data++; + } +} + static void hv7131r_probe(struct gspca_dev *gspca_dev) { i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ @@ -1164,129 +1191,6 @@ static void configure_gpio(struct gspca_dev *gspca_dev, } } -static void hv7131R_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - static const u8 SetSensorClk[] = /* 0x08 Mclk */ - { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 }; - - while (hv7131r_sensor_init[i][0]) { - i2c_w8(gspca_dev, hv7131r_sensor_init[i]); - i++; - } - i2c_w8(gspca_dev, SetSensorClk); -} - -static void mi0360_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - - while (mi0360_sensor_init[i][0]) { - i2c_w8(gspca_dev, mi0360_sensor_init[i]); - i++; - } -} - -static void mo4000_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - - while (mo4000_sensor_init[i][0]) { - i2c_w8(gspca_dev, mo4000_sensor_init[i]); - i++; - } -} - -static void mt9v111_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - - i2c_w8(gspca_dev, mt9v111_sensor_init[i]); - i++; - msleep(20); - while (mt9v111_sensor_init[i][0]) { - i2c_w8(gspca_dev, mt9v111_sensor_init[i]); - i++; - } -} - -static void om6802_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - - while (om6802_sensor_init[i][0]) { - i2c_w8(gspca_dev, om6802_sensor_init[i]); - i++; - } -} - -static void ov7630_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - - i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */ - i++; - i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */ - i++; - msleep(20); - i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */ - i++; - i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */ - i++; - msleep(20); - i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */ - i++; -/*jfm:win i2c_r from 00 to 80*/ - - while (ov7630_sensor_init[i][0]) { - i2c_w8(gspca_dev, ov7630_sensor_init[i]); - i++; - } -} - -static void ov7648_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - - i2c_w8(gspca_dev, ov7648_sensor_init[i]); - i++; -/* win: dble reset */ - i2c_w8(gspca_dev, ov7648_sensor_init[i]); /* reset */ - i++; - msleep(20); -/* win: i2c reg read 00..7f */ - while (ov7648_sensor_init[i][0]) { - i2c_w8(gspca_dev, ov7648_sensor_init[i]); - i++; - } -} - -static void ov7660_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - - i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */ - i++; - msleep(20); - while (ov7660_sensor_init[i][0]) { - i2c_w8(gspca_dev, ov7660_sensor_init[i]); - i++; - } -} - -static void sp80708_InitSensor(struct gspca_dev *gspca_dev) -{ - int i = 0; - - i2c_w8(gspca_dev, sp80708_sensor_init[i]); /* reset SCCB */ - i++; - msleep(20); - while (sp80708_sensor_init[i][0]) { - i2c_w8(gspca_dev, sp80708_sensor_init[i]); - i++; - } -} - /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -1801,6 +1705,9 @@ static int sd_start(struct gspca_dev *gspca_dev) break; } + /* initialize the sensor */ + i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); + mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; if (mode) reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */ @@ -1808,14 +1715,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ reg17 = 0x61; /* 0x:20: enable sensor clock */ switch (sd->sensor) { - case SENSOR_HV7131R: - hv7131R_InitSensor(gspca_dev); - break; - case SENSOR_MI0360: - mi0360_InitSensor(gspca_dev); - break; case SENSOR_MO4000: - mo4000_InitSensor(gspca_dev); if (mode) { /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ reg1 = 0x06; /* clk 24Mz */ @@ -1825,7 +1725,6 @@ static int sd_start(struct gspca_dev *gspca_dev) } break; case SENSOR_MT9V111: - mt9v111_InitSensor(gspca_dev); if (mode) { reg1 = 0x04; /* 320 clk 48Mhz */ } else { @@ -1834,22 +1733,18 @@ static int sd_start(struct gspca_dev *gspca_dev) } break; case SENSOR_OM6802: - om6802_InitSensor(gspca_dev); reg17 = 0x64; /* 640 MCKSIZE */ break; case SENSOR_OV7630: - ov7630_InitSensor(gspca_dev); setvflip(sd); reg17 = 0xe2; reg1 = 0x44; break; case SENSOR_OV7648: - ov7648_InitSensor(gspca_dev); reg17 = 0x21; /* reg1 = 0x42; * 42 - 46? */ break; case SENSOR_OV7660: - ov7660_InitSensor(gspca_dev); if (sd->bridge == BRIDGE_SN9C120) { if (mode) { /* 320x240 - 160x120 */ reg17 = 0xa2; @@ -1863,7 +1758,6 @@ static int sd_start(struct gspca_dev *gspca_dev) break; default: /* case SENSOR_SP80708: */ - sp80708_InitSensor(gspca_dev); if (mode) { /*?? reg1 = 0x04; * 320 clk 48Mhz */ } else { From a782636c26b7468345d2c3b67952bf695a39cdfa Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Nov 2009 09:21:06 -0300 Subject: [PATCH 182/345] V4L/DVB (13302): gspca - sonixj: Fix some bad values of sensor om6802. - sensor address is 0x34 - sensor i2c is 100 kHz Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 63371bbe3da9..159f9f7be307 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -973,7 +973,14 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) struct sd *sd = (struct sd *) gspca_dev; PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); - gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */ + switch (sd->sensor) { + case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */ + gspca_dev->usb_buf[0] = 0x80 | (2 << 4); + break; + default: /* i2c command = a1 (400 kHz) */ + gspca_dev->usb_buf[0] = 0x81 | (2 << 4); + break; + } gspca_dev->usb_buf[1] = sd->i2c_base; gspca_dev->usb_buf[2] = reg; gspca_dev->usb_buf[3] = val; @@ -1012,7 +1019,14 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) struct sd *sd = (struct sd *) gspca_dev; u8 mode[8]; - mode[0] = 0x81 | 0x10; + switch (sd->sensor) { + case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */ + mode[0] = 0x80 | 0x10; + break; + default: /* i2c command = 91 (400 kHz) */ + mode[0] = 0x81 | 0x10; + break; + } mode[1] = sd->i2c_base; mode[2] = reg; mode[3] = 0; @@ -1022,7 +1036,7 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) mode[7] = 0x10; i2c_w8(gspca_dev, mode); msleep(2); - mode[0] = 0x81 | (5 << 4) | 0x02; + mode[0] = (mode[0] & 0x81) | (5 << 4) | 0x02; mode[2] = 0; i2c_w8(gspca_dev, mode); msleep(2); @@ -2216,7 +2230,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x21)}, */ {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, /* {USB_DEVICE(0x0c45, 0x60c2), BSI(SN9C105, P1030xC, 0x??)}, */ -/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x21)}, */ +/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x34)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ @@ -2228,7 +2242,7 @@ static const __devinitdata struct usb_device_id device_table[] = { #endif {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ /* {USB_DEVICE(0x0c45, 0x6102), BSI(SN9C120, P1030xC, ??)}, */ -/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6802, 0x21)}, */ +/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6802, 0x34)}, */ {USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/ @@ -2236,7 +2250,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x610f), BSI(SN9C120, S5K53BEB, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ - {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/ + {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C120, OM6802, 0x34)}, /*sn9c325?*/ /*bw600.inf:*/ {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/ {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)}, @@ -2255,7 +2269,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)}, /* {USB_DEVICE(0x0c45, 0x6142), BSI(SN9C120, PO2030N, ??)}, *sn9c120b*/ {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, /*sn9c120b*/ - {USB_DEVICE(0x0c45, 0x6148), BSI(SN9C120, OM6802, 0x21)}, /*sn9c120b*/ + {USB_DEVICE(0x0c45, 0x6148), BSI(SN9C120, OM6802, 0x34)}, /*sn9c120b*/ {} }; MODULE_DEVICE_TABLE(usb, device_table); From 3fccb774ef6e43c2d80d322a5b52564db3067ef8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Nov 2009 09:54:04 -0300 Subject: [PATCH 183/345] V4L/DVB (13303): gspca - sonixj: Change sensor and om6802 exchanges. - the sensors are now initialized sooner - om6802: . set some parameters in factory mode . lack of some parameters . gpio adjustments Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 110 +++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 20 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 159f9f7be307..c1b6c9565584 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -574,7 +574,9 @@ static const u8 mt9v111_sensor_init[][8] = { {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */ {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */ {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, - /*******/ + {} +}; +static const u8 mt9v111_sensor_param1[][8] = { {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x09, 0x01, 0x2c, 0x00, 0x00, 0x10}, @@ -587,11 +589,16 @@ static const u8 mt9v111_sensor_init[][8] = { {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */ {} }; +static const u8 om6802_init0[2][8] = { +/*fixme: variable*/ + {0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10}, +}; static const u8 om6802_sensor_init[][8] = { - {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10}, + /* factory mode */ {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10}, /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */ {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10}, /* white balance & auto-exposure */ @@ -614,11 +621,14 @@ static const u8 om6802_sensor_init[][8] = { /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10}, * auto frame rate */ /* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */ - -/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */ -/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */ -/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */ -/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */ + {0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10}, + {} +}; +static const u8 om6802_sensor_param1[][8] = { + {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, {} }; static const u8 ov7630_sensor_init[][8] = { @@ -704,7 +714,9 @@ static const u8 ov7648_sensor_init[][8] = { /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */ /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */ /* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */ -/*...*/ + {} +}; +static const u8 ov7648_sensor_param1[][8] = { /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN * set by setvflip */ @@ -786,8 +798,11 @@ static const u8 ov7660_sensor_init[][8] = { {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */ +/* not in all ms-win traces*/ {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, -/****** (some exchanges in the win trace) ******/ + {} +}; +static const u8 ov7660_sensor_param1[][8] = { {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ /* bits[3..0]reserved */ {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, @@ -800,6 +815,7 @@ static const u8 ov7660_sensor_init[][8] = { {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */ /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */ /****** (some exchanges in the win trace) ******/ +/*fixme:param2*/ {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */ {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */ {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */ @@ -807,6 +823,7 @@ static const u8 ov7660_sensor_init[][8] = { /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */ /****** (some exchanges in the win trace) ******/ /******!! startsensor KO if changed !!****/ +/*fixme: param3*/ {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, @@ -886,7 +903,9 @@ static const u8 sp80708_sensor_init[][8] = { {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10}, - /********/ + {} +}; +static const u8 sp80708_sensor_param1[][8] = { {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10}, @@ -1125,7 +1144,7 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) } } -static void configure_gpio(struct gspca_dev *gspca_dev, +static void bridge_init(struct gspca_dev *gspca_dev, const u8 *sn9c1xx) { struct sd *sd = (struct sd *) gspca_dev; @@ -1166,10 +1185,22 @@ static void configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x40); break; case SENSOR_OM6802: - reg_w1(gspca_dev, 0x02, 0x71); - reg_w1(gspca_dev, 0x01, 0x42); + msleep(10); + reg_w1(gspca_dev, 0x02, 0x73); + reg_w1(gspca_dev, 0x17, 0x60); + reg_w1(gspca_dev, 0x01, 0x22); + msleep(100); + reg_w1(gspca_dev, 0x01, 0x62); + reg_w1(gspca_dev, 0x17, 0x64); reg_w1(gspca_dev, 0x17, 0x64); reg_w1(gspca_dev, 0x01, 0x42); + msleep(10); + reg_w1(gspca_dev, 0x01, 0x42); + i2c_w8(gspca_dev, om6802_init0[0]); + i2c_w8(gspca_dev, om6802_init0[1]); + msleep(15); + reg_w1(gspca_dev, 0x02, 0x71); + msleep(150); break; case SENSOR_OV7630: reg_w1(gspca_dev, 0x01, 0x61); @@ -1639,8 +1670,9 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; - u8 reg1, reg17; + u8 reg1, reg2, reg17; const u8 *sn9c1xx; + const u8 (*init)[8]; int mode; static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; @@ -1656,8 +1688,25 @@ static int sd_start(struct gspca_dev *gspca_dev) 0x21); /* JPEG 422 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); - sn9c1xx = sn_tb[(int) sd->sensor]; - configure_gpio(gspca_dev, sn9c1xx); + /* initialize the bridge */ + sn9c1xx = sn_tb[sd->sensor]; + bridge_init(gspca_dev, sn9c1xx); + /* initialize the sensor */ + i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); + + switch (sd->sensor) { + case SENSOR_OM6802: + reg2 = 0x71; + break; + case SENSOR_SP80708: + reg2 = 0x62; + break; + default: + reg2 = 0x40; + break; + } + reg_w1(gspca_dev, 0x02, reg2); + reg_w1(gspca_dev, 0x02, reg2); reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); @@ -1704,6 +1753,10 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x9a, 0x07); reg_w1(gspca_dev, 0x99, 0x59); break; + case SENSOR_OM6802: + reg_w1(gspca_dev, 0x9a, 0x08); + reg_w1(gspca_dev, 0x99, 0x10); + break; case SENSOR_OV7648: reg_w1(gspca_dev, 0x9a, 0x0a); reg_w1(gspca_dev, 0x99, 0x60); @@ -1719,9 +1772,12 @@ static int sd_start(struct gspca_dev *gspca_dev) break; } - /* initialize the sensor */ - i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); + reg_w(gspca_dev, 0x84, reg84, sizeof reg84); + reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */ + reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ + reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ + init = NULL; mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; if (mode) reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */ @@ -1739,6 +1795,7 @@ static int sd_start(struct gspca_dev *gspca_dev) } break; case SENSOR_MT9V111: + init = mt9v111_sensor_param1; if (mode) { reg1 = 0x04; /* 320 clk 48Mhz */ } else { @@ -1747,6 +1804,7 @@ static int sd_start(struct gspca_dev *gspca_dev) } break; case SENSOR_OM6802: + init = om6802_sensor_param1; reg17 = 0x64; /* 640 MCKSIZE */ break; case SENSOR_OV7630: @@ -1755,10 +1813,12 @@ static int sd_start(struct gspca_dev *gspca_dev) reg1 = 0x44; break; case SENSOR_OV7648: + init = ov7648_sensor_param1; reg17 = 0x21; /* reg1 = 0x42; * 42 - 46? */ break; case SENSOR_OV7660: + init = ov7660_sensor_param1; if (sd->bridge == BRIDGE_SN9C120) { if (mode) { /* 320x240 - 160x120 */ reg17 = 0xa2; @@ -1772,6 +1832,7 @@ static int sd_start(struct gspca_dev *gspca_dev) break; default: /* case SENSOR_SP80708: */ + init = sp80708_sensor_param1; if (mode) { /*?? reg1 = 0x04; * 320 clk 48Mhz */ } else { @@ -1780,6 +1841,13 @@ static int sd_start(struct gspca_dev *gspca_dev) } break; } + + /* more sensor initialization - param1 */ + if (init != NULL) { + i2c_w_seq(gspca_dev, init); +/* init = NULL; */ + } + reg_w(gspca_dev, 0xc0, C0, 6); reg_w(gspca_dev, 0xca, CA, 4); switch (sd->sensor) { @@ -1794,6 +1862,7 @@ static int sd_start(struct gspca_dev *gspca_dev) break; } + /* here change size mode 0 -> VGA; 1 -> CIF */ sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40; reg_w1(gspca_dev, 0x18, sd->reg18); @@ -1801,6 +1870,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x17, reg17); reg_w1(gspca_dev, 0x01, reg1); + switch (sd->sensor) { case SENSOR_OV7630: setvflip(sd); From 98941e4dade35ab2e83c9bc796fdc76ed3636a75 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Nov 2009 09:56:59 -0300 Subject: [PATCH 184/345] V4L/DVB (13304): gspca - sonixj: Don't access the sensor when setting the bridge. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index c1b6c9565584..bd076605c4bb 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -304,7 +304,7 @@ static const u8 sn_hv7131[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ - 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, + 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, /* reg18 reg19 reg1a reg1b */ @@ -315,7 +315,7 @@ static const u8 sn_mi0360[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ - 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, /* reg18 reg19 reg1a reg1b */ @@ -337,7 +337,7 @@ static const u8 sn_mt9v111[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x5c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x81, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40, /* reg18 reg19 reg1a reg1b */ @@ -359,7 +359,7 @@ static const u8 sn_ov7630[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ - 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10, + 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2, /* reg18 reg19 reg1a reg1b */ @@ -370,7 +370,7 @@ static const u8 sn_ov7648[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00, /* reg18 reg19 reg1a reg1b */ @@ -392,7 +392,7 @@ static const u8 sn_sp80708[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x81, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00, /* reg18 reg19 reg1a reg1b */ From 0939e266697d516ba09cfaec6a97887600a4162d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Nov 2009 09:58:49 -0300 Subject: [PATCH 185/345] V4L/DVB (13305): gspca - sonixj: The V flip control does not exist for all sensors. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index bd076605c4bb..e75e7e36e7da 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1549,6 +1549,8 @@ static void setvflip(struct sd *sd) { u8 comn; + if (sd->gspca_dev.ctrl_dis & (1 << VFLIP_IDX)) + return; if (sd->sensor == SENSOR_OV7630) { comn = 0x02; if (!sd->vflip) From 5b34e3e4eb993578c313f473ff60df62e0c24379 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Nov 2009 10:00:48 -0300 Subject: [PATCH 186/345] V4L/DVB (13306): gspca - sonixj: Change the copyright. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index e75e7e36e7da..a9643a0f78d5 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1,8 +1,7 @@ /* - * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library - * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr - * - * V4L2 by Jean-Francois Moine + * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver + * Copyright (C) 2009 Jean-Francois Moine + * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr * * 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 From 3bc766ad374d04349ba09bd93f51980ad29d11c3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 21 Oct 2009 18:36:18 -0300 Subject: [PATCH 187/345] V4L/DVB (13308): uvcvideo: Add support for MSI StarCam 370i webcams The MSI StarCam 370i (1b3b:2951) requires the MINMAX quirk. Add a corresponding entry in the device IDs list. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index ab4a60102d08..782faf6970b4 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -2136,6 +2136,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STATUS_INTERVAL }, + /* MSI StarCam 370i */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1b3b, + .idProduct = 0x2951, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* SiGma Micro USB Web Camera */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, From 350d6407f84db58e2dfb5a5a5283982130746a41 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 4 Nov 2009 11:53:49 -0300 Subject: [PATCH 188/345] V4L/DVB (13310): uvcvideo: Return -EINVAL instead of -ENODEV in read() -EINVAL is required by the V4L2 specification. -ENODEV is simply wrong as the device exists. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_v4l2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index b3478d0eaf41..be3da56d4db3 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1035,7 +1035,7 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n"); - return -ENODEV; + return -EINVAL; } /* From 56205cc0dd703be70b4ea1138a7e774e058d79fa Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 4 Nov 2009 16:38:04 -0300 Subject: [PATCH 189/345] V4L/DVB (13323): gspca - zc3xx: Adjust the exchanges of sensors mi0360soc and pb0330. - the pb03303x exchanges were the mi0360soc ones - add the new sensor mi0360soc - the new exchanges are taken from the info file of the ms-win driver of the webcams 0ac8:301b and 0ac8:303b (vm30x.inf) Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 995 +++++++++++++----------------- 1 file changed, 421 insertions(+), 574 deletions(-) diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index e57f9dd68a48..113050792246 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -61,17 +61,18 @@ struct sd { #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_PAS202B 12 -#define SENSOR_PB0330 13 -#define SENSOR_PO2030 14 -#define SENSOR_TAS5130CK 15 -#define SENSOR_TAS5130CXX 16 -#define SENSOR_TAS5130C_VF0250 17 -#define SENSOR_MAX 18 +#define SENSOR_MI0360SOC 9 +#define SENSOR_OV7620 10 +/*#define SENSOR_OV7648 10 - same values */ +#define SENSOR_OV7630C 11 +#define SENSOR_PAS106 12 +#define SENSOR_PAS202B 13 +#define SENSOR_PB0330 14 /* (MI0360) */ +#define SENSOR_PO2030 15 +#define SENSOR_TAS5130CK 16 +#define SENSOR_TAS5130CXX 17 +#define SENSOR_TAS5130C_VF0250 18 +#define SENSOR_MAX 19 unsigned short chip_revision; u8 *jpeg_hdr; @@ -4235,153 +4236,8 @@ static const struct usb_action pas202b_NoFlikerScale[] = { {} }; -static const struct usb_action pb03303x_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, /* 8b -> dc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xaa, 0x01, 0x0001}, - {0xaa, 0x06, 0x0000}, - {0xaa, 0x08, 0x0483}, - {0xaa, 0x01, 0x0004}, - {0xaa, 0x08, 0x0006}, - {0xaa, 0x02, 0x0011}, - {0xaa, 0x03, 0x01e7}, - {0xaa, 0x04, 0x0287}, - {0xaa, 0x07, 0x3002}, - {0xaa, 0x20, 0x1100}, - {0xaa, 0x35, 0x0050}, - {0xaa, 0x30, 0x0005}, - {0xaa, 0x31, 0x0000}, - {0xaa, 0x58, 0x0078}, - {0xaa, 0x62, 0x0411}, - {0xaa, 0x2b, 0x0028}, - {0xaa, 0x2c, 0x0030}, - {0xaa, 0x2d, 0x0030}, - {0xaa, 0x2e, 0x0028}, - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {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, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, - {0xa0, 0x61, ZC3XX_R116_RGAIN}, - {0xa0, 0x65, ZC3XX_R118_BGAIN}, - - {0xa1, 0x01, 0x0002}, - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x0d, 0x003a}, - {0xa0, 0x02, 0x003b}, - {0xa0, 0x00, 0x0038}, - {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ - {0xa0, 0x38, ZC3XX_R121_GAMMA01}, - {0xa0, 0x59, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x92, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, - {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x22, 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, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0009}, - {0xaa, 0x09, 0x0134}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xec, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x9c, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; - -static const struct usb_action pb03303x_InitialScale[] = { +/* mi0360soc and pb0330 from vm30x.inf for 0ac8:301b and 0ac8:303b 07/02/13 */ +static const struct usb_action mi0360soc_Initial[] = { /* 640x480 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, @@ -4390,15 +4246,70 @@ static const struct usb_action pb03303x_InitialScale[] = { {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, /* 8b -> dc */ + {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, + {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, /*jfm: was 03*/ +/* {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, */ {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, + {0xdd, 0x00, 0x0200}, + {0xaa, 0x01, 0x0001}, + {0xaa, 0x06, 0x0000}, + {0xaa, 0x08, 0x0483}, + {0xaa, 0x01, 0x0004}, + {0xaa, 0x08, 0x0006}, + {0xaa, 0x02, 0x0011}, + {0xaa, 0x03, 0x01e5}, /*jfm: was 01e7*/ + {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/ + {0xaa, 0x07, 0x3002}, + {0xaa, 0x20, 0x5100}, /*jfm: was 1100*/ + {0xaa, 0x35, 0x507f}, /*jfm: was 0050*/ + {0xaa, 0x30, 0x0005}, + {0xaa, 0x31, 0x0000}, + {0xaa, 0x58, 0x0078}, + {0xaa, 0x62, 0x0411}, + {0xaa, 0x2b, 0x0028}, + {0xaa, 0x2c, 0x007f}, /*jfm: was 0030*/ + {0xaa, 0x2d, 0x007f}, /*jfm: was 0030*/ + {0xaa, 0x2e, 0x007f}, /*jfm: was 0030*/ + {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, + {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /*jfm: was 37*/ + {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, + {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, + {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, + {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/ + {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, + {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, + {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, + {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, + {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, + {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, /* jfm: was 78 */ + {0xa0, 0x61, ZC3XX_R116_RGAIN}, + {0xa0, 0x65, ZC3XX_R118_BGAIN}, + {} +}; +static const struct usb_action mi0360soc_InitialScale[] = { /* 320x240 */ + {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, + {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, + {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, + {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, + {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, + {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, + {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, + {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, + {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, + {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, /*jfm: was 03*/ +/* {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, */ + {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, + {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, + {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, + {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, + {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, + {0xdd, 0x00, 0x0200}, {0xaa, 0x01, 0x0001}, {0xaa, 0x06, 0x0000}, {0xaa, 0x08, 0x0483}, @@ -4408,111 +4319,111 @@ static const struct usb_action pb03303x_InitialScale[] = { {0xaa, 0x03, 0x01e7}, {0xaa, 0x04, 0x0287}, {0xaa, 0x07, 0x3002}, - {0xaa, 0x20, 0x1100}, - {0xaa, 0x35, 0x0050}, + {0xaa, 0x20, 0x5100}, /*jfm: was 1100*/ + {0xaa, 0x35, 0x007f}, /*jfm: was 0050*/ {0xaa, 0x30, 0x0005}, {0xaa, 0x31, 0x0000}, {0xaa, 0x58, 0x0078}, {0xaa, 0x62, 0x0411}, - {0xaa, 0x2b, 0x0028}, - {0xaa, 0x2c, 0x0030}, - {0xaa, 0x2d, 0x0030}, - {0xaa, 0x2e, 0x0028}, + {0xaa, 0x2b, 0x007f}, /*jfm: was 28*/ + {0xaa, 0x2c, 0x007f}, /*jfm: was 30*/ + {0xaa, 0x2d, 0x007f}, /*jfm: was 30*/ + {0xaa, 0x2e, 0x007f}, /*jfm: was 28*/ {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, + {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /*jfm: was 37*/ {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x00, 0x01ad}, + {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/ {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, + {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, /*jfm: was 78*/ {0xa0, 0x61, ZC3XX_R116_RGAIN}, {0xa0, 0x65, ZC3XX_R118_BGAIN}, - - {0xa1, 0x01, 0x0002}, - - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - - {0xa0, 0x0d, 0x003a}, - {0xa0, 0x02, 0x003b}, - {0xa0, 0x00, 0x0038}, - {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - - {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ - {0xa0, 0x38, ZC3XX_R121_GAMMA01}, - {0xa0, 0x59, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x92, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, - {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x22, 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, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, + {} +}; +static const struct usb_action mi360soc_AE50HZ[] = { {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0009}, - {0xaa, 0x09, 0x0134}, + {0xbb, 0x00, 0x0562}, + {0xbb, 0x01, 0x09aa}, {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xec, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW}, {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x9c, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, + {} +}; +static const struct usb_action mi360soc_AE50HZScale[] = { + {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0509}, + {0xbb, 0x01, 0x0934}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, + {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, + {} +}; +static const struct usb_action mi360soc_AE60HZ[] = { + {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x053d}, + {0xbb, 0x01, 0x096e}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, + {} +}; +static const struct usb_action mi360soc_AE60HZScale[] = { + {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0509}, + {0xbb, 0x01, 0x0983}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, @@ -4522,16 +4433,105 @@ static const struct usb_action pb03303x_InitialScale[] = { {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, + {} +}; +static const struct usb_action mi360soc_AENoFliker[] = { + {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0509}, + {0xbb, 0x01, 0x0960}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, {} }; -static const struct usb_action pb0330xx_Initial[] = { - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0008}, +static const struct usb_action mi360soc_AENoFlikerScale[] = { + {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0534}, + {0xbb, 0x02, 0x0960}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x34, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, + {} +}; + +static const struct usb_action pb0330_Initial[] = { /* 640x480 */ + {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, + {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ + {0xa0, 0x0a, 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, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, + {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, + {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, + {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, + {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, + {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, + {0xdd, 0x00, 0x0200}, + {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, + {0xaa, 0x01, 0x0006}, + {0xaa, 0x02, 0x0011}, + {0xaa, 0x03, 0x01e5}, /*jfm: was 1e7*/ + {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/ + {0xaa, 0x06, 0x0003}, + {0xaa, 0x07, 0x3002}, + {0xaa, 0x20, 0x1100}, + {0xaa, 0x2f, 0xf7b0}, + {0xaa, 0x30, 0x0005}, + {0xaa, 0x31, 0x0000}, + {0xaa, 0x34, 0x0100}, + {0xaa, 0x35, 0x0060}, + {0xaa, 0x3d, 0x068f}, + {0xaa, 0x40, 0x01e0}, + {0xaa, 0x58, 0x0078}, + {0xaa, 0x62, 0x0411}, + {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, + {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, + {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, + {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, + {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, + {0xa0, 0x09, 0x01ad}, /*jfm: was 00 */ + {0xa0, 0x15, 0x01ae}, + {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, + {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, + {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, + {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, + {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, + {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/ + {} +}; +static const struct usb_action pb0330_InitialScale[] = { /* 320x240 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, @@ -4547,6 +4547,7 @@ static const struct usb_action pb0330xx_Initial[] = { {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, + {0xdd, 0x00, 0x0200}, {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, {0xaa, 0x01, 0x0006}, {0xaa, 0x02, 0x0011}, @@ -4569,293 +4570,146 @@ static const struct usb_action pb0330xx_Initial[] = { {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x00, 0x01ad}, + {0xa0, 0x09, 0x01ad}, + {0xa0, 0x15, 0x01ae}, {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, - {0xa1, 0x01, 0x0002}, - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, - {0xa1, 0x01, 0x0091}, - {0xa1, 0x01, 0x0095}, - {0xa1, 0x01, 0x0096}, - {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - - {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0066}, - {0xaa, 0x09, 0x02b2}, - {0xaa, 0x10, 0x0002}, - - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0007}, -/* {0xa0, 0x30, 0x0007}, */ -/* {0xa0, 0x00, 0x0007}, */ - {} -}; - -static const struct usb_action pb0330xx_InitialScale[] = { - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 10 */ - {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, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x0006}, - {0xaa, 0x02, 0x0011}, - {0xaa, 0x03, 0x01e7}, - {0xaa, 0x04, 0x0287}, - {0xaa, 0x06, 0x0003}, - {0xaa, 0x07, 0x3002}, - {0xaa, 0x20, 0x1100}, - {0xaa, 0x2f, 0xf7b0}, - {0xaa, 0x30, 0x0005}, - {0xaa, 0x31, 0x0000}, - {0xaa, 0x34, 0x0100}, - {0xaa, 0x35, 0x0060}, - {0xaa, 0x3d, 0x068f}, - {0xaa, 0x40, 0x01e0}, - {0xaa, 0x58, 0x0078}, - {0xaa, 0x62, 0x0411}, - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {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, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, - {0xa1, 0x01, 0x0002}, - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, - {0xa1, 0x01, 0x0091}, - {0xa1, 0x01, 0x0095}, - {0xa1, 0x01, 0x0096}, - {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - - {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0066}, - {0xaa, 0x09, 0x02b2}, - {0xaa, 0x10, 0x0002}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0007}, -/* {0xa0, 0x30, 0x0007}, */ -/* {0xa0, 0x00, 0x0007}, */ + {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/ {} }; static const struct usb_action pb0330_50HZ[] = { - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ - {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,ee,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ - {0xa0, 0x68, ZC3XX_R01D_HSYNC_0}, /* 00,1d,68,cc */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x055c}, + {0xbb, 0x01, 0x09aa}, + {0xbb, 0x00, 0x1001}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xc4, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x5c, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, {} }; static const struct usb_action pb0330_50HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ - {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,a0,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x7a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7a,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ - {0xa0, 0xe5, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e5,cc */ - {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f0,cc */ - {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */ + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0566}, + {0xbb, 0x02, 0x09b2}, + {0xbb, 0x00, 0x1002}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, {} }; static const struct usb_action pb0330_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ - {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,dd,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ - {0xa0, 0x43, ZC3XX_R01D_HSYNC_0}, /* 00,1d,43,cc */ - {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */ - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0535}, + {0xbb, 0x01, 0x0974}, + {0xbb, 0x00, 0x1001}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xd0, ZC3XX_R020_HSYNC_3}, {} }; static const struct usb_action pb0330_60HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ - {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,a0,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x7a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7a,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ - {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */ - {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */ - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0535}, + {0xbb, 0x02, 0x096c}, + {0xbb, 0x00, 0x1002}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x7c, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xd0, ZC3XX_R020_HSYNC_3}, {} }; static const struct usb_action pb0330_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {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, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,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, 0x09, ZC3XX_R01D_HSYNC_0}, /* 00,1d,09,cc */ - {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */ - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0509}, + {0xbb, 0x02, 0x0940}, + {0xbb, 0x00, 0x1002}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, {} }; static const struct usb_action pb0330_NoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {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, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,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, 0x09, ZC3XX_R01D_HSYNC_0}, /* 00,1d,09,cc */ - {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */ - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ + {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, + {0xbb, 0x00, 0x0535}, + {0xbb, 0x01, 0x0980}, + {0xbb, 0x00, 0x1001}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, + {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, + {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, + {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, + {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, + {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, + {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, + {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, + {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, + {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, + {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, + {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, + {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, {} }; @@ -6131,15 +5985,16 @@ static void setmatrix(struct gspca_dev *gspca_dev) NULL, /* SENSOR_HV7131C 6 */ NULL, /* SENSOR_ICM105A 7 */ NULL, /* SENSOR_MC501CB 8 */ - ov7620_matrix, /* SENSOR_OV7620 9 */ - NULL, /* SENSOR_OV7630C 10 */ - NULL, /* SENSOR_PAS106 11 */ - pas202b_matrix, /* SENSOR_PAS202B 12 */ - NULL, /* SENSOR_PB0330 13 */ - po2030_matrix, /* SENSOR_PO2030 14 */ - NULL, /* SENSOR_TAS5130CK 15 */ - tas5130c_matrix, /* SENSOR_TAS5130CXX 16 */ - vf0250_matrix, /* SENSOR_TAS5130C_VF0250 17 */ + gc0305_matrix, /* SENSOR_MI0360SOC 9 */ + ov7620_matrix, /* SENSOR_OV7620 10 */ + NULL, /* SENSOR_OV7630C 11 */ + NULL, /* SENSOR_PAS106 12 */ + pas202b_matrix, /* SENSOR_PAS202B 13 */ + gc0305_matrix, /* SENSOR_PB0330 14 */ + po2030_matrix, /* SENSOR_PO2030 15 */ + NULL, /* SENSOR_TAS5130CK 16 */ + tas5130c_matrix, /* SENSOR_TAS5130CXX 17 */ + vf0250_matrix, /* SENSOR_TAS5130C_VF0250 18 */ }; matrix = matrix_tb[sd->sensor]; @@ -6379,39 +6234,43 @@ static int setlightfreq(struct gspca_dev *gspca_dev) {MC501CB_NoFliker, MC501CB_NoFlikerScale, MC501CB_50HZ, MC501CB_50HZScale, MC501CB_60HZ, MC501CB_60HZScale}, -/* SENSOR_OV7620 9 */ +/* SENSOR_MI0360SOC 9 */ + {mi360soc_AENoFlikerScale, mi360soc_AENoFliker, + mi360soc_AE50HZScale, mi360soc_AE50HZ, + mi360soc_AE60HZScale, mi360soc_AE60HZ}, +/* SENSOR_OV7620 10 */ {OV7620_NoFliker, OV7620_NoFliker, OV7620_50HZ, OV7620_50HZ, OV7620_60HZ, OV7620_60HZ}, -/* SENSOR_OV7630C 10 */ +/* SENSOR_OV7630C 11 */ {NULL, NULL, NULL, NULL, NULL, NULL}, -/* SENSOR_PAS106 11 */ +/* SENSOR_PAS106 12 */ {pas106b_NoFliker, pas106b_NoFliker, pas106b_50HZ, pas106b_50HZ, pas106b_60HZ, pas106b_60HZ}, -/* SENSOR_PAS202B 12 */ +/* SENSOR_PAS202B 13 */ {pas202b_NoFlikerScale, pas202b_NoFliker, pas202b_50HZScale, pas202b_50HZ, pas202b_60HZScale, pas202b_60HZ}, -/* SENSOR_PB0330 13 */ - {pb0330_NoFliker, pb0330_NoFlikerScale, - pb0330_50HZ, pb0330_50HZScale, - pb0330_60HZ, pb0330_60HZScale}, -/* SENSOR_PO2030 14 */ +/* SENSOR_PB0330 14 */ + {pb0330_NoFlikerScale, pb0330_NoFliker, + pb0330_50HZScale, pb0330_50HZ, + pb0330_60HZScale, pb0330_60HZ}, +/* SENSOR_PO2030 15 */ {PO2030_NoFliker, PO2030_NoFliker, PO2030_50HZ, PO2030_50HZ, PO2030_60HZ, PO2030_60HZ}, -/* SENSOR_TAS5130CK 15 */ +/* SENSOR_TAS5130CK 16 */ {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, tas5130cxx_50HZScale, tas5130cxx_50HZ, tas5130cxx_60HZScale, tas5130cxx_60HZ}, -/* SENSOR_TAS5130CXX 16 */ +/* SENSOR_TAS5130CXX 17 */ {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, tas5130cxx_50HZScale, tas5130cxx_50HZ, tas5130cxx_60HZScale, tas5130cxx_60HZ}, -/* SENSOR_TAS5130C_VF0250 17 */ +/* SENSOR_TAS5130C_VF0250 18 */ {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, @@ -6468,6 +6327,7 @@ static void send_unknown(struct usb_device *dev, int sensor) case SENSOR_ADCM2700: case SENSOR_GC0305: case SENSOR_OV7620: + case SENSOR_MI0360SOC: case SENSOR_PB0330: case SENSOR_PO2030: reg_w(dev, 0x0d, 0x003a); @@ -6603,7 +6463,7 @@ struct sensor_by_chipset_revision { }; static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { {0xc000, 0x12}, /* TAS5130C */ - {0xc001, 0x13}, /* MI0360 */ + {0xc001, 0x13}, /* MI0360SOC */ {0xe001, 0x13}, {0x8001, 0x13}, {0x8000, 0x14}, /* CS2102K */ @@ -6772,15 +6632,16 @@ static int sd_config(struct gspca_dev *gspca_dev, 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_PAS202B 12 */ - 4, /* SENSOR_PB0330 13 */ - 4, /* SENSOR_PO2030 14 */ - 4, /* SENSOR_TAS5130CK 15 */ - 3, /* SENSOR_TAS5130CXX 16 */ - 3, /* SENSOR_TAS5130C_VF0250 17 */ + 4, /* SENSOR_MI0360SOC 9 */ + 3, /* SENSOR_OV7620 10 */ + 4, /* SENSOR_OV7630C 11 */ + 4, /* SENSOR_PAS106 12 */ + 4, /* SENSOR_PAS202B 13 */ + 4, /* SENSOR_PB0330 14 */ + 4, /* SENSOR_PO2030 15 */ + 4, /* SENSOR_TAS5130CK 16 */ + 3, /* SENSOR_TAS5130CXX 17 */ + 3, /* SENSOR_TAS5130C_VF0250 18 */ }; /* define some sensors from the vendor/product */ @@ -6851,9 +6712,9 @@ static int sd_config(struct gspca_dev *gspca_dev, break; case 0x13: PDEBUG(D_PROBE, - "Find Sensor MI0360. Chip revision %x", + "Find Sensor MI0360SOC. Chip revision %x", sd->chip_revision); - sd->sensor = SENSOR_PB0330; + sd->sensor = SENSOR_MI0360SOC; break; case 0x14: PDEBUG(D_PROBE, @@ -6967,17 +6828,17 @@ static int sd_start(struct gspca_dev *gspca_dev) {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */ {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */ {MC501CB_InitialScale, MC501CB_Initial}, /* 8 */ - {OV7620_mode0, OV7620_mode1}, /* 9 */ - {ov7630c_InitialScale, ov7630c_Initial}, /* 10 */ - {pas106b_InitialScale, pas106b_Initial}, /* 11 */ - {pas202b_Initial, pas202b_InitialScale}, /* 12 */ - {pb0330xx_InitialScale, pb0330xx_Initial}, /* 13 */ -/* or {pb03303x_InitialScale, pb03303x_Initial}, */ - {PO2030_mode0, PO2030_mode1}, /* 14 */ - {tas5130CK_InitialScale, tas5130CK_Initial}, /* 15 */ - {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 16 */ + {mi0360soc_Initial, mi0360soc_InitialScale}, /* 9 */ + {OV7620_mode0, OV7620_mode1}, /* 10 */ + {ov7630c_InitialScale, ov7630c_Initial}, /* 11 */ + {pas106b_InitialScale, pas106b_Initial}, /* 12 */ + {pas202b_Initial, pas202b_InitialScale}, /* 13 */ + {pb0330_Initial, pb0330_InitialScale}, /* 14 */ + {PO2030_mode0, PO2030_mode1}, /* 15 */ + {tas5130CK_InitialScale, tas5130CK_Initial}, /* 16 */ + {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 17 */ {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial}, - /* 17 */ + /* 18 */ }; /* create the JPEG header */ @@ -6997,19 +6858,6 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_PAS106: usb_exchange(gspca_dev, pas106b_Initial_com); break; - case SENSOR_PB0330: - if (mode) { - if (sd->chip_revision == 0xc001 - || sd->chip_revision == 0xe001 - || sd->chip_revision == 0x8001) - zc3_init = pb03303x_Initial; - } else { - if (sd->chip_revision == 0xc001 - || sd->chip_revision == 0xe001 - || sd->chip_revision == 0x8001) - zc3_init = pb03303x_InitialScale; - } - break; } usb_exchange(gspca_dev, zc3_init); @@ -7051,7 +6899,6 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_CS2102K: /* gamma set in xxx_Initial */ case SENSOR_HDCS2020b: - case SENSOR_PB0330: /* pb with chip_revision - see above */ case SENSOR_OV7630C: case SENSOR_TAS5130CK: break; From 4f7309e27865b88df7b0b0ad59e0376dba1806af Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Thu, 5 Nov 2009 05:35:08 -0300 Subject: [PATCH 190/345] V4L/DVB (13324): gspca - pac7302/pac7311: Handle return value of usb_control_msg(). The function usb_control_msg() can return error any time so at least warn the user if an error happens. No message is printed in case of normal operation. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7302.c | 24 +++++++++++++++++++++--- drivers/media/video/gspca/pac7311.c | 24 +++++++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 228b414709f7..60d1a31f5307 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -335,14 +335,20 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, const char *buffer, int len) { + int ret; + memcpy(gspca_dev->usb_buf, buffer, len); - usb_control_msg(gspca_dev->dev, + ret = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 1, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, len, 500); + if (ret < 0) + PDEBUG(D_ERR, "reg_w_buf(): " + "Failed to write registers to index 0x%x, error %i", + index, ret); } @@ -350,13 +356,19 @@ static void reg_w(struct gspca_dev *gspca_dev, __u8 index, __u8 value) { + int ret; + gspca_dev->usb_buf[0] = value; - usb_control_msg(gspca_dev->dev, + ret = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, gspca_dev->usb_buf, 1, 500); + if (ret < 0) + PDEBUG(D_ERR, "reg_w(): " + "Failed to write register to index 0x%x, value 0x%x, error %i", + index, value, ret); } static void reg_w_seq(struct gspca_dev *gspca_dev, @@ -373,17 +385,23 @@ static void reg_w_page(struct gspca_dev *gspca_dev, const __u8 *page, int len) { int index; + int ret; for (index = 0; index < len; index++) { if (page[index] == SKIP) /* skip this index */ continue; gspca_dev->usb_buf[0] = page[index]; - usb_control_msg(gspca_dev->dev, + ret = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, gspca_dev->usb_buf, 1, 500); + if (ret < 0) + PDEBUG(D_ERR, "reg_w_page(): " + "Failed to write register to index 0x%x, " + "value 0x%x, error %i", + index, page[index], ret); } } diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index a2f788468ec0..82cdd43aada9 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -263,14 +263,20 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, const char *buffer, int len) { + int ret; + memcpy(gspca_dev->usb_buf, buffer, len); - usb_control_msg(gspca_dev->dev, + ret = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 1, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, len, 500); + if (ret < 0) + PDEBUG(D_ERR, "reg_w_buf(): " + "Failed to write registers to index 0x%x, error %i", + index, ret); } @@ -278,13 +284,19 @@ static void reg_w(struct gspca_dev *gspca_dev, __u8 index, __u8 value) { + int ret; + gspca_dev->usb_buf[0] = value; - usb_control_msg(gspca_dev->dev, + ret = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, gspca_dev->usb_buf, 1, 500); + if (ret < 0) + PDEBUG(D_ERR, "reg_w(): " + "Failed to write register to index 0x%x, value 0x%x, error %i", + index, value, ret); } static void reg_w_seq(struct gspca_dev *gspca_dev, @@ -301,17 +313,23 @@ static void reg_w_page(struct gspca_dev *gspca_dev, const __u8 *page, int len) { int index; + int ret; for (index = 0; index < len; index++) { if (page[index] == SKIP) /* skip this index */ continue; gspca_dev->usb_buf[0] = page[index]; - usb_control_msg(gspca_dev->dev, + ret = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, gspca_dev->usb_buf, 1, 500); + if (ret < 0) + PDEBUG(D_ERR, "reg_w_page(): " + "Failed to write register to index 0x%x, " + "value 0x%x, error %i", + index, page[index], ret); } } From 8337fc3053f4189fb64d60495ed89df5befa2a6b Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Thu, 5 Nov 2009 05:40:46 -0300 Subject: [PATCH 191/345] V4L/DVB (13325): gspca - pac7302/pac7311: Fix buffer overrun. The reg_w_seq() function expects the sequence length in entries and not in bytes. One entry in init_7302 and init_7311 is two bytes and not one. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7302.c | 2 +- drivers/media/video/gspca/pac7311.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 60d1a31f5307..09d3d191d949 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -571,7 +571,7 @@ static void sethvflip(struct gspca_dev *gspca_dev) /* this function is called at probe and resume time for pac7302 */ static int sd_init(struct gspca_dev *gspca_dev) { - reg_w_seq(gspca_dev, init_7302, sizeof init_7302); + reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); return 0; } diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 82cdd43aada9..b1127d948974 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -469,7 +469,7 @@ static void sethvflip(struct gspca_dev *gspca_dev) /* this function is called at probe and resume time for pac7311 */ static int sd_init(struct gspca_dev *gspca_dev) { - reg_w_seq(gspca_dev, init_7311, sizeof init_7311); + reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); return 0; } From fc099f0e0e52a349a3fe92bfb8d3fb6ec5378174 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Nov 2009 14:51:01 -0300 Subject: [PATCH 192/345] V4L/DVB (13327): em28xx: fix alt modprobe parameter It seems that some patch broke alt modprobe parameter. Fix it to allow changing alternate interfaces during module load and at runtime. If changed during runtime, you'll need to stop a and restart stream for the parameter to be used. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 13 ++++++++++++- drivers/media/video/em28xx/em28xx.h | 3 --- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index a88257a7d94f..33586004eb44 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -50,7 +50,7 @@ MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __func__ , ##arg); } while (0) -static int alt = EM28XX_PINOUT; +static int alt; module_param(alt, int, 0644); MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); @@ -778,6 +778,16 @@ int em28xx_set_alternate(struct em28xx *dev) int i; unsigned int min_pkt_size = dev->width * 2 + 4; + /* + * alt = 0 is used only for control messages, so, only values + * greater than 0 can be used for streaming. + */ + if (alt && alt < dev->num_alt) { + em28xx_coredbg("alternate forced to %d\n", dev->alt); + dev->alt = alt; + goto set_alt; + } + /* When image size is bigger than a certain value, the frame size should be increased, otherwise, only green screen will be received. @@ -798,6 +808,7 @@ int em28xx_set_alternate(struct em28xx *dev) dev->alt = i; } +set_alt: if (dev->alt != prev_alt) { em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", min_pkt_size, dev->alt); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index a476f7bb7bf8..bca5cbb7931c 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -143,9 +143,6 @@ */ #define EM28XX_NUM_PACKETS 40 -/* default alternate; 0 means choose the best */ -#define EM28XX_PINOUT 0 - #define EM28XX_INTERLACED_DEFAULT 1 /* From f57b17c3956f2e1e70f63dd2ed8088b582f3915e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 12 Nov 2009 11:21:05 -0300 Subject: [PATCH 193/345] V4L/DVB (13328): em28xx: Add chip ID for em2800 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 3 +++ drivers/media/video/em28xx/em28xx-reg.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 1e1937070738..00bceb865a7c 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2532,6 +2532,9 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->chip_id = retval; switch (dev->chip_id) { + case CHIP_ID_EM2800: + em28xx_info("chip ID is em2800\n"); + break; case CHIP_ID_EM2710: em28xx_info("chip ID is em2710\n"); break; diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index ed12e7ffcbd0..058ac87639ce 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h @@ -192,6 +192,7 @@ /* FIXME: Need to be populated with the other chip ID's */ enum em28xx_chip_id { + CHIP_ID_EM2800 = 7, CHIP_ID_EM2710 = 17, CHIP_ID_EM2820 = 18, /* Also used by some em2710 */ CHIP_ID_EM2840 = 20, From af5c8e1523edf792f57ec938aef9423783af25e1 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 27 Oct 2009 23:33:21 -0300 Subject: [PATCH 194/345] V4L/DVB (13329): s5h1409: provide HVR-1600 specific optimizations Perform some optimization of the register configuration based on a trace of the HVR-1600 Windows i2c traffic (and consultation with Steven Toth). Note that some of these values may be able to be moved into the common driver, but I am holding off on that until they can be tested with other boards. This work was sponsored by ONELAN Limited. Cc: Steven Toth Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/s5h1409.c | 15 +++++++++++++++ drivers/media/dvb/frontends/s5h1409.h | 7 +++++++ drivers/media/video/cx18/cx18-dvb.c | 3 ++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index fb3011518427..85fba581c5ab 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -614,6 +614,21 @@ static int s5h1409_init(struct dvb_frontend *fe) /* The datasheet says that after initialisation, VSB is default */ state->current_modulation = VSB_8; + /* Optimize for the HVR-1600 if appropriate. Note that some of these + may get folded into the generic case after testing with other + devices */ + if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) { + /* VSB AGC REF */ + s5h1409_writereg(state, 0x09, 0x0050); + + /* Unknown but Windows driver does it... */ + s5h1409_writereg(state, 0x21, 0x0001); + s5h1409_writereg(state, 0x50, 0x030e); + + /* QAM AGC REF */ + s5h1409_writereg(state, 0x82, 0x0800); + } + if (state->config->output_mode == S5H1409_SERIAL_OUTPUT) s5h1409_writereg(state, 0xab, s5h1409_readreg(state, 0xab) | 0x100); /* Serial */ diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h index 070d9743e330..91f2ebd1a534 100644 --- a/drivers/media/dvb/frontends/s5h1409.h +++ b/drivers/media/dvb/frontends/s5h1409.h @@ -57,6 +57,13 @@ struct s5h1409_config { #define S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK 2 #define S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3 u16 mpeg_timing; + + /* HVR-1600 optimizations (to better work with MXL5005s) + Note: some of these are likely to be folded into the generic driver + after being regression tested with other boards */ +#define S5H1409_HVR1600_NOOPTIMIZE 0 +#define S5H1409_HVR1600_OPTIMIZE 1 + u8 hvr1600_opt; }; #if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \ diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 51a0c33b25b7..f402e798e323 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -71,7 +71,8 @@ static struct s5h1409_config hauppauge_hvr1600_config = { .qam_if = 44000, .inversion = S5H1409_INVERSION_OFF, .status_mode = S5H1409_DEMODLOCKING, - .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK + .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, + .hvr1600_opt = S5H1409_HVR1600_OPTIMIZE }; /* From f0cd44b4a1a7465230dfbe1e645d9dc73f83cb13 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 28 Oct 2009 01:26:05 -0300 Subject: [PATCH 195/345] V4L/DVB (13330): s5h1409: properly handle QAM optimization after lock achieved The sh51409 driver was only doing the QAM optimization a single time, and it would only occur if you received a lock instantaneously after the tuning request. Restructure the code so that the optimization occurs once you reach a signal lock. Note that this depends on the caller polling for status, but we don't have much choice at this point without an independent thread monitoring the lock status. Also, at this point pretty much every application polls for status lock after doing the tune, so the likelihood of the optimization not occurring in the real world is pretty low. The state machine has also been reworked such that setting the interleave mode is now a dependency of doing the QAM optimization. Before both were mutually exclusive, which was not consistent with the Windows driver. We now have a single state machine that controls both. The changes as-is are only enabled for the HVR-1600. Once the changes are tested with some of the other boards, this change should be made generic and the "_legacy" functions should be removed. This work was sponsored by ONELAN Limited. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/s5h1409.c | 136 ++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 85fba581c5ab..5507159a23b1 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -44,7 +44,15 @@ struct s5h1409_state { int if_freq; u32 is_qam_locked; - u32 qam_state; + + /* QAM tuning state goes through the following state transitions */ +#define QAM_STATE_UNTUNED 0 +#define QAM_STATE_TUNING_STARTED 1 +#define QAM_STATE_INTERLEAVE_SET 2 +#define QAM_STATE_QAM_OPTIMIZED_L1 3 +#define QAM_STATE_QAM_OPTIMIZED_L2 4 +#define QAM_STATE_QAM_OPTIMIZED_L3 5 + u8 qam_state; }; static int debug; @@ -347,7 +355,7 @@ static int s5h1409_softreset(struct dvb_frontend *fe) s5h1409_writereg(state, 0xf5, 0); s5h1409_writereg(state, 0xf5, 1); state->is_qam_locked = 0; - state->qam_state = 0; + state->qam_state = QAM_STATE_UNTUNED; return 0; } @@ -474,6 +482,59 @@ static void s5h1409_set_qam_amhum_mode(struct dvb_frontend *fe) struct s5h1409_state *state = fe->demodulator_priv; u16 reg; + if (state->qam_state < QAM_STATE_INTERLEAVE_SET) { + /* We should not perform amhum optimization until + the interleave mode has been configured */ + return; + } + + if (state->qam_state == QAM_STATE_QAM_OPTIMIZED_L3) { + /* We've already reached the maximum optimization level, so + dont bother banging on the status registers */ + return; + } + + /* QAM EQ lock check */ + reg = s5h1409_readreg(state, 0xf0); + + if ((reg >> 13) & 0x1) { + reg &= 0xff; + + s5h1409_writereg(state, 0x96, 0x000c); + if (reg < 0x68) { + if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L3) { + dprintk("%s() setting QAM state to OPT_L3\n", + __func__); + s5h1409_writereg(state, 0x93, 0x3130); + s5h1409_writereg(state, 0x9e, 0x2836); + state->qam_state = QAM_STATE_QAM_OPTIMIZED_L3; + } + } else { + if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L2) { + dprintk("%s() setting QAM state to OPT_L2\n", + __func__); + s5h1409_writereg(state, 0x93, 0x3332); + s5h1409_writereg(state, 0x9e, 0x2c37); + state->qam_state = QAM_STATE_QAM_OPTIMIZED_L2; + } + } + + } else { + if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L1) { + dprintk("%s() setting QAM state to OPT_L1\n", __func__); + s5h1409_writereg(state, 0x96, 0x0008); + s5h1409_writereg(state, 0x93, 0x3332); + s5h1409_writereg(state, 0x9e, 0x2c37); + state->qam_state = QAM_STATE_QAM_OPTIMIZED_L1; + } + } +} + +static void s5h1409_set_qam_amhum_mode_legacy(struct dvb_frontend *fe) +{ + struct s5h1409_state *state = fe->demodulator_priv; + u16 reg; + if (state->is_qam_locked) return; @@ -506,6 +567,46 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe) struct s5h1409_state *state = fe->demodulator_priv; u16 reg, reg1, reg2; + if (state->qam_state >= QAM_STATE_INTERLEAVE_SET) { + /* We've done the optimization already */ + return; + } + + reg = s5h1409_readreg(state, 0xf1); + + /* Master lock */ + if ((reg >> 15) & 0x1) { + if (state->qam_state == QAM_STATE_UNTUNED || + state->qam_state == QAM_STATE_TUNING_STARTED) { + dprintk("%s() setting QAM state to INTERLEAVE_SET\n", + __func__); + reg1 = s5h1409_readreg(state, 0xb2); + reg2 = s5h1409_readreg(state, 0xad); + + s5h1409_writereg(state, 0x96, 0x0020); + s5h1409_writereg(state, 0xad, + (((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff))); + s5h1409_writereg(state, 0xab, + s5h1409_readreg(state, 0xab) & 0xeffe); + state->qam_state = QAM_STATE_INTERLEAVE_SET; + } + } else { + if (state->qam_state == QAM_STATE_UNTUNED) { + dprintk("%s() setting QAM state to TUNING_STARTED\n", + __func__); + s5h1409_writereg(state, 0x96, 0x08); + s5h1409_writereg(state, 0xab, + s5h1409_readreg(state, 0xab) | 0x1001); + state->qam_state = QAM_STATE_TUNING_STARTED; + } + } +} + +static void s5h1409_set_qam_interleave_mode_legacy(struct dvb_frontend *fe) +{ + struct s5h1409_state *state = fe->demodulator_priv; + u16 reg, reg1, reg2; + reg = s5h1409_readreg(state, 0xf1); /* Master lock */ @@ -553,16 +654,24 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, fe->ops.i2c_gate_ctrl(fe, 0); } - /* Optimize the demod for QAM */ - if (p->u.vsb.modulation != VSB_8) { - s5h1409_set_qam_amhum_mode(fe); - s5h1409_set_qam_interleave_mode(fe); - } - /* Issue a reset to the demod so it knows to resync against the newly tuned frequency */ s5h1409_softreset(fe); + /* Optimize the demod for QAM */ + if (state->current_modulation != VSB_8) { + /* This almost certainly applies to all boards, but for now + only do it for the HVR-1600. Once the other boards are + tested, the "legacy" versions can just go away */ + if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) { + s5h1409_set_qam_amhum_mode(fe); + s5h1409_set_qam_interleave_mode(fe); + } else { + s5h1409_set_qam_amhum_mode_legacy(fe); + s5h1409_set_qam_interleave_mode_legacy(fe); + } + } + return 0; } @@ -656,6 +765,17 @@ static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status) *status = 0; + /* Optimize the demod for QAM */ + if (state->current_modulation != VSB_8) { + /* This almost certainly applies to all boards, but for now + only do it for the HVR-1600. Once the other boards are + tested, the "legacy" versions can just go away */ + if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) { + s5h1409_set_qam_amhum_mode(fe); + s5h1409_set_qam_interleave_mode(fe); + } + } + /* Get the demodulator status */ reg = s5h1409_readreg(state, 0xf1); if (reg & 0x1000) From 48c511ed675772bd08044d97756f7f7aae5168eb Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 28 Oct 2009 23:10:16 -0300 Subject: [PATCH 196/345] V4L/DVB (13331): mxl5005s: provide ability to override QAM gain for HVR-1600 The HVR-1600 doesn't use the standard mechanism for computing the gain when in QAM mode, instead always forcing it to be 0x02. Provide the ability to override the algorithm on a per-board basis. This change results in an improvement of 0.4-0.6 dB for QAM tuning. This work was sponsored by ONELAN Limited. Cc: Steven Toth Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 5 ++++- drivers/media/common/tuners/mxl5005s.h | 4 ++++ drivers/media/video/cx18/cx18-dvb.c | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 0803dab58fff..605e28b73263 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -2789,7 +2789,10 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) /* add for 2.6.5 Special setting for QAM */ if (state->Mod_Type == MXL_QAM) { - if (state->RF_IN < 680000000) + if (state->config->qam_gain != 0) + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, + state->config->qam_gain); + else if (state->RF_IN < 680000000) status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3); else status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2); diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 7ac6815b30aa..fc8a1ffc53b4 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -108,6 +108,10 @@ struct mxl5005s_config { #define MXL_LOW_IF 1 u8 if_mode; + /* Some boards need to override the built-in logic for determining + the gain when in QAM mode (the HVR-1600 is one such case) */ + u8 qam_gain; + /* Stuff I don't know what to do with */ u8 AgcMasterByte; }; diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index f402e798e323..54a6fd3f7af5 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -61,6 +61,7 @@ static struct mxl5005s_config hauppauge_hvr1600_tuner = { .top = MXL5005S_TOP_25P2, .mod_mode = MXL_DIGITAL_MODE, .if_mode = MXL_ZERO_IF, + .qam_gain = 0x02, .AgcMasterByte = 0x00, }; From adcd8de6de36f67241a5c3562f2ef1d5998b30a9 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 2 Nov 2009 01:30:40 -0300 Subject: [PATCH 197/345] V4L/DVB (13332): s5h1409: remove a set register that would cause lock to be lost. On particularly weak signals, changing register 0xab after setting the interleave mode will cause the FEC lock to get lost (while still holding the EQ lock). So remove the write entirely, which seems to have had no adverse effect in either of my ClearQAM environments (and in particular resolves the customer's reported issue). Also flip around the order of the amhum optimization and the interleave setup to be consistent with the windows driver, which has the side-benefit of doing them both in the same call (since the amhum optimization can only be done once the interleave setup). This work was sponsored by ONELAN Limited. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/s5h1409.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 5507159a23b1..0e2f61a8978f 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -586,8 +586,6 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe) s5h1409_writereg(state, 0x96, 0x0020); s5h1409_writereg(state, 0xad, (((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff))); - s5h1409_writereg(state, 0xab, - s5h1409_readreg(state, 0xab) & 0xeffe); state->qam_state = QAM_STATE_INTERLEAVE_SET; } } else { @@ -664,8 +662,8 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, only do it for the HVR-1600. Once the other boards are tested, the "legacy" versions can just go away */ if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) { - s5h1409_set_qam_amhum_mode(fe); s5h1409_set_qam_interleave_mode(fe); + s5h1409_set_qam_amhum_mode(fe); } else { s5h1409_set_qam_amhum_mode_legacy(fe); s5h1409_set_qam_interleave_mode_legacy(fe); @@ -771,8 +769,8 @@ static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status) only do it for the HVR-1600. Once the other boards are tested, the "legacy" versions can just go away */ if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) { - s5h1409_set_qam_amhum_mode(fe); s5h1409_set_qam_interleave_mode(fe); + s5h1409_set_qam_amhum_mode(fe); } } From 873688cd30294412e185ba39f8487e3eed0f692d Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Sat, 17 Oct 2009 08:23:00 -0300 Subject: [PATCH 198/345] V4L/DVB (13334): stv6110: add configurable gain It has positive effect for NetUP Dual DVB-S2 CI card. Signed-off-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv6110.c | 13 ++++--------- drivers/media/dvb/frontends/stv6110.h | 1 + drivers/media/video/cx23885/cx23885-dvb.c | 2 ++ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb/frontends/stv6110.c b/drivers/media/dvb/frontends/stv6110.c index dcf1b21ea974..bef0cc838471 100644 --- a/drivers/media/dvb/frontends/stv6110.c +++ b/drivers/media/dvb/frontends/stv6110.c @@ -37,6 +37,7 @@ struct stv6110_priv { u32 mclk; u8 clk_div; + u8 gain; u8 regs[8]; }; @@ -255,7 +256,7 @@ static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency) u8 ret = 0x04; u32 divider, ref, p, presc, i, result_freq, vco_freq; s32 p_calc, p_calc_opt = 1000, r_div, r_div_opt = 0, p_val; - s32 srate; u8 gain; + s32 srate; dprintk("%s, freq=%d kHz, mclk=%d Hz\n", __func__, frequency, priv->mclk); @@ -273,15 +274,8 @@ static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency) } else srate = 15000000; - if (srate >= 15000000) - gain = 3; /* +6 dB */ - else if (srate >= 5000000) - gain = 3; /* +6 dB */ - else - gain = 3; /* +6 dB */ - priv->regs[RSTV6110_CTRL2] &= ~0x0f; - priv->regs[RSTV6110_CTRL2] |= (gain & 0x0f); + priv->regs[RSTV6110_CTRL2] |= (priv->gain & 0x0f); if (frequency <= 1023000) { p = 1; @@ -436,6 +430,7 @@ struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe, priv->i2c = i2c; priv->mclk = config->mclk; priv->clk_div = config->clk_div; + priv->gain = config->gain; memcpy(&priv->regs, ®0[1], 8); diff --git a/drivers/media/dvb/frontends/stv6110.h b/drivers/media/dvb/frontends/stv6110.h index 9db2402410f6..fe71bba6a26e 100644 --- a/drivers/media/dvb/frontends/stv6110.h +++ b/drivers/media/dvb/frontends/stv6110.h @@ -41,6 +41,7 @@ struct stv6110_config { u8 i2c_address; u32 mclk; + u8 gain; u8 clk_div; /* divisor value for the output clock */ }; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index f4f046cd81a5..0180b75d1f3d 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -414,12 +414,14 @@ static struct stv6110_config netup_stv6110_tunerconfig_a = { .i2c_address = 0x60, .mclk = 16000000, .clk_div = 1, + .gain = 8, /* +16 dB - maximum gain */ }; static struct stv6110_config netup_stv6110_tunerconfig_b = { .i2c_address = 0x63, .mclk = 16000000, .clk_div = 1, + .gain = 8, /* +16 dB - maximum gain */ }; static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) From 9329fb5b731cd535a7c7d0690d30e872f29a33d3 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Sat, 17 Oct 2009 08:38:45 -0300 Subject: [PATCH 199/345] V4L/DVB (13335): stv0900: fix diseqc support for NetUP card Signed-off-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_core.c | 31 ++++++++++++++-------- drivers/media/video/cx23885/cx23885-dvb.c | 8 +++--- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 768a1611e8ce..4729be7fdf7b 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -1771,7 +1771,6 @@ static int stv0900_diseqc_send(struct stv0900_internal *i_params , u8 *Data, msleep(10); i++; } - break; } @@ -1795,19 +1794,20 @@ static int stv0900_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) struct stv0900_internal *i_params = state->internal; enum fe_stv0900_demod_num demod = state->demod; s32 mode_field; - u32 diseqc_fifo; + u8 data; dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); - dmd_reg(diseqc_fifo, R0900_P1_DISTXDATA, R0900_P2_DISTXDATA); switch (burst) { case SEC_MINI_A: stv0900_write_bits(i_params, mode_field, 3);/* Unmodulated */ - stv0900_write_reg(i_params, diseqc_fifo, 0x00); + data = 0x00; + stv0900_diseqc_send(state->internal, &data, 1, state->demod); break; case SEC_MINI_B: stv0900_write_bits(i_params, mode_field, 2);/* Modulated */ - stv0900_write_reg(i_params, diseqc_fifo, 0xff); + data = 0xff; + stv0900_diseqc_send(state->internal, &data, 1, state->demod); break; } @@ -1858,28 +1858,37 @@ static int stv0900_recv_slave_reply(struct dvb_frontend *fe, return 0; } -static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t toneoff) { struct stv0900_state *state = fe->demodulator_priv; struct stv0900_internal *i_params = state->internal; enum fe_stv0900_demod_num demod = state->demod; s32 mode_field, reset_field; - dprintk("%s: %s\n", __func__, ((tone == 0) ? "Off" : "On")); + dprintk("%s: %s\n", __func__, ((toneoff == 0) ? "On" : "Off")); dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); dmd_reg(reset_field, F0900_P1_DISEQC_RESET, F0900_P2_DISEQC_RESET); - if (tone) { - /*Set the DiseqC mode to 22Khz continues tone*/ + switch (toneoff) { + case SEC_TONE_ON: + /*Set the DiseqC mode to 22Khz _continues_ tone*/ stv0900_write_bits(i_params, mode_field, 0); stv0900_write_bits(i_params, reset_field, 1); /*release DiseqC reset to enable the 22KHz tone*/ stv0900_write_bits(i_params, reset_field, 0); - } else { - stv0900_write_bits(i_params, mode_field, 0); + break; + case SEC_TONE_OFF: + /*return diseqc mode to config->diseqc_mode. + Usually it's without _continues_ tone */ + stv0900_write_bits(i_params, mode_field, + state->config->diseqc_mode); /*maintain the DiseqC reset to disable the 22KHz tone*/ stv0900_write_bits(i_params, reset_field, 1); + stv0900_write_bits(i_params, reset_field, 0); + break; + default: + return -EINVAL; } return 0; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 0180b75d1f3d..305f4710b5eb 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -839,8 +839,8 @@ static int dvb_register(struct cx23885_tsport *port) if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, - LNBH24_PCL, - LNBH24_TTX, 0x09)) + LNBH24_PCL | LNBH24_TTX, + LNBH24_TEN, 0x09)) printk(KERN_ERR "No LNBH24 found!\n"); @@ -860,8 +860,8 @@ static int dvb_register(struct cx23885_tsport *port) if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, - LNBH24_PCL, - LNBH24_TTX, 0x0a)) + LNBH24_PCL | LNBH24_TTX, + LNBH24_TEN, 0x0a)) printk(KERN_ERR "No LNBH24 found!\n"); From 29372a8daec4c1dca83e294006488b1d47dd965c Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 17 Oct 2009 08:58:26 -0300 Subject: [PATCH 200/345] V4L/DVB (13336): stv0900: config definition for single/dual mode Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900.h | 1 + drivers/media/dvb/frontends/stv0900_core.c | 4 ++-- drivers/media/video/cx23885/cx23885-dvb.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h index bf4e9b633044..446bdfc8ad10 100644 --- a/drivers/media/dvb/frontends/stv0900.h +++ b/drivers/media/dvb/frontends/stv0900.h @@ -36,6 +36,7 @@ struct stv0900_reg { struct stv0900_config { u8 demod_address; + u8 demod_mode; u32 xtal; u8 clkmode;/* 0 for CLKI, 2 for XTALI */ diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 4729be7fdf7b..c8c72f56fdd9 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -1400,7 +1400,7 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, dprintk("%s\n", __func__); - if (temp_int != NULL) { + if ((temp_int != NULL) && (p_init->demod_mode == STV0900_DUAL)) { state->internal = temp_int->internal; (state->internal->dmds_used)++; dprintk("%s: Find Internal Structure!\n", __func__); @@ -1972,7 +1972,7 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, case 0: case 1: init_params.dmd_ref_clk = config->xtal; - init_params.demod_mode = STV0900_DUAL; + init_params.demod_mode = config->demod_mode; init_params.rolloff = STV0900_35; init_params.path1_ts_clock = config->path1_mode; init_params.tun1_maddress = config->tun1_maddress; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 305f4710b5eb..44e5fade0488 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -400,6 +400,7 @@ static struct stv0900_reg stv0900_ts_regs[] = { static struct stv0900_config netup_stv0900_config = { .demod_address = 0x68, + .demod_mode = 1, /* dual */ .xtal = 8000000, .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ .diseqc_mode = 2,/* 2/3 PWM */ From 502cd96d5b0714e0ab022766014f58b0684699a8 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 27 Oct 2009 14:59:53 -0300 Subject: [PATCH 201/345] V4L/DVB (13337): Change str snr scale for stv0900/903 and Netup Dual DVB-S2 card. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_core.c | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index c8c72f56fdd9..11dbe942aa41 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -599,6 +599,8 @@ static s32 stv0900_get_rf_level(struct stv0900_internal *i_params, break; } + dprintk("%s: AGC Gain = 0x%x\n", __func__, agc_gain); + imin = 0; imax = lookup->size - 1; if (INRANGE(lookup->table[imin].regval, agc_gain, lookup->table[imax].regval)) { @@ -634,7 +636,14 @@ static int stv0900_read_signal_strength(struct dvb_frontend *fe, u16 *strength) s32 rflevel = stv0900_get_rf_level(internal, &stv0900_rf, state->demod); - *strength = (rflevel + 100) * (16383 / 105); + rflevel = (rflevel + 100) * (65535 / 70); + if (rflevel < 0) + rflevel = 0; + + if (rflevel > 65535) + rflevel = 65535; + + *strength = rflevel; return 0; } @@ -709,6 +718,8 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, } } + dprintk("%s: Quality = %d\n", __func__, c_n); + return c_n; } @@ -752,10 +763,16 @@ static int stv0900_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr) { - *snr = stv0900_carr_get_quality(fe, + s32 snrlcl = stv0900_carr_get_quality(fe, (const struct stv0900_table *)&stv0900_s2_cn); - *snr += 30; - *snr *= (16383 / 1030); + snrlcl = (snrlcl + 30) * 384; + if (snrlcl < 0) + snrlcl = 0; + + if (snrlcl > 65535) + snrlcl = 65535; + + *snr = snrlcl; return 0; } From 46960eea9c0f7abb3a0a65276939762b97eac337 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 6 Nov 2009 23:07:56 -0300 Subject: [PATCH 202/345] V4L/DVB (13338): stv0900: big rework to support cut 3.0. Patch 1 of 4. Also patch changes logic to prevent code repetitions and big indents. It makes checkpatch silent :) Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_init.h | 257 ++++++++++++++++----- drivers/media/dvb/frontends/stv0900_priv.h | 81 ++----- 2 files changed, 224 insertions(+), 114 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0900_init.h b/drivers/media/dvb/frontends/stv0900_init.h index ff388b47a4e3..b684df9995d8 100644 --- a/drivers/media/dvb/frontends/stv0900_init.h +++ b/drivers/media/dvb/frontends/stv0900_init.h @@ -141,85 +141,228 @@ struct stv0900_short_frames_car_loop_optim { }; +struct stv0900_short_frames_car_loop_optim_vs_mod { + enum fe_stv0900_modulation modulation; + u8 car_loop_2; /* SR<3msps */ + u8 car_loop_5; /* 3 Date: Fri, 6 Nov 2009 23:23:29 -0300 Subject: [PATCH 203/345] V4L/DVB (13339): stv0900: big rework to support cut 3.0. Patch 2 of 4. Also patch changes logic to prevent code repetitions and big indents. It makes checkpatch silent :) Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_reg.h | 4988 +++++++++++---------- 1 file changed, 2588 insertions(+), 2400 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0900_reg.h b/drivers/media/dvb/frontends/stv0900_reg.h index 264f9cf9a17e..7b8edf192e97 100644 --- a/drivers/media/dvb/frontends/stv0900_reg.h +++ b/drivers/media/dvb/frontends/stv0900_reg.h @@ -14,7 +14,7 @@ * * 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 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * @@ -26,3762 +26,3950 @@ #ifndef STV0900_REG_H #define STV0900_REG_H +extern s32 shiftx(s32 x, int demod, s32 shift); + +#define REGx(x) shiftx(x, demod, 0x200) +#define FLDx(x) shiftx(x, demod, 0x2000000) + /*MID*/ -#define R0900_MID 0xf100 -#define F0900_MCHIP_IDENT 0xf10000f0 -#define F0900_MRELEASE 0xf100000f +#define R0900_MID 0xf100 +#define F0900_MCHIP_IDENT 0xf10000f0 +#define F0900_MRELEASE 0xf100000f /*DACR1*/ -#define R0900_DACR1 0xf113 -#define F0900_DAC_MODE 0xf11300e0 -#define F0900_DAC_VALUE1 0xf113000f +#define R0900_DACR1 0xf113 +#define F0900_DAC_MODE 0xf11300e0 +#define F0900_DAC_VALUE1 0xf113000f /*DACR2*/ -#define R0900_DACR2 0xf114 -#define F0900_DAC_VALUE0 0xf11400ff +#define R0900_DACR2 0xf114 +#define F0900_DAC_VALUE0 0xf11400ff /*OUTCFG*/ -#define R0900_OUTCFG 0xf11c -#define F0900_INV_DATA6 0xf11c0080 -#define F0900_OUTSERRS1_HZ 0xf11c0040 -#define F0900_OUTSERRS2_HZ 0xf11c0020 -#define F0900_OUTSERRS3_HZ 0xf11c0010 -#define F0900_OUTPARRS3_HZ 0xf11c0008 -#define F0900_OUTHZ3_CONTROL 0xf11c0007 - -/*MODECFG*/ -#define R0900_MODECFG 0xf11d -#define F0900_FECSPY_SEL_2 0xf11d0020 -#define F0900_HWARE_SEL_2 0xf11d0010 -#define F0900_PKTDEL_SEL_2 0xf11d0008 -#define F0900_DISEQC_SEL_2 0xf11d0004 -#define F0900_VIT_SEL_2 0xf11d0002 -#define F0900_DEMOD_SEL_2 0xf11d0001 +#define R0900_OUTCFG 0xf11c +#define F0900_OUTSERRS1_HZ 0xf11c0040 +#define F0900_OUTSERRS2_HZ 0xf11c0020 +#define F0900_OUTSERRS3_HZ 0xf11c0010 +#define F0900_OUTPARRS3_HZ 0xf11c0008 /*IRQSTATUS3*/ -#define R0900_IRQSTATUS3 0xf120 -#define F0900_SPLL_LOCK 0xf1200020 -#define F0900_SSTREAM_LCK_3 0xf1200010 -#define F0900_SSTREAM_LCK_2 0xf1200008 -#define F0900_SSTREAM_LCK_1 0xf1200004 -#define F0900_SDVBS1_PRF_2 0xf1200002 -#define F0900_SDVBS1_PRF_1 0xf1200001 +#define R0900_IRQSTATUS3 0xf120 +#define F0900_SPLL_LOCK 0xf1200020 +#define F0900_SSTREAM_LCK_3 0xf1200010 +#define F0900_SSTREAM_LCK_2 0xf1200008 +#define F0900_SSTREAM_LCK_1 0xf1200004 +#define F0900_SDVBS1_PRF_2 0xf1200002 +#define F0900_SDVBS1_PRF_1 0xf1200001 /*IRQSTATUS2*/ -#define R0900_IRQSTATUS2 0xf121 -#define F0900_SSPY_ENDSIM_3 0xf1210080 -#define F0900_SSPY_ENDSIM_2 0xf1210040 -#define F0900_SSPY_ENDSIM_1 0xf1210020 -#define F0900_SPKTDEL_ERROR_2 0xf1210010 -#define F0900_SPKTDEL_LOCKB_2 0xf1210008 -#define F0900_SPKTDEL_LOCK_2 0xf1210004 -#define F0900_SPKTDEL_ERROR_1 0xf1210002 -#define F0900_SPKTDEL_LOCKB_1 0xf1210001 +#define R0900_IRQSTATUS2 0xf121 +#define F0900_SSPY_ENDSIM_3 0xf1210080 +#define F0900_SSPY_ENDSIM_2 0xf1210040 +#define F0900_SSPY_ENDSIM_1 0xf1210020 +#define F0900_SPKTDEL_ERROR_2 0xf1210010 +#define F0900_SPKTDEL_LOCKB_2 0xf1210008 +#define F0900_SPKTDEL_LOCK_2 0xf1210004 +#define F0900_SPKTDEL_ERROR_1 0xf1210002 +#define F0900_SPKTDEL_LOCKB_1 0xf1210001 /*IRQSTATUS1*/ -#define R0900_IRQSTATUS1 0xf122 -#define F0900_SPKTDEL_LOCK_1 0xf1220080 -#define F0900_SEXTPINB2 0xf1220040 -#define F0900_SEXTPIN2 0xf1220020 -#define F0900_SEXTPINB1 0xf1220010 -#define F0900_SEXTPIN1 0xf1220008 -#define F0900_SDEMOD_LOCKB_2 0xf1220004 -#define F0900_SDEMOD_LOCK_2 0xf1220002 -#define F0900_SDEMOD_IRQ_2 0xf1220001 +#define R0900_IRQSTATUS1 0xf122 +#define F0900_SPKTDEL_LOCK_1 0xf1220080 +#define F0900_SDEMOD_LOCKB_2 0xf1220004 +#define F0900_SDEMOD_LOCK_2 0xf1220002 +#define F0900_SDEMOD_IRQ_2 0xf1220001 /*IRQSTATUS0*/ -#define R0900_IRQSTATUS0 0xf123 -#define F0900_SDEMOD_LOCKB_1 0xf1230080 -#define F0900_SDEMOD_LOCK_1 0xf1230040 -#define F0900_SDEMOD_IRQ_1 0xf1230020 -#define F0900_SBCH_ERRFLAG 0xf1230010 -#define F0900_SDISEQC2RX_IRQ 0xf1230008 -#define F0900_SDISEQC2TX_IRQ 0xf1230004 -#define F0900_SDISEQC1RX_IRQ 0xf1230002 -#define F0900_SDISEQC1TX_IRQ 0xf1230001 +#define R0900_IRQSTATUS0 0xf123 +#define F0900_SDEMOD_LOCKB_1 0xf1230080 +#define F0900_SDEMOD_LOCK_1 0xf1230040 +#define F0900_SDEMOD_IRQ_1 0xf1230020 +#define F0900_SBCH_ERRFLAG 0xf1230010 +#define F0900_SDISEQC2RX_IRQ 0xf1230008 +#define F0900_SDISEQC2TX_IRQ 0xf1230004 +#define F0900_SDISEQC1RX_IRQ 0xf1230002 +#define F0900_SDISEQC1TX_IRQ 0xf1230001 /*IRQMASK3*/ -#define R0900_IRQMASK3 0xf124 -#define F0900_MPLL_LOCK 0xf1240020 -#define F0900_MSTREAM_LCK_3 0xf1240010 -#define F0900_MSTREAM_LCK_2 0xf1240008 -#define F0900_MSTREAM_LCK_1 0xf1240004 -#define F0900_MDVBS1_PRF_2 0xf1240002 -#define F0900_MDVBS1_PRF_1 0xf1240001 +#define R0900_IRQMASK3 0xf124 +#define F0900_MPLL_LOCK 0xf1240020 +#define F0900_MSTREAM_LCK_3 0xf1240010 +#define F0900_MSTREAM_LCK_2 0xf1240008 +#define F0900_MSTREAM_LCK_1 0xf1240004 +#define F0900_MDVBS1_PRF_2 0xf1240002 +#define F0900_MDVBS1_PRF_1 0xf1240001 /*IRQMASK2*/ -#define R0900_IRQMASK2 0xf125 -#define F0900_MSPY_ENDSIM_3 0xf1250080 -#define F0900_MSPY_ENDSIM_2 0xf1250040 -#define F0900_MSPY_ENDSIM_1 0xf1250020 -#define F0900_MPKTDEL_ERROR_2 0xf1250010 -#define F0900_MPKTDEL_LOCKB_2 0xf1250008 -#define F0900_MPKTDEL_LOCK_2 0xf1250004 -#define F0900_MPKTDEL_ERROR_1 0xf1250002 -#define F0900_MPKTDEL_LOCKB_1 0xf1250001 +#define R0900_IRQMASK2 0xf125 +#define F0900_MSPY_ENDSIM_3 0xf1250080 +#define F0900_MSPY_ENDSIM_2 0xf1250040 +#define F0900_MSPY_ENDSIM_1 0xf1250020 +#define F0900_MPKTDEL_ERROR_2 0xf1250010 +#define F0900_MPKTDEL_LOCKB_2 0xf1250008 +#define F0900_MPKTDEL_LOCK_2 0xf1250004 +#define F0900_MPKTDEL_ERROR_1 0xf1250002 +#define F0900_MPKTDEL_LOCKB_1 0xf1250001 /*IRQMASK1*/ -#define R0900_IRQMASK1 0xf126 -#define F0900_MPKTDEL_LOCK_1 0xf1260080 -#define F0900_MEXTPINB2 0xf1260040 -#define F0900_MEXTPIN2 0xf1260020 -#define F0900_MEXTPINB1 0xf1260010 -#define F0900_MEXTPIN1 0xf1260008 -#define F0900_MDEMOD_LOCKB_2 0xf1260004 -#define F0900_MDEMOD_LOCK_2 0xf1260002 -#define F0900_MDEMOD_IRQ_2 0xf1260001 +#define R0900_IRQMASK1 0xf126 +#define F0900_MPKTDEL_LOCK_1 0xf1260080 +#define F0900_MEXTPINB2 0xf1260040 +#define F0900_MEXTPIN2 0xf1260020 +#define F0900_MEXTPINB1 0xf1260010 +#define F0900_MEXTPIN1 0xf1260008 +#define F0900_MDEMOD_LOCKB_2 0xf1260004 +#define F0900_MDEMOD_LOCK_2 0xf1260002 +#define F0900_MDEMOD_IRQ_2 0xf1260001 /*IRQMASK0*/ -#define R0900_IRQMASK0 0xf127 -#define F0900_MDEMOD_LOCKB_1 0xf1270080 -#define F0900_MDEMOD_LOCK_1 0xf1270040 -#define F0900_MDEMOD_IRQ_1 0xf1270020 -#define F0900_MBCH_ERRFLAG 0xf1270010 -#define F0900_MDISEQC2RX_IRQ 0xf1270008 -#define F0900_MDISEQC2TX_IRQ 0xf1270004 -#define F0900_MDISEQC1RX_IRQ 0xf1270002 -#define F0900_MDISEQC1TX_IRQ 0xf1270001 +#define R0900_IRQMASK0 0xf127 +#define F0900_MDEMOD_LOCKB_1 0xf1270080 +#define F0900_MDEMOD_LOCK_1 0xf1270040 +#define F0900_MDEMOD_IRQ_1 0xf1270020 +#define F0900_MBCH_ERRFLAG 0xf1270010 +#define F0900_MDISEQC2RX_IRQ 0xf1270008 +#define F0900_MDISEQC2TX_IRQ 0xf1270004 +#define F0900_MDISEQC1RX_IRQ 0xf1270002 +#define F0900_MDISEQC1TX_IRQ 0xf1270001 /*I2CCFG*/ -#define R0900_I2CCFG 0xf129 -#define F0900_I2C2_FASTMODE 0xf1290080 -#define F0900_STATUS_WR2 0xf1290040 -#define F0900_I2C2ADDR_INC 0xf1290030 -#define F0900_I2C_FASTMODE 0xf1290008 -#define F0900_STATUS_WR 0xf1290004 -#define F0900_I2CADDR_INC 0xf1290003 +#define R0900_I2CCFG 0xf129 +#define F0900_I2C_FASTMODE 0xf1290008 +#define F0900_I2CADDR_INC 0xf1290003 /*P1_I2CRPT*/ -#define R0900_P1_I2CRPT 0xf12a -#define F0900_P1_I2CT_ON 0xf12a0080 -#define F0900_P1_ENARPT_LEVEL 0xf12a0070 -#define F0900_P1_SCLT_DELAY 0xf12a0008 -#define F0900_P1_STOP_ENABLE 0xf12a0004 -#define F0900_P1_STOP_SDAT2SDA 0xf12a0002 +#define R0900_P1_I2CRPT 0xf12a +#define I2CRPT shiftx(R0900_P1_I2CRPT, demod, -1) +#define F0900_P1_I2CT_ON 0xf12a0080 +#define I2CT_ON shiftx(F0900_P1_I2CT_ON, demod, -0x10000) +#define F0900_P1_ENARPT_LEVEL 0xf12a0070 +#define F0900_P1_SCLT_DELAY 0xf12a0008 +#define F0900_P1_STOP_ENABLE 0xf12a0004 +#define F0900_P1_STOP_SDAT2SDA 0xf12a0002 /*P2_I2CRPT*/ -#define R0900_P2_I2CRPT 0xf12b -#define F0900_P2_I2CT_ON 0xf12b0080 -#define F0900_P2_ENARPT_LEVEL 0xf12b0070 -#define F0900_P2_SCLT_DELAY 0xf12b0008 -#define F0900_P2_STOP_ENABLE 0xf12b0004 -#define F0900_P2_STOP_SDAT2SDA 0xf12b0002 +#define R0900_P2_I2CRPT 0xf12b +#define F0900_P2_I2CT_ON 0xf12b0080 +#define F0900_P2_ENARPT_LEVEL 0xf12b0070 +#define F0900_P2_SCLT_DELAY 0xf12b0008 +#define F0900_P2_STOP_ENABLE 0xf12b0004 +#define F0900_P2_STOP_SDAT2SDA 0xf12b0002 + +/*IOPVALUE6*/ +#define R0900_IOPVALUE6 0xf138 +#define F0900_VSCL 0xf1380004 +#define F0900_VSDA 0xf1380002 +#define F0900_VDATA3_0 0xf1380001 + +/*IOPVALUE5*/ +#define R0900_IOPVALUE5 0xf139 +#define F0900_VDATA3_1 0xf1390080 +#define F0900_VDATA3_2 0xf1390040 +#define F0900_VDATA3_3 0xf1390020 +#define F0900_VDATA3_4 0xf1390010 +#define F0900_VDATA3_5 0xf1390008 +#define F0900_VDATA3_6 0xf1390004 +#define F0900_VDATA3_7 0xf1390002 +#define F0900_VCLKOUT3 0xf1390001 + +/*IOPVALUE4*/ +#define R0900_IOPVALUE4 0xf13a +#define F0900_VSTROUT3 0xf13a0080 +#define F0900_VDPN3 0xf13a0040 +#define F0900_VERROR3 0xf13a0020 +#define F0900_VDATA2_7 0xf13a0010 +#define F0900_VCLKOUT2 0xf13a0008 +#define F0900_VSTROUT2 0xf13a0004 +#define F0900_VDPN2 0xf13a0002 +#define F0900_VERROR2 0xf13a0001 + +/*IOPVALUE3*/ +#define R0900_IOPVALUE3 0xf13b +#define F0900_VDATA1_7 0xf13b0080 +#define F0900_VCLKOUT1 0xf13b0040 +#define F0900_VSTROUT1 0xf13b0020 +#define F0900_VDPN1 0xf13b0010 +#define F0900_VERROR1 0xf13b0008 +#define F0900_VCLKOUT27 0xf13b0004 +#define F0900_VDISEQCOUT2 0xf13b0002 +#define F0900_VSCLT2 0xf13b0001 + +/*IOPVALUE2*/ +#define R0900_IOPVALUE2 0xf13c +#define F0900_VSDAT2 0xf13c0080 +#define F0900_VAGCRF2 0xf13c0040 +#define F0900_VDISEQCOUT1 0xf13c0020 +#define F0900_VSCLT1 0xf13c0010 +#define F0900_VSDAT1 0xf13c0008 +#define F0900_VAGCRF1 0xf13c0004 +#define F0900_VDIRCLK 0xf13c0002 +#define F0900_VSTDBY 0xf13c0001 + +/*IOPVALUE1*/ +#define R0900_IOPVALUE1 0xf13d +#define F0900_VCS1 0xf13d0080 +#define F0900_VCS0 0xf13d0040 +#define F0900_VGPIO13 0xf13d0020 +#define F0900_VGPIO12 0xf13d0010 +#define F0900_VGPIO11 0xf13d0008 +#define F0900_VGPIO10 0xf13d0004 +#define F0900_VGPIO9 0xf13d0002 +#define F0900_VGPIO8 0xf13d0001 + +/*IOPVALUE0*/ +#define R0900_IOPVALUE0 0xf13e +#define F0900_VGPIO7 0xf13e0080 +#define F0900_VGPIO6 0xf13e0040 +#define F0900_VGPIO5 0xf13e0020 +#define F0900_VGPIO4 0xf13e0010 +#define F0900_VGPIO3 0xf13e0008 +#define F0900_VGPIO2 0xf13e0004 +#define F0900_VGPIO1 0xf13e0002 +#define F0900_VCLKI2 0xf13e0001 /*CLKI2CFG*/ -#define R0900_CLKI2CFG 0xf140 -#define F0900_CLKI2_OPD 0xf1400080 -#define F0900_CLKI2_CONFIG 0xf140007e -#define F0900_CLKI2_XOR 0xf1400001 +#define R0900_CLKI2CFG 0xf140 +#define F0900_CLKI2_OPD 0xf1400080 +#define F0900_CLKI2_CONFIG 0xf140007e +#define F0900_CLKI2_XOR 0xf1400001 /*GPIO1CFG*/ -#define R0900_GPIO1CFG 0xf141 -#define F0900_GPIO1_OPD 0xf1410080 -#define F0900_GPIO1_CONFIG 0xf141007e -#define F0900_GPIO1_XOR 0xf1410001 +#define R0900_GPIO1CFG 0xf141 +#define F0900_GPIO1_OPD 0xf1410080 +#define F0900_GPIO1_CONFIG 0xf141007e +#define F0900_GPIO1_XOR 0xf1410001 /*GPIO2CFG*/ -#define R0900_GPIO2CFG 0xf142 -#define F0900_GPIO2_OPD 0xf1420080 -#define F0900_GPIO2_CONFIG 0xf142007e -#define F0900_GPIO2_XOR 0xf1420001 +#define R0900_GPIO2CFG 0xf142 +#define F0900_GPIO2_OPD 0xf1420080 +#define F0900_GPIO2_CONFIG 0xf142007e +#define F0900_GPIO2_XOR 0xf1420001 /*GPIO3CFG*/ -#define R0900_GPIO3CFG 0xf143 -#define F0900_GPIO3_OPD 0xf1430080 -#define F0900_GPIO3_CONFIG 0xf143007e -#define F0900_GPIO3_XOR 0xf1430001 +#define R0900_GPIO3CFG 0xf143 +#define F0900_GPIO3_OPD 0xf1430080 +#define F0900_GPIO3_CONFIG 0xf143007e +#define F0900_GPIO3_XOR 0xf1430001 /*GPIO4CFG*/ -#define R0900_GPIO4CFG 0xf144 -#define F0900_GPIO4_OPD 0xf1440080 -#define F0900_GPIO4_CONFIG 0xf144007e -#define F0900_GPIO4_XOR 0xf1440001 +#define R0900_GPIO4CFG 0xf144 +#define F0900_GPIO4_OPD 0xf1440080 +#define F0900_GPIO4_CONFIG 0xf144007e +#define F0900_GPIO4_XOR 0xf1440001 /*GPIO5CFG*/ -#define R0900_GPIO5CFG 0xf145 -#define F0900_GPIO5_OPD 0xf1450080 -#define F0900_GPIO5_CONFIG 0xf145007e -#define F0900_GPIO5_XOR 0xf1450001 +#define R0900_GPIO5CFG 0xf145 +#define F0900_GPIO5_OPD 0xf1450080 +#define F0900_GPIO5_CONFIG 0xf145007e +#define F0900_GPIO5_XOR 0xf1450001 /*GPIO6CFG*/ -#define R0900_GPIO6CFG 0xf146 -#define F0900_GPIO6_OPD 0xf1460080 -#define F0900_GPIO6_CONFIG 0xf146007e -#define F0900_GPIO6_XOR 0xf1460001 +#define R0900_GPIO6CFG 0xf146 +#define F0900_GPIO6_OPD 0xf1460080 +#define F0900_GPIO6_CONFIG 0xf146007e +#define F0900_GPIO6_XOR 0xf1460001 /*GPIO7CFG*/ -#define R0900_GPIO7CFG 0xf147 -#define F0900_GPIO7_OPD 0xf1470080 -#define F0900_GPIO7_CONFIG 0xf147007e -#define F0900_GPIO7_XOR 0xf1470001 +#define R0900_GPIO7CFG 0xf147 +#define F0900_GPIO7_OPD 0xf1470080 +#define F0900_GPIO7_CONFIG 0xf147007e +#define F0900_GPIO7_XOR 0xf1470001 /*GPIO8CFG*/ -#define R0900_GPIO8CFG 0xf148 -#define F0900_GPIO8_OPD 0xf1480080 -#define F0900_GPIO8_CONFIG 0xf148007e -#define F0900_GPIO8_XOR 0xf1480001 +#define R0900_GPIO8CFG 0xf148 +#define F0900_GPIO8_OPD 0xf1480080 +#define F0900_GPIO8_CONFIG 0xf148007e +#define F0900_GPIO8_XOR 0xf1480001 /*GPIO9CFG*/ -#define R0900_GPIO9CFG 0xf149 -#define F0900_GPIO9_OPD 0xf1490080 -#define F0900_GPIO9_CONFIG 0xf149007e -#define F0900_GPIO9_XOR 0xf1490001 +#define R0900_GPIO9CFG 0xf149 +#define F0900_GPIO9_OPD 0xf1490080 +#define F0900_GPIO9_CONFIG 0xf149007e +#define F0900_GPIO9_XOR 0xf1490001 /*GPIO10CFG*/ -#define R0900_GPIO10CFG 0xf14a -#define F0900_GPIO10_OPD 0xf14a0080 -#define F0900_GPIO10_CONFIG 0xf14a007e -#define F0900_GPIO10_XOR 0xf14a0001 +#define R0900_GPIO10CFG 0xf14a +#define F0900_GPIO10_OPD 0xf14a0080 +#define F0900_GPIO10_CONFIG 0xf14a007e +#define F0900_GPIO10_XOR 0xf14a0001 /*GPIO11CFG*/ -#define R0900_GPIO11CFG 0xf14b -#define F0900_GPIO11_OPD 0xf14b0080 -#define F0900_GPIO11_CONFIG 0xf14b007e -#define F0900_GPIO11_XOR 0xf14b0001 +#define R0900_GPIO11CFG 0xf14b +#define F0900_GPIO11_OPD 0xf14b0080 +#define F0900_GPIO11_CONFIG 0xf14b007e +#define F0900_GPIO11_XOR 0xf14b0001 /*GPIO12CFG*/ -#define R0900_GPIO12CFG 0xf14c -#define F0900_GPIO12_OPD 0xf14c0080 -#define F0900_GPIO12_CONFIG 0xf14c007e -#define F0900_GPIO12_XOR 0xf14c0001 +#define R0900_GPIO12CFG 0xf14c +#define F0900_GPIO12_OPD 0xf14c0080 +#define F0900_GPIO12_CONFIG 0xf14c007e +#define F0900_GPIO12_XOR 0xf14c0001 /*GPIO13CFG*/ -#define R0900_GPIO13CFG 0xf14d -#define F0900_GPIO13_OPD 0xf14d0080 -#define F0900_GPIO13_CONFIG 0xf14d007e -#define F0900_GPIO13_XOR 0xf14d0001 +#define R0900_GPIO13CFG 0xf14d +#define F0900_GPIO13_OPD 0xf14d0080 +#define F0900_GPIO13_CONFIG 0xf14d007e +#define F0900_GPIO13_XOR 0xf14d0001 /*CS0CFG*/ -#define R0900_CS0CFG 0xf14e -#define F0900_CS0_OPD 0xf14e0080 -#define F0900_CS0_CONFIG 0xf14e007e -#define F0900_CS0_XOR 0xf14e0001 +#define R0900_CS0CFG 0xf14e +#define F0900_CS0_OPD 0xf14e0080 +#define F0900_CS0_CONFIG 0xf14e007e +#define F0900_CS0_XOR 0xf14e0001 /*CS1CFG*/ -#define R0900_CS1CFG 0xf14f -#define F0900_CS1_OPD 0xf14f0080 -#define F0900_CS1_CONFIG 0xf14f007e -#define F0900_CS1_XOR 0xf14f0001 +#define R0900_CS1CFG 0xf14f +#define F0900_CS1_OPD 0xf14f0080 +#define F0900_CS1_CONFIG 0xf14f007e +#define F0900_CS1_XOR 0xf14f0001 /*STDBYCFG*/ -#define R0900_STDBYCFG 0xf150 -#define F0900_STDBY_OPD 0xf1500080 -#define F0900_STDBY_CONFIG 0xf150007e -#define F0900_STBDY_XOR 0xf1500001 +#define R0900_STDBYCFG 0xf150 +#define F0900_STDBY_OPD 0xf1500080 +#define F0900_STDBY_CONFIG 0xf150007e +#define F0900_STBDY_XOR 0xf1500001 /*DIRCLKCFG*/ -#define R0900_DIRCLKCFG 0xf151 -#define F0900_DIRCLK_OPD 0xf1510080 -#define F0900_DIRCLK_CONFIG 0xf151007e -#define F0900_DIRCLK_XOR 0xf1510001 +#define R0900_DIRCLKCFG 0xf151 +#define F0900_DIRCLK_OPD 0xf1510080 +#define F0900_DIRCLK_CONFIG 0xf151007e +#define F0900_DIRCLK_XOR 0xf1510001 /*AGCRF1CFG*/ -#define R0900_AGCRF1CFG 0xf152 -#define F0900_AGCRF1_OPD 0xf1520080 -#define F0900_AGCRF1_CONFIG 0xf152007e -#define F0900_AGCRF1_XOR 0xf1520001 +#define R0900_AGCRF1CFG 0xf152 +#define F0900_AGCRF1_OPD 0xf1520080 +#define F0900_AGCRF1_CONFIG 0xf152007e +#define F0900_AGCRF1_XOR 0xf1520001 /*SDAT1CFG*/ -#define R0900_SDAT1CFG 0xf153 -#define F0900_SDAT1_OPD 0xf1530080 -#define F0900_SDAT1_CONFIG 0xf153007e -#define F0900_SDAT1_XOR 0xf1530001 +#define R0900_SDAT1CFG 0xf153 +#define F0900_SDAT1_OPD 0xf1530080 +#define F0900_SDAT1_CONFIG 0xf153007e +#define F0900_SDAT1_XOR 0xf1530001 /*SCLT1CFG*/ -#define R0900_SCLT1CFG 0xf154 -#define F0900_SCLT1_OPD 0xf1540080 -#define F0900_SCLT1_CONFIG 0xf154007e -#define F0900_SCLT1_XOR 0xf1540001 +#define R0900_SCLT1CFG 0xf154 +#define F0900_SCLT1_OPD 0xf1540080 +#define F0900_SCLT1_CONFIG 0xf154007e +#define F0900_SCLT1_XOR 0xf1540001 /*DISEQCO1CFG*/ -#define R0900_DISEQCO1CFG 0xf155 -#define F0900_DISEQCO1_OPD 0xf1550080 -#define F0900_DISEQCO1_CONFIG 0xf155007e -#define F0900_DISEQC1_XOR 0xf1550001 +#define R0900_DISEQCO1CFG 0xf155 +#define F0900_DISEQCO1_OPD 0xf1550080 +#define F0900_DISEQCO1_CONFIG 0xf155007e +#define F0900_DISEQC1_XOR 0xf1550001 /*AGCRF2CFG*/ -#define R0900_AGCRF2CFG 0xf156 -#define F0900_AGCRF2_OPD 0xf1560080 -#define F0900_AGCRF2_CONFIG 0xf156007e -#define F0900_AGCRF2_XOR 0xf1560001 +#define R0900_AGCRF2CFG 0xf156 +#define F0900_AGCRF2_OPD 0xf1560080 +#define F0900_AGCRF2_CONFIG 0xf156007e +#define F0900_AGCRF2_XOR 0xf1560001 /*SDAT2CFG*/ -#define R0900_SDAT2CFG 0xf157 -#define F0900_SDAT2_OPD 0xf1570080 -#define F0900_SDAT2_CONFIG 0xf157007e -#define F0900_SDAT2_XOR 0xf1570001 +#define R0900_SDAT2CFG 0xf157 +#define F0900_SDAT2_OPD 0xf1570080 +#define F0900_SDAT2_CONFIG 0xf157007e +#define F0900_SDAT2_XOR 0xf1570001 /*SCLT2CFG*/ -#define R0900_SCLT2CFG 0xf158 -#define F0900_SCLT2_OPD 0xf1580080 -#define F0900_SCLT2_CONFIG 0xf158007e -#define F0900_SCLT2_XOR 0xf1580001 +#define R0900_SCLT2CFG 0xf158 +#define F0900_SCLT2_OPD 0xf1580080 +#define F0900_SCLT2_CONFIG 0xf158007e +#define F0900_SCLT2_XOR 0xf1580001 /*DISEQCO2CFG*/ -#define R0900_DISEQCO2CFG 0xf159 -#define F0900_DISEQCO2_OPD 0xf1590080 -#define F0900_DISEQCO2_CONFIG 0xf159007e -#define F0900_DISEQC2_XOR 0xf1590001 +#define R0900_DISEQCO2CFG 0xf159 +#define F0900_DISEQCO2_OPD 0xf1590080 +#define F0900_DISEQCO2_CONFIG 0xf159007e +#define F0900_DISEQC2_XOR 0xf1590001 /*CLKOUT27CFG*/ -#define R0900_CLKOUT27CFG 0xf15a -#define F0900_CLKOUT27_OPD 0xf15a0080 -#define F0900_CLKOUT27_CONFIG 0xf15a007e -#define F0900_CLKOUT27_XOR 0xf15a0001 +#define R0900_CLKOUT27CFG 0xf15a +#define F0900_CLKOUT27_OPD 0xf15a0080 +#define F0900_CLKOUT27_CONFIG 0xf15a007e +#define F0900_CLKOUT27_XOR 0xf15a0001 /*ERROR1CFG*/ -#define R0900_ERROR1CFG 0xf15b -#define F0900_ERROR1_OPD 0xf15b0080 -#define F0900_ERROR1_CONFIG 0xf15b007e -#define F0900_ERROR1_XOR 0xf15b0001 +#define R0900_ERROR1CFG 0xf15b +#define F0900_ERROR1_OPD 0xf15b0080 +#define F0900_ERROR1_CONFIG 0xf15b007e +#define F0900_ERROR1_XOR 0xf15b0001 /*DPN1CFG*/ -#define R0900_DPN1CFG 0xf15c -#define F0900_DPN1_OPD 0xf15c0080 -#define F0900_DPN1_CONFIG 0xf15c007e -#define F0900_DPN1_XOR 0xf15c0001 +#define R0900_DPN1CFG 0xf15c +#define F0900_DPN1_OPD 0xf15c0080 +#define F0900_DPN1_CONFIG 0xf15c007e +#define F0900_DPN1_XOR 0xf15c0001 /*STROUT1CFG*/ -#define R0900_STROUT1CFG 0xf15d -#define F0900_STROUT1_OPD 0xf15d0080 -#define F0900_STROUT1_CONFIG 0xf15d007e -#define F0900_STROUT1_XOR 0xf15d0001 +#define R0900_STROUT1CFG 0xf15d +#define F0900_STROUT1_OPD 0xf15d0080 +#define F0900_STROUT1_CONFIG 0xf15d007e +#define F0900_STROUT1_XOR 0xf15d0001 /*CLKOUT1CFG*/ -#define R0900_CLKOUT1CFG 0xf15e -#define F0900_CLKOUT1_OPD 0xf15e0080 -#define F0900_CLKOUT1_CONFIG 0xf15e007e -#define F0900_CLKOUT1_XOR 0xf15e0001 +#define R0900_CLKOUT1CFG 0xf15e +#define F0900_CLKOUT1_OPD 0xf15e0080 +#define F0900_CLKOUT1_CONFIG 0xf15e007e +#define F0900_CLKOUT1_XOR 0xf15e0001 /*DATA71CFG*/ -#define R0900_DATA71CFG 0xf15f -#define F0900_DATA71_OPD 0xf15f0080 -#define F0900_DATA71_CONFIG 0xf15f007e -#define F0900_DATA71_XOR 0xf15f0001 +#define R0900_DATA71CFG 0xf15f +#define F0900_DATA71_OPD 0xf15f0080 +#define F0900_DATA71_CONFIG 0xf15f007e +#define F0900_DATA71_XOR 0xf15f0001 /*ERROR2CFG*/ -#define R0900_ERROR2CFG 0xf160 -#define F0900_ERROR2_OPD 0xf1600080 -#define F0900_ERROR2_CONFIG 0xf160007e -#define F0900_ERROR2_XOR 0xf1600001 +#define R0900_ERROR2CFG 0xf160 +#define F0900_ERROR2_OPD 0xf1600080 +#define F0900_ERROR2_CONFIG 0xf160007e +#define F0900_ERROR2_XOR 0xf1600001 /*DPN2CFG*/ -#define R0900_DPN2CFG 0xf161 -#define F0900_DPN2_OPD 0xf1610080 -#define F0900_DPN2_CONFIG 0xf161007e -#define F0900_DPN2_XOR 0xf1610001 +#define R0900_DPN2CFG 0xf161 +#define F0900_DPN2_OPD 0xf1610080 +#define F0900_DPN2_CONFIG 0xf161007e +#define F0900_DPN2_XOR 0xf1610001 /*STROUT2CFG*/ -#define R0900_STROUT2CFG 0xf162 -#define F0900_STROUT2_OPD 0xf1620080 -#define F0900_STROUT2_CONFIG 0xf162007e -#define F0900_STROUT2_XOR 0xf1620001 +#define R0900_STROUT2CFG 0xf162 +#define F0900_STROUT2_OPD 0xf1620080 +#define F0900_STROUT2_CONFIG 0xf162007e +#define F0900_STROUT2_XOR 0xf1620001 /*CLKOUT2CFG*/ -#define R0900_CLKOUT2CFG 0xf163 -#define F0900_CLKOUT2_OPD 0xf1630080 -#define F0900_CLKOUT2_CONFIG 0xf163007e -#define F0900_CLKOUT2_XOR 0xf1630001 +#define R0900_CLKOUT2CFG 0xf163 +#define F0900_CLKOUT2_OPD 0xf1630080 +#define F0900_CLKOUT2_CONFIG 0xf163007e +#define F0900_CLKOUT2_XOR 0xf1630001 /*DATA72CFG*/ -#define R0900_DATA72CFG 0xf164 -#define F0900_DATA72_OPD 0xf1640080 -#define F0900_DATA72_CONFIG 0xf164007e -#define F0900_DATA72_XOR 0xf1640001 +#define R0900_DATA72CFG 0xf164 +#define F0900_DATA72_OPD 0xf1640080 +#define F0900_DATA72_CONFIG 0xf164007e +#define F0900_DATA72_XOR 0xf1640001 /*ERROR3CFG*/ -#define R0900_ERROR3CFG 0xf165 -#define F0900_ERROR3_OPD 0xf1650080 -#define F0900_ERROR3_CONFIG 0xf165007e -#define F0900_ERROR3_XOR 0xf1650001 +#define R0900_ERROR3CFG 0xf165 +#define F0900_ERROR3_OPD 0xf1650080 +#define F0900_ERROR3_CONFIG 0xf165007e +#define F0900_ERROR3_XOR 0xf1650001 /*DPN3CFG*/ -#define R0900_DPN3CFG 0xf166 -#define F0900_DPN3_OPD 0xf1660080 -#define F0900_DPN3_CONFIG 0xf166007e -#define F0900_DPN3_XOR 0xf1660001 +#define R0900_DPN3CFG 0xf166 +#define F0900_DPN3_OPD 0xf1660080 +#define F0900_DPN3_CONFIG 0xf166007e +#define F0900_DPN3_XOR 0xf1660001 /*STROUT3CFG*/ -#define R0900_STROUT3CFG 0xf167 -#define F0900_STROUT3_OPD 0xf1670080 -#define F0900_STROUT3_CONFIG 0xf167007e -#define F0900_STROUT3_XOR 0xf1670001 +#define R0900_STROUT3CFG 0xf167 +#define F0900_STROUT3_OPD 0xf1670080 +#define F0900_STROUT3_CONFIG 0xf167007e +#define F0900_STROUT3_XOR 0xf1670001 /*CLKOUT3CFG*/ -#define R0900_CLKOUT3CFG 0xf168 -#define F0900_CLKOUT3_OPD 0xf1680080 -#define F0900_CLKOUT3_CONFIG 0xf168007e -#define F0900_CLKOUT3_XOR 0xf1680001 +#define R0900_CLKOUT3CFG 0xf168 +#define F0900_CLKOUT3_OPD 0xf1680080 +#define F0900_CLKOUT3_CONFIG 0xf168007e +#define F0900_CLKOUT3_XOR 0xf1680001 /*DATA73CFG*/ -#define R0900_DATA73CFG 0xf169 -#define F0900_DATA73_OPD 0xf1690080 -#define F0900_DATA73_CONFIG 0xf169007e -#define F0900_DATA73_XOR 0xf1690001 +#define R0900_DATA73CFG 0xf169 +#define F0900_DATA73_OPD 0xf1690080 +#define F0900_DATA73_CONFIG 0xf169007e +#define F0900_DATA73_XOR 0xf1690001 + +/*STRSTATUS1*/ +#define R0900_STRSTATUS1 0xf16a +#define F0900_STRSTATUS_SEL2 0xf16a00f0 +#define F0900_STRSTATUS_SEL1 0xf16a000f + +/*STRSTATUS2*/ +#define R0900_STRSTATUS2 0xf16b +#define F0900_STRSTATUS_SEL4 0xf16b00f0 +#define F0900_STRSTATUS_SEL3 0xf16b000f + +/*STRSTATUS3*/ +#define R0900_STRSTATUS3 0xf16c +#define F0900_STRSTATUS_SEL6 0xf16c00f0 +#define F0900_STRSTATUS_SEL5 0xf16c000f /*FSKTFC2*/ -#define R0900_FSKTFC2 0xf170 -#define F0900_FSKT_KMOD 0xf17000fc -#define F0900_FSKT_CAR2 0xf1700003 +#define R0900_FSKTFC2 0xf170 +#define F0900_FSKT_KMOD 0xf17000fc +#define F0900_FSKT_CAR2 0xf1700003 /*FSKTFC1*/ -#define R0900_FSKTFC1 0xf171 -#define F0900_FSKT_CAR1 0xf17100ff +#define R0900_FSKTFC1 0xf171 +#define F0900_FSKT_CAR1 0xf17100ff /*FSKTFC0*/ -#define R0900_FSKTFC0 0xf172 -#define F0900_FSKT_CAR0 0xf17200ff +#define R0900_FSKTFC0 0xf172 +#define F0900_FSKT_CAR0 0xf17200ff /*FSKTDELTAF1*/ -#define R0900_FSKTDELTAF1 0xf173 -#define F0900_FSKT_DELTAF1 0xf173000f +#define R0900_FSKTDELTAF1 0xf173 +#define F0900_FSKT_DELTAF1 0xf173000f /*FSKTDELTAF0*/ -#define R0900_FSKTDELTAF0 0xf174 -#define F0900_FSKT_DELTAF0 0xf17400ff +#define R0900_FSKTDELTAF0 0xf174 +#define F0900_FSKT_DELTAF0 0xf17400ff /*FSKTCTRL*/ -#define R0900_FSKTCTRL 0xf175 -#define F0900_FSKT_EN_SGN 0xf1750040 -#define F0900_FSKT_MOD_SGN 0xf1750020 -#define F0900_FSKT_MOD_EN 0xf175001c -#define F0900_FSKT_DACMODE 0xf1750003 +#define R0900_FSKTCTRL 0xf175 +#define F0900_FSKT_EN_SGN 0xf1750040 +#define F0900_FSKT_MOD_SGN 0xf1750020 +#define F0900_FSKT_MOD_EN 0xf175001c +#define F0900_FSKT_DACMODE 0xf1750003 /*FSKRFC2*/ -#define R0900_FSKRFC2 0xf176 -#define F0900_FSKR_DETSGN 0xf1760040 -#define F0900_FSKR_OUTSGN 0xf1760020 -#define F0900_FSKR_KAGC 0xf176001c -#define F0900_FSKR_CAR2 0xf1760003 +#define R0900_FSKRFC2 0xf176 +#define F0900_FSKR_DETSGN 0xf1760040 +#define F0900_FSKR_OUTSGN 0xf1760020 +#define F0900_FSKR_KAGC 0xf176001c +#define F0900_FSKR_CAR2 0xf1760003 /*FSKRFC1*/ -#define R0900_FSKRFC1 0xf177 -#define F0900_FSKR_CAR1 0xf17700ff +#define R0900_FSKRFC1 0xf177 +#define F0900_FSKR_CAR1 0xf17700ff /*FSKRFC0*/ -#define R0900_FSKRFC0 0xf178 -#define F0900_FSKR_CAR0 0xf17800ff +#define R0900_FSKRFC0 0xf178 +#define F0900_FSKR_CAR0 0xf17800ff /*FSKRK1*/ -#define R0900_FSKRK1 0xf179 -#define F0900_FSKR_K1_EXP 0xf17900e0 -#define F0900_FSKR_K1_MANT 0xf179001f +#define R0900_FSKRK1 0xf179 +#define F0900_FSKR_K1_EXP 0xf17900e0 +#define F0900_FSKR_K1_MANT 0xf179001f /*FSKRK2*/ -#define R0900_FSKRK2 0xf17a -#define F0900_FSKR_K2_EXP 0xf17a00e0 -#define F0900_FSKR_K2_MANT 0xf17a001f +#define R0900_FSKRK2 0xf17a +#define F0900_FSKR_K2_EXP 0xf17a00e0 +#define F0900_FSKR_K2_MANT 0xf17a001f /*FSKRAGCR*/ -#define R0900_FSKRAGCR 0xf17b -#define F0900_FSKR_OUTCTL 0xf17b00c0 -#define F0900_FSKR_AGC_REF 0xf17b003f +#define R0900_FSKRAGCR 0xf17b +#define F0900_FSKR_OUTCTL 0xf17b00c0 +#define F0900_FSKR_AGC_REF 0xf17b003f /*FSKRAGC*/ -#define R0900_FSKRAGC 0xf17c -#define F0900_FSKR_AGC_ACCU 0xf17c00ff +#define R0900_FSKRAGC 0xf17c +#define F0900_FSKR_AGC_ACCU 0xf17c00ff /*FSKRALPHA*/ -#define R0900_FSKRALPHA 0xf17d -#define F0900_FSKR_ALPHA_EXP 0xf17d001c -#define F0900_FSKR_ALPHA_M 0xf17d0003 +#define R0900_FSKRALPHA 0xf17d +#define F0900_FSKR_ALPHA_EXP 0xf17d001c +#define F0900_FSKR_ALPHA_M 0xf17d0003 /*FSKRPLTH1*/ -#define R0900_FSKRPLTH1 0xf17e -#define F0900_FSKR_BETA 0xf17e00f0 -#define F0900_FSKR_PLL_TRESH1 0xf17e000f +#define R0900_FSKRPLTH1 0xf17e +#define F0900_FSKR_BETA 0xf17e00f0 +#define F0900_FSKR_PLL_TRESH1 0xf17e000f /*FSKRPLTH0*/ -#define R0900_FSKRPLTH0 0xf17f -#define F0900_FSKR_PLL_TRESH0 0xf17f00ff +#define R0900_FSKRPLTH0 0xf17f +#define F0900_FSKR_PLL_TRESH0 0xf17f00ff /*FSKRDF1*/ -#define R0900_FSKRDF1 0xf180 -#define F0900_FSKR_OUT 0xf1800080 -#define F0900_FSKR_DELTAF1 0xf180001f +#define R0900_FSKRDF1 0xf180 +#define F0900_FSKR_OUT 0xf1800080 +#define F0900_FSKR_DELTAF1 0xf180001f /*FSKRDF0*/ -#define R0900_FSKRDF0 0xf181 -#define F0900_FSKR_DELTAF0 0xf18100ff +#define R0900_FSKRDF0 0xf181 +#define F0900_FSKR_DELTAF0 0xf18100ff /*FSKRSTEPP*/ -#define R0900_FSKRSTEPP 0xf182 -#define F0900_FSKR_STEP_PLUS 0xf18200ff +#define R0900_FSKRSTEPP 0xf182 +#define F0900_FSKR_STEP_PLUS 0xf18200ff /*FSKRSTEPM*/ -#define R0900_FSKRSTEPM 0xf183 -#define F0900_FSKR_STEP_MINUS 0xf18300ff +#define R0900_FSKRSTEPM 0xf183 +#define F0900_FSKR_STEP_MINUS 0xf18300ff /*FSKRDET1*/ -#define R0900_FSKRDET1 0xf184 -#define F0900_FSKR_DETECT 0xf1840080 -#define F0900_FSKR_CARDET_ACCU1 0xf184000f +#define R0900_FSKRDET1 0xf184 +#define F0900_FSKR_DETECT 0xf1840080 +#define F0900_FSKR_CARDET_ACCU1 0xf184000f /*FSKRDET0*/ -#define R0900_FSKRDET0 0xf185 -#define F0900_FSKR_CARDET_ACCU0 0xf18500ff +#define R0900_FSKRDET0 0xf185 +#define F0900_FSKR_CARDET_ACCU0 0xf18500ff /*FSKRDTH1*/ -#define R0900_FSKRDTH1 0xf186 -#define F0900_FSKR_CARLOSS_THRESH1 0xf18600f0 -#define F0900_FSKR_CARDET_THRESH1 0xf186000f +#define R0900_FSKRDTH1 0xf186 +#define F0900_FSKR_CARLOSS_THRESH1 0xf18600f0 +#define F0900_FSKR_CARDET_THRESH1 0xf186000f /*FSKRDTH0*/ -#define R0900_FSKRDTH0 0xf187 -#define F0900_FSKR_CARDET_THRESH0 0xf18700ff +#define R0900_FSKRDTH0 0xf187 +#define F0900_FSKR_CARDET_THRESH0 0xf18700ff /*FSKRLOSS*/ -#define R0900_FSKRLOSS 0xf188 -#define F0900_FSKR_CARLOSS_THRESH0 0xf18800ff +#define R0900_FSKRLOSS 0xf188 +#define F0900_FSKR_CARLOSS_THRESH0 0xf18800ff /*P2_DISTXCTL*/ -#define R0900_P2_DISTXCTL 0xf190 -#define F0900_P2_TIM_OFF 0xf1900080 -#define F0900_P2_DISEQC_RESET 0xf1900040 -#define F0900_P2_TIM_CMD 0xf1900030 -#define F0900_P2_DIS_PRECHARGE 0xf1900008 -#define F0900_P2_DISTX_MODE 0xf1900007 +#define R0900_P2_DISTXCTL 0xf190 +#define F0900_P2_TIM_OFF 0xf1900080 +#define F0900_P2_DISEQC_RESET 0xf1900040 +#define F0900_P2_TIM_CMD 0xf1900030 +#define F0900_P2_DIS_PRECHARGE 0xf1900008 +#define F0900_P2_DISTX_MODE 0xf1900007 /*P2_DISRXCTL*/ -#define R0900_P2_DISRXCTL 0xf191 -#define F0900_P2_RECEIVER_ON 0xf1910080 -#define F0900_P2_IGNO_SHORT22K 0xf1910040 -#define F0900_P2_ONECHIP_TRX 0xf1910020 -#define F0900_P2_EXT_ENVELOP 0xf1910010 -#define F0900_P2_PIN_SELECT 0xf191000c -#define F0900_P2_IRQ_RXEND 0xf1910002 -#define F0900_P2_IRQ_4NBYTES 0xf1910001 +#define R0900_P2_DISRXCTL 0xf191 +#define F0900_P2_RECEIVER_ON 0xf1910080 +#define F0900_P2_IGNO_SHORT22K 0xf1910040 +#define F0900_P2_ONECHIP_TRX 0xf1910020 +#define F0900_P2_EXT_ENVELOP 0xf1910010 +#define F0900_P2_PIN_SELECT0 0xf191000c +#define F0900_P2_IRQ_RXEND 0xf1910002 +#define F0900_P2_IRQ_4NBYTES 0xf1910001 /*P2_DISRX_ST0*/ -#define R0900_P2_DISRX_ST0 0xf194 -#define F0900_P2_RX_END 0xf1940080 -#define F0900_P2_RX_ACTIVE 0xf1940040 -#define F0900_P2_SHORT_22KHZ 0xf1940020 -#define F0900_P2_CONT_TONE 0xf1940010 -#define F0900_P2_FIFO_4BREADY 0xf1940008 -#define F0900_P2_FIFO_EMPTY 0xf1940004 -#define F0900_P2_ABORT_DISRX 0xf1940001 +#define R0900_P2_DISRX_ST0 0xf194 +#define F0900_P2_RX_END 0xf1940080 +#define F0900_P2_RX_ACTIVE 0xf1940040 +#define F0900_P2_SHORT_22KHZ 0xf1940020 +#define F0900_P2_CONT_TONE 0xf1940010 +#define F0900_P2_FIFO_4BREADY 0xf1940008 +#define F0900_P2_FIFO_EMPTY 0xf1940004 +#define F0900_P2_ABORT_DISRX 0xf1940001 /*P2_DISRX_ST1*/ -#define R0900_P2_DISRX_ST1 0xf195 -#define F0900_P2_RX_FAIL 0xf1950080 -#define F0900_P2_FIFO_PARITYFAIL 0xf1950040 -#define F0900_P2_RX_NONBYTE 0xf1950020 -#define F0900_P2_FIFO_OVERFLOW 0xf1950010 -#define F0900_P2_FIFO_BYTENBR 0xf195000f +#define R0900_P2_DISRX_ST1 0xf195 +#define F0900_P2_RX_FAIL 0xf1950080 +#define F0900_P2_FIFO_PARITYFAIL 0xf1950040 +#define F0900_P2_RX_NONBYTE 0xf1950020 +#define F0900_P2_FIFO_OVERFLOW 0xf1950010 +#define F0900_P2_FIFO_BYTENBR 0xf195000f /*P2_DISRXDATA*/ -#define R0900_P2_DISRXDATA 0xf196 -#define F0900_P2_DISRX_DATA 0xf19600ff +#define R0900_P2_DISRXDATA 0xf196 +#define F0900_P2_DISRX_DATA 0xf19600ff /*P2_DISTXDATA*/ -#define R0900_P2_DISTXDATA 0xf197 -#define F0900_P2_DISEQC_FIFO 0xf19700ff +#define R0900_P2_DISTXDATA 0xf197 +#define F0900_P2_DISEQC_FIFO 0xf19700ff /*P2_DISTXSTATUS*/ -#define R0900_P2_DISTXSTATUS 0xf198 -#define F0900_P2_TX_FAIL 0xf1980080 -#define F0900_P2_FIFO_FULL 0xf1980040 -#define F0900_P2_TX_IDLE 0xf1980020 -#define F0900_P2_GAP_BURST 0xf1980010 -#define F0900_P2_TXFIFO_BYTES 0xf198000f +#define R0900_P2_DISTXSTATUS 0xf198 +#define F0900_P2_TX_FAIL 0xf1980080 +#define F0900_P2_FIFO_FULL 0xf1980040 +#define F0900_P2_TX_IDLE 0xf1980020 +#define F0900_P2_GAP_BURST 0xf1980010 +#define F0900_P2_TXFIFO_BYTES 0xf198000f /*P2_F22TX*/ -#define R0900_P2_F22TX 0xf199 -#define F0900_P2_F22_REG 0xf19900ff +#define R0900_P2_F22TX 0xf199 +#define F0900_P2_F22_REG 0xf19900ff /*P2_F22RX*/ -#define R0900_P2_F22RX 0xf19a -#define F0900_P2_F22RX_REG 0xf19a00ff +#define R0900_P2_F22RX 0xf19a +#define F0900_P2_F22RX_REG 0xf19a00ff /*P2_ACRPRESC*/ -#define R0900_P2_ACRPRESC 0xf19c -#define F0900_P2_ACR_CODFRDY 0xf19c0008 -#define F0900_P2_ACR_PRESC 0xf19c0007 +#define R0900_P2_ACRPRESC 0xf19c +#define F0900_P2_ACR_PRESC 0xf19c0007 /*P2_ACRDIV*/ -#define R0900_P2_ACRDIV 0xf19d -#define F0900_P2_ACR_DIV 0xf19d00ff +#define R0900_P2_ACRDIV 0xf19d +#define F0900_P2_ACR_DIV 0xf19d00ff /*P1_DISTXCTL*/ -#define R0900_P1_DISTXCTL 0xf1a0 -#define F0900_P1_TIM_OFF 0xf1a00080 -#define F0900_P1_DISEQC_RESET 0xf1a00040 -#define F0900_P1_TIM_CMD 0xf1a00030 -#define F0900_P1_DIS_PRECHARGE 0xf1a00008 -#define F0900_P1_DISTX_MODE 0xf1a00007 +#define R0900_P1_DISTXCTL 0xf1a0 +#define DISTXCTL shiftx(R0900_P1_DISTXCTL, demod, 0x10) +#define F0900_P1_TIM_OFF 0xf1a00080 +#define F0900_P1_DISEQC_RESET 0xf1a00040 +#define DISEQC_RESET shiftx(F0900_P1_DISEQC_RESET, demod, 0x100000) +#define F0900_P1_TIM_CMD 0xf1a00030 +#define F0900_P1_DIS_PRECHARGE 0xf1a00008 +#define DIS_PRECHARGE shiftx(F0900_P1_DIS_PRECHARGE, demod, 0x100000) +#define F0900_P1_DISTX_MODE 0xf1a00007 +#define DISTX_MODE shiftx(F0900_P1_DISTX_MODE, demod, 0x100000) /*P1_DISRXCTL*/ -#define R0900_P1_DISRXCTL 0xf1a1 -#define F0900_P1_RECEIVER_ON 0xf1a10080 -#define F0900_P1_IGNO_SHORT22K 0xf1a10040 -#define F0900_P1_ONECHIP_TRX 0xf1a10020 -#define F0900_P1_EXT_ENVELOP 0xf1a10010 -#define F0900_P1_PIN_SELECT 0xf1a1000c -#define F0900_P1_IRQ_RXEND 0xf1a10002 -#define F0900_P1_IRQ_4NBYTES 0xf1a10001 +#define R0900_P1_DISRXCTL 0xf1a1 +#define DISRXCTL shiftx(R0900_P1_DISRXCTL, demod, 0x10) +#define F0900_P1_RECEIVER_ON 0xf1a10080 +#define F0900_P1_IGNO_SHORT22K 0xf1a10040 +#define F0900_P1_ONECHIP_TRX 0xf1a10020 +#define F0900_P1_EXT_ENVELOP 0xf1a10010 +#define F0900_P1_PIN_SELECT0 0xf1a1000c +#define F0900_P1_IRQ_RXEND 0xf1a10002 +#define F0900_P1_IRQ_4NBYTES 0xf1a10001 /*P1_DISRX_ST0*/ -#define R0900_P1_DISRX_ST0 0xf1a4 -#define F0900_P1_RX_END 0xf1a40080 -#define F0900_P1_RX_ACTIVE 0xf1a40040 -#define F0900_P1_SHORT_22KHZ 0xf1a40020 -#define F0900_P1_CONT_TONE 0xf1a40010 -#define F0900_P1_FIFO_4BREADY 0xf1a40008 -#define F0900_P1_FIFO_EMPTY 0xf1a40004 -#define F0900_P1_ABORT_DISRX 0xf1a40001 +#define R0900_P1_DISRX_ST0 0xf1a4 +#define DISRX_ST0 shiftx(R0900_P1_DISRX_ST0, demod, 0x10) +#define F0900_P1_RX_END 0xf1a40080 +#define RX_END shiftx(F0900_P1_RX_END, demod, 0x100000) +#define F0900_P1_RX_ACTIVE 0xf1a40040 +#define F0900_P1_SHORT_22KHZ 0xf1a40020 +#define F0900_P1_CONT_TONE 0xf1a40010 +#define F0900_P1_FIFO_4BREADY 0xf1a40008 +#define F0900_P1_FIFO_EMPTY 0xf1a40004 +#define F0900_P1_ABORT_DISRX 0xf1a40001 /*P1_DISRX_ST1*/ -#define R0900_P1_DISRX_ST1 0xf1a5 -#define F0900_P1_RX_FAIL 0xf1a50080 -#define F0900_P1_FIFO_PARITYFAIL 0xf1a50040 -#define F0900_P1_RX_NONBYTE 0xf1a50020 -#define F0900_P1_FIFO_OVERFLOW 0xf1a50010 -#define F0900_P1_FIFO_BYTENBR 0xf1a5000f +#define R0900_P1_DISRX_ST1 0xf1a5 +#define DISRX_ST1 shiftx(R0900_P1_DISRX_ST1, demod, 0x10) +#define F0900_P1_RX_FAIL 0xf1a50080 +#define F0900_P1_FIFO_PARITYFAIL 0xf1a50040 +#define F0900_P1_RX_NONBYTE 0xf1a50020 +#define F0900_P1_FIFO_OVERFLOW 0xf1a50010 +#define F0900_P1_FIFO_BYTENBR 0xf1a5000f +#define FIFO_BYTENBR shiftx(F0900_P1_FIFO_BYTENBR, demod, 0x100000) /*P1_DISRXDATA*/ -#define R0900_P1_DISRXDATA 0xf1a6 -#define F0900_P1_DISRX_DATA 0xf1a600ff +#define R0900_P1_DISRXDATA 0xf1a6 +#define DISRXDATA shiftx(R0900_P1_DISRXDATA, demod, 0x10) +#define F0900_P1_DISRX_DATA 0xf1a600ff /*P1_DISTXDATA*/ -#define R0900_P1_DISTXDATA 0xf1a7 -#define F0900_P1_DISEQC_FIFO 0xf1a700ff +#define R0900_P1_DISTXDATA 0xf1a7 +#define DISTXDATA shiftx(R0900_P1_DISTXDATA, demod, 0x10) +#define F0900_P1_DISEQC_FIFO 0xf1a700ff /*P1_DISTXSTATUS*/ -#define R0900_P1_DISTXSTATUS 0xf1a8 -#define F0900_P1_TX_FAIL 0xf1a80080 -#define F0900_P1_FIFO_FULL 0xf1a80040 -#define F0900_P1_TX_IDLE 0xf1a80020 -#define F0900_P1_GAP_BURST 0xf1a80010 -#define F0900_P1_TXFIFO_BYTES 0xf1a8000f +#define R0900_P1_DISTXSTATUS 0xf1a8 +#define F0900_P1_TX_FAIL 0xf1a80080 +#define F0900_P1_FIFO_FULL 0xf1a80040 +#define FIFO_FULL shiftx(F0900_P1_FIFO_FULL, demod, 0x100000) +#define F0900_P1_TX_IDLE 0xf1a80020 +#define TX_IDLE shiftx(F0900_P1_TX_IDLE, demod, 0x100000) +#define F0900_P1_GAP_BURST 0xf1a80010 +#define F0900_P1_TXFIFO_BYTES 0xf1a8000f /*P1_F22TX*/ -#define R0900_P1_F22TX 0xf1a9 -#define F0900_P1_F22_REG 0xf1a900ff +#define R0900_P1_F22TX 0xf1a9 +#define F22TX shiftx(R0900_P1_F22TX, demod, 0x10) +#define F0900_P1_F22_REG 0xf1a900ff /*P1_F22RX*/ -#define R0900_P1_F22RX 0xf1aa -#define F0900_P1_F22RX_REG 0xf1aa00ff +#define R0900_P1_F22RX 0xf1aa +#define F22RX shiftx(R0900_P1_F22RX, demod, 0x10) +#define F0900_P1_F22RX_REG 0xf1aa00ff /*P1_ACRPRESC*/ -#define R0900_P1_ACRPRESC 0xf1ac -#define F0900_P1_ACR_CODFRDY 0xf1ac0008 -#define F0900_P1_ACR_PRESC 0xf1ac0007 +#define R0900_P1_ACRPRESC 0xf1ac +#define ACRPRESC shiftx(R0900_P1_ACRPRESC, demod, 0x10) +#define F0900_P1_ACR_PRESC 0xf1ac0007 /*P1_ACRDIV*/ -#define R0900_P1_ACRDIV 0xf1ad -#define F0900_P1_ACR_DIV 0xf1ad00ff +#define R0900_P1_ACRDIV 0xf1ad +#define ACRDIV shiftx(R0900_P1_ACRDIV, demod, 0x10) +#define F0900_P1_ACR_DIV 0xf1ad00ff /*NCOARSE*/ -#define R0900_NCOARSE 0xf1b3 -#define F0900_M_DIV 0xf1b300ff +#define R0900_NCOARSE 0xf1b3 +#define F0900_M_DIV 0xf1b300ff /*SYNTCTRL*/ -#define R0900_SYNTCTRL 0xf1b6 -#define F0900_STANDBY 0xf1b60080 -#define F0900_BYPASSPLLCORE 0xf1b60040 -#define F0900_SELX1RATIO 0xf1b60020 -#define F0900_I2C_TUD 0xf1b60010 -#define F0900_STOP_PLL 0xf1b60008 -#define F0900_BYPASSPLLFSK 0xf1b60004 -#define F0900_SELOSCI 0xf1b60002 -#define F0900_BYPASSPLLADC 0xf1b60001 +#define R0900_SYNTCTRL 0xf1b6 +#define F0900_STANDBY 0xf1b60080 +#define F0900_BYPASSPLLCORE 0xf1b60040 +#define F0900_SELX1RATIO 0xf1b60020 +#define F0900_STOP_PLL 0xf1b60008 +#define F0900_BYPASSPLLFSK 0xf1b60004 +#define F0900_SELOSCI 0xf1b60002 +#define F0900_BYPASSPLLADC 0xf1b60001 /*FILTCTRL*/ -#define R0900_FILTCTRL 0xf1b7 -#define F0900_INV_CLK135 0xf1b70080 -#define F0900_PERM_BYPDIS 0xf1b70040 -#define F0900_SEL_FSKCKDIV 0xf1b70004 -#define F0900_INV_CLKFSK 0xf1b70002 -#define F0900_BYPASS_APPLI 0xf1b70001 +#define R0900_FILTCTRL 0xf1b7 +#define F0900_INV_CLK135 0xf1b70080 +#define F0900_SEL_FSKCKDIV 0xf1b70004 +#define F0900_INV_CLKFSK 0xf1b70002 +#define F0900_BYPASS_APPLI 0xf1b70001 /*PLLSTAT*/ -#define R0900_PLLSTAT 0xf1b8 -#define F0900_ACM_SEL 0xf1b80080 -#define F0900_DTV_SEL 0xf1b80040 -#define F0900_PLLLOCK 0xf1b80001 +#define R0900_PLLSTAT 0xf1b8 +#define F0900_PLLLOCK 0xf1b80001 /*STOPCLK1*/ -#define R0900_STOPCLK1 0xf1c2 -#define F0900_STOP_CLKPKDT2 0xf1c20040 -#define F0900_STOP_CLKPKDT1 0xf1c20020 -#define F0900_STOP_CLKFEC 0xf1c20010 -#define F0900_STOP_CLKADCI2 0xf1c20008 -#define F0900_INV_CLKADCI2 0xf1c20004 -#define F0900_STOP_CLKADCI1 0xf1c20002 -#define F0900_INV_CLKADCI1 0xf1c20001 +#define R0900_STOPCLK1 0xf1c2 +#define F0900_STOP_CLKPKDT2 0xf1c20040 +#define F0900_STOP_CLKPKDT1 0xf1c20020 +#define F0900_STOP_CLKFEC 0xf1c20010 +#define F0900_STOP_CLKADCI2 0xf1c20008 +#define F0900_INV_CLKADCI2 0xf1c20004 +#define F0900_STOP_CLKADCI1 0xf1c20002 +#define F0900_INV_CLKADCI1 0xf1c20001 /*STOPCLK2*/ -#define R0900_STOPCLK2 0xf1c3 -#define F0900_STOP_CLKSAMP2 0xf1c30010 -#define F0900_STOP_CLKSAMP1 0xf1c30008 -#define F0900_STOP_CLKVIT2 0xf1c30004 -#define F0900_STOP_CLKVIT1 0xf1c30002 -#define F0900_STOP_CLKTS 0xf1c30001 +#define R0900_STOPCLK2 0xf1c3 +#define F0900_STOP_CLKSAMP2 0xf1c30010 +#define F0900_STOP_CLKSAMP1 0xf1c30008 +#define F0900_STOP_CLKVIT2 0xf1c30004 +#define F0900_STOP_CLKVIT1 0xf1c30002 +#define STOP_CLKVIT shiftx(F0900_STOP_CLKVIT1, demod, -2) +#define F0900_STOP_CLKTS 0xf1c30001 /*TSTTNR0*/ -#define R0900_TSTTNR0 0xf1df -#define F0900_SEL_FSK 0xf1df0080 -#define F0900_FSK_PON 0xf1df0004 -#define F0900_FSK_OPENLOOP 0xf1df0002 +#define R0900_TSTTNR0 0xf1df +#define F0900_SEL_FSK 0xf1df0080 +#define F0900_FSK_PON 0xf1df0004 /*TSTTNR1*/ -#define R0900_TSTTNR1 0xf1e0 -#define F0900_BYPASS_ADC1 0xf1e00080 -#define F0900_INVADC1_CKOUT 0xf1e00040 -#define F0900_SELIQSRC1 0xf1e00030 -#define F0900_ADC1_PON 0xf1e00002 -#define F0900_ADC1_INMODE 0xf1e00001 +#define R0900_TSTTNR1 0xf1e0 +#define F0900_ADC1_PON 0xf1e00002 +#define F0900_ADC1_INMODE 0xf1e00001 /*TSTTNR2*/ -#define R0900_TSTTNR2 0xf1e1 -#define F0900_DISEQC1_PON 0xf1e10020 -#define F0900_DISEQC1_TEST 0xf1e1001f +#define R0900_TSTTNR2 0xf1e1 +#define F0900_DISEQC1_PON 0xf1e10020 /*TSTTNR3*/ -#define R0900_TSTTNR3 0xf1e2 -#define F0900_BYPASS_ADC2 0xf1e20080 -#define F0900_INVADC2_CKOUT 0xf1e20040 -#define F0900_SELIQSRC2 0xf1e20030 -#define F0900_ADC2_PON 0xf1e20002 -#define F0900_ADC2_INMODE 0xf1e20001 +#define R0900_TSTTNR3 0xf1e2 +#define F0900_ADC2_PON 0xf1e20002 +#define F0900_ADC2_INMODE 0xf1e20001 /*TSTTNR4*/ -#define R0900_TSTTNR4 0xf1e3 -#define F0900_DISEQC2_PON 0xf1e30020 -#define F0900_DISEQC2_TEST 0xf1e3001f +#define R0900_TSTTNR4 0xf1e3 +#define F0900_DISEQC2_PON 0xf1e30020 /*P2_IQCONST*/ -#define R0900_P2_IQCONST 0xf200 -#define F0900_P2_CONSTEL_SELECT 0xf2000060 -#define F0900_P2_IQSYMB_SEL 0xf200001f +#define R0900_P2_IQCONST 0xf200 +#define F0900_P2_CONSTEL_SELECT 0xf2000060 +#define F0900_P2_IQSYMB_SEL 0xf200001f /*P2_NOSCFG*/ -#define R0900_P2_NOSCFG 0xf201 -#define F0900_P2_DUMMYPL_NOSDATA 0xf2010020 -#define F0900_P2_NOSPLH_BETA 0xf2010018 -#define F0900_P2_NOSDATA_BETA 0xf2010007 +#define R0900_P2_NOSCFG 0xf201 +#define F0900_P2_DUMMYPL_NOSDATA 0xf2010020 +#define F0900_P2_NOSPLH_BETA 0xf2010018 +#define F0900_P2_NOSDATA_BETA 0xf2010007 /*P2_ISYMB*/ -#define R0900_P2_ISYMB 0xf202 -#define F0900_P2_I_SYMBOL 0xf20201ff +#define R0900_P2_ISYMB 0xf202 +#define F0900_P2_I_SYMBOL 0xf20201ff /*P2_QSYMB*/ -#define R0900_P2_QSYMB 0xf203 -#define F0900_P2_Q_SYMBOL 0xf20301ff +#define R0900_P2_QSYMB 0xf203 +#define F0900_P2_Q_SYMBOL 0xf20301ff /*P2_AGC1CFG*/ -#define R0900_P2_AGC1CFG 0xf204 -#define F0900_P2_DC_FROZEN 0xf2040080 -#define F0900_P2_DC_CORRECT 0xf2040040 -#define F0900_P2_AMM_FROZEN 0xf2040020 -#define F0900_P2_AMM_CORRECT 0xf2040010 -#define F0900_P2_QUAD_FROZEN 0xf2040008 -#define F0900_P2_QUAD_CORRECT 0xf2040004 -#define F0900_P2_DCCOMP_SLOW 0xf2040002 -#define F0900_P2_IQMISM_SLOW 0xf2040001 +#define R0900_P2_AGC1CFG 0xf204 +#define F0900_P2_DC_FROZEN 0xf2040080 +#define F0900_P2_DC_CORRECT 0xf2040040 +#define F0900_P2_AMM_FROZEN 0xf2040020 +#define F0900_P2_AMM_CORRECT 0xf2040010 +#define F0900_P2_QUAD_FROZEN 0xf2040008 +#define F0900_P2_QUAD_CORRECT 0xf2040004 /*P2_AGC1CN*/ -#define R0900_P2_AGC1CN 0xf206 -#define F0900_P2_AGC1_LOCKED 0xf2060080 -#define F0900_P2_AGC1_OVERFLOW 0xf2060040 -#define F0900_P2_AGC1_NOSLOWLK 0xf2060020 -#define F0900_P2_AGC1_MINPOWER 0xf2060010 -#define F0900_P2_AGCOUT_FAST 0xf2060008 -#define F0900_P2_AGCIQ_BETA 0xf2060007 +#define R0900_P2_AGC1CN 0xf206 +#define F0900_P2_AGC1_LOCKED 0xf2060080 +#define F0900_P2_AGC1_MINPOWER 0xf2060010 +#define F0900_P2_AGCOUT_FAST 0xf2060008 +#define F0900_P2_AGCIQ_BETA 0xf2060007 /*P2_AGC1REF*/ -#define R0900_P2_AGC1REF 0xf207 -#define F0900_P2_AGCIQ_REF 0xf20700ff +#define R0900_P2_AGC1REF 0xf207 +#define F0900_P2_AGCIQ_REF 0xf20700ff /*P2_IDCCOMP*/ -#define R0900_P2_IDCCOMP 0xf208 -#define F0900_P2_IAVERAGE_ADJ 0xf20801ff +#define R0900_P2_IDCCOMP 0xf208 +#define F0900_P2_IAVERAGE_ADJ 0xf20801ff /*P2_QDCCOMP*/ -#define R0900_P2_QDCCOMP 0xf209 -#define F0900_P2_QAVERAGE_ADJ 0xf20901ff +#define R0900_P2_QDCCOMP 0xf209 +#define F0900_P2_QAVERAGE_ADJ 0xf20901ff /*P2_POWERI*/ -#define R0900_P2_POWERI 0xf20a -#define F0900_P2_POWER_I 0xf20a00ff +#define R0900_P2_POWERI 0xf20a +#define F0900_P2_POWER_I 0xf20a00ff /*P2_POWERQ*/ -#define R0900_P2_POWERQ 0xf20b -#define F0900_P2_POWER_Q 0xf20b00ff +#define R0900_P2_POWERQ 0xf20b +#define F0900_P2_POWER_Q 0xf20b00ff /*P2_AGC1AMM*/ -#define R0900_P2_AGC1AMM 0xf20c -#define F0900_P2_AMM_VALUE 0xf20c00ff +#define R0900_P2_AGC1AMM 0xf20c +#define F0900_P2_AMM_VALUE 0xf20c00ff /*P2_AGC1QUAD*/ -#define R0900_P2_AGC1QUAD 0xf20d -#define F0900_P2_QUAD_VALUE 0xf20d01ff +#define R0900_P2_AGC1QUAD 0xf20d +#define F0900_P2_QUAD_VALUE 0xf20d01ff /*P2_AGCIQIN1*/ -#define R0900_P2_AGCIQIN1 0xf20e -#define F0900_P2_AGCIQ_VALUE1 0xf20e00ff +#define R0900_P2_AGCIQIN1 0xf20e +#define F0900_P2_AGCIQ_VALUE1 0xf20e00ff /*P2_AGCIQIN0*/ -#define R0900_P2_AGCIQIN0 0xf20f -#define F0900_P2_AGCIQ_VALUE0 0xf20f00ff +#define R0900_P2_AGCIQIN0 0xf20f +#define F0900_P2_AGCIQ_VALUE0 0xf20f00ff /*P2_DEMOD*/ -#define R0900_P2_DEMOD 0xf210 -#define F0900_P2_DEMOD_STOP 0xf2100040 -#define F0900_P2_SPECINV_CONTROL 0xf2100030 -#define F0900_P2_FORCE_ENASAMP 0xf2100008 -#define F0900_P2_MANUAL_ROLLOFF 0xf2100004 -#define F0900_P2_ROLLOFF_CONTROL 0xf2100003 +#define R0900_P2_DEMOD 0xf210 +#define F0900_P2_MANUALS2_ROLLOFF 0xf2100080 +#define F0900_P2_SPECINV_CONTROL 0xf2100030 +#define F0900_P2_FORCE_ENASAMP 0xf2100008 +#define F0900_P2_MANUALSX_ROLLOFF 0xf2100004 +#define F0900_P2_ROLLOFF_CONTROL 0xf2100003 /*P2_DMDMODCOD*/ -#define R0900_P2_DMDMODCOD 0xf211 -#define F0900_P2_MANUAL_MODCOD 0xf2110080 -#define F0900_P2_DEMOD_MODCOD 0xf211007c -#define F0900_P2_DEMOD_TYPE 0xf2110003 +#define R0900_P2_DMDMODCOD 0xf211 +#define F0900_P2_MANUAL_MODCOD 0xf2110080 +#define F0900_P2_DEMOD_MODCOD 0xf211007c +#define F0900_P2_DEMOD_TYPE 0xf2110003 /*P2_DSTATUS*/ -#define R0900_P2_DSTATUS 0xf212 -#define F0900_P2_CAR_LOCK 0xf2120080 -#define F0900_P2_TMGLOCK_QUALITY 0xf2120060 -#define F0900_P2_SDVBS1_ENABLE 0xf2120010 -#define F0900_P2_LOCK_DEFINITIF 0xf2120008 -#define F0900_P2_TIMING_IS_LOCKED 0xf2120004 -#define F0900_P2_COARSE_TMGLOCK 0xf2120002 -#define F0900_P2_COARSE_CARLOCK 0xf2120001 +#define R0900_P2_DSTATUS 0xf212 +#define F0900_P2_CAR_LOCK 0xf2120080 +#define F0900_P2_TMGLOCK_QUALITY 0xf2120060 +#define F0900_P2_LOCK_DEFINITIF 0xf2120008 +#define F0900_P2_OVADC_DETECT 0xf2120001 /*P2_DSTATUS2*/ -#define R0900_P2_DSTATUS2 0xf213 -#define F0900_P2_DEMOD_DELOCK 0xf2130080 -#define F0900_P2_DEMOD_TIMEOUT 0xf2130040 -#define F0900_P2_MODCODRQ_SYNCTAG 0xf2130020 -#define F0900_P2_POLYPH_SATEVENT 0xf2130010 -#define F0900_P2_AGC1_NOSIGNALACK 0xf2130008 -#define F0900_P2_AGC2_OVERFLOW 0xf2130004 -#define F0900_P2_CFR_OVERFLOW 0xf2130002 -#define F0900_P2_GAMMA_OVERUNDER 0xf2130001 +#define R0900_P2_DSTATUS2 0xf213 +#define F0900_P2_DEMOD_DELOCK 0xf2130080 +#define F0900_P2_AGC1_NOSIGNALACK 0xf2130008 +#define F0900_P2_AGC2_OVERFLOW 0xf2130004 +#define F0900_P2_CFR_OVERFLOW 0xf2130002 +#define F0900_P2_GAMMA_OVERUNDER 0xf2130001 /*P2_DMDCFGMD*/ -#define R0900_P2_DMDCFGMD 0xf214 -#define F0900_P2_DVBS2_ENABLE 0xf2140080 -#define F0900_P2_DVBS1_ENABLE 0xf2140040 -#define F0900_P2_CFR_AUTOSCAN 0xf2140020 -#define F0900_P2_SCAN_ENABLE 0xf2140010 -#define F0900_P2_TUN_AUTOSCAN 0xf2140008 -#define F0900_P2_NOFORCE_RELOCK 0xf2140004 -#define F0900_P2_TUN_RNG 0xf2140003 +#define R0900_P2_DMDCFGMD 0xf214 +#define F0900_P2_DVBS2_ENABLE 0xf2140080 +#define F0900_P2_DVBS1_ENABLE 0xf2140040 +#define F0900_P2_SCAN_ENABLE 0xf2140010 +#define F0900_P2_CFR_AUTOSCAN 0xf2140008 +#define F0900_P2_TUN_RNG 0xf2140003 /*P2_DMDCFG2*/ -#define R0900_P2_DMDCFG2 0xf215 -#define F0900_P2_AGC1_WAITLOCK 0xf2150080 -#define F0900_P2_S1S2_SEQUENTIAL 0xf2150040 -#define F0900_P2_OVERFLOW_TIMEOUT 0xf2150020 -#define F0900_P2_SCANFAIL_TIMEOUT 0xf2150010 -#define F0900_P2_DMDTOUT_BACK 0xf2150008 -#define F0900_P2_CARLOCK_S1ENABLE 0xf2150004 -#define F0900_P2_COARSE_LK3MODE 0xf2150002 -#define F0900_P2_COARSE_LK2MODE 0xf2150001 +#define R0900_P2_DMDCFG2 0xf215 +#define F0900_P2_S1S2_SEQUENTIAL 0xf2150040 +#define F0900_P2_INFINITE_RELOCK 0xf2150010 /*P2_DMDISTATE*/ -#define R0900_P2_DMDISTATE 0xf216 -#define F0900_P2_I2C_NORESETDMODE 0xf2160080 -#define F0900_P2_FORCE_ETAPED 0xf2160040 -#define F0900_P2_SDMDRST_DIRCLK 0xf2160020 -#define F0900_P2_I2C_DEMOD_MODE 0xf216001f +#define R0900_P2_DMDISTATE 0xf216 +#define F0900_P2_I2C_DEMOD_MODE 0xf216001f /*P2_DMDT0M*/ -#define R0900_P2_DMDT0M 0xf217 -#define F0900_P2_DMDT0_MIN 0xf21700ff +#define R0900_P2_DMDT0M 0xf217 +#define F0900_P2_DMDT0_MIN 0xf21700ff /*P2_DMDSTATE*/ -#define R0900_P2_DMDSTATE 0xf21b -#define F0900_P2_DEMOD_LOCKED 0xf21b0080 -#define F0900_P2_HEADER_MODE 0xf21b0060 -#define F0900_P2_DEMOD_MODE 0xf21b001f +#define R0900_P2_DMDSTATE 0xf21b +#define F0900_P2_HEADER_MODE 0xf21b0060 /*P2_DMDFLYW*/ -#define R0900_P2_DMDFLYW 0xf21c -#define F0900_P2_I2C_IRQVAL 0xf21c00f0 -#define F0900_P2_FLYWHEEL_CPT 0xf21c000f +#define R0900_P2_DMDFLYW 0xf21c +#define F0900_P2_I2C_IRQVAL 0xf21c00f0 +#define F0900_P2_FLYWHEEL_CPT 0xf21c000f /*P2_DSTATUS3*/ -#define R0900_P2_DSTATUS3 0xf21d -#define F0900_P2_CFR_ZIGZAG 0xf21d0080 -#define F0900_P2_DEMOD_CFGMODE 0xf21d0060 -#define F0900_P2_GAMMA_LOWBAUDRATE 0xf21d0010 -#define F0900_P2_RELOCK_MODE 0xf21d0008 -#define F0900_P2_DEMOD_FAIL 0xf21d0004 -#define F0900_P2_ETAPE1A_DVBXMEM 0xf21d0003 +#define R0900_P2_DSTATUS3 0xf21d +#define F0900_P2_DEMOD_CFGMODE 0xf21d0060 /*P2_DMDCFG3*/ -#define R0900_P2_DMDCFG3 0xf21e -#define F0900_P2_DVBS1_TMGWAIT 0xf21e0080 -#define F0900_P2_NO_BWCENTERING 0xf21e0040 -#define F0900_P2_INV_SEQSRCH 0xf21e0020 -#define F0900_P2_DIS_SFRUPLOW_TRK 0xf21e0010 -#define F0900_P2_NOSTOP_FIFOFULL 0xf21e0008 -#define F0900_P2_LOCKTIME_MODE 0xf21e0007 +#define R0900_P2_DMDCFG3 0xf21e +#define F0900_P2_NOSTOP_FIFOFULL 0xf21e0008 /*P2_DMDCFG4*/ -#define R0900_P2_DMDCFG4 0xf21f -#define F0900_P2_TUNER_NRELAUNCH 0xf21f0008 -#define F0900_P2_DIS_CLKENABLE 0xf21f0004 -#define F0900_P2_DIS_HDRDIVLOCK 0xf21f0002 -#define F0900_P2_NO_TNRWBINIT 0xf21f0001 +#define R0900_P2_DMDCFG4 0xf21f +#define F0900_P2_TUNER_NRELAUNCH 0xf21f0008 /*P2_CORRELMANT*/ -#define R0900_P2_CORRELMANT 0xf220 -#define F0900_P2_CORREL_MANT 0xf22000ff +#define R0900_P2_CORRELMANT 0xf220 +#define F0900_P2_CORREL_MANT 0xf22000ff /*P2_CORRELABS*/ -#define R0900_P2_CORRELABS 0xf221 -#define F0900_P2_CORREL_ABS 0xf22100ff +#define R0900_P2_CORRELABS 0xf221 +#define F0900_P2_CORREL_ABS 0xf22100ff /*P2_CORRELEXP*/ -#define R0900_P2_CORRELEXP 0xf222 -#define F0900_P2_CORREL_ABSEXP 0xf22200f0 -#define F0900_P2_CORREL_EXP 0xf222000f +#define R0900_P2_CORRELEXP 0xf222 +#define F0900_P2_CORREL_ABSEXP 0xf22200f0 +#define F0900_P2_CORREL_EXP 0xf222000f /*P2_PLHMODCOD*/ -#define R0900_P2_PLHMODCOD 0xf224 -#define F0900_P2_SPECINV_DEMOD 0xf2240080 -#define F0900_P2_PLH_MODCOD 0xf224007c -#define F0900_P2_PLH_TYPE 0xf2240003 +#define R0900_P2_PLHMODCOD 0xf224 +#define F0900_P2_SPECINV_DEMOD 0xf2240080 +#define F0900_P2_PLH_MODCOD 0xf224007c +#define F0900_P2_PLH_TYPE 0xf2240003 -/*P2_AGCK32*/ -#define R0900_P2_AGCK32 0xf22b -#define F0900_P2_R3ADJOFF_32APSK 0xf22b0080 -#define F0900_P2_R2ADJOFF_32APSK 0xf22b0040 -#define F0900_P2_R1ADJOFF_32APSK 0xf22b0020 -#define F0900_P2_RADJ_32APSK 0xf22b001f +/*P2_DMDREG*/ +#define R0900_P2_DMDREG 0xf225 +#define F0900_P2_DECIM_PLFRAMES 0xf2250001 /*P2_AGC2O*/ -#define R0900_P2_AGC2O 0xf22c -#define F0900_P2_AGC2REF_ADJUSTING 0xf22c0080 -#define F0900_P2_AGC2_COARSEFAST 0xf22c0040 -#define F0900_P2_AGC2_LKSQRT 0xf22c0020 -#define F0900_P2_AGC2_LKMODE 0xf22c0010 -#define F0900_P2_AGC2_LKEQUA 0xf22c0008 -#define F0900_P2_AGC2_COEF 0xf22c0007 +#define R0900_P2_AGC2O 0xf22c +#define F0900_P2_AGC2_COEF 0xf22c0007 /*P2_AGC2REF*/ -#define R0900_P2_AGC2REF 0xf22d -#define F0900_P2_AGC2_REF 0xf22d00ff +#define R0900_P2_AGC2REF 0xf22d +#define F0900_P2_AGC2_REF 0xf22d00ff /*P2_AGC1ADJ*/ -#define R0900_P2_AGC1ADJ 0xf22e -#define F0900_P2_AGC1ADJ_MANUAL 0xf22e0080 -#define F0900_P2_AGC1_ADJUSTED 0xf22e017f +#define R0900_P2_AGC1ADJ 0xf22e +#define F0900_P2_AGC1_ADJUSTED 0xf22e007f /*P2_AGC2I1*/ -#define R0900_P2_AGC2I1 0xf236 -#define F0900_P2_AGC2_INTEGRATOR1 0xf23600ff +#define R0900_P2_AGC2I1 0xf236 +#define F0900_P2_AGC2_INTEGRATOR1 0xf23600ff /*P2_AGC2I0*/ -#define R0900_P2_AGC2I0 0xf237 -#define F0900_P2_AGC2_INTEGRATOR0 0xf23700ff +#define R0900_P2_AGC2I0 0xf237 +#define F0900_P2_AGC2_INTEGRATOR0 0xf23700ff /*P2_CARCFG*/ -#define R0900_P2_CARCFG 0xf238 -#define F0900_P2_CFRUPLOW_AUTO 0xf2380080 -#define F0900_P2_CFRUPLOW_TEST 0xf2380040 -#define F0900_P2_EN_CAR2CENTER 0xf2380020 -#define F0900_P2_CARHDR_NODIV8 0xf2380010 -#define F0900_P2_I2C_ROTA 0xf2380008 -#define F0900_P2_ROTAON 0xf2380004 -#define F0900_P2_PH_DET_ALGO 0xf2380003 +#define R0900_P2_CARCFG 0xf238 +#define F0900_P2_CFRUPLOW_AUTO 0xf2380080 +#define F0900_P2_CFRUPLOW_TEST 0xf2380040 +#define F0900_P2_ROTAON 0xf2380004 +#define F0900_P2_PH_DET_ALGO 0xf2380003 /*P2_ACLC*/ -#define R0900_P2_ACLC 0xf239 -#define F0900_P2_STOP_S2ALPHA 0xf23900c0 -#define F0900_P2_CAR_ALPHA_MANT 0xf2390030 -#define F0900_P2_CAR_ALPHA_EXP 0xf239000f +#define R0900_P2_ACLC 0xf239 +#define F0900_P2_CAR_ALPHA_MANT 0xf2390030 +#define F0900_P2_CAR_ALPHA_EXP 0xf239000f /*P2_BCLC*/ -#define R0900_P2_BCLC 0xf23a -#define F0900_P2_STOP_S2BETA 0xf23a00c0 -#define F0900_P2_CAR_BETA_MANT 0xf23a0030 -#define F0900_P2_CAR_BETA_EXP 0xf23a000f +#define R0900_P2_BCLC 0xf23a +#define F0900_P2_CAR_BETA_MANT 0xf23a0030 +#define F0900_P2_CAR_BETA_EXP 0xf23a000f /*P2_CARFREQ*/ -#define R0900_P2_CARFREQ 0xf23d -#define F0900_P2_KC_COARSE_EXP 0xf23d00f0 -#define F0900_P2_BETA_FREQ 0xf23d000f +#define R0900_P2_CARFREQ 0xf23d +#define F0900_P2_KC_COARSE_EXP 0xf23d00f0 +#define F0900_P2_BETA_FREQ 0xf23d000f /*P2_CARHDR*/ -#define R0900_P2_CARHDR 0xf23e -#define F0900_P2_K_FREQ_HDR 0xf23e00ff +#define R0900_P2_CARHDR 0xf23e +#define F0900_P2_K_FREQ_HDR 0xf23e00ff /*P2_LDT*/ -#define R0900_P2_LDT 0xf23f -#define F0900_P2_CARLOCK_THRES 0xf23f01ff +#define R0900_P2_LDT 0xf23f +#define F0900_P2_CARLOCK_THRES 0xf23f01ff /*P2_LDT2*/ -#define R0900_P2_LDT2 0xf240 -#define F0900_P2_CARLOCK_THRES2 0xf24001ff +#define R0900_P2_LDT2 0xf240 +#define F0900_P2_CARLOCK_THRES2 0xf24001ff /*P2_CFRICFG*/ -#define R0900_P2_CFRICFG 0xf241 -#define F0900_P2_CFRINIT_UNVALRNG 0xf2410080 -#define F0900_P2_CFRINIT_LUNVALCPT 0xf2410040 -#define F0900_P2_CFRINIT_ABORTDBL 0xf2410020 -#define F0900_P2_CFRINIT_ABORTPRED 0xf2410010 -#define F0900_P2_CFRINIT_UNVALSKIP 0xf2410008 -#define F0900_P2_CFRINIT_CSTINC 0xf2410004 -#define F0900_P2_NEG_CFRSTEP 0xf2410001 +#define R0900_P2_CFRICFG 0xf241 +#define F0900_P2_NEG_CFRSTEP 0xf2410001 /*P2_CFRUP1*/ -#define R0900_P2_CFRUP1 0xf242 -#define F0900_P2_CFR_UP1 0xf24201ff +#define R0900_P2_CFRUP1 0xf242 +#define F0900_P2_CFR_UP1 0xf24201ff /*P2_CFRUP0*/ -#define R0900_P2_CFRUP0 0xf243 -#define F0900_P2_CFR_UP0 0xf24300ff +#define R0900_P2_CFRUP0 0xf243 +#define F0900_P2_CFR_UP0 0xf24300ff /*P2_CFRLOW1*/ -#define R0900_P2_CFRLOW1 0xf246 -#define F0900_P2_CFR_LOW1 0xf24601ff +#define R0900_P2_CFRLOW1 0xf246 +#define F0900_P2_CFR_LOW1 0xf24601ff /*P2_CFRLOW0*/ -#define R0900_P2_CFRLOW0 0xf247 -#define F0900_P2_CFR_LOW0 0xf24700ff +#define R0900_P2_CFRLOW0 0xf247 +#define F0900_P2_CFR_LOW0 0xf24700ff /*P2_CFRINIT1*/ -#define R0900_P2_CFRINIT1 0xf248 -#define F0900_P2_CFR_INIT1 0xf24801ff +#define R0900_P2_CFRINIT1 0xf248 +#define F0900_P2_CFR_INIT1 0xf24801ff /*P2_CFRINIT0*/ -#define R0900_P2_CFRINIT0 0xf249 -#define F0900_P2_CFR_INIT0 0xf24900ff +#define R0900_P2_CFRINIT0 0xf249 +#define F0900_P2_CFR_INIT0 0xf24900ff /*P2_CFRINC1*/ -#define R0900_P2_CFRINC1 0xf24a -#define F0900_P2_MANUAL_CFRINC 0xf24a0080 -#define F0900_P2_CFR_INC1 0xf24a017f +#define R0900_P2_CFRINC1 0xf24a +#define F0900_P2_MANUAL_CFRINC 0xf24a0080 +#define F0900_P2_CFR_INC1 0xf24a003f /*P2_CFRINC0*/ -#define R0900_P2_CFRINC0 0xf24b -#define F0900_P2_CFR_INC0 0xf24b00f0 +#define R0900_P2_CFRINC0 0xf24b +#define F0900_P2_CFR_INC0 0xf24b00f8 /*P2_CFR2*/ -#define R0900_P2_CFR2 0xf24c -#define F0900_P2_CAR_FREQ2 0xf24c01ff +#define R0900_P2_CFR2 0xf24c +#define F0900_P2_CAR_FREQ2 0xf24c01ff /*P2_CFR1*/ -#define R0900_P2_CFR1 0xf24d -#define F0900_P2_CAR_FREQ1 0xf24d00ff +#define R0900_P2_CFR1 0xf24d +#define F0900_P2_CAR_FREQ1 0xf24d00ff /*P2_CFR0*/ -#define R0900_P2_CFR0 0xf24e -#define F0900_P2_CAR_FREQ0 0xf24e00ff +#define R0900_P2_CFR0 0xf24e +#define F0900_P2_CAR_FREQ0 0xf24e00ff /*P2_LDI*/ -#define R0900_P2_LDI 0xf24f -#define F0900_P2_LOCK_DET_INTEGR 0xf24f01ff +#define R0900_P2_LDI 0xf24f +#define F0900_P2_LOCK_DET_INTEGR 0xf24f01ff /*P2_TMGCFG*/ -#define R0900_P2_TMGCFG 0xf250 -#define F0900_P2_TMGLOCK_BETA 0xf25000c0 -#define F0900_P2_NOTMG_GROUPDELAY 0xf2500020 -#define F0900_P2_DO_TIMING_CORR 0xf2500010 -#define F0900_P2_MANUAL_SCAN 0xf250000c -#define F0900_P2_TMG_MINFREQ 0xf2500003 +#define R0900_P2_TMGCFG 0xf250 +#define F0900_P2_TMGLOCK_BETA 0xf25000c0 +#define F0900_P2_DO_TIMING_CORR 0xf2500010 +#define F0900_P2_TMG_MINFREQ 0xf2500003 /*P2_RTC*/ -#define R0900_P2_RTC 0xf251 -#define F0900_P2_TMGALPHA_EXP 0xf25100f0 -#define F0900_P2_TMGBETA_EXP 0xf251000f +#define R0900_P2_RTC 0xf251 +#define F0900_P2_TMGALPHA_EXP 0xf25100f0 +#define F0900_P2_TMGBETA_EXP 0xf251000f /*P2_RTCS2*/ -#define R0900_P2_RTCS2 0xf252 -#define F0900_P2_TMGALPHAS2_EXP 0xf25200f0 -#define F0900_P2_TMGBETAS2_EXP 0xf252000f +#define R0900_P2_RTCS2 0xf252 +#define F0900_P2_TMGALPHAS2_EXP 0xf25200f0 +#define F0900_P2_TMGBETAS2_EXP 0xf252000f /*P2_TMGTHRISE*/ -#define R0900_P2_TMGTHRISE 0xf253 -#define F0900_P2_TMGLOCK_THRISE 0xf25300ff +#define R0900_P2_TMGTHRISE 0xf253 +#define F0900_P2_TMGLOCK_THRISE 0xf25300ff /*P2_TMGTHFALL*/ -#define R0900_P2_TMGTHFALL 0xf254 -#define F0900_P2_TMGLOCK_THFALL 0xf25400ff +#define R0900_P2_TMGTHFALL 0xf254 +#define F0900_P2_TMGLOCK_THFALL 0xf25400ff /*P2_SFRUPRATIO*/ -#define R0900_P2_SFRUPRATIO 0xf255 -#define F0900_P2_SFR_UPRATIO 0xf25500ff +#define R0900_P2_SFRUPRATIO 0xf255 +#define F0900_P2_SFR_UPRATIO 0xf25500ff /*P2_SFRLOWRATIO*/ -#define R0900_P2_SFRLOWRATIO 0xf256 -#define F0900_P2_SFR_LOWRATIO 0xf25600ff +#define R0900_P2_SFRLOWRATIO 0xf256 +#define F0900_P2_SFR_LOWRATIO 0xf25600ff /*P2_KREFTMG*/ -#define R0900_P2_KREFTMG 0xf258 -#define F0900_P2_KREF_TMG 0xf25800ff +#define R0900_P2_KREFTMG 0xf258 +#define F0900_P2_KREF_TMG 0xf25800ff /*P2_SFRSTEP*/ -#define R0900_P2_SFRSTEP 0xf259 -#define F0900_P2_SFR_SCANSTEP 0xf25900f0 -#define F0900_P2_SFR_CENTERSTEP 0xf259000f +#define R0900_P2_SFRSTEP 0xf259 +#define F0900_P2_SFR_SCANSTEP 0xf25900f0 +#define F0900_P2_SFR_CENTERSTEP 0xf259000f /*P2_TMGCFG2*/ -#define R0900_P2_TMGCFG2 0xf25a -#define F0900_P2_DIS_AUTOSAMP 0xf25a0008 -#define F0900_P2_SCANINIT_QUART 0xf25a0004 -#define F0900_P2_NOTMG_DVBS1DERAT 0xf25a0002 -#define F0900_P2_SFRRATIO_FINE 0xf25a0001 +#define R0900_P2_TMGCFG2 0xf25a +#define F0900_P2_SFRRATIO_FINE 0xf25a0001 + +/*P2_KREFTMG2*/ +#define R0900_P2_KREFTMG2 0xf25b +#define F0900_P2_KREF_TMG2 0xf25b00ff /*P2_SFRINIT1*/ -#define R0900_P2_SFRINIT1 0xf25e -#define F0900_P2_SFR_INIT1 0xf25e00ff +#define R0900_P2_SFRINIT1 0xf25e +#define F0900_P2_SFR_INIT1 0xf25e007f /*P2_SFRINIT0*/ -#define R0900_P2_SFRINIT0 0xf25f -#define F0900_P2_SFR_INIT0 0xf25f00ff +#define R0900_P2_SFRINIT0 0xf25f +#define F0900_P2_SFR_INIT0 0xf25f00ff /*P2_SFRUP1*/ -#define R0900_P2_SFRUP1 0xf260 -#define F0900_P2_AUTO_GUP 0xf2600080 -#define F0900_P2_SYMB_FREQ_UP1 0xf260007f +#define R0900_P2_SFRUP1 0xf260 +#define F0900_P2_AUTO_GUP 0xf2600080 +#define F0900_P2_SYMB_FREQ_UP1 0xf260007f /*P2_SFRUP0*/ -#define R0900_P2_SFRUP0 0xf261 -#define F0900_P2_SYMB_FREQ_UP0 0xf26100ff +#define R0900_P2_SFRUP0 0xf261 +#define F0900_P2_SYMB_FREQ_UP0 0xf26100ff /*P2_SFRLOW1*/ -#define R0900_P2_SFRLOW1 0xf262 -#define F0900_P2_AUTO_GLOW 0xf2620080 -#define F0900_P2_SYMB_FREQ_LOW1 0xf262007f +#define R0900_P2_SFRLOW1 0xf262 +#define F0900_P2_AUTO_GLOW 0xf2620080 +#define F0900_P2_SYMB_FREQ_LOW1 0xf262007f /*P2_SFRLOW0*/ -#define R0900_P2_SFRLOW0 0xf263 -#define F0900_P2_SYMB_FREQ_LOW0 0xf26300ff +#define R0900_P2_SFRLOW0 0xf263 +#define F0900_P2_SYMB_FREQ_LOW0 0xf26300ff /*P2_SFR3*/ -#define R0900_P2_SFR3 0xf264 -#define F0900_P2_SYMB_FREQ3 0xf26400ff +#define R0900_P2_SFR3 0xf264 +#define F0900_P2_SYMB_FREQ3 0xf26400ff /*P2_SFR2*/ -#define R0900_P2_SFR2 0xf265 -#define F0900_P2_SYMB_FREQ2 0xf26500ff +#define R0900_P2_SFR2 0xf265 +#define F0900_P2_SYMB_FREQ2 0xf26500ff /*P2_SFR1*/ -#define R0900_P2_SFR1 0xf266 -#define F0900_P2_SYMB_FREQ1 0xf26600ff +#define R0900_P2_SFR1 0xf266 +#define F0900_P2_SYMB_FREQ1 0xf26600ff /*P2_SFR0*/ -#define R0900_P2_SFR0 0xf267 -#define F0900_P2_SYMB_FREQ0 0xf26700ff +#define R0900_P2_SFR0 0xf267 +#define F0900_P2_SYMB_FREQ0 0xf26700ff /*P2_TMGREG2*/ -#define R0900_P2_TMGREG2 0xf268 -#define F0900_P2_TMGREG2 0xf26800ff +#define R0900_P2_TMGREG2 0xf268 +#define F0900_P2_TMGREG2 0xf26800ff /*P2_TMGREG1*/ -#define R0900_P2_TMGREG1 0xf269 -#define F0900_P2_TMGREG1 0xf26900ff +#define R0900_P2_TMGREG1 0xf269 +#define F0900_P2_TMGREG1 0xf26900ff /*P2_TMGREG0*/ -#define R0900_P2_TMGREG0 0xf26a -#define F0900_P2_TMGREG0 0xf26a00ff +#define R0900_P2_TMGREG0 0xf26a +#define F0900_P2_TMGREG0 0xf26a00ff /*P2_TMGLOCK1*/ -#define R0900_P2_TMGLOCK1 0xf26b -#define F0900_P2_TMGLOCK_LEVEL1 0xf26b01ff +#define R0900_P2_TMGLOCK1 0xf26b +#define F0900_P2_TMGLOCK_LEVEL1 0xf26b01ff /*P2_TMGLOCK0*/ -#define R0900_P2_TMGLOCK0 0xf26c -#define F0900_P2_TMGLOCK_LEVEL0 0xf26c00ff +#define R0900_P2_TMGLOCK0 0xf26c +#define F0900_P2_TMGLOCK_LEVEL0 0xf26c00ff /*P2_TMGOBS*/ -#define R0900_P2_TMGOBS 0xf26d -#define F0900_P2_ROLLOFF_STATUS 0xf26d00c0 -#define F0900_P2_SCAN_SIGN 0xf26d0030 -#define F0900_P2_TMG_SCANNING 0xf26d0008 -#define F0900_P2_CHCENTERING_MODE 0xf26d0004 -#define F0900_P2_TMG_SCANFAIL 0xf26d0002 +#define R0900_P2_TMGOBS 0xf26d +#define F0900_P2_ROLLOFF_STATUS 0xf26d00c0 /*P2_EQUALCFG*/ -#define R0900_P2_EQUALCFG 0xf26f -#define F0900_P2_NOTMG_NEGALWAIT 0xf26f0080 -#define F0900_P2_EQUAL_ON 0xf26f0040 -#define F0900_P2_SEL_EQUALCOR 0xf26f0038 -#define F0900_P2_MU_EQUALDFE 0xf26f0007 +#define R0900_P2_EQUALCFG 0xf26f +#define F0900_P2_EQUAL_ON 0xf26f0040 +#define F0900_P2_MU_EQUALDFE 0xf26f0007 /*P2_EQUAI1*/ -#define R0900_P2_EQUAI1 0xf270 -#define F0900_P2_EQUA_ACCI1 0xf27001ff +#define R0900_P2_EQUAI1 0xf270 +#define F0900_P2_EQUA_ACCI1 0xf27001ff /*P2_EQUAQ1*/ -#define R0900_P2_EQUAQ1 0xf271 -#define F0900_P2_EQUA_ACCQ1 0xf27101ff +#define R0900_P2_EQUAQ1 0xf271 +#define F0900_P2_EQUA_ACCQ1 0xf27101ff /*P2_EQUAI2*/ -#define R0900_P2_EQUAI2 0xf272 -#define F0900_P2_EQUA_ACCI2 0xf27201ff +#define R0900_P2_EQUAI2 0xf272 +#define F0900_P2_EQUA_ACCI2 0xf27201ff /*P2_EQUAQ2*/ -#define R0900_P2_EQUAQ2 0xf273 -#define F0900_P2_EQUA_ACCQ2 0xf27301ff +#define R0900_P2_EQUAQ2 0xf273 +#define F0900_P2_EQUA_ACCQ2 0xf27301ff /*P2_EQUAI3*/ -#define R0900_P2_EQUAI3 0xf274 -#define F0900_P2_EQUA_ACCI3 0xf27401ff +#define R0900_P2_EQUAI3 0xf274 +#define F0900_P2_EQUA_ACCI3 0xf27401ff /*P2_EQUAQ3*/ -#define R0900_P2_EQUAQ3 0xf275 -#define F0900_P2_EQUA_ACCQ3 0xf27501ff +#define R0900_P2_EQUAQ3 0xf275 +#define F0900_P2_EQUA_ACCQ3 0xf27501ff /*P2_EQUAI4*/ -#define R0900_P2_EQUAI4 0xf276 -#define F0900_P2_EQUA_ACCI4 0xf27601ff +#define R0900_P2_EQUAI4 0xf276 +#define F0900_P2_EQUA_ACCI4 0xf27601ff /*P2_EQUAQ4*/ -#define R0900_P2_EQUAQ4 0xf277 -#define F0900_P2_EQUA_ACCQ4 0xf27701ff +#define R0900_P2_EQUAQ4 0xf277 +#define F0900_P2_EQUA_ACCQ4 0xf27701ff /*P2_EQUAI5*/ -#define R0900_P2_EQUAI5 0xf278 -#define F0900_P2_EQUA_ACCI5 0xf27801ff +#define R0900_P2_EQUAI5 0xf278 +#define F0900_P2_EQUA_ACCI5 0xf27801ff /*P2_EQUAQ5*/ -#define R0900_P2_EQUAQ5 0xf279 -#define F0900_P2_EQUA_ACCQ5 0xf27901ff +#define R0900_P2_EQUAQ5 0xf279 +#define F0900_P2_EQUA_ACCQ5 0xf27901ff /*P2_EQUAI6*/ -#define R0900_P2_EQUAI6 0xf27a -#define F0900_P2_EQUA_ACCI6 0xf27a01ff +#define R0900_P2_EQUAI6 0xf27a +#define F0900_P2_EQUA_ACCI6 0xf27a01ff /*P2_EQUAQ6*/ -#define R0900_P2_EQUAQ6 0xf27b -#define F0900_P2_EQUA_ACCQ6 0xf27b01ff +#define R0900_P2_EQUAQ6 0xf27b +#define F0900_P2_EQUA_ACCQ6 0xf27b01ff /*P2_EQUAI7*/ -#define R0900_P2_EQUAI7 0xf27c -#define F0900_P2_EQUA_ACCI7 0xf27c01ff +#define R0900_P2_EQUAI7 0xf27c +#define F0900_P2_EQUA_ACCI7 0xf27c01ff /*P2_EQUAQ7*/ -#define R0900_P2_EQUAQ7 0xf27d -#define F0900_P2_EQUA_ACCQ7 0xf27d01ff +#define R0900_P2_EQUAQ7 0xf27d +#define F0900_P2_EQUA_ACCQ7 0xf27d01ff /*P2_EQUAI8*/ -#define R0900_P2_EQUAI8 0xf27e -#define F0900_P2_EQUA_ACCI8 0xf27e01ff +#define R0900_P2_EQUAI8 0xf27e +#define F0900_P2_EQUA_ACCI8 0xf27e01ff /*P2_EQUAQ8*/ -#define R0900_P2_EQUAQ8 0xf27f -#define F0900_P2_EQUA_ACCQ8 0xf27f01ff +#define R0900_P2_EQUAQ8 0xf27f +#define F0900_P2_EQUA_ACCQ8 0xf27f01ff /*P2_NNOSDATAT1*/ -#define R0900_P2_NNOSDATAT1 0xf280 -#define F0900_P2_NOSDATAT_NORMED1 0xf28000ff +#define R0900_P2_NNOSDATAT1 0xf280 +#define F0900_P2_NOSDATAT_NORMED1 0xf28000ff /*P2_NNOSDATAT0*/ -#define R0900_P2_NNOSDATAT0 0xf281 -#define F0900_P2_NOSDATAT_NORMED0 0xf28100ff +#define R0900_P2_NNOSDATAT0 0xf281 +#define F0900_P2_NOSDATAT_NORMED0 0xf28100ff /*P2_NNOSDATA1*/ -#define R0900_P2_NNOSDATA1 0xf282 -#define F0900_P2_NOSDATA_NORMED1 0xf28200ff +#define R0900_P2_NNOSDATA1 0xf282 +#define F0900_P2_NOSDATA_NORMED1 0xf28200ff /*P2_NNOSDATA0*/ -#define R0900_P2_NNOSDATA0 0xf283 -#define F0900_P2_NOSDATA_NORMED0 0xf28300ff +#define R0900_P2_NNOSDATA0 0xf283 +#define F0900_P2_NOSDATA_NORMED0 0xf28300ff /*P2_NNOSPLHT1*/ -#define R0900_P2_NNOSPLHT1 0xf284 -#define F0900_P2_NOSPLHT_NORMED1 0xf28400ff +#define R0900_P2_NNOSPLHT1 0xf284 +#define F0900_P2_NOSPLHT_NORMED1 0xf28400ff /*P2_NNOSPLHT0*/ -#define R0900_P2_NNOSPLHT0 0xf285 -#define F0900_P2_NOSPLHT_NORMED0 0xf28500ff +#define R0900_P2_NNOSPLHT0 0xf285 +#define F0900_P2_NOSPLHT_NORMED0 0xf28500ff /*P2_NNOSPLH1*/ -#define R0900_P2_NNOSPLH1 0xf286 -#define F0900_P2_NOSPLH_NORMED1 0xf28600ff +#define R0900_P2_NNOSPLH1 0xf286 +#define F0900_P2_NOSPLH_NORMED1 0xf28600ff /*P2_NNOSPLH0*/ -#define R0900_P2_NNOSPLH0 0xf287 -#define F0900_P2_NOSPLH_NORMED0 0xf28700ff +#define R0900_P2_NNOSPLH0 0xf287 +#define F0900_P2_NOSPLH_NORMED0 0xf28700ff /*P2_NOSDATAT1*/ -#define R0900_P2_NOSDATAT1 0xf288 -#define F0900_P2_NOSDATAT_UNNORMED1 0xf28800ff +#define R0900_P2_NOSDATAT1 0xf288 +#define F0900_P2_NOSDATAT_UNNORMED1 0xf28800ff /*P2_NOSDATAT0*/ -#define R0900_P2_NOSDATAT0 0xf289 -#define F0900_P2_NOSDATAT_UNNORMED0 0xf28900ff +#define R0900_P2_NOSDATAT0 0xf289 +#define F0900_P2_NOSDATAT_UNNORMED0 0xf28900ff /*P2_NOSDATA1*/ -#define R0900_P2_NOSDATA1 0xf28a -#define F0900_P2_NOSDATA_UNNORMED1 0xf28a00ff +#define R0900_P2_NOSDATA1 0xf28a +#define F0900_P2_NOSDATA_UNNORMED1 0xf28a00ff /*P2_NOSDATA0*/ -#define R0900_P2_NOSDATA0 0xf28b -#define F0900_P2_NOSDATA_UNNORMED0 0xf28b00ff +#define R0900_P2_NOSDATA0 0xf28b +#define F0900_P2_NOSDATA_UNNORMED0 0xf28b00ff /*P2_NOSPLHT1*/ -#define R0900_P2_NOSPLHT1 0xf28c -#define F0900_P2_NOSPLHT_UNNORMED1 0xf28c00ff +#define R0900_P2_NOSPLHT1 0xf28c +#define F0900_P2_NOSPLHT_UNNORMED1 0xf28c00ff /*P2_NOSPLHT0*/ -#define R0900_P2_NOSPLHT0 0xf28d -#define F0900_P2_NOSPLHT_UNNORMED0 0xf28d00ff +#define R0900_P2_NOSPLHT0 0xf28d +#define F0900_P2_NOSPLHT_UNNORMED0 0xf28d00ff /*P2_NOSPLH1*/ -#define R0900_P2_NOSPLH1 0xf28e -#define F0900_P2_NOSPLH_UNNORMED1 0xf28e00ff +#define R0900_P2_NOSPLH1 0xf28e +#define F0900_P2_NOSPLH_UNNORMED1 0xf28e00ff /*P2_NOSPLH0*/ -#define R0900_P2_NOSPLH0 0xf28f -#define F0900_P2_NOSPLH_UNNORMED0 0xf28f00ff +#define R0900_P2_NOSPLH0 0xf28f +#define F0900_P2_NOSPLH_UNNORMED0 0xf28f00ff /*P2_CAR2CFG*/ -#define R0900_P2_CAR2CFG 0xf290 -#define F0900_P2_DESCRAMB_OFF 0xf2900080 -#define F0900_P2_PN4_SELECT 0xf2900040 -#define F0900_P2_CFR2_STOPDVBS1 0xf2900020 -#define F0900_P2_STOP_CFR2UPDATE 0xf2900010 -#define F0900_P2_STOP_NCO2UPDATE 0xf2900008 -#define F0900_P2_ROTA2ON 0xf2900004 -#define F0900_P2_PH_DET_ALGO2 0xf2900003 +#define R0900_P2_CAR2CFG 0xf290 +#define F0900_P2_CARRIER3_DISABLE 0xf2900040 +#define F0900_P2_ROTA2ON 0xf2900004 +#define F0900_P2_PH_DET_ALGO2 0xf2900003 -/*P2_ACLC2*/ -#define R0900_P2_ACLC2 0xf291 -#define F0900_P2_CAR2_PUNCT_ADERAT 0xf2910040 -#define F0900_P2_CAR2_ALPHA_MANT 0xf2910030 -#define F0900_P2_CAR2_ALPHA_EXP 0xf291000f - -/*P2_BCLC2*/ -#define R0900_P2_BCLC2 0xf292 -#define F0900_P2_DVBS2_NIP 0xf2920080 -#define F0900_P2_CAR2_PUNCT_BDERAT 0xf2920040 -#define F0900_P2_CAR2_BETA_MANT 0xf2920030 -#define F0900_P2_CAR2_BETA_EXP 0xf292000f +/*P2_CFR2CFR1*/ +#define R0900_P2_CFR2CFR1 0xf291 +#define F0900_P2_CFR2TOCFR1_DVBS1 0xf29100c0 +#define F0900_P2_EN_S2CAR2CENTER 0xf2910020 +#define F0900_P2_DIS_BCHERRCFR2 0xf2910010 +#define F0900_P2_CFR2TOCFR1_BETA 0xf2910007 /*P2_CFR22*/ -#define R0900_P2_CFR22 0xf293 -#define F0900_P2_CAR2_FREQ2 0xf29301ff +#define R0900_P2_CFR22 0xf293 +#define F0900_P2_CAR2_FREQ2 0xf29301ff /*P2_CFR21*/ -#define R0900_P2_CFR21 0xf294 -#define F0900_P2_CAR2_FREQ1 0xf29400ff +#define R0900_P2_CFR21 0xf294 +#define F0900_P2_CAR2_FREQ1 0xf29400ff /*P2_CFR20*/ -#define R0900_P2_CFR20 0xf295 -#define F0900_P2_CAR2_FREQ0 0xf29500ff +#define R0900_P2_CFR20 0xf295 +#define F0900_P2_CAR2_FREQ0 0xf29500ff /*P2_ACLC2S2Q*/ -#define R0900_P2_ACLC2S2Q 0xf297 -#define F0900_P2_ENAB_SPSKSYMB 0xf2970080 -#define F0900_P2_CAR2S2_QADERAT 0xf2970040 -#define F0900_P2_CAR2S2_Q_ALPH_M 0xf2970030 -#define F0900_P2_CAR2S2_Q_ALPH_E 0xf297000f +#define R0900_P2_ACLC2S2Q 0xf297 +#define F0900_P2_ENAB_SPSKSYMB 0xf2970080 +#define F0900_P2_CAR2S2_Q_ALPH_M 0xf2970030 +#define F0900_P2_CAR2S2_Q_ALPH_E 0xf297000f /*P2_ACLC2S28*/ -#define R0900_P2_ACLC2S28 0xf298 -#define F0900_P2_OLDI3Q_MODE 0xf2980080 -#define F0900_P2_CAR2S2_8ADERAT 0xf2980040 -#define F0900_P2_CAR2S2_8_ALPH_M 0xf2980030 -#define F0900_P2_CAR2S2_8_ALPH_E 0xf298000f +#define R0900_P2_ACLC2S28 0xf298 +#define F0900_P2_OLDI3Q_MODE 0xf2980080 +#define F0900_P2_CAR2S2_8_ALPH_M 0xf2980030 +#define F0900_P2_CAR2S2_8_ALPH_E 0xf298000f /*P2_ACLC2S216A*/ -#define R0900_P2_ACLC2S216A 0xf299 -#define F0900_P2_CAR2S2_16ADERAT 0xf2990040 -#define F0900_P2_CAR2S2_16A_ALPH_M 0xf2990030 -#define F0900_P2_CAR2S2_16A_ALPH_E 0xf299000f +#define R0900_P2_ACLC2S216A 0xf299 +#define F0900_P2_DIS_C3STOPA2 0xf2990080 +#define F0900_P2_CAR2S2_16ADERAT 0xf2990040 +#define F0900_P2_CAR2S2_16A_ALPH_M 0xf2990030 +#define F0900_P2_CAR2S2_16A_ALPH_E 0xf299000f /*P2_ACLC2S232A*/ -#define R0900_P2_ACLC2S232A 0xf29a -#define F0900_P2_CAR2S2_32ADERAT 0xf29a0040 -#define F0900_P2_CAR2S2_32A_ALPH_M 0xf29a0030 -#define F0900_P2_CAR2S2_32A_ALPH_E 0xf29a000f +#define R0900_P2_ACLC2S232A 0xf29a +#define F0900_P2_CAR2S2_32ADERAT 0xf29a0040 +#define F0900_P2_CAR2S2_32A_ALPH_M 0xf29a0030 +#define F0900_P2_CAR2S2_32A_ALPH_E 0xf29a000f /*P2_BCLC2S2Q*/ -#define R0900_P2_BCLC2S2Q 0xf29c -#define F0900_P2_DVBS2S2Q_NIP 0xf29c0080 -#define F0900_P2_CAR2S2_QBDERAT 0xf29c0040 -#define F0900_P2_CAR2S2_Q_BETA_M 0xf29c0030 -#define F0900_P2_CAR2S2_Q_BETA_E 0xf29c000f +#define R0900_P2_BCLC2S2Q 0xf29c +#define F0900_P2_CAR2S2_Q_BETA_M 0xf29c0030 +#define F0900_P2_CAR2S2_Q_BETA_E 0xf29c000f /*P2_BCLC2S28*/ -#define R0900_P2_BCLC2S28 0xf29d -#define F0900_P2_DVBS2S28_NIP 0xf29d0080 -#define F0900_P2_CAR2S2_8BDERAT 0xf29d0040 -#define F0900_P2_CAR2S2_8_BETA_M 0xf29d0030 -#define F0900_P2_CAR2S2_8_BETA_E 0xf29d000f +#define R0900_P2_BCLC2S28 0xf29d +#define F0900_P2_CAR2S2_8_BETA_M 0xf29d0030 +#define F0900_P2_CAR2S2_8_BETA_E 0xf29d000f /*P2_BCLC2S216A*/ -#define R0900_P2_BCLC2S216A 0xf29e -#define F0900_P2_DVBS2S216A_NIP 0xf29e0080 -#define F0900_P2_CAR2S2_16BDERAT 0xf29e0040 -#define F0900_P2_CAR2S2_16A_BETA_M 0xf29e0030 -#define F0900_P2_CAR2S2_16A_BETA_E 0xf29e000f +#define R0900_P2_BCLC2S216A 0xf29e /*P2_BCLC2S232A*/ -#define R0900_P2_BCLC2S232A 0xf29f -#define F0900_P2_DVBS2S232A_NIP 0xf29f0080 -#define F0900_P2_CAR2S2_32BDERAT 0xf29f0040 -#define F0900_P2_CAR2S2_32A_BETA_M 0xf29f0030 -#define F0900_P2_CAR2S2_32A_BETA_E 0xf29f000f +#define R0900_P2_BCLC2S232A 0xf29f /*P2_PLROOT2*/ -#define R0900_P2_PLROOT2 0xf2ac -#define F0900_P2_SHORTFR_DISABLE 0xf2ac0080 -#define F0900_P2_LONGFR_DISABLE 0xf2ac0040 -#define F0900_P2_DUMMYPL_DISABLE 0xf2ac0020 -#define F0900_P2_SHORTFR_AVOID 0xf2ac0010 -#define F0900_P2_PLSCRAMB_MODE 0xf2ac000c -#define F0900_P2_PLSCRAMB_ROOT2 0xf2ac0003 +#define R0900_P2_PLROOT2 0xf2ac +#define F0900_P2_PLSCRAMB_MODE 0xf2ac000c +#define F0900_P2_PLSCRAMB_ROOT2 0xf2ac0003 /*P2_PLROOT1*/ -#define R0900_P2_PLROOT1 0xf2ad -#define F0900_P2_PLSCRAMB_ROOT1 0xf2ad00ff +#define R0900_P2_PLROOT1 0xf2ad +#define F0900_P2_PLSCRAMB_ROOT1 0xf2ad00ff /*P2_PLROOT0*/ -#define R0900_P2_PLROOT0 0xf2ae -#define F0900_P2_PLSCRAMB_ROOT0 0xf2ae00ff +#define R0900_P2_PLROOT0 0xf2ae +#define F0900_P2_PLSCRAMB_ROOT0 0xf2ae00ff /*P2_MODCODLST0*/ -#define R0900_P2_MODCODLST0 0xf2b0 -#define F0900_P2_EN_TOKEN31 0xf2b00080 -#define F0900_P2_SYNCTAG_SELECT 0xf2b00040 -#define F0900_P2_MODCODRQ_MODE 0xf2b00030 +#define R0900_P2_MODCODLST0 0xf2b0 /*P2_MODCODLST1*/ -#define R0900_P2_MODCODLST1 0xf2b1 -#define F0900_P2_DIS_MODCOD29 0xf2b100f0 -#define F0900_P2_DIS_32PSK_9_10 0xf2b1000f +#define R0900_P2_MODCODLST1 0xf2b1 +#define F0900_P2_DIS_MODCOD29 0xf2b100f0 +#define F0900_P2_DIS_32PSK_9_10 0xf2b1000f /*P2_MODCODLST2*/ -#define R0900_P2_MODCODLST2 0xf2b2 -#define F0900_P2_DIS_32PSK_8_9 0xf2b200f0 -#define F0900_P2_DIS_32PSK_5_6 0xf2b2000f +#define R0900_P2_MODCODLST2 0xf2b2 +#define F0900_P2_DIS_32PSK_8_9 0xf2b200f0 +#define F0900_P2_DIS_32PSK_5_6 0xf2b2000f /*P2_MODCODLST3*/ -#define R0900_P2_MODCODLST3 0xf2b3 -#define F0900_P2_DIS_32PSK_4_5 0xf2b300f0 -#define F0900_P2_DIS_32PSK_3_4 0xf2b3000f +#define R0900_P2_MODCODLST3 0xf2b3 +#define F0900_P2_DIS_32PSK_4_5 0xf2b300f0 +#define F0900_P2_DIS_32PSK_3_4 0xf2b3000f /*P2_MODCODLST4*/ -#define R0900_P2_MODCODLST4 0xf2b4 -#define F0900_P2_DIS_16PSK_9_10 0xf2b400f0 -#define F0900_P2_DIS_16PSK_8_9 0xf2b4000f +#define R0900_P2_MODCODLST4 0xf2b4 +#define F0900_P2_DIS_16PSK_9_10 0xf2b400f0 +#define F0900_P2_DIS_16PSK_8_9 0xf2b4000f /*P2_MODCODLST5*/ -#define R0900_P2_MODCODLST5 0xf2b5 -#define F0900_P2_DIS_16PSK_5_6 0xf2b500f0 -#define F0900_P2_DIS_16PSK_4_5 0xf2b5000f +#define R0900_P2_MODCODLST5 0xf2b5 +#define F0900_P2_DIS_16PSK_5_6 0xf2b500f0 +#define F0900_P2_DIS_16PSK_4_5 0xf2b5000f /*P2_MODCODLST6*/ -#define R0900_P2_MODCODLST6 0xf2b6 -#define F0900_P2_DIS_16PSK_3_4 0xf2b600f0 -#define F0900_P2_DIS_16PSK_2_3 0xf2b6000f +#define R0900_P2_MODCODLST6 0xf2b6 +#define F0900_P2_DIS_16PSK_3_4 0xf2b600f0 +#define F0900_P2_DIS_16PSK_2_3 0xf2b6000f /*P2_MODCODLST7*/ -#define R0900_P2_MODCODLST7 0xf2b7 -#define F0900_P2_DIS_8P_9_10 0xf2b700f0 -#define F0900_P2_DIS_8P_8_9 0xf2b7000f +#define R0900_P2_MODCODLST7 0xf2b7 +#define F0900_P2_DIS_8P_9_10 0xf2b700f0 +#define F0900_P2_DIS_8P_8_9 0xf2b7000f /*P2_MODCODLST8*/ -#define R0900_P2_MODCODLST8 0xf2b8 -#define F0900_P2_DIS_8P_5_6 0xf2b800f0 -#define F0900_P2_DIS_8P_3_4 0xf2b8000f +#define R0900_P2_MODCODLST8 0xf2b8 +#define F0900_P2_DIS_8P_5_6 0xf2b800f0 +#define F0900_P2_DIS_8P_3_4 0xf2b8000f /*P2_MODCODLST9*/ -#define R0900_P2_MODCODLST9 0xf2b9 -#define F0900_P2_DIS_8P_2_3 0xf2b900f0 -#define F0900_P2_DIS_8P_3_5 0xf2b9000f +#define R0900_P2_MODCODLST9 0xf2b9 +#define F0900_P2_DIS_8P_2_3 0xf2b900f0 +#define F0900_P2_DIS_8P_3_5 0xf2b9000f /*P2_MODCODLSTA*/ -#define R0900_P2_MODCODLSTA 0xf2ba -#define F0900_P2_DIS_QP_9_10 0xf2ba00f0 -#define F0900_P2_DIS_QP_8_9 0xf2ba000f +#define R0900_P2_MODCODLSTA 0xf2ba +#define F0900_P2_DIS_QP_9_10 0xf2ba00f0 +#define F0900_P2_DIS_QP_8_9 0xf2ba000f /*P2_MODCODLSTB*/ -#define R0900_P2_MODCODLSTB 0xf2bb -#define F0900_P2_DIS_QP_5_6 0xf2bb00f0 -#define F0900_P2_DIS_QP_4_5 0xf2bb000f +#define R0900_P2_MODCODLSTB 0xf2bb +#define F0900_P2_DIS_QP_5_6 0xf2bb00f0 +#define F0900_P2_DIS_QP_4_5 0xf2bb000f /*P2_MODCODLSTC*/ -#define R0900_P2_MODCODLSTC 0xf2bc -#define F0900_P2_DIS_QP_3_4 0xf2bc00f0 -#define F0900_P2_DIS_QP_2_3 0xf2bc000f +#define R0900_P2_MODCODLSTC 0xf2bc +#define F0900_P2_DIS_QP_3_4 0xf2bc00f0 +#define F0900_P2_DIS_QP_2_3 0xf2bc000f /*P2_MODCODLSTD*/ -#define R0900_P2_MODCODLSTD 0xf2bd -#define F0900_P2_DIS_QP_3_5 0xf2bd00f0 -#define F0900_P2_DIS_QP_1_2 0xf2bd000f +#define R0900_P2_MODCODLSTD 0xf2bd +#define F0900_P2_DIS_QP_3_5 0xf2bd00f0 +#define F0900_P2_DIS_QP_1_2 0xf2bd000f /*P2_MODCODLSTE*/ -#define R0900_P2_MODCODLSTE 0xf2be -#define F0900_P2_DIS_QP_2_5 0xf2be00f0 -#define F0900_P2_DIS_QP_1_3 0xf2be000f +#define R0900_P2_MODCODLSTE 0xf2be +#define F0900_P2_DIS_QP_2_5 0xf2be00f0 +#define F0900_P2_DIS_QP_1_3 0xf2be000f /*P2_MODCODLSTF*/ -#define R0900_P2_MODCODLSTF 0xf2bf -#define F0900_P2_DIS_QP_1_4 0xf2bf00f0 -#define F0900_P2_DDEMOD_SET 0xf2bf0002 -#define F0900_P2_DDEMOD_MASK 0xf2bf0001 +#define R0900_P2_MODCODLSTF 0xf2bf +#define F0900_P2_DIS_QP_1_4 0xf2bf00f0 + +/*P2_GAUSSR0*/ +#define R0900_P2_GAUSSR0 0xf2c0 +#define F0900_P2_EN_CCIMODE 0xf2c00080 +#define F0900_P2_R0_GAUSSIEN 0xf2c0007f + +/*P2_CCIR0*/ +#define R0900_P2_CCIR0 0xf2c1 +#define F0900_P2_CCIDETECT_PLHONLY 0xf2c10080 +#define F0900_P2_R0_CCI 0xf2c1007f + +/*P2_CCIQUANT*/ +#define R0900_P2_CCIQUANT 0xf2c2 +#define F0900_P2_CCI_BETA 0xf2c200e0 +#define F0900_P2_CCI_QUANT 0xf2c2001f + +/*P2_CCITHRES*/ +#define R0900_P2_CCITHRES 0xf2c3 +#define F0900_P2_CCI_THRESHOLD 0xf2c300ff + +/*P2_CCIACC*/ +#define R0900_P2_CCIACC 0xf2c4 +#define F0900_P2_CCI_VALUE 0xf2c400ff /*P2_DMDRESCFG*/ -#define R0900_P2_DMDRESCFG 0xf2c6 -#define F0900_P2_DMDRES_RESET 0xf2c60080 -#define F0900_P2_DMDRES_NOISESQR 0xf2c60010 -#define F0900_P2_DMDRES_STRALL 0xf2c60008 -#define F0900_P2_DMDRES_NEWONLY 0xf2c60004 -#define F0900_P2_DMDRES_NOSTORE 0xf2c60002 -#define F0900_P2_DMDRES_AGC2MEM 0xf2c60001 +#define R0900_P2_DMDRESCFG 0xf2c6 +#define F0900_P2_DMDRES_RESET 0xf2c60080 +#define F0900_P2_DMDRES_STRALL 0xf2c60008 +#define F0900_P2_DMDRES_NEWONLY 0xf2c60004 +#define F0900_P2_DMDRES_NOSTORE 0xf2c60002 /*P2_DMDRESADR*/ -#define R0900_P2_DMDRESADR 0xf2c7 -#define F0900_P2_SUSP_PREDCANAL 0xf2c70080 -#define F0900_P2_DMDRES_VALIDCFR 0xf2c70040 -#define F0900_P2_DMDRES_MEMFULL 0xf2c70030 -#define F0900_P2_DMDRES_RESNBR 0xf2c7000f +#define R0900_P2_DMDRESADR 0xf2c7 +#define F0900_P2_DMDRES_VALIDCFR 0xf2c70040 +#define F0900_P2_DMDRES_MEMFULL 0xf2c70030 +#define F0900_P2_DMDRES_RESNBR 0xf2c7000f /*P2_DMDRESDATA7*/ -#define R0900_P2_DMDRESDATA7 0xf2c8 -#define F0900_P2_DMDRES_DATA7 0xf2c800ff +#define R0900_P2_DMDRESDATA7 0xf2c8 +#define F0900_P2_DMDRES_DATA7 0xf2c800ff /*P2_DMDRESDATA6*/ -#define R0900_P2_DMDRESDATA6 0xf2c9 -#define F0900_P2_DMDRES_DATA6 0xf2c900ff +#define R0900_P2_DMDRESDATA6 0xf2c9 +#define F0900_P2_DMDRES_DATA6 0xf2c900ff /*P2_DMDRESDATA5*/ -#define R0900_P2_DMDRESDATA5 0xf2ca -#define F0900_P2_DMDRES_DATA5 0xf2ca00ff +#define R0900_P2_DMDRESDATA5 0xf2ca +#define F0900_P2_DMDRES_DATA5 0xf2ca00ff /*P2_DMDRESDATA4*/ -#define R0900_P2_DMDRESDATA4 0xf2cb -#define F0900_P2_DMDRES_DATA4 0xf2cb00ff +#define R0900_P2_DMDRESDATA4 0xf2cb +#define F0900_P2_DMDRES_DATA4 0xf2cb00ff /*P2_DMDRESDATA3*/ -#define R0900_P2_DMDRESDATA3 0xf2cc -#define F0900_P2_DMDRES_DATA3 0xf2cc00ff +#define R0900_P2_DMDRESDATA3 0xf2cc +#define F0900_P2_DMDRES_DATA3 0xf2cc00ff /*P2_DMDRESDATA2*/ -#define R0900_P2_DMDRESDATA2 0xf2cd -#define F0900_P2_DMDRES_DATA2 0xf2cd00ff +#define R0900_P2_DMDRESDATA2 0xf2cd +#define F0900_P2_DMDRES_DATA2 0xf2cd00ff /*P2_DMDRESDATA1*/ -#define R0900_P2_DMDRESDATA1 0xf2ce -#define F0900_P2_DMDRES_DATA1 0xf2ce00ff +#define R0900_P2_DMDRESDATA1 0xf2ce +#define F0900_P2_DMDRES_DATA1 0xf2ce00ff /*P2_DMDRESDATA0*/ -#define R0900_P2_DMDRESDATA0 0xf2cf -#define F0900_P2_DMDRES_DATA0 0xf2cf00ff +#define R0900_P2_DMDRESDATA0 0xf2cf +#define F0900_P2_DMDRES_DATA0 0xf2cf00ff /*P2_FFEI1*/ -#define R0900_P2_FFEI1 0xf2d0 -#define F0900_P2_FFE_ACCI1 0xf2d001ff +#define R0900_P2_FFEI1 0xf2d0 +#define F0900_P2_FFE_ACCI1 0xf2d001ff /*P2_FFEQ1*/ -#define R0900_P2_FFEQ1 0xf2d1 -#define F0900_P2_FFE_ACCQ1 0xf2d101ff +#define R0900_P2_FFEQ1 0xf2d1 +#define F0900_P2_FFE_ACCQ1 0xf2d101ff /*P2_FFEI2*/ -#define R0900_P2_FFEI2 0xf2d2 -#define F0900_P2_FFE_ACCI2 0xf2d201ff +#define R0900_P2_FFEI2 0xf2d2 +#define F0900_P2_FFE_ACCI2 0xf2d201ff /*P2_FFEQ2*/ -#define R0900_P2_FFEQ2 0xf2d3 -#define F0900_P2_FFE_ACCQ2 0xf2d301ff +#define R0900_P2_FFEQ2 0xf2d3 +#define F0900_P2_FFE_ACCQ2 0xf2d301ff /*P2_FFEI3*/ -#define R0900_P2_FFEI3 0xf2d4 -#define F0900_P2_FFE_ACCI3 0xf2d401ff +#define R0900_P2_FFEI3 0xf2d4 +#define F0900_P2_FFE_ACCI3 0xf2d401ff /*P2_FFEQ3*/ -#define R0900_P2_FFEQ3 0xf2d5 -#define F0900_P2_FFE_ACCQ3 0xf2d501ff +#define R0900_P2_FFEQ3 0xf2d5 +#define F0900_P2_FFE_ACCQ3 0xf2d501ff /*P2_FFEI4*/ -#define R0900_P2_FFEI4 0xf2d6 -#define F0900_P2_FFE_ACCI4 0xf2d601ff +#define R0900_P2_FFEI4 0xf2d6 +#define F0900_P2_FFE_ACCI4 0xf2d601ff /*P2_FFEQ4*/ -#define R0900_P2_FFEQ4 0xf2d7 -#define F0900_P2_FFE_ACCQ4 0xf2d701ff +#define R0900_P2_FFEQ4 0xf2d7 +#define F0900_P2_FFE_ACCQ4 0xf2d701ff /*P2_FFECFG*/ -#define R0900_P2_FFECFG 0xf2d8 -#define F0900_P2_EQUALFFE_ON 0xf2d80040 -#define F0900_P2_EQUAL_USEDSYMB 0xf2d80030 -#define F0900_P2_MU_EQUALFFE 0xf2d80007 +#define R0900_P2_FFECFG 0xf2d8 +#define F0900_P2_EQUALFFE_ON 0xf2d80040 +#define F0900_P2_MU_EQUALFFE 0xf2d80007 /*P2_TNRCFG*/ -#define R0900_P2_TNRCFG 0xf2e0 -#define F0900_P2_TUN_ACKFAIL 0xf2e00080 -#define F0900_P2_TUN_TYPE 0xf2e00070 -#define F0900_P2_TUN_SECSTOP 0xf2e00008 -#define F0900_P2_TUN_VCOSRCH 0xf2e00004 -#define F0900_P2_TUN_MADDRESS 0xf2e00003 +#define R0900_P2_TNRCFG 0xf2e0 +#define F0900_P2_TUN_ACKFAIL 0xf2e00080 +#define F0900_P2_TUN_TYPE 0xf2e00070 +#define F0900_P2_TUN_SECSTOP 0xf2e00008 +#define F0900_P2_TUN_VCOSRCH 0xf2e00004 +#define F0900_P2_TUN_MADDRESS 0xf2e00003 /*P2_TNRCFG2*/ -#define R0900_P2_TNRCFG2 0xf2e1 -#define F0900_P2_TUN_IQSWAP 0xf2e10080 -#define F0900_P2_STB6110_STEP2MHZ 0xf2e10040 -#define F0900_P2_STB6120_DBLI2C 0xf2e10020 -#define F0900_P2_DIS_FCCK 0xf2e10010 -#define F0900_P2_DIS_LPEN 0xf2e10008 -#define F0900_P2_DIS_BWCALC 0xf2e10004 -#define F0900_P2_SHORT_WAITSTATES 0xf2e10002 -#define F0900_P2_DIS_2BWAGC1 0xf2e10001 +#define R0900_P2_TNRCFG2 0xf2e1 +#define F0900_P2_TUN_IQSWAP 0xf2e10080 +#define F0900_P2_DIS_BWCALC 0xf2e10004 +#define F0900_P2_SHORT_WAITSTATES 0xf2e10002 /*P2_TNRXTAL*/ -#define R0900_P2_TNRXTAL 0xf2e4 -#define F0900_P2_TUN_MCLKDECIMAL 0xf2e400e0 -#define F0900_P2_TUN_XTALFREQ 0xf2e4001f +#define R0900_P2_TNRXTAL 0xf2e4 +#define F0900_P2_TUN_XTALFREQ 0xf2e4001f /*P2_TNRSTEPS*/ -#define R0900_P2_TNRSTEPS 0xf2e7 -#define F0900_P2_TUNER_BW1P6 0xf2e70080 -#define F0900_P2_BWINC_OFFSET 0xf2e70070 -#define F0900_P2_SOFTSTEP_RNG 0xf2e70008 -#define F0900_P2_TUN_BWOFFSET 0xf2e70107 +#define R0900_P2_TNRSTEPS 0xf2e7 +#define F0900_P2_TUNER_BW0P125 0xf2e70080 +#define F0900_P2_BWINC_OFFSET 0xf2e70170 +#define F0900_P2_SOFTSTEP_RNG 0xf2e70008 +#define F0900_P2_TUN_BWOFFSET 0xf2e70007 /*P2_TNRGAIN*/ -#define R0900_P2_TNRGAIN 0xf2e8 -#define F0900_P2_TUN_KDIVEN 0xf2e800c0 -#define F0900_P2_STB6X00_OCK 0xf2e80030 -#define F0900_P2_TUN_GAIN 0xf2e8000f +#define R0900_P2_TNRGAIN 0xf2e8 +#define F0900_P2_TUN_KDIVEN 0xf2e800c0 +#define F0900_P2_STB6X00_OCK 0xf2e80030 +#define F0900_P2_TUN_GAIN 0xf2e8000f /*P2_TNRRF1*/ -#define R0900_P2_TNRRF1 0xf2e9 -#define F0900_P2_TUN_RFFREQ2 0xf2e900ff +#define R0900_P2_TNRRF1 0xf2e9 +#define F0900_P2_TUN_RFFREQ2 0xf2e900ff /*P2_TNRRF0*/ -#define R0900_P2_TNRRF0 0xf2ea -#define F0900_P2_TUN_RFFREQ1 0xf2ea00ff +#define R0900_P2_TNRRF0 0xf2ea +#define F0900_P2_TUN_RFFREQ1 0xf2ea00ff /*P2_TNRBW*/ -#define R0900_P2_TNRBW 0xf2eb -#define F0900_P2_TUN_RFFREQ0 0xf2eb00c0 -#define F0900_P2_TUN_BW 0xf2eb003f +#define R0900_P2_TNRBW 0xf2eb +#define F0900_P2_TUN_RFFREQ0 0xf2eb00c0 +#define F0900_P2_TUN_BW 0xf2eb003f /*P2_TNRADJ*/ -#define R0900_P2_TNRADJ 0xf2ec -#define F0900_P2_STB61X0_RCLK 0xf2ec0080 -#define F0900_P2_STB61X0_CALTIME 0xf2ec0040 -#define F0900_P2_STB6X00_DLB 0xf2ec0038 -#define F0900_P2_STB6000_FCL 0xf2ec0007 +#define R0900_P2_TNRADJ 0xf2ec +#define F0900_P2_STB61X0_CALTIME 0xf2ec0040 /*P2_TNRCTL2*/ -#define R0900_P2_TNRCTL2 0xf2ed -#define F0900_P2_STB61X0_LCP1_RCCKOFF 0xf2ed0080 -#define F0900_P2_STB61X0_LCP0 0xf2ed0040 -#define F0900_P2_STB61X0_XTOUT_RFOUTS 0xf2ed0020 -#define F0900_P2_STB61X0_XTON_MCKDV 0xf2ed0010 -#define F0900_P2_STB61X0_CALOFF_DCOFF 0xf2ed0008 -#define F0900_P2_STB6110_LPT 0xf2ed0004 -#define F0900_P2_STB6110_RX 0xf2ed0002 -#define F0900_P2_STB6110_SYN 0xf2ed0001 +#define R0900_P2_TNRCTL2 0xf2ed +#define F0900_P2_STB61X0_RCCKOFF 0xf2ed0080 +#define F0900_P2_STB61X0_ICP_SDOFF 0xf2ed0040 +#define F0900_P2_STB61X0_DCLOOPOFF 0xf2ed0020 +#define F0900_P2_STB61X0_REFOUTSEL 0xf2ed0010 +#define F0900_P2_STB61X0_CALOFF 0xf2ed0008 +#define F0900_P2_STB6XX0_LPT_BEN 0xf2ed0004 +#define F0900_P2_STB6XX0_RX_OSCP 0xf2ed0002 +#define F0900_P2_STB6XX0_SYN 0xf2ed0001 /*P2_TNRCFG3*/ -#define R0900_P2_TNRCFG3 0xf2ee -#define F0900_P2_STB6120_DISCTRL1 0xf2ee0080 -#define F0900_P2_STB6120_INVORDER 0xf2ee0040 -#define F0900_P2_STB6120_ENCTRL6 0xf2ee0020 -#define F0900_P2_TUN_PLLFREQ 0xf2ee001c -#define F0900_P2_TUN_I2CFREQ_MODE 0xf2ee0003 +#define R0900_P2_TNRCFG3 0xf2ee +#define F0900_P2_TUN_PLLFREQ 0xf2ee001c +#define F0900_P2_TUN_I2CFREQ_MODE 0xf2ee0003 /*P2_TNRLAUNCH*/ -#define R0900_P2_TNRLAUNCH 0xf2f0 +#define R0900_P2_TNRLAUNCH 0xf2f0 /*P2_TNRLD*/ -#define R0900_P2_TNRLD 0xf2f0 -#define F0900_P2_TUNLD_VCOING 0xf2f00080 -#define F0900_P2_TUN_REG1FAIL 0xf2f00040 -#define F0900_P2_TUN_REG2FAIL 0xf2f00020 -#define F0900_P2_TUN_REG3FAIL 0xf2f00010 -#define F0900_P2_TUN_REG4FAIL 0xf2f00008 -#define F0900_P2_TUN_REG5FAIL 0xf2f00004 -#define F0900_P2_TUN_BWING 0xf2f00002 -#define F0900_P2_TUN_LOCKED 0xf2f00001 +#define R0900_P2_TNRLD 0xf2f0 +#define F0900_P2_TUNLD_VCOING 0xf2f00080 +#define F0900_P2_TUN_REG1FAIL 0xf2f00040 +#define F0900_P2_TUN_REG2FAIL 0xf2f00020 +#define F0900_P2_TUN_REG3FAIL 0xf2f00010 +#define F0900_P2_TUN_REG4FAIL 0xf2f00008 +#define F0900_P2_TUN_REG5FAIL 0xf2f00004 +#define F0900_P2_TUN_BWING 0xf2f00002 +#define F0900_P2_TUN_LOCKED 0xf2f00001 /*P2_TNROBSL*/ -#define R0900_P2_TNROBSL 0xf2f6 -#define F0900_P2_TUN_I2CABORTED 0xf2f60080 -#define F0900_P2_TUN_LPEN 0xf2f60040 -#define F0900_P2_TUN_FCCK 0xf2f60020 -#define F0900_P2_TUN_I2CLOCKED 0xf2f60010 -#define F0900_P2_TUN_PROGDONE 0xf2f6000c -#define F0900_P2_TUN_RFRESTE1 0xf2f60003 +#define R0900_P2_TNROBSL 0xf2f6 +#define F0900_P2_TUN_I2CABORTED 0xf2f60080 +#define F0900_P2_TUN_LPEN 0xf2f60040 +#define F0900_P2_TUN_FCCK 0xf2f60020 +#define F0900_P2_TUN_I2CLOCKED 0xf2f60010 +#define F0900_P2_TUN_PROGDONE 0xf2f6000c +#define F0900_P2_TUN_RFRESTE1 0xf2f60003 /*P2_TNRRESTE*/ -#define R0900_P2_TNRRESTE 0xf2f7 -#define F0900_P2_TUN_RFRESTE0 0xf2f700ff +#define R0900_P2_TNRRESTE 0xf2f7 +#define F0900_P2_TUN_RFRESTE0 0xf2f700ff /*P2_SMAPCOEF7*/ -#define R0900_P2_SMAPCOEF7 0xf300 -#define F0900_P2_DIS_QSCALE 0xf3000080 -#define F0900_P2_SMAPCOEF_Q_LLR12 0xf300017f +#define R0900_P2_SMAPCOEF7 0xf300 +#define F0900_P2_DIS_QSCALE 0xf3000080 +#define F0900_P2_SMAPCOEF_Q_LLR12 0xf300017f /*P2_SMAPCOEF6*/ -#define R0900_P2_SMAPCOEF6 0xf301 -#define F0900_P2_DIS_NEWSCALE 0xf3010008 -#define F0900_P2_ADJ_8PSKLLR1 0xf3010004 -#define F0900_P2_OLD_8PSKLLR1 0xf3010002 -#define F0900_P2_DIS_AB8PSK 0xf3010001 +#define R0900_P2_SMAPCOEF6 0xf301 +#define F0900_P2_ADJ_8PSKLLR1 0xf3010004 +#define F0900_P2_OLD_8PSKLLR1 0xf3010002 +#define F0900_P2_DIS_AB8PSK 0xf3010001 /*P2_SMAPCOEF5*/ -#define R0900_P2_SMAPCOEF5 0xf302 -#define F0900_P2_DIS_8SCALE 0xf3020080 -#define F0900_P2_SMAPCOEF_8P_LLR23 0xf302017f +#define R0900_P2_SMAPCOEF5 0xf302 +#define F0900_P2_DIS_8SCALE 0xf3020080 +#define F0900_P2_SMAPCOEF_8P_LLR23 0xf302017f + +/*P2_NCO2MAX1*/ +#define R0900_P2_NCO2MAX1 0xf314 +#define F0900_P2_TETA2_MAXVABS1 0xf31400ff + +/*P2_NCO2MAX0*/ +#define R0900_P2_NCO2MAX0 0xf315 +#define F0900_P2_TETA2_MAXVABS0 0xf31500ff + +/*P2_NCO2FR1*/ +#define R0900_P2_NCO2FR1 0xf316 +#define F0900_P2_NCO2FINAL_ANGLE1 0xf31600ff + +/*P2_NCO2FR0*/ +#define R0900_P2_NCO2FR0 0xf317 +#define F0900_P2_NCO2FINAL_ANGLE0 0xf31700ff + +/*P2_CFR2AVRGE1*/ +#define R0900_P2_CFR2AVRGE1 0xf318 +#define F0900_P2_I2C_CFR2AVERAGE1 0xf31800ff + +/*P2_CFR2AVRGE0*/ +#define R0900_P2_CFR2AVRGE0 0xf319 +#define F0900_P2_I2C_CFR2AVERAGE0 0xf31900ff /*P2_DMDPLHSTAT*/ -#define R0900_P2_DMDPLHSTAT 0xf320 -#define F0900_P2_PLH_STATISTIC 0xf32000ff +#define R0900_P2_DMDPLHSTAT 0xf320 +#define F0900_P2_PLH_STATISTIC 0xf32000ff /*P2_LOCKTIME3*/ -#define R0900_P2_LOCKTIME3 0xf322 -#define F0900_P2_DEMOD_LOCKTIME3 0xf32200ff +#define R0900_P2_LOCKTIME3 0xf322 +#define F0900_P2_DEMOD_LOCKTIME3 0xf32200ff /*P2_LOCKTIME2*/ -#define R0900_P2_LOCKTIME2 0xf323 -#define F0900_P2_DEMOD_LOCKTIME2 0xf32300ff +#define R0900_P2_LOCKTIME2 0xf323 +#define F0900_P2_DEMOD_LOCKTIME2 0xf32300ff /*P2_LOCKTIME1*/ -#define R0900_P2_LOCKTIME1 0xf324 -#define F0900_P2_DEMOD_LOCKTIME1 0xf32400ff +#define R0900_P2_LOCKTIME1 0xf324 +#define F0900_P2_DEMOD_LOCKTIME1 0xf32400ff /*P2_LOCKTIME0*/ -#define R0900_P2_LOCKTIME0 0xf325 -#define F0900_P2_DEMOD_LOCKTIME0 0xf32500ff +#define R0900_P2_LOCKTIME0 0xf325 +#define F0900_P2_DEMOD_LOCKTIME0 0xf32500ff /*P2_VITSCALE*/ -#define R0900_P2_VITSCALE 0xf332 -#define F0900_P2_NVTH_NOSRANGE 0xf3320080 -#define F0900_P2_VERROR_MAXMODE 0xf3320040 -#define F0900_P2_KDIV_MODE 0xf3320030 -#define F0900_P2_NSLOWSN_LOCKED 0xf3320008 -#define F0900_P2_DELOCK_PRFLOSS 0xf3320004 -#define F0900_P2_DIS_RSFLOCK 0xf3320002 +#define R0900_P2_VITSCALE 0xf332 +#define F0900_P2_NVTH_NOSRANGE 0xf3320080 +#define F0900_P2_VERROR_MAXMODE 0xf3320040 +#define F0900_P2_NSLOWSN_LOCKED 0xf3320008 +#define F0900_P2_DIS_RSFLOCK 0xf3320002 /*P2_FECM*/ -#define R0900_P2_FECM 0xf333 -#define F0900_P2_DSS_DVB 0xf3330080 -#define F0900_P2_DEMOD_BYPASS 0xf3330040 -#define F0900_P2_CMP_SLOWMODE 0xf3330020 -#define F0900_P2_DSS_SRCH 0xf3330010 -#define F0900_P2_DIFF_MODEVIT 0xf3330004 -#define F0900_P2_SYNCVIT 0xf3330002 -#define F0900_P2_IQINV 0xf3330001 +#define R0900_P2_FECM 0xf333 +#define F0900_P2_DSS_DVB 0xf3330080 +#define F0900_P2_DSS_SRCH 0xf3330010 +#define F0900_P2_SYNCVIT 0xf3330002 +#define F0900_P2_IQINV 0xf3330001 /*P2_VTH12*/ -#define R0900_P2_VTH12 0xf334 -#define F0900_P2_VTH12 0xf33400ff +#define R0900_P2_VTH12 0xf334 +#define F0900_P2_VTH12 0xf33400ff /*P2_VTH23*/ -#define R0900_P2_VTH23 0xf335 -#define F0900_P2_VTH23 0xf33500ff +#define R0900_P2_VTH23 0xf335 +#define F0900_P2_VTH23 0xf33500ff /*P2_VTH34*/ -#define R0900_P2_VTH34 0xf336 -#define F0900_P2_VTH34 0xf33600ff +#define R0900_P2_VTH34 0xf336 +#define F0900_P2_VTH34 0xf33600ff /*P2_VTH56*/ -#define R0900_P2_VTH56 0xf337 -#define F0900_P2_VTH56 0xf33700ff +#define R0900_P2_VTH56 0xf337 +#define F0900_P2_VTH56 0xf33700ff /*P2_VTH67*/ -#define R0900_P2_VTH67 0xf338 -#define F0900_P2_VTH67 0xf33800ff +#define R0900_P2_VTH67 0xf338 +#define F0900_P2_VTH67 0xf33800ff /*P2_VTH78*/ -#define R0900_P2_VTH78 0xf339 -#define F0900_P2_VTH78 0xf33900ff +#define R0900_P2_VTH78 0xf339 +#define F0900_P2_VTH78 0xf33900ff /*P2_VITCURPUN*/ -#define R0900_P2_VITCURPUN 0xf33a -#define F0900_P2_VIT_MAPPING 0xf33a00e0 -#define F0900_P2_VIT_CURPUN 0xf33a001f +#define R0900_P2_VITCURPUN 0xf33a +#define F0900_P2_VIT_CURPUN 0xf33a001f /*P2_VERROR*/ -#define R0900_P2_VERROR 0xf33b -#define F0900_P2_REGERR_VIT 0xf33b00ff +#define R0900_P2_VERROR 0xf33b +#define F0900_P2_REGERR_VIT 0xf33b00ff /*P2_PRVIT*/ -#define R0900_P2_PRVIT 0xf33c -#define F0900_P2_DIS_VTHLOCK 0xf33c0040 -#define F0900_P2_E7_8VIT 0xf33c0020 -#define F0900_P2_E6_7VIT 0xf33c0010 -#define F0900_P2_E5_6VIT 0xf33c0008 -#define F0900_P2_E3_4VIT 0xf33c0004 -#define F0900_P2_E2_3VIT 0xf33c0002 -#define F0900_P2_E1_2VIT 0xf33c0001 +#define R0900_P2_PRVIT 0xf33c +#define F0900_P2_DIS_VTHLOCK 0xf33c0040 +#define F0900_P2_E7_8VIT 0xf33c0020 +#define F0900_P2_E6_7VIT 0xf33c0010 +#define F0900_P2_E5_6VIT 0xf33c0008 +#define F0900_P2_E3_4VIT 0xf33c0004 +#define F0900_P2_E2_3VIT 0xf33c0002 +#define F0900_P2_E1_2VIT 0xf33c0001 /*P2_VAVSRVIT*/ -#define R0900_P2_VAVSRVIT 0xf33d -#define F0900_P2_AMVIT 0xf33d0080 -#define F0900_P2_FROZENVIT 0xf33d0040 -#define F0900_P2_SNVIT 0xf33d0030 -#define F0900_P2_TOVVIT 0xf33d000c -#define F0900_P2_HYPVIT 0xf33d0003 +#define R0900_P2_VAVSRVIT 0xf33d +#define F0900_P2_AMVIT 0xf33d0080 +#define F0900_P2_FROZENVIT 0xf33d0040 +#define F0900_P2_SNVIT 0xf33d0030 +#define F0900_P2_TOVVIT 0xf33d000c +#define F0900_P2_HYPVIT 0xf33d0003 /*P2_VSTATUSVIT*/ -#define R0900_P2_VSTATUSVIT 0xf33e -#define F0900_P2_VITERBI_ON 0xf33e0080 -#define F0900_P2_END_LOOPVIT 0xf33e0040 -#define F0900_P2_VITERBI_DEPRF 0xf33e0020 -#define F0900_P2_PRFVIT 0xf33e0010 -#define F0900_P2_LOCKEDVIT 0xf33e0008 -#define F0900_P2_VITERBI_DELOCK 0xf33e0004 -#define F0900_P2_VIT_DEMODSEL 0xf33e0002 -#define F0900_P2_VITERBI_COMPOUT 0xf33e0001 +#define R0900_P2_VSTATUSVIT 0xf33e +#define F0900_P2_PRFVIT 0xf33e0010 +#define F0900_P2_LOCKEDVIT 0xf33e0008 /*P2_VTHINUSE*/ -#define R0900_P2_VTHINUSE 0xf33f -#define F0900_P2_VIT_INUSE 0xf33f00ff +#define R0900_P2_VTHINUSE 0xf33f +#define F0900_P2_VIT_INUSE 0xf33f00ff /*P2_KDIV12*/ -#define R0900_P2_KDIV12 0xf340 -#define F0900_P2_KDIV12_MANUAL 0xf3400080 -#define F0900_P2_K_DIVIDER_12 0xf340007f +#define R0900_P2_KDIV12 0xf340 +#define F0900_P2_K_DIVIDER_12 0xf340007f /*P2_KDIV23*/ -#define R0900_P2_KDIV23 0xf341 -#define F0900_P2_KDIV23_MANUAL 0xf3410080 -#define F0900_P2_K_DIVIDER_23 0xf341007f +#define R0900_P2_KDIV23 0xf341 +#define F0900_P2_K_DIVIDER_23 0xf341007f /*P2_KDIV34*/ -#define R0900_P2_KDIV34 0xf342 -#define F0900_P2_KDIV34_MANUAL 0xf3420080 -#define F0900_P2_K_DIVIDER_34 0xf342007f +#define R0900_P2_KDIV34 0xf342 +#define F0900_P2_K_DIVIDER_34 0xf342007f /*P2_KDIV56*/ -#define R0900_P2_KDIV56 0xf343 -#define F0900_P2_KDIV56_MANUAL 0xf3430080 -#define F0900_P2_K_DIVIDER_56 0xf343007f +#define R0900_P2_KDIV56 0xf343 +#define F0900_P2_K_DIVIDER_56 0xf343007f /*P2_KDIV67*/ -#define R0900_P2_KDIV67 0xf344 -#define F0900_P2_KDIV67_MANUAL 0xf3440080 -#define F0900_P2_K_DIVIDER_67 0xf344007f +#define R0900_P2_KDIV67 0xf344 +#define F0900_P2_K_DIVIDER_67 0xf344007f /*P2_KDIV78*/ -#define R0900_P2_KDIV78 0xf345 -#define F0900_P2_KDIV78_MANUAL 0xf3450080 -#define F0900_P2_K_DIVIDER_78 0xf345007f +#define R0900_P2_KDIV78 0xf345 +#define F0900_P2_K_DIVIDER_78 0xf345007f /*P2_PDELCTRL1*/ -#define R0900_P2_PDELCTRL1 0xf350 -#define F0900_P2_INV_MISMASK 0xf3500080 -#define F0900_P2_FORCE_ACCEPTED 0xf3500040 -#define F0900_P2_FILTER_EN 0xf3500020 -#define F0900_P2_FORCE_PKTDELINUSE 0xf3500010 -#define F0900_P2_HYSTEN 0xf3500008 -#define F0900_P2_HYSTSWRST 0xf3500004 -#define F0900_P2_EN_MIS00 0xf3500002 -#define F0900_P2_ALGOSWRST 0xf3500001 +#define R0900_P2_PDELCTRL1 0xf350 +#define F0900_P2_INV_MISMASK 0xf3500080 +#define F0900_P2_FILTER_EN 0xf3500020 +#define F0900_P2_EN_MIS00 0xf3500002 +#define F0900_P2_ALGOSWRST 0xf3500001 /*P2_PDELCTRL2*/ -#define R0900_P2_PDELCTRL2 0xf351 -#define F0900_P2_FORCE_CONTINUOUS 0xf3510080 -#define F0900_P2_RESET_UPKO_COUNT 0xf3510040 -#define F0900_P2_USER_PKTDELIN_NB 0xf3510020 -#define F0900_P2_FORCE_LOCKED 0xf3510010 -#define F0900_P2_DATA_UNBBSCRAM 0xf3510008 -#define F0900_P2_FORCE_LONGPKT 0xf3510004 -#define F0900_P2_FRAME_MODE 0xf3510002 +#define R0900_P2_PDELCTRL2 0xf351 +#define F0900_P2_RESET_UPKO_COUNT 0xf3510040 +#define F0900_P2_FRAME_MODE 0xf3510002 +#define F0900_P2_NOBCHERRFLG_USE 0xf3510001 /*P2_HYSTTHRESH*/ -#define R0900_P2_HYSTTHRESH 0xf354 -#define F0900_P2_UNLCK_THRESH 0xf35400f0 -#define F0900_P2_DELIN_LCK_THRESH 0xf354000f +#define R0900_P2_HYSTTHRESH 0xf354 +#define F0900_P2_UNLCK_THRESH 0xf35400f0 +#define F0900_P2_DELIN_LCK_THRESH 0xf354000f /*P2_ISIENTRY*/ -#define R0900_P2_ISIENTRY 0xf35e -#define F0900_P2_ISI_ENTRY 0xf35e00ff +#define R0900_P2_ISIENTRY 0xf35e +#define F0900_P2_ISI_ENTRY 0xf35e00ff /*P2_ISIBITENA*/ -#define R0900_P2_ISIBITENA 0xf35f -#define F0900_P2_ISI_BIT_EN 0xf35f00ff +#define R0900_P2_ISIBITENA 0xf35f +#define F0900_P2_ISI_BIT_EN 0xf35f00ff /*P2_MATSTR1*/ -#define R0900_P2_MATSTR1 0xf360 -#define F0900_P2_MATYPE_CURRENT1 0xf36000ff +#define R0900_P2_MATSTR1 0xf360 +#define F0900_P2_MATYPE_CURRENT1 0xf36000ff /*P2_MATSTR0*/ -#define R0900_P2_MATSTR0 0xf361 -#define F0900_P2_MATYPE_CURRENT0 0xf36100ff +#define R0900_P2_MATSTR0 0xf361 +#define F0900_P2_MATYPE_CURRENT0 0xf36100ff /*P2_UPLSTR1*/ -#define R0900_P2_UPLSTR1 0xf362 -#define F0900_P2_UPL_CURRENT1 0xf36200ff +#define R0900_P2_UPLSTR1 0xf362 +#define F0900_P2_UPL_CURRENT1 0xf36200ff /*P2_UPLSTR0*/ -#define R0900_P2_UPLSTR0 0xf363 -#define F0900_P2_UPL_CURRENT0 0xf36300ff +#define R0900_P2_UPLSTR0 0xf363 +#define F0900_P2_UPL_CURRENT0 0xf36300ff /*P2_DFLSTR1*/ -#define R0900_P2_DFLSTR1 0xf364 -#define F0900_P2_DFL_CURRENT1 0xf36400ff +#define R0900_P2_DFLSTR1 0xf364 +#define F0900_P2_DFL_CURRENT1 0xf36400ff /*P2_DFLSTR0*/ -#define R0900_P2_DFLSTR0 0xf365 -#define F0900_P2_DFL_CURRENT0 0xf36500ff +#define R0900_P2_DFLSTR0 0xf365 +#define F0900_P2_DFL_CURRENT0 0xf36500ff /*P2_SYNCSTR*/ -#define R0900_P2_SYNCSTR 0xf366 -#define F0900_P2_SYNC_CURRENT 0xf36600ff +#define R0900_P2_SYNCSTR 0xf366 +#define F0900_P2_SYNC_CURRENT 0xf36600ff /*P2_SYNCDSTR1*/ -#define R0900_P2_SYNCDSTR1 0xf367 -#define F0900_P2_SYNCD_CURRENT1 0xf36700ff +#define R0900_P2_SYNCDSTR1 0xf367 +#define F0900_P2_SYNCD_CURRENT1 0xf36700ff /*P2_SYNCDSTR0*/ -#define R0900_P2_SYNCDSTR0 0xf368 -#define F0900_P2_SYNCD_CURRENT0 0xf36800ff +#define R0900_P2_SYNCDSTR0 0xf368 +#define F0900_P2_SYNCD_CURRENT0 0xf36800ff /*P2_PDELSTATUS1*/ -#define R0900_P2_PDELSTATUS1 0xf369 -#define F0900_P2_PKTDELIN_DELOCK 0xf3690080 -#define F0900_P2_SYNCDUPDFL_BADDFL 0xf3690040 -#define F0900_P2_CONTINUOUS_STREAM 0xf3690020 -#define F0900_P2_UNACCEPTED_STREAM 0xf3690010 -#define F0900_P2_BCH_ERROR_FLAG 0xf3690008 -#define F0900_P2_BBHCRCKO 0xf3690004 -#define F0900_P2_PKTDELIN_LOCK 0xf3690002 -#define F0900_P2_FIRST_LOCK 0xf3690001 +#define R0900_P2_PDELSTATUS1 0xf369 +#define F0900_P2_PKTDELIN_DELOCK 0xf3690080 +#define F0900_P2_SYNCDUPDFL_BADDFL 0xf3690040 +#define F0900_P2_CONTINUOUS_STREAM 0xf3690020 +#define F0900_P2_UNACCEPTED_STREAM 0xf3690010 +#define F0900_P2_BCH_ERROR_FLAG 0xf3690008 +#define F0900_P2_PKTDELIN_LOCK 0xf3690002 +#define F0900_P2_FIRST_LOCK 0xf3690001 /*P2_PDELSTATUS2*/ -#define R0900_P2_PDELSTATUS2 0xf36a -#define F0900_P2_PKTDEL_DEMODSEL 0xf36a0080 -#define F0900_P2_FRAME_MODCOD 0xf36a007c -#define F0900_P2_FRAME_TYPE 0xf36a0003 +#define R0900_P2_PDELSTATUS2 0xf36a +#define F0900_P2_FRAME_MODCOD 0xf36a007c +#define F0900_P2_FRAME_TYPE 0xf36a0003 /*P2_BBFCRCKO1*/ -#define R0900_P2_BBFCRCKO1 0xf36b -#define F0900_P2_BBHCRC_KOCNT1 0xf36b00ff +#define R0900_P2_BBFCRCKO1 0xf36b +#define F0900_P2_BBHCRC_KOCNT1 0xf36b00ff /*P2_BBFCRCKO0*/ -#define R0900_P2_BBFCRCKO0 0xf36c -#define F0900_P2_BBHCRC_KOCNT0 0xf36c00ff +#define R0900_P2_BBFCRCKO0 0xf36c +#define F0900_P2_BBHCRC_KOCNT0 0xf36c00ff /*P2_UPCRCKO1*/ -#define R0900_P2_UPCRCKO1 0xf36d -#define F0900_P2_PKTCRC_KOCNT1 0xf36d00ff +#define R0900_P2_UPCRCKO1 0xf36d +#define F0900_P2_PKTCRC_KOCNT1 0xf36d00ff /*P2_UPCRCKO0*/ -#define R0900_P2_UPCRCKO0 0xf36e -#define F0900_P2_PKTCRC_KOCNT0 0xf36e00ff +#define R0900_P2_UPCRCKO0 0xf36e +#define F0900_P2_PKTCRC_KOCNT0 0xf36e00ff + +/*P2_PDELCTRL3*/ +#define R0900_P2_PDELCTRL3 0xf36f +#define F0900_P2_PKTDEL_CONTFAIL 0xf36f0080 +#define F0900_P2_NOFIFO_BCHERR 0xf36f0020 /*P2_TSSTATEM*/ -#define R0900_P2_TSSTATEM 0xf370 -#define F0900_P2_TSDIL_ON 0xf3700080 -#define F0900_P2_TSSKIPRS_ON 0xf3700040 -#define F0900_P2_TSRS_ON 0xf3700020 -#define F0900_P2_TSDESCRAMB_ON 0xf3700010 -#define F0900_P2_TSFRAME_MODE 0xf3700008 -#define F0900_P2_TS_DISABLE 0xf3700004 -#define F0900_P2_TSACM_MODE 0xf3700002 -#define F0900_P2_TSOUT_NOSYNC 0xf3700001 +#define R0900_P2_TSSTATEM 0xf370 +#define F0900_P2_TSDIL_ON 0xf3700080 +#define F0900_P2_TSRS_ON 0xf3700020 +#define F0900_P2_TSDESCRAMB_ON 0xf3700010 +#define F0900_P2_TSFRAME_MODE 0xf3700008 +#define F0900_P2_TS_DISABLE 0xf3700004 +#define F0900_P2_TSOUT_NOSYNC 0xf3700001 /*P2_TSCFGH*/ -#define R0900_P2_TSCFGH 0xf372 -#define F0900_P2_TSFIFO_DVBCI 0xf3720080 -#define F0900_P2_TSFIFO_SERIAL 0xf3720040 -#define F0900_P2_TSFIFO_TEIUPDATE 0xf3720020 -#define F0900_P2_TSFIFO_DUTY50 0xf3720010 -#define F0900_P2_TSFIFO_HSGNLOUT 0xf3720008 -#define F0900_P2_TSFIFO_ERRMODE 0xf3720006 -#define F0900_P2_RST_HWARE 0xf3720001 +#define R0900_P2_TSCFGH 0xf372 +#define F0900_P2_TSFIFO_DVBCI 0xf3720080 +#define F0900_P2_TSFIFO_SERIAL 0xf3720040 +#define F0900_P2_TSFIFO_TEIUPDATE 0xf3720020 +#define F0900_P2_TSFIFO_DUTY50 0xf3720010 +#define F0900_P2_TSFIFO_HSGNLOUT 0xf3720008 +#define F0900_P2_TSFIFO_ERRMODE 0xf3720006 +#define F0900_P2_RST_HWARE 0xf3720001 /*P2_TSCFGM*/ -#define R0900_P2_TSCFGM 0xf373 -#define F0900_P2_TSFIFO_MANSPEED 0xf37300c0 -#define F0900_P2_TSFIFO_PERMDATA 0xf3730020 -#define F0900_P2_TSFIFO_NONEWSGNL 0xf3730010 -#define F0900_P2_TSFIFO_BITSPEED 0xf3730008 -#define F0900_P2_NPD_SPECDVBS2 0xf3730004 -#define F0900_P2_TSFIFO_STOPCKDIS 0xf3730002 -#define F0900_P2_TSFIFO_INVDATA 0xf3730001 +#define R0900_P2_TSCFGM 0xf373 +#define F0900_P2_TSFIFO_MANSPEED 0xf37300c0 +#define F0900_P2_TSFIFO_PERMDATA 0xf3730020 +#define F0900_P2_TSFIFO_DPUNACT 0xf3730002 +#define F0900_P2_TSFIFO_INVDATA 0xf3730001 /*P2_TSCFGL*/ -#define R0900_P2_TSCFGL 0xf374 -#define F0900_P2_TSFIFO_BCLKDEL1CK 0xf37400c0 -#define F0900_P2_BCHERROR_MODE 0xf3740030 -#define F0900_P2_TSFIFO_NSGNL2DATA 0xf3740008 -#define F0900_P2_TSFIFO_EMBINDVB 0xf3740004 -#define F0900_P2_TSFIFO_DPUNACT 0xf3740002 -#define F0900_P2_TSFIFO_NPDOFF 0xf3740001 +#define R0900_P2_TSCFGL 0xf374 +#define F0900_P2_TSFIFO_BCLKDEL1CK 0xf37400c0 +#define F0900_P2_BCHERROR_MODE 0xf3740030 +#define F0900_P2_TSFIFO_NSGNL2DATA 0xf3740008 +#define F0900_P2_TSFIFO_EMBINDVB 0xf3740004 +#define F0900_P2_TSFIFO_BITSPEED 0xf3740003 /*P2_TSINSDELH*/ -#define R0900_P2_TSINSDELH 0xf376 -#define F0900_P2_TSDEL_SYNCBYTE 0xf3760080 -#define F0900_P2_TSDEL_XXHEADER 0xf3760040 -#define F0900_P2_TSDEL_BBHEADER 0xf3760020 -#define F0900_P2_TSDEL_DATAFIELD 0xf3760010 -#define F0900_P2_TSINSDEL_ISCR 0xf3760008 -#define F0900_P2_TSINSDEL_NPD 0xf3760004 -#define F0900_P2_TSINSDEL_RSPARITY 0xf3760002 -#define F0900_P2_TSINSDEL_CRC8 0xf3760001 +#define R0900_P2_TSINSDELH 0xf376 +#define F0900_P2_TSDEL_SYNCBYTE 0xf3760080 +#define F0900_P2_TSDEL_XXHEADER 0xf3760040 +#define F0900_P2_TSDEL_BBHEADER 0xf3760020 +#define F0900_P2_TSDEL_DATAFIELD 0xf3760010 +#define F0900_P2_TSINSDEL_ISCR 0xf3760008 +#define F0900_P2_TSINSDEL_NPD 0xf3760004 +#define F0900_P2_TSINSDEL_RSPARITY 0xf3760002 +#define F0900_P2_TSINSDEL_CRC8 0xf3760001 + +/*P2_TSDIVN*/ +#define R0900_P2_TSDIVN 0xf379 +#define F0900_P2_TSFIFO_SPEEDMODE 0xf37900c0 + +/*P2_TSCFG4*/ +#define R0900_P2_TSCFG4 0xf37a +#define F0900_P2_TSFIFO_TSSPEEDMODE 0xf37a00c0 /*P2_TSSPEED*/ -#define R0900_P2_TSSPEED 0xf380 -#define F0900_P2_TSFIFO_OUTSPEED 0xf38000ff +#define R0900_P2_TSSPEED 0xf380 +#define F0900_P2_TSFIFO_OUTSPEED 0xf38000ff /*P2_TSSTATUS*/ -#define R0900_P2_TSSTATUS 0xf381 -#define F0900_P2_TSFIFO_LINEOK 0xf3810080 -#define F0900_P2_TSFIFO_ERROR 0xf3810040 -#define F0900_P2_TSFIFO_DATA7 0xf3810020 -#define F0900_P2_TSFIFO_NOSYNC 0xf3810010 -#define F0900_P2_ISCR_INITIALIZED 0xf3810008 -#define F0900_P2_ISCR_UPDATED 0xf3810004 -#define F0900_P2_SOFFIFO_UNREGUL 0xf3810002 -#define F0900_P2_DIL_READY 0xf3810001 +#define R0900_P2_TSSTATUS 0xf381 +#define F0900_P2_TSFIFO_LINEOK 0xf3810080 +#define F0900_P2_TSFIFO_ERROR 0xf3810040 +#define F0900_P2_DIL_READY 0xf3810001 /*P2_TSSTATUS2*/ -#define R0900_P2_TSSTATUS2 0xf382 -#define F0900_P2_TSFIFO_DEMODSEL 0xf3820080 -#define F0900_P2_TSFIFOSPEED_STORE 0xf3820040 -#define F0900_P2_DILXX_RESET 0xf3820020 -#define F0900_P2_TSSERIAL_IMPOS 0xf3820010 -#define F0900_P2_TSFIFO_LINENOK 0xf3820008 -#define F0900_P2_BITSPEED_EVENT 0xf3820004 -#define F0900_P2_SCRAMBDETECT 0xf3820002 -#define F0900_P2_ULDTV67_FALSELOCK 0xf3820001 +#define R0900_P2_TSSTATUS2 0xf382 +#define F0900_P2_TSFIFO_DEMODSEL 0xf3820080 +#define F0900_P2_TSFIFOSPEED_STORE 0xf3820040 +#define F0900_P2_DILXX_RESET 0xf3820020 +#define F0900_P2_TSSERIAL_IMPOS 0xf3820010 +#define F0900_P2_SCRAMBDETECT 0xf3820002 /*P2_TSBITRATE1*/ -#define R0900_P2_TSBITRATE1 0xf383 -#define F0900_P2_TSFIFO_BITRATE1 0xf38300ff +#define R0900_P2_TSBITRATE1 0xf383 +#define F0900_P2_TSFIFO_BITRATE1 0xf38300ff /*P2_TSBITRATE0*/ -#define R0900_P2_TSBITRATE0 0xf384 -#define F0900_P2_TSFIFO_BITRATE0 0xf38400ff +#define R0900_P2_TSBITRATE0 0xf384 +#define F0900_P2_TSFIFO_BITRATE0 0xf38400ff /*P2_ERRCTRL1*/ -#define R0900_P2_ERRCTRL1 0xf398 -#define F0900_P2_ERR_SOURCE1 0xf39800f0 -#define F0900_P2_NUM_EVENT1 0xf3980007 +#define R0900_P2_ERRCTRL1 0xf398 +#define F0900_P2_ERR_SOURCE1 0xf39800f0 +#define F0900_P2_NUM_EVENT1 0xf3980007 /*P2_ERRCNT12*/ -#define R0900_P2_ERRCNT12 0xf399 -#define F0900_P2_ERRCNT1_OLDVALUE 0xf3990080 -#define F0900_P2_ERR_CNT12 0xf399007f +#define R0900_P2_ERRCNT12 0xf399 +#define F0900_P2_ERRCNT1_OLDVALUE 0xf3990080 +#define F0900_P2_ERR_CNT12 0xf399007f /*P2_ERRCNT11*/ -#define R0900_P2_ERRCNT11 0xf39a -#define F0900_P2_ERR_CNT11 0xf39a00ff +#define R0900_P2_ERRCNT11 0xf39a +#define F0900_P2_ERR_CNT11 0xf39a00ff /*P2_ERRCNT10*/ -#define R0900_P2_ERRCNT10 0xf39b -#define F0900_P2_ERR_CNT10 0xf39b00ff +#define R0900_P2_ERRCNT10 0xf39b +#define F0900_P2_ERR_CNT10 0xf39b00ff /*P2_ERRCTRL2*/ -#define R0900_P2_ERRCTRL2 0xf39c -#define F0900_P2_ERR_SOURCE2 0xf39c00f0 -#define F0900_P2_NUM_EVENT2 0xf39c0007 +#define R0900_P2_ERRCTRL2 0xf39c +#define F0900_P2_ERR_SOURCE2 0xf39c00f0 +#define F0900_P2_NUM_EVENT2 0xf39c0007 /*P2_ERRCNT22*/ -#define R0900_P2_ERRCNT22 0xf39d -#define F0900_P2_ERRCNT2_OLDVALUE 0xf39d0080 -#define F0900_P2_ERR_CNT22 0xf39d007f +#define R0900_P2_ERRCNT22 0xf39d +#define F0900_P2_ERRCNT2_OLDVALUE 0xf39d0080 +#define F0900_P2_ERR_CNT22 0xf39d007f /*P2_ERRCNT21*/ -#define R0900_P2_ERRCNT21 0xf39e -#define F0900_P2_ERR_CNT21 0xf39e00ff +#define R0900_P2_ERRCNT21 0xf39e +#define F0900_P2_ERR_CNT21 0xf39e00ff /*P2_ERRCNT20*/ -#define R0900_P2_ERRCNT20 0xf39f -#define F0900_P2_ERR_CNT20 0xf39f00ff +#define R0900_P2_ERRCNT20 0xf39f +#define F0900_P2_ERR_CNT20 0xf39f00ff /*P2_FECSPY*/ -#define R0900_P2_FECSPY 0xf3a0 -#define F0900_P2_SPY_ENABLE 0xf3a00080 -#define F0900_P2_NO_SYNCBYTE 0xf3a00040 -#define F0900_P2_SERIAL_MODE 0xf3a00020 -#define F0900_P2_UNUSUAL_PACKET 0xf3a00010 -#define F0900_P2_BER_PACKMODE 0xf3a00008 -#define F0900_P2_BERMETER_LMODE 0xf3a00002 -#define F0900_P2_BERMETER_RESET 0xf3a00001 +#define R0900_P2_FECSPY 0xf3a0 +#define F0900_P2_SPY_ENABLE 0xf3a00080 +#define F0900_P2_NO_SYNCBYTE 0xf3a00040 +#define F0900_P2_SERIAL_MODE 0xf3a00020 +#define F0900_P2_UNUSUAL_PACKET 0xf3a00010 +#define F0900_P2_BERMETER_DATAMODE 0xf3a00008 +#define F0900_P2_BERMETER_LMODE 0xf3a00002 +#define F0900_P2_BERMETER_RESET 0xf3a00001 /*P2_FSPYCFG*/ -#define R0900_P2_FSPYCFG 0xf3a1 -#define F0900_P2_FECSPY_INPUT 0xf3a100c0 -#define F0900_P2_RST_ON_ERROR 0xf3a10020 -#define F0900_P2_ONE_SHOT 0xf3a10010 -#define F0900_P2_I2C_MODE 0xf3a1000c -#define F0900_P2_SPY_HYSTERESIS 0xf3a10003 +#define R0900_P2_FSPYCFG 0xf3a1 +#define F0900_P2_FECSPY_INPUT 0xf3a100c0 +#define F0900_P2_RST_ON_ERROR 0xf3a10020 +#define F0900_P2_ONE_SHOT 0xf3a10010 +#define F0900_P2_I2C_MODE 0xf3a1000c +#define F0900_P2_SPY_HYSTERESIS 0xf3a10003 /*P2_FSPYDATA*/ -#define R0900_P2_FSPYDATA 0xf3a2 -#define F0900_P2_SPY_STUFFING 0xf3a20080 -#define F0900_P2_NOERROR_PKTJITTER 0xf3a20040 -#define F0900_P2_SPY_CNULLPKT 0xf3a20020 -#define F0900_P2_SPY_OUTDATA_MODE 0xf3a2001f +#define R0900_P2_FSPYDATA 0xf3a2 +#define F0900_P2_SPY_STUFFING 0xf3a20080 +#define F0900_P2_SPY_CNULLPKT 0xf3a20020 +#define F0900_P2_SPY_OUTDATA_MODE 0xf3a2001f /*P2_FSPYOUT*/ -#define R0900_P2_FSPYOUT 0xf3a3 -#define F0900_P2_FSPY_DIRECT 0xf3a30080 -#define F0900_P2_SPY_OUTDATA_BUS 0xf3a30038 -#define F0900_P2_STUFF_MODE 0xf3a30007 +#define R0900_P2_FSPYOUT 0xf3a3 +#define F0900_P2_FSPY_DIRECT 0xf3a30080 +#define F0900_P2_STUFF_MODE 0xf3a30007 /*P2_FSTATUS*/ -#define R0900_P2_FSTATUS 0xf3a4 -#define F0900_P2_SPY_ENDSIM 0xf3a40080 -#define F0900_P2_VALID_SIM 0xf3a40040 -#define F0900_P2_FOUND_SIGNAL 0xf3a40020 -#define F0900_P2_DSS_SYNCBYTE 0xf3a40010 -#define F0900_P2_RESULT_STATE 0xf3a4000f +#define R0900_P2_FSTATUS 0xf3a4 +#define F0900_P2_SPY_ENDSIM 0xf3a40080 +#define F0900_P2_VALID_SIM 0xf3a40040 +#define F0900_P2_FOUND_SIGNAL 0xf3a40020 +#define F0900_P2_DSS_SYNCBYTE 0xf3a40010 +#define F0900_P2_RESULT_STATE 0xf3a4000f /*P2_FBERCPT4*/ -#define R0900_P2_FBERCPT4 0xf3a8 -#define F0900_P2_FBERMETER_CPT4 0xf3a800ff +#define R0900_P2_FBERCPT4 0xf3a8 +#define F0900_P2_FBERMETER_CPT4 0xf3a800ff /*P2_FBERCPT3*/ -#define R0900_P2_FBERCPT3 0xf3a9 -#define F0900_P2_FBERMETER_CPT3 0xf3a900ff +#define R0900_P2_FBERCPT3 0xf3a9 +#define F0900_P2_FBERMETER_CPT3 0xf3a900ff /*P2_FBERCPT2*/ -#define R0900_P2_FBERCPT2 0xf3aa -#define F0900_P2_FBERMETER_CPT2 0xf3aa00ff +#define R0900_P2_FBERCPT2 0xf3aa +#define F0900_P2_FBERMETER_CPT2 0xf3aa00ff /*P2_FBERCPT1*/ -#define R0900_P2_FBERCPT1 0xf3ab -#define F0900_P2_FBERMETER_CPT1 0xf3ab00ff +#define R0900_P2_FBERCPT1 0xf3ab +#define F0900_P2_FBERMETER_CPT1 0xf3ab00ff /*P2_FBERCPT0*/ -#define R0900_P2_FBERCPT0 0xf3ac -#define F0900_P2_FBERMETER_CPT0 0xf3ac00ff +#define R0900_P2_FBERCPT0 0xf3ac +#define F0900_P2_FBERMETER_CPT0 0xf3ac00ff /*P2_FBERERR2*/ -#define R0900_P2_FBERERR2 0xf3ad -#define F0900_P2_FBERMETER_ERR2 0xf3ad00ff +#define R0900_P2_FBERERR2 0xf3ad +#define F0900_P2_FBERMETER_ERR2 0xf3ad00ff /*P2_FBERERR1*/ -#define R0900_P2_FBERERR1 0xf3ae -#define F0900_P2_FBERMETER_ERR1 0xf3ae00ff +#define R0900_P2_FBERERR1 0xf3ae +#define F0900_P2_FBERMETER_ERR1 0xf3ae00ff /*P2_FBERERR0*/ -#define R0900_P2_FBERERR0 0xf3af -#define F0900_P2_FBERMETER_ERR0 0xf3af00ff +#define R0900_P2_FBERERR0 0xf3af +#define F0900_P2_FBERMETER_ERR0 0xf3af00ff /*P2_FSPYBER*/ -#define R0900_P2_FSPYBER 0xf3b2 -#define F0900_P2_FSPYOBS_XORREAD 0xf3b20040 -#define F0900_P2_FSPYBER_OBSMODE 0xf3b20020 -#define F0900_P2_FSPYBER_SYNCBYTE 0xf3b20010 -#define F0900_P2_FSPYBER_UNSYNC 0xf3b20008 -#define F0900_P2_FSPYBER_CTIME 0xf3b20007 +#define R0900_P2_FSPYBER 0xf3b2 +#define F0900_P2_FSPYBER_SYNCBYTE 0xf3b20010 +#define F0900_P2_FSPYBER_UNSYNC 0xf3b20008 +#define F0900_P2_FSPYBER_CTIME 0xf3b20007 /*P1_IQCONST*/ -#define R0900_P1_IQCONST 0xf400 -#define F0900_P1_CONSTEL_SELECT 0xf4000060 -#define F0900_P1_IQSYMB_SEL 0xf400001f +#define R0900_P1_IQCONST 0xf400 +#define IQCONST REGx(R0900_P1_IQCONST) +#define F0900_P1_CONSTEL_SELECT 0xf4000060 +#define F0900_P1_IQSYMB_SEL 0xf400001f /*P1_NOSCFG*/ -#define R0900_P1_NOSCFG 0xf401 -#define F0900_P1_DUMMYPL_NOSDATA 0xf4010020 -#define F0900_P1_NOSPLH_BETA 0xf4010018 -#define F0900_P1_NOSDATA_BETA 0xf4010007 +#define R0900_P1_NOSCFG 0xf401 +#define NOSCFG REGx(R0900_P1_NOSCFG) +#define F0900_P1_DUMMYPL_NOSDATA 0xf4010020 +#define F0900_P1_NOSPLH_BETA 0xf4010018 +#define F0900_P1_NOSDATA_BETA 0xf4010007 /*P1_ISYMB*/ -#define R0900_P1_ISYMB 0xf402 -#define F0900_P1_I_SYMBOL 0xf40201ff +#define R0900_P1_ISYMB 0xf402 +#define ISYMB REGx(R0900_P1_ISYMB) +#define F0900_P1_I_SYMBOL 0xf40201ff /*P1_QSYMB*/ -#define R0900_P1_QSYMB 0xf403 -#define F0900_P1_Q_SYMBOL 0xf40301ff +#define R0900_P1_QSYMB 0xf403 +#define QSYMB REGx(R0900_P1_QSYMB) +#define F0900_P1_Q_SYMBOL 0xf40301ff /*P1_AGC1CFG*/ -#define R0900_P1_AGC1CFG 0xf404 -#define F0900_P1_DC_FROZEN 0xf4040080 -#define F0900_P1_DC_CORRECT 0xf4040040 -#define F0900_P1_AMM_FROZEN 0xf4040020 -#define F0900_P1_AMM_CORRECT 0xf4040010 -#define F0900_P1_QUAD_FROZEN 0xf4040008 -#define F0900_P1_QUAD_CORRECT 0xf4040004 -#define F0900_P1_DCCOMP_SLOW 0xf4040002 -#define F0900_P1_IQMISM_SLOW 0xf4040001 +#define R0900_P1_AGC1CFG 0xf404 +#define AGC1CFG REGx(R0900_P1_AGC1CFG) +#define F0900_P1_DC_FROZEN 0xf4040080 +#define F0900_P1_DC_CORRECT 0xf4040040 +#define F0900_P1_AMM_FROZEN 0xf4040020 +#define F0900_P1_AMM_CORRECT 0xf4040010 +#define F0900_P1_QUAD_FROZEN 0xf4040008 +#define F0900_P1_QUAD_CORRECT 0xf4040004 /*P1_AGC1CN*/ -#define R0900_P1_AGC1CN 0xf406 -#define F0900_P1_AGC1_LOCKED 0xf4060080 -#define F0900_P1_AGC1_OVERFLOW 0xf4060040 -#define F0900_P1_AGC1_NOSLOWLK 0xf4060020 -#define F0900_P1_AGC1_MINPOWER 0xf4060010 -#define F0900_P1_AGCOUT_FAST 0xf4060008 -#define F0900_P1_AGCIQ_BETA 0xf4060007 +#define R0900_P1_AGC1CN 0xf406 +#define AGC1CN REGx(R0900_P1_AGC1CN) +#define F0900_P1_AGC1_LOCKED 0xf4060080 +#define F0900_P1_AGC1_MINPOWER 0xf4060010 +#define F0900_P1_AGCOUT_FAST 0xf4060008 +#define F0900_P1_AGCIQ_BETA 0xf4060007 /*P1_AGC1REF*/ -#define R0900_P1_AGC1REF 0xf407 -#define F0900_P1_AGCIQ_REF 0xf40700ff +#define R0900_P1_AGC1REF 0xf407 +#define AGC1REF REGx(R0900_P1_AGC1REF) +#define F0900_P1_AGCIQ_REF 0xf40700ff /*P1_IDCCOMP*/ -#define R0900_P1_IDCCOMP 0xf408 -#define F0900_P1_IAVERAGE_ADJ 0xf40801ff +#define R0900_P1_IDCCOMP 0xf408 +#define IDCCOMP REGx(R0900_P1_IDCCOMP) +#define F0900_P1_IAVERAGE_ADJ 0xf40801ff /*P1_QDCCOMP*/ -#define R0900_P1_QDCCOMP 0xf409 -#define F0900_P1_QAVERAGE_ADJ 0xf40901ff +#define R0900_P1_QDCCOMP 0xf409 +#define QDCCOMP REGx(R0900_P1_QDCCOMP) +#define F0900_P1_QAVERAGE_ADJ 0xf40901ff /*P1_POWERI*/ -#define R0900_P1_POWERI 0xf40a -#define F0900_P1_POWER_I 0xf40a00ff +#define R0900_P1_POWERI 0xf40a +#define POWERI REGx(R0900_P1_POWERI) +#define F0900_P1_POWER_I 0xf40a00ff +#define POWER_I FLDx(F0900_P1_POWER_I) /*P1_POWERQ*/ -#define R0900_P1_POWERQ 0xf40b -#define F0900_P1_POWER_Q 0xf40b00ff +#define R0900_P1_POWERQ 0xf40b +#define POWERQ REGx(R0900_P1_POWERQ) +#define F0900_P1_POWER_Q 0xf40b00ff +#define POWER_Q FLDx(F0900_P1_POWER_Q) /*P1_AGC1AMM*/ -#define R0900_P1_AGC1AMM 0xf40c -#define F0900_P1_AMM_VALUE 0xf40c00ff +#define R0900_P1_AGC1AMM 0xf40c +#define AGC1AMM REGx(R0900_P1_AGC1AMM) +#define F0900_P1_AMM_VALUE 0xf40c00ff /*P1_AGC1QUAD*/ -#define R0900_P1_AGC1QUAD 0xf40d -#define F0900_P1_QUAD_VALUE 0xf40d01ff +#define R0900_P1_AGC1QUAD 0xf40d +#define AGC1QUAD REGx(R0900_P1_AGC1QUAD) +#define F0900_P1_QUAD_VALUE 0xf40d01ff /*P1_AGCIQIN1*/ -#define R0900_P1_AGCIQIN1 0xf40e -#define F0900_P1_AGCIQ_VALUE1 0xf40e00ff +#define R0900_P1_AGCIQIN1 0xf40e +#define AGCIQIN1 REGx(R0900_P1_AGCIQIN1) +#define F0900_P1_AGCIQ_VALUE1 0xf40e00ff +#define AGCIQ_VALUE1 FLDx(F0900_P1_AGCIQ_VALUE1) /*P1_AGCIQIN0*/ -#define R0900_P1_AGCIQIN0 0xf40f -#define F0900_P1_AGCIQ_VALUE0 0xf40f00ff +#define R0900_P1_AGCIQIN0 0xf40f +#define AGCIQIN0 REGx(R0900_P1_AGCIQIN0) +#define F0900_P1_AGCIQ_VALUE0 0xf40f00ff +#define AGCIQ_VALUE0 FLDx(F0900_P1_AGCIQ_VALUE0) /*P1_DEMOD*/ -#define R0900_P1_DEMOD 0xf410 -#define F0900_P1_DEMOD_STOP 0xf4100040 -#define F0900_P1_SPECINV_CONTROL 0xf4100030 -#define F0900_P1_FORCE_ENASAMP 0xf4100008 -#define F0900_P1_MANUAL_ROLLOFF 0xf4100004 -#define F0900_P1_ROLLOFF_CONTROL 0xf4100003 +#define R0900_P1_DEMOD 0xf410 +#define DEMOD REGx(R0900_P1_DEMOD) +#define F0900_P1_MANUALS2_ROLLOFF 0xf4100080 +#define MANUALS2_ROLLOFF FLDx(F0900_P1_MANUALS2_ROLLOFF) + +#define F0900_P1_SPECINV_CONTROL 0xf4100030 +#define SPECINV_CONTROL FLDx(F0900_P1_SPECINV_CONTROL) +#define F0900_P1_FORCE_ENASAMP 0xf4100008 +#define F0900_P1_MANUALSX_ROLLOFF 0xf4100004 +#define MANUALSX_ROLLOFF FLDx(F0900_P1_MANUALSX_ROLLOFF) +#define F0900_P1_ROLLOFF_CONTROL 0xf4100003 +#define ROLLOFF_CONTROL FLDx(F0900_P1_ROLLOFF_CONTROL) /*P1_DMDMODCOD*/ -#define R0900_P1_DMDMODCOD 0xf411 -#define F0900_P1_MANUAL_MODCOD 0xf4110080 -#define F0900_P1_DEMOD_MODCOD 0xf411007c -#define F0900_P1_DEMOD_TYPE 0xf4110003 +#define R0900_P1_DMDMODCOD 0xf411 +#define DMDMODCOD REGx(R0900_P1_DMDMODCOD) +#define F0900_P1_MANUAL_MODCOD 0xf4110080 +#define F0900_P1_DEMOD_MODCOD 0xf411007c +#define DEMOD_MODCOD FLDx(F0900_P1_DEMOD_MODCOD) +#define F0900_P1_DEMOD_TYPE 0xf4110003 +#define DEMOD_TYPE FLDx(F0900_P1_DEMOD_TYPE) /*P1_DSTATUS*/ -#define R0900_P1_DSTATUS 0xf412 -#define F0900_P1_CAR_LOCK 0xf4120080 -#define F0900_P1_TMGLOCK_QUALITY 0xf4120060 -#define F0900_P1_SDVBS1_ENABLE 0xf4120010 -#define F0900_P1_LOCK_DEFINITIF 0xf4120008 -#define F0900_P1_TIMING_IS_LOCKED 0xf4120004 -#define F0900_P1_COARSE_TMGLOCK 0xf4120002 -#define F0900_P1_COARSE_CARLOCK 0xf4120001 +#define R0900_P1_DSTATUS 0xf412 +#define DSTATUS REGx(R0900_P1_DSTATUS) +#define F0900_P1_CAR_LOCK 0xf4120080 +#define F0900_P1_TMGLOCK_QUALITY 0xf4120060 +#define TMGLOCK_QUALITY FLDx(F0900_P1_TMGLOCK_QUALITY) +#define F0900_P1_LOCK_DEFINITIF 0xf4120008 +#define LOCK_DEFINITIF FLDx(F0900_P1_LOCK_DEFINITIF) +#define F0900_P1_OVADC_DETECT 0xf4120001 /*P1_DSTATUS2*/ -#define R0900_P1_DSTATUS2 0xf413 -#define F0900_P1_DEMOD_DELOCK 0xf4130080 -#define F0900_P1_DEMOD_TIMEOUT 0xf4130040 -#define F0900_P1_MODCODRQ_SYNCTAG 0xf4130020 -#define F0900_P1_POLYPH_SATEVENT 0xf4130010 -#define F0900_P1_AGC1_NOSIGNALACK 0xf4130008 -#define F0900_P1_AGC2_OVERFLOW 0xf4130004 -#define F0900_P1_CFR_OVERFLOW 0xf4130002 -#define F0900_P1_GAMMA_OVERUNDER 0xf4130001 +#define R0900_P1_DSTATUS2 0xf413 +#define DSTATUS2 REGx(R0900_P1_DSTATUS2) +#define F0900_P1_DEMOD_DELOCK 0xf4130080 +#define F0900_P1_AGC1_NOSIGNALACK 0xf4130008 +#define F0900_P1_AGC2_OVERFLOW 0xf4130004 +#define F0900_P1_CFR_OVERFLOW 0xf4130002 +#define F0900_P1_GAMMA_OVERUNDER 0xf4130001 /*P1_DMDCFGMD*/ -#define R0900_P1_DMDCFGMD 0xf414 -#define F0900_P1_DVBS2_ENABLE 0xf4140080 -#define F0900_P1_DVBS1_ENABLE 0xf4140040 -#define F0900_P1_CFR_AUTOSCAN 0xf4140020 -#define F0900_P1_SCAN_ENABLE 0xf4140010 -#define F0900_P1_TUN_AUTOSCAN 0xf4140008 -#define F0900_P1_NOFORCE_RELOCK 0xf4140004 -#define F0900_P1_TUN_RNG 0xf4140003 +#define R0900_P1_DMDCFGMD 0xf414 +#define DMDCFGMD REGx(R0900_P1_DMDCFGMD) +#define F0900_P1_DVBS2_ENABLE 0xf4140080 +#define DVBS2_ENABLE FLDx(F0900_P1_DVBS2_ENABLE) +#define F0900_P1_DVBS1_ENABLE 0xf4140040 +#define DVBS1_ENABLE FLDx(F0900_P1_DVBS1_ENABLE) +#define F0900_P1_SCAN_ENABLE 0xf4140010 +#define SCAN_ENABLE FLDx(F0900_P1_SCAN_ENABLE) +#define F0900_P1_CFR_AUTOSCAN 0xf4140008 +#define CFR_AUTOSCAN FLDx(F0900_P1_CFR_AUTOSCAN) +#define F0900_P1_TUN_RNG 0xf4140003 /*P1_DMDCFG2*/ -#define R0900_P1_DMDCFG2 0xf415 -#define F0900_P1_AGC1_WAITLOCK 0xf4150080 -#define F0900_P1_S1S2_SEQUENTIAL 0xf4150040 -#define F0900_P1_OVERFLOW_TIMEOUT 0xf4150020 -#define F0900_P1_SCANFAIL_TIMEOUT 0xf4150010 -#define F0900_P1_DMDTOUT_BACK 0xf4150008 -#define F0900_P1_CARLOCK_S1ENABLE 0xf4150004 -#define F0900_P1_COARSE_LK3MODE 0xf4150002 -#define F0900_P1_COARSE_LK2MODE 0xf4150001 +#define R0900_P1_DMDCFG2 0xf415 +#define DMDCFG2 REGx(R0900_P1_DMDCFG2) +#define F0900_P1_S1S2_SEQUENTIAL 0xf4150040 +#define S1S2_SEQUENTIAL FLDx(F0900_P1_S1S2_SEQUENTIAL) +#define F0900_P1_INFINITE_RELOCK 0xf4150010 /*P1_DMDISTATE*/ -#define R0900_P1_DMDISTATE 0xf416 -#define F0900_P1_I2C_NORESETDMODE 0xf4160080 -#define F0900_P1_FORCE_ETAPED 0xf4160040 -#define F0900_P1_SDMDRST_DIRCLK 0xf4160020 -#define F0900_P1_I2C_DEMOD_MODE 0xf416001f +#define R0900_P1_DMDISTATE 0xf416 +#define DMDISTATE REGx(R0900_P1_DMDISTATE) +#define F0900_P1_I2C_DEMOD_MODE 0xf416001f +#define DEMOD_MODE FLDx(F0900_P1_I2C_DEMOD_MODE) /*P1_DMDT0M*/ -#define R0900_P1_DMDT0M 0xf417 -#define F0900_P1_DMDT0_MIN 0xf41700ff +#define R0900_P1_DMDT0M 0xf417 +#define DMDT0M REGx(R0900_P1_DMDT0M) +#define F0900_P1_DMDT0_MIN 0xf41700ff /*P1_DMDSTATE*/ -#define R0900_P1_DMDSTATE 0xf41b -#define F0900_P1_DEMOD_LOCKED 0xf41b0080 -#define F0900_P1_HEADER_MODE 0xf41b0060 -#define F0900_P1_DEMOD_MODE 0xf41b001f +#define R0900_P1_DMDSTATE 0xf41b +#define DMDSTATE REGx(R0900_P1_DMDSTATE) +#define F0900_P1_HEADER_MODE 0xf41b0060 +#define HEADER_MODE FLDx(F0900_P1_HEADER_MODE) /*P1_DMDFLYW*/ -#define R0900_P1_DMDFLYW 0xf41c -#define F0900_P1_I2C_IRQVAL 0xf41c00f0 -#define F0900_P1_FLYWHEEL_CPT 0xf41c000f +#define R0900_P1_DMDFLYW 0xf41c +#define DMDFLYW REGx(R0900_P1_DMDFLYW) +#define F0900_P1_I2C_IRQVAL 0xf41c00f0 +#define F0900_P1_FLYWHEEL_CPT 0xf41c000f +#define FLYWHEEL_CPT FLDx(F0900_P1_FLYWHEEL_CPT) /*P1_DSTATUS3*/ -#define R0900_P1_DSTATUS3 0xf41d -#define F0900_P1_CFR_ZIGZAG 0xf41d0080 -#define F0900_P1_DEMOD_CFGMODE 0xf41d0060 -#define F0900_P1_GAMMA_LOWBAUDRATE 0xf41d0010 -#define F0900_P1_RELOCK_MODE 0xf41d0008 -#define F0900_P1_DEMOD_FAIL 0xf41d0004 -#define F0900_P1_ETAPE1A_DVBXMEM 0xf41d0003 +#define R0900_P1_DSTATUS3 0xf41d +#define DSTATUS3 REGx(R0900_P1_DSTATUS3) +#define F0900_P1_DEMOD_CFGMODE 0xf41d0060 /*P1_DMDCFG3*/ -#define R0900_P1_DMDCFG3 0xf41e -#define F0900_P1_DVBS1_TMGWAIT 0xf41e0080 -#define F0900_P1_NO_BWCENTERING 0xf41e0040 -#define F0900_P1_INV_SEQSRCH 0xf41e0020 -#define F0900_P1_DIS_SFRUPLOW_TRK 0xf41e0010 -#define F0900_P1_NOSTOP_FIFOFULL 0xf41e0008 -#define F0900_P1_LOCKTIME_MODE 0xf41e0007 +#define R0900_P1_DMDCFG3 0xf41e +#define DMDCFG3 REGx(R0900_P1_DMDCFG3) +#define F0900_P1_NOSTOP_FIFOFULL 0xf41e0008 /*P1_DMDCFG4*/ -#define R0900_P1_DMDCFG4 0xf41f -#define F0900_P1_TUNER_NRELAUNCH 0xf41f0008 -#define F0900_P1_DIS_CLKENABLE 0xf41f0004 -#define F0900_P1_DIS_HDRDIVLOCK 0xf41f0002 -#define F0900_P1_NO_TNRWBINIT 0xf41f0001 +#define R0900_P1_DMDCFG4 0xf41f +#define DMDCFG4 REGx(R0900_P1_DMDCFG4) +#define F0900_P1_TUNER_NRELAUNCH 0xf41f0008 /*P1_CORRELMANT*/ -#define R0900_P1_CORRELMANT 0xf420 -#define F0900_P1_CORREL_MANT 0xf42000ff +#define R0900_P1_CORRELMANT 0xf420 +#define CORRELMANT REGx(R0900_P1_CORRELMANT) +#define F0900_P1_CORREL_MANT 0xf42000ff /*P1_CORRELABS*/ -#define R0900_P1_CORRELABS 0xf421 -#define F0900_P1_CORREL_ABS 0xf42100ff +#define R0900_P1_CORRELABS 0xf421 +#define CORRELABS REGx(R0900_P1_CORRELABS) +#define F0900_P1_CORREL_ABS 0xf42100ff /*P1_CORRELEXP*/ -#define R0900_P1_CORRELEXP 0xf422 -#define F0900_P1_CORREL_ABSEXP 0xf42200f0 -#define F0900_P1_CORREL_EXP 0xf422000f +#define R0900_P1_CORRELEXP 0xf422 +#define CORRELEXP REGx(R0900_P1_CORRELEXP) +#define F0900_P1_CORREL_ABSEXP 0xf42200f0 +#define F0900_P1_CORREL_EXP 0xf422000f /*P1_PLHMODCOD*/ -#define R0900_P1_PLHMODCOD 0xf424 -#define F0900_P1_SPECINV_DEMOD 0xf4240080 -#define F0900_P1_PLH_MODCOD 0xf424007c -#define F0900_P1_PLH_TYPE 0xf4240003 +#define R0900_P1_PLHMODCOD 0xf424 +#define PLHMODCOD REGx(R0900_P1_PLHMODCOD) +#define F0900_P1_SPECINV_DEMOD 0xf4240080 +#define SPECINV_DEMOD FLDx(F0900_P1_SPECINV_DEMOD) +#define F0900_P1_PLH_MODCOD 0xf424007c +#define F0900_P1_PLH_TYPE 0xf4240003 -/*P1_AGCK32*/ -#define R0900_P1_AGCK32 0xf42b -#define F0900_P1_R3ADJOFF_32APSK 0xf42b0080 -#define F0900_P1_R2ADJOFF_32APSK 0xf42b0040 -#define F0900_P1_R1ADJOFF_32APSK 0xf42b0020 -#define F0900_P1_RADJ_32APSK 0xf42b001f +/*P1_DMDREG*/ +#define R0900_P1_DMDREG 0xf425 +#define DMDREG REGx(R0900_P1_DMDREG) +#define F0900_P1_DECIM_PLFRAMES 0xf4250001 /*P1_AGC2O*/ -#define R0900_P1_AGC2O 0xf42c -#define F0900_P1_AGC2REF_ADJUSTING 0xf42c0080 -#define F0900_P1_AGC2_COARSEFAST 0xf42c0040 -#define F0900_P1_AGC2_LKSQRT 0xf42c0020 -#define F0900_P1_AGC2_LKMODE 0xf42c0010 -#define F0900_P1_AGC2_LKEQUA 0xf42c0008 -#define F0900_P1_AGC2_COEF 0xf42c0007 +#define R0900_P1_AGC2O 0xf42c +#define AGC2O REGx(R0900_P1_AGC2O) +#define F0900_P1_AGC2_COEF 0xf42c0007 /*P1_AGC2REF*/ -#define R0900_P1_AGC2REF 0xf42d -#define F0900_P1_AGC2_REF 0xf42d00ff +#define R0900_P1_AGC2REF 0xf42d +#define AGC2REF REGx(R0900_P1_AGC2REF) +#define F0900_P1_AGC2_REF 0xf42d00ff /*P1_AGC1ADJ*/ -#define R0900_P1_AGC1ADJ 0xf42e -#define F0900_P1_AGC1ADJ_MANUAL 0xf42e0080 -#define F0900_P1_AGC1_ADJUSTED 0xf42e017f +#define R0900_P1_AGC1ADJ 0xf42e +#define AGC1ADJ REGx(R0900_P1_AGC1ADJ) +#define F0900_P1_AGC1_ADJUSTED 0xf42e007f /*P1_AGC2I1*/ -#define R0900_P1_AGC2I1 0xf436 -#define F0900_P1_AGC2_INTEGRATOR1 0xf43600ff +#define R0900_P1_AGC2I1 0xf436 +#define AGC2I1 REGx(R0900_P1_AGC2I1) +#define F0900_P1_AGC2_INTEGRATOR1 0xf43600ff /*P1_AGC2I0*/ -#define R0900_P1_AGC2I0 0xf437 -#define F0900_P1_AGC2_INTEGRATOR0 0xf43700ff +#define R0900_P1_AGC2I0 0xf437 +#define AGC2I0 REGx(R0900_P1_AGC2I0) +#define F0900_P1_AGC2_INTEGRATOR0 0xf43700ff /*P1_CARCFG*/ -#define R0900_P1_CARCFG 0xf438 -#define F0900_P1_CFRUPLOW_AUTO 0xf4380080 -#define F0900_P1_CFRUPLOW_TEST 0xf4380040 -#define F0900_P1_EN_CAR2CENTER 0xf4380020 -#define F0900_P1_CARHDR_NODIV8 0xf4380010 -#define F0900_P1_I2C_ROTA 0xf4380008 -#define F0900_P1_ROTAON 0xf4380004 -#define F0900_P1_PH_DET_ALGO 0xf4380003 +#define R0900_P1_CARCFG 0xf438 +#define CARCFG REGx(R0900_P1_CARCFG) +#define F0900_P1_CFRUPLOW_AUTO 0xf4380080 +#define F0900_P1_CFRUPLOW_TEST 0xf4380040 +#define F0900_P1_ROTAON 0xf4380004 +#define F0900_P1_PH_DET_ALGO 0xf4380003 /*P1_ACLC*/ -#define R0900_P1_ACLC 0xf439 -#define F0900_P1_STOP_S2ALPHA 0xf43900c0 -#define F0900_P1_CAR_ALPHA_MANT 0xf4390030 -#define F0900_P1_CAR_ALPHA_EXP 0xf439000f +#define R0900_P1_ACLC 0xf439 +#define ACLC REGx(R0900_P1_ACLC) +#define F0900_P1_CAR_ALPHA_MANT 0xf4390030 +#define F0900_P1_CAR_ALPHA_EXP 0xf439000f /*P1_BCLC*/ -#define R0900_P1_BCLC 0xf43a -#define F0900_P1_STOP_S2BETA 0xf43a00c0 -#define F0900_P1_CAR_BETA_MANT 0xf43a0030 -#define F0900_P1_CAR_BETA_EXP 0xf43a000f +#define R0900_P1_BCLC 0xf43a +#define BCLC REGx(R0900_P1_BCLC) +#define F0900_P1_CAR_BETA_MANT 0xf43a0030 +#define F0900_P1_CAR_BETA_EXP 0xf43a000f /*P1_CARFREQ*/ -#define R0900_P1_CARFREQ 0xf43d -#define F0900_P1_KC_COARSE_EXP 0xf43d00f0 -#define F0900_P1_BETA_FREQ 0xf43d000f +#define R0900_P1_CARFREQ 0xf43d +#define CARFREQ REGx(R0900_P1_CARFREQ) +#define F0900_P1_KC_COARSE_EXP 0xf43d00f0 +#define F0900_P1_BETA_FREQ 0xf43d000f /*P1_CARHDR*/ -#define R0900_P1_CARHDR 0xf43e -#define F0900_P1_K_FREQ_HDR 0xf43e00ff +#define R0900_P1_CARHDR 0xf43e +#define CARHDR REGx(R0900_P1_CARHDR) +#define F0900_P1_K_FREQ_HDR 0xf43e00ff /*P1_LDT*/ -#define R0900_P1_LDT 0xf43f -#define F0900_P1_CARLOCK_THRES 0xf43f01ff +#define R0900_P1_LDT 0xf43f +#define LDT REGx(R0900_P1_LDT) +#define F0900_P1_CARLOCK_THRES 0xf43f01ff /*P1_LDT2*/ -#define R0900_P1_LDT2 0xf440 -#define F0900_P1_CARLOCK_THRES2 0xf44001ff +#define R0900_P1_LDT2 0xf440 +#define LDT2 REGx(R0900_P1_LDT2) +#define F0900_P1_CARLOCK_THRES2 0xf44001ff /*P1_CFRICFG*/ -#define R0900_P1_CFRICFG 0xf441 -#define F0900_P1_CFRINIT_UNVALRNG 0xf4410080 -#define F0900_P1_CFRINIT_LUNVALCPT 0xf4410040 -#define F0900_P1_CFRINIT_ABORTDBL 0xf4410020 -#define F0900_P1_CFRINIT_ABORTPRED 0xf4410010 -#define F0900_P1_CFRINIT_UNVALSKIP 0xf4410008 -#define F0900_P1_CFRINIT_CSTINC 0xf4410004 -#define F0900_P1_NEG_CFRSTEP 0xf4410001 +#define R0900_P1_CFRICFG 0xf441 +#define CFRICFG REGx(R0900_P1_CFRICFG) +#define F0900_P1_NEG_CFRSTEP 0xf4410001 /*P1_CFRUP1*/ -#define R0900_P1_CFRUP1 0xf442 -#define F0900_P1_CFR_UP1 0xf44201ff +#define R0900_P1_CFRUP1 0xf442 +#define CFRUP1 REGx(R0900_P1_CFRUP1) +#define F0900_P1_CFR_UP1 0xf44201ff +#define CFR_UP1 FLDx(F0900_P1_CFR_UP1) /*P1_CFRUP0*/ -#define R0900_P1_CFRUP0 0xf443 -#define F0900_P1_CFR_UP0 0xf44300ff +#define R0900_P1_CFRUP0 0xf443 +#define CFRUP0 REGx(R0900_P1_CFRUP0) +#define F0900_P1_CFR_UP0 0xf44300ff +#define CFR_UP0 FLDx(F0900_P1_CFR_UP0) /*P1_CFRLOW1*/ -#define R0900_P1_CFRLOW1 0xf446 -#define F0900_P1_CFR_LOW1 0xf44601ff +#define R0900_P1_CFRLOW1 0xf446 +#define CFRLOW1 REGx(R0900_P1_CFRLOW1) +#define F0900_P1_CFR_LOW1 0xf44601ff +#define CFR_LOW1 FLDx(F0900_P1_CFR_LOW1) /*P1_CFRLOW0*/ -#define R0900_P1_CFRLOW0 0xf447 -#define F0900_P1_CFR_LOW0 0xf44700ff +#define R0900_P1_CFRLOW0 0xf447 +#define CFRLOW0 REGx(R0900_P1_CFRLOW0) +#define F0900_P1_CFR_LOW0 0xf44700ff +#define CFR_LOW0 FLDx(F0900_P1_CFR_LOW0) /*P1_CFRINIT1*/ -#define R0900_P1_CFRINIT1 0xf448 -#define F0900_P1_CFR_INIT1 0xf44801ff +#define R0900_P1_CFRINIT1 0xf448 +#define CFRINIT1 REGx(R0900_P1_CFRINIT1) +#define F0900_P1_CFR_INIT1 0xf44801ff +#define CFR_INIT1 FLDx(F0900_P1_CFR_INIT1) /*P1_CFRINIT0*/ -#define R0900_P1_CFRINIT0 0xf449 -#define F0900_P1_CFR_INIT0 0xf44900ff +#define R0900_P1_CFRINIT0 0xf449 +#define CFRINIT0 REGx(R0900_P1_CFRINIT0) +#define F0900_P1_CFR_INIT0 0xf44900ff +#define CFR_INIT0 FLDx(F0900_P1_CFR_INIT0) /*P1_CFRINC1*/ -#define R0900_P1_CFRINC1 0xf44a -#define F0900_P1_MANUAL_CFRINC 0xf44a0080 -#define F0900_P1_CFR_INC1 0xf44a017f +#define R0900_P1_CFRINC1 0xf44a +#define CFRINC1 REGx(R0900_P1_CFRINC1) +#define F0900_P1_MANUAL_CFRINC 0xf44a0080 +#define F0900_P1_CFR_INC1 0xf44a003f /*P1_CFRINC0*/ -#define R0900_P1_CFRINC0 0xf44b -#define F0900_P1_CFR_INC0 0xf44b00f0 +#define R0900_P1_CFRINC0 0xf44b +#define CFRINC0 REGx(R0900_P1_CFRINC0) +#define F0900_P1_CFR_INC0 0xf44b00f8 /*P1_CFR2*/ -#define R0900_P1_CFR2 0xf44c -#define F0900_P1_CAR_FREQ2 0xf44c01ff +#define R0900_P1_CFR2 0xf44c +#define CFR2 REGx(R0900_P1_CFR2) +#define F0900_P1_CAR_FREQ2 0xf44c01ff +#define CAR_FREQ2 FLDx(F0900_P1_CAR_FREQ2) /*P1_CFR1*/ -#define R0900_P1_CFR1 0xf44d -#define F0900_P1_CAR_FREQ1 0xf44d00ff +#define R0900_P1_CFR1 0xf44d +#define CFR1 REGx(R0900_P1_CFR1) +#define F0900_P1_CAR_FREQ1 0xf44d00ff +#define CAR_FREQ1 FLDx(F0900_P1_CAR_FREQ1) /*P1_CFR0*/ -#define R0900_P1_CFR0 0xf44e -#define F0900_P1_CAR_FREQ0 0xf44e00ff +#define R0900_P1_CFR0 0xf44e +#define CFR0 REGx(R0900_P1_CFR0) +#define F0900_P1_CAR_FREQ0 0xf44e00ff +#define CAR_FREQ0 FLDx(F0900_P1_CAR_FREQ0) /*P1_LDI*/ -#define R0900_P1_LDI 0xf44f -#define F0900_P1_LOCK_DET_INTEGR 0xf44f01ff +#define R0900_P1_LDI 0xf44f +#define LDI REGx(R0900_P1_LDI) +#define F0900_P1_LOCK_DET_INTEGR 0xf44f01ff /*P1_TMGCFG*/ -#define R0900_P1_TMGCFG 0xf450 -#define F0900_P1_TMGLOCK_BETA 0xf45000c0 -#define F0900_P1_NOTMG_GROUPDELAY 0xf4500020 -#define F0900_P1_DO_TIMING_CORR 0xf4500010 -#define F0900_P1_MANUAL_SCAN 0xf450000c -#define F0900_P1_TMG_MINFREQ 0xf4500003 +#define R0900_P1_TMGCFG 0xf450 +#define TMGCFG REGx(R0900_P1_TMGCFG) +#define F0900_P1_TMGLOCK_BETA 0xf45000c0 +#define F0900_P1_DO_TIMING_CORR 0xf4500010 +#define F0900_P1_TMG_MINFREQ 0xf4500003 /*P1_RTC*/ -#define R0900_P1_RTC 0xf451 -#define F0900_P1_TMGALPHA_EXP 0xf45100f0 -#define F0900_P1_TMGBETA_EXP 0xf451000f +#define R0900_P1_RTC 0xf451 +#define RTC REGx(R0900_P1_RTC) +#define F0900_P1_TMGALPHA_EXP 0xf45100f0 +#define F0900_P1_TMGBETA_EXP 0xf451000f /*P1_RTCS2*/ -#define R0900_P1_RTCS2 0xf452 -#define F0900_P1_TMGALPHAS2_EXP 0xf45200f0 -#define F0900_P1_TMGBETAS2_EXP 0xf452000f +#define R0900_P1_RTCS2 0xf452 +#define RTCS2 REGx(R0900_P1_RTCS2) +#define F0900_P1_TMGALPHAS2_EXP 0xf45200f0 +#define F0900_P1_TMGBETAS2_EXP 0xf452000f /*P1_TMGTHRISE*/ -#define R0900_P1_TMGTHRISE 0xf453 -#define F0900_P1_TMGLOCK_THRISE 0xf45300ff +#define R0900_P1_TMGTHRISE 0xf453 +#define TMGTHRISE REGx(R0900_P1_TMGTHRISE) +#define F0900_P1_TMGLOCK_THRISE 0xf45300ff /*P1_TMGTHFALL*/ -#define R0900_P1_TMGTHFALL 0xf454 -#define F0900_P1_TMGLOCK_THFALL 0xf45400ff +#define R0900_P1_TMGTHFALL 0xf454 +#define TMGTHFALL REGx(R0900_P1_TMGTHFALL) +#define F0900_P1_TMGLOCK_THFALL 0xf45400ff /*P1_SFRUPRATIO*/ -#define R0900_P1_SFRUPRATIO 0xf455 -#define F0900_P1_SFR_UPRATIO 0xf45500ff +#define R0900_P1_SFRUPRATIO 0xf455 +#define SFRUPRATIO REGx(R0900_P1_SFRUPRATIO) +#define F0900_P1_SFR_UPRATIO 0xf45500ff /*P1_SFRLOWRATIO*/ -#define R0900_P1_SFRLOWRATIO 0xf456 -#define F0900_P1_SFR_LOWRATIO 0xf45600ff +#define R0900_P1_SFRLOWRATIO 0xf456 +#define F0900_P1_SFR_LOWRATIO 0xf45600ff /*P1_KREFTMG*/ -#define R0900_P1_KREFTMG 0xf458 -#define F0900_P1_KREF_TMG 0xf45800ff +#define R0900_P1_KREFTMG 0xf458 +#define KREFTMG REGx(R0900_P1_KREFTMG) +#define F0900_P1_KREF_TMG 0xf45800ff /*P1_SFRSTEP*/ -#define R0900_P1_SFRSTEP 0xf459 -#define F0900_P1_SFR_SCANSTEP 0xf45900f0 -#define F0900_P1_SFR_CENTERSTEP 0xf459000f +#define R0900_P1_SFRSTEP 0xf459 +#define SFRSTEP REGx(R0900_P1_SFRSTEP) +#define F0900_P1_SFR_SCANSTEP 0xf45900f0 +#define F0900_P1_SFR_CENTERSTEP 0xf459000f /*P1_TMGCFG2*/ -#define R0900_P1_TMGCFG2 0xf45a -#define F0900_P1_DIS_AUTOSAMP 0xf45a0008 -#define F0900_P1_SCANINIT_QUART 0xf45a0004 -#define F0900_P1_NOTMG_DVBS1DERAT 0xf45a0002 -#define F0900_P1_SFRRATIO_FINE 0xf45a0001 +#define R0900_P1_TMGCFG2 0xf45a +#define TMGCFG2 REGx(R0900_P1_TMGCFG2) +#define F0900_P1_SFRRATIO_FINE 0xf45a0001 + +/*P1_KREFTMG2*/ +#define R0900_P1_KREFTMG2 0xf45b +#define KREFTMG2 REGx(R0900_P1_KREFTMG2) +#define F0900_P1_KREF_TMG2 0xf45b00ff /*P1_SFRINIT1*/ -#define R0900_P1_SFRINIT1 0xf45e -#define F0900_P1_SFR_INIT1 0xf45e00ff +#define R0900_P1_SFRINIT1 0xf45e +#define SFRINIT1 REGx(R0900_P1_SFRINIT1) +#define F0900_P1_SFR_INIT1 0xf45e007f /*P1_SFRINIT0*/ -#define R0900_P1_SFRINIT0 0xf45f -#define F0900_P1_SFR_INIT0 0xf45f00ff +#define R0900_P1_SFRINIT0 0xf45f +#define SFRINIT0 REGx(R0900_P1_SFRINIT0) +#define F0900_P1_SFR_INIT0 0xf45f00ff /*P1_SFRUP1*/ -#define R0900_P1_SFRUP1 0xf460 -#define F0900_P1_AUTO_GUP 0xf4600080 -#define F0900_P1_SYMB_FREQ_UP1 0xf460007f +#define R0900_P1_SFRUP1 0xf460 +#define SFRUP1 REGx(R0900_P1_SFRUP1) +#define F0900_P1_AUTO_GUP 0xf4600080 +#define AUTO_GUP FLDx(F0900_P1_AUTO_GUP) +#define F0900_P1_SYMB_FREQ_UP1 0xf460007f /*P1_SFRUP0*/ -#define R0900_P1_SFRUP0 0xf461 -#define F0900_P1_SYMB_FREQ_UP0 0xf46100ff +#define R0900_P1_SFRUP0 0xf461 +#define SFRUP0 REGx(R0900_P1_SFRUP0) +#define F0900_P1_SYMB_FREQ_UP0 0xf46100ff /*P1_SFRLOW1*/ -#define R0900_P1_SFRLOW1 0xf462 -#define F0900_P1_AUTO_GLOW 0xf4620080 -#define F0900_P1_SYMB_FREQ_LOW1 0xf462007f +#define R0900_P1_SFRLOW1 0xf462 +#define SFRLOW1 REGx(R0900_P1_SFRLOW1) +#define F0900_P1_AUTO_GLOW 0xf4620080 +#define AUTO_GLOW FLDx(F0900_P1_AUTO_GLOW) +#define F0900_P1_SYMB_FREQ_LOW1 0xf462007f /*P1_SFRLOW0*/ -#define R0900_P1_SFRLOW0 0xf463 -#define F0900_P1_SYMB_FREQ_LOW0 0xf46300ff +#define R0900_P1_SFRLOW0 0xf463 +#define SFRLOW0 REGx(R0900_P1_SFRLOW0) +#define F0900_P1_SYMB_FREQ_LOW0 0xf46300ff /*P1_SFR3*/ -#define R0900_P1_SFR3 0xf464 -#define F0900_P1_SYMB_FREQ3 0xf46400ff +#define R0900_P1_SFR3 0xf464 +#define SFR3 REGx(R0900_P1_SFR3) +#define F0900_P1_SYMB_FREQ3 0xf46400ff +#define SYMB_FREQ3 FLDx(F0900_P1_SYMB_FREQ3) /*P1_SFR2*/ -#define R0900_P1_SFR2 0xf465 -#define F0900_P1_SYMB_FREQ2 0xf46500ff +#define R0900_P1_SFR2 0xf465 +#define SFR2 REGx(R0900_P1_SFR2) +#define F0900_P1_SYMB_FREQ2 0xf46500ff +#define SYMB_FREQ2 FLDx(F0900_P1_SYMB_FREQ2) /*P1_SFR1*/ -#define R0900_P1_SFR1 0xf466 -#define F0900_P1_SYMB_FREQ1 0xf46600ff +#define R0900_P1_SFR1 0xf466 +#define SFR1 REGx(R0900_P1_SFR1) +#define F0900_P1_SYMB_FREQ1 0xf46600ff +#define SYMB_FREQ1 FLDx(F0900_P1_SYMB_FREQ1) /*P1_SFR0*/ -#define R0900_P1_SFR0 0xf467 -#define F0900_P1_SYMB_FREQ0 0xf46700ff +#define R0900_P1_SFR0 0xf467 +#define SFR0 REGx(R0900_P1_SFR0) +#define F0900_P1_SYMB_FREQ0 0xf46700ff +#define SYMB_FREQ0 FLDx(F0900_P1_SYMB_FREQ0) /*P1_TMGREG2*/ -#define R0900_P1_TMGREG2 0xf468 -#define F0900_P1_TMGREG2 0xf46800ff +#define R0900_P1_TMGREG2 0xf468 +#define TMGREG2 REGx(R0900_P1_TMGREG2) +#define F0900_P1_TMGREG2 0xf46800ff /*P1_TMGREG1*/ -#define R0900_P1_TMGREG1 0xf469 -#define F0900_P1_TMGREG1 0xf46900ff +#define R0900_P1_TMGREG1 0xf469 +#define TMGREG1 REGx(R0900_P1_TMGREG1) +#define F0900_P1_TMGREG1 0xf46900ff /*P1_TMGREG0*/ -#define R0900_P1_TMGREG0 0xf46a -#define F0900_P1_TMGREG0 0xf46a00ff +#define R0900_P1_TMGREG0 0xf46a +#define TMGREG0 REGx(R0900_P1_TMGREG0) +#define F0900_P1_TMGREG0 0xf46a00ff /*P1_TMGLOCK1*/ -#define R0900_P1_TMGLOCK1 0xf46b -#define F0900_P1_TMGLOCK_LEVEL1 0xf46b01ff +#define R0900_P1_TMGLOCK1 0xf46b +#define TMGLOCK1 REGx(R0900_P1_TMGLOCK1) +#define F0900_P1_TMGLOCK_LEVEL1 0xf46b01ff /*P1_TMGLOCK0*/ -#define R0900_P1_TMGLOCK0 0xf46c -#define F0900_P1_TMGLOCK_LEVEL0 0xf46c00ff +#define R0900_P1_TMGLOCK0 0xf46c +#define TMGLOCK0 REGx(R0900_P1_TMGLOCK0) +#define F0900_P1_TMGLOCK_LEVEL0 0xf46c00ff /*P1_TMGOBS*/ -#define R0900_P1_TMGOBS 0xf46d -#define F0900_P1_ROLLOFF_STATUS 0xf46d00c0 -#define F0900_P1_SCAN_SIGN 0xf46d0030 -#define F0900_P1_TMG_SCANNING 0xf46d0008 -#define F0900_P1_CHCENTERING_MODE 0xf46d0004 -#define F0900_P1_TMG_SCANFAIL 0xf46d0002 +#define R0900_P1_TMGOBS 0xf46d +#define TMGOBS REGx(R0900_P1_TMGOBS) +#define F0900_P1_ROLLOFF_STATUS 0xf46d00c0 +#define ROLLOFF_STATUS FLDx(F0900_P1_ROLLOFF_STATUS) /*P1_EQUALCFG*/ -#define R0900_P1_EQUALCFG 0xf46f -#define F0900_P1_NOTMG_NEGALWAIT 0xf46f0080 -#define F0900_P1_EQUAL_ON 0xf46f0040 -#define F0900_P1_SEL_EQUALCOR 0xf46f0038 -#define F0900_P1_MU_EQUALDFE 0xf46f0007 +#define R0900_P1_EQUALCFG 0xf46f +#define EQUALCFG REGx(R0900_P1_EQUALCFG) +#define F0900_P1_EQUAL_ON 0xf46f0040 +#define F0900_P1_MU_EQUALDFE 0xf46f0007 /*P1_EQUAI1*/ -#define R0900_P1_EQUAI1 0xf470 -#define F0900_P1_EQUA_ACCI1 0xf47001ff +#define R0900_P1_EQUAI1 0xf470 +#define EQUAI1 REGx(R0900_P1_EQUAI1) +#define F0900_P1_EQUA_ACCI1 0xf47001ff /*P1_EQUAQ1*/ -#define R0900_P1_EQUAQ1 0xf471 -#define F0900_P1_EQUA_ACCQ1 0xf47101ff +#define R0900_P1_EQUAQ1 0xf471 +#define EQUAQ1 REGx(R0900_P1_EQUAQ1) +#define F0900_P1_EQUA_ACCQ1 0xf47101ff /*P1_EQUAI2*/ -#define R0900_P1_EQUAI2 0xf472 -#define F0900_P1_EQUA_ACCI2 0xf47201ff +#define R0900_P1_EQUAI2 0xf472 +#define EQUAI2 REGx(R0900_P1_EQUAI2) +#define F0900_P1_EQUA_ACCI2 0xf47201ff /*P1_EQUAQ2*/ -#define R0900_P1_EQUAQ2 0xf473 -#define F0900_P1_EQUA_ACCQ2 0xf47301ff +#define R0900_P1_EQUAQ2 0xf473 +#define EQUAQ2 REGx(R0900_P1_EQUAQ2) +#define F0900_P1_EQUA_ACCQ2 0xf47301ff /*P1_EQUAI3*/ -#define R0900_P1_EQUAI3 0xf474 -#define F0900_P1_EQUA_ACCI3 0xf47401ff +#define R0900_P1_EQUAI3 0xf474 +#define EQUAI3 REGx(R0900_P1_EQUAI3) +#define F0900_P1_EQUA_ACCI3 0xf47401ff /*P1_EQUAQ3*/ -#define R0900_P1_EQUAQ3 0xf475 -#define F0900_P1_EQUA_ACCQ3 0xf47501ff +#define R0900_P1_EQUAQ3 0xf475 +#define EQUAQ3 REGx(R0900_P1_EQUAQ3) +#define F0900_P1_EQUA_ACCQ3 0xf47501ff /*P1_EQUAI4*/ -#define R0900_P1_EQUAI4 0xf476 -#define F0900_P1_EQUA_ACCI4 0xf47601ff +#define R0900_P1_EQUAI4 0xf476 +#define EQUAI4 REGx(R0900_P1_EQUAI4) +#define F0900_P1_EQUA_ACCI4 0xf47601ff /*P1_EQUAQ4*/ -#define R0900_P1_EQUAQ4 0xf477 -#define F0900_P1_EQUA_ACCQ4 0xf47701ff +#define R0900_P1_EQUAQ4 0xf477 +#define EQUAQ4 REGx(R0900_P1_EQUAQ4) +#define F0900_P1_EQUA_ACCQ4 0xf47701ff /*P1_EQUAI5*/ -#define R0900_P1_EQUAI5 0xf478 -#define F0900_P1_EQUA_ACCI5 0xf47801ff +#define R0900_P1_EQUAI5 0xf478 +#define EQUAI5 REGx(R0900_P1_EQUAI5) +#define F0900_P1_EQUA_ACCI5 0xf47801ff /*P1_EQUAQ5*/ -#define R0900_P1_EQUAQ5 0xf479 -#define F0900_P1_EQUA_ACCQ5 0xf47901ff +#define R0900_P1_EQUAQ5 0xf479 +#define EQUAQ5 REGx(R0900_P1_EQUAQ5) +#define F0900_P1_EQUA_ACCQ5 0xf47901ff /*P1_EQUAI6*/ -#define R0900_P1_EQUAI6 0xf47a -#define F0900_P1_EQUA_ACCI6 0xf47a01ff +#define R0900_P1_EQUAI6 0xf47a +#define EQUAI6 REGx(R0900_P1_EQUAI6) +#define F0900_P1_EQUA_ACCI6 0xf47a01ff /*P1_EQUAQ6*/ -#define R0900_P1_EQUAQ6 0xf47b -#define F0900_P1_EQUA_ACCQ6 0xf47b01ff +#define R0900_P1_EQUAQ6 0xf47b +#define EQUAQ6 REGx(R0900_P1_EQUAQ6) +#define F0900_P1_EQUA_ACCQ6 0xf47b01ff /*P1_EQUAI7*/ -#define R0900_P1_EQUAI7 0xf47c -#define F0900_P1_EQUA_ACCI7 0xf47c01ff +#define R0900_P1_EQUAI7 0xf47c +#define EQUAI7 REGx(R0900_P1_EQUAI7) +#define F0900_P1_EQUA_ACCI7 0xf47c01ff /*P1_EQUAQ7*/ -#define R0900_P1_EQUAQ7 0xf47d -#define F0900_P1_EQUA_ACCQ7 0xf47d01ff +#define R0900_P1_EQUAQ7 0xf47d +#define EQUAQ7 REGx(R0900_P1_EQUAQ7) +#define F0900_P1_EQUA_ACCQ7 0xf47d01ff /*P1_EQUAI8*/ -#define R0900_P1_EQUAI8 0xf47e -#define F0900_P1_EQUA_ACCI8 0xf47e01ff +#define R0900_P1_EQUAI8 0xf47e +#define EQUAI8 REGx(R0900_P1_EQUAI8) +#define F0900_P1_EQUA_ACCI8 0xf47e01ff /*P1_EQUAQ8*/ -#define R0900_P1_EQUAQ8 0xf47f -#define F0900_P1_EQUA_ACCQ8 0xf47f01ff +#define R0900_P1_EQUAQ8 0xf47f +#define EQUAQ8 REGx(R0900_P1_EQUAQ8) +#define F0900_P1_EQUA_ACCQ8 0xf47f01ff /*P1_NNOSDATAT1*/ -#define R0900_P1_NNOSDATAT1 0xf480 -#define F0900_P1_NOSDATAT_NORMED1 0xf48000ff +#define R0900_P1_NNOSDATAT1 0xf480 +#define NNOSDATAT1 REGx(R0900_P1_NNOSDATAT1) +#define F0900_P1_NOSDATAT_NORMED1 0xf48000ff +#define NOSDATAT_NORMED1 FLDx(F0900_P1_NOSDATAT_NORMED1) /*P1_NNOSDATAT0*/ -#define R0900_P1_NNOSDATAT0 0xf481 -#define F0900_P1_NOSDATAT_NORMED0 0xf48100ff +#define R0900_P1_NNOSDATAT0 0xf481 +#define NNOSDATAT0 REGx(R0900_P1_NNOSDATAT0) +#define F0900_P1_NOSDATAT_NORMED0 0xf48100ff +#define NOSDATAT_NORMED0 FLDx(F0900_P1_NOSDATAT_NORMED0) /*P1_NNOSDATA1*/ -#define R0900_P1_NNOSDATA1 0xf482 -#define F0900_P1_NOSDATA_NORMED1 0xf48200ff +#define R0900_P1_NNOSDATA1 0xf482 +#define NNOSDATA1 REGx(R0900_P1_NNOSDATA1) +#define F0900_P1_NOSDATA_NORMED1 0xf48200ff /*P1_NNOSDATA0*/ -#define R0900_P1_NNOSDATA0 0xf483 -#define F0900_P1_NOSDATA_NORMED0 0xf48300ff +#define R0900_P1_NNOSDATA0 0xf483 +#define NNOSDATA0 REGx(R0900_P1_NNOSDATA0) +#define F0900_P1_NOSDATA_NORMED0 0xf48300ff /*P1_NNOSPLHT1*/ -#define R0900_P1_NNOSPLHT1 0xf484 -#define F0900_P1_NOSPLHT_NORMED1 0xf48400ff +#define R0900_P1_NNOSPLHT1 0xf484 +#define NNOSPLHT1 REGx(R0900_P1_NNOSPLHT1) +#define F0900_P1_NOSPLHT_NORMED1 0xf48400ff +#define NOSPLHT_NORMED1 FLDx(F0900_P1_NOSPLHT_NORMED1) /*P1_NNOSPLHT0*/ -#define R0900_P1_NNOSPLHT0 0xf485 -#define F0900_P1_NOSPLHT_NORMED0 0xf48500ff +#define R0900_P1_NNOSPLHT0 0xf485 +#define NNOSPLHT0 REGx(R0900_P1_NNOSPLHT0) +#define F0900_P1_NOSPLHT_NORMED0 0xf48500ff +#define NOSPLHT_NORMED0 FLDx(F0900_P1_NOSPLHT_NORMED0) /*P1_NNOSPLH1*/ -#define R0900_P1_NNOSPLH1 0xf486 -#define F0900_P1_NOSPLH_NORMED1 0xf48600ff +#define R0900_P1_NNOSPLH1 0xf486 +#define NNOSPLH1 REGx(R0900_P1_NNOSPLH1) +#define F0900_P1_NOSPLH_NORMED1 0xf48600ff /*P1_NNOSPLH0*/ -#define R0900_P1_NNOSPLH0 0xf487 -#define F0900_P1_NOSPLH_NORMED0 0xf48700ff +#define R0900_P1_NNOSPLH0 0xf487 +#define NNOSPLH0 REGx(R0900_P1_NNOSPLH0) +#define F0900_P1_NOSPLH_NORMED0 0xf48700ff /*P1_NOSDATAT1*/ -#define R0900_P1_NOSDATAT1 0xf488 -#define F0900_P1_NOSDATAT_UNNORMED1 0xf48800ff +#define R0900_P1_NOSDATAT1 0xf488 +#define NOSDATAT1 REGx(R0900_P1_NOSDATAT1) +#define F0900_P1_NOSDATAT_UNNORMED1 0xf48800ff /*P1_NOSDATAT0*/ -#define R0900_P1_NOSDATAT0 0xf489 -#define F0900_P1_NOSDATAT_UNNORMED0 0xf48900ff +#define R0900_P1_NOSDATAT0 0xf489 +#define NOSDATAT0 REGx(R0900_P1_NOSDATAT0) +#define F0900_P1_NOSDATAT_UNNORMED0 0xf48900ff /*P1_NOSDATA1*/ -#define R0900_P1_NOSDATA1 0xf48a -#define F0900_P1_NOSDATA_UNNORMED1 0xf48a00ff +#define R0900_P1_NOSDATA1 0xf48a +#define NOSDATA1 REGx(R0900_P1_NOSDATA1) +#define F0900_P1_NOSDATA_UNNORMED1 0xf48a00ff /*P1_NOSDATA0*/ -#define R0900_P1_NOSDATA0 0xf48b -#define F0900_P1_NOSDATA_UNNORMED0 0xf48b00ff +#define R0900_P1_NOSDATA0 0xf48b +#define NOSDATA0 REGx(R0900_P1_NOSDATA0) +#define F0900_P1_NOSDATA_UNNORMED0 0xf48b00ff /*P1_NOSPLHT1*/ -#define R0900_P1_NOSPLHT1 0xf48c -#define F0900_P1_NOSPLHT_UNNORMED1 0xf48c00ff +#define R0900_P1_NOSPLHT1 0xf48c +#define NOSPLHT1 REGx(R0900_P1_NOSPLHT1) +#define F0900_P1_NOSPLHT_UNNORMED1 0xf48c00ff /*P1_NOSPLHT0*/ -#define R0900_P1_NOSPLHT0 0xf48d -#define F0900_P1_NOSPLHT_UNNORMED0 0xf48d00ff +#define R0900_P1_NOSPLHT0 0xf48d +#define NOSPLHT0 REGx(R0900_P1_NOSPLHT0) +#define F0900_P1_NOSPLHT_UNNORMED0 0xf48d00ff /*P1_NOSPLH1*/ -#define R0900_P1_NOSPLH1 0xf48e -#define F0900_P1_NOSPLH_UNNORMED1 0xf48e00ff +#define R0900_P1_NOSPLH1 0xf48e +#define NOSPLH1 REGx(R0900_P1_NOSPLH1) +#define F0900_P1_NOSPLH_UNNORMED1 0xf48e00ff /*P1_NOSPLH0*/ -#define R0900_P1_NOSPLH0 0xf48f -#define F0900_P1_NOSPLH_UNNORMED0 0xf48f00ff +#define R0900_P1_NOSPLH0 0xf48f +#define NOSPLH0 REGx(R0900_P1_NOSPLH0) +#define F0900_P1_NOSPLH_UNNORMED0 0xf48f00ff /*P1_CAR2CFG*/ -#define R0900_P1_CAR2CFG 0xf490 -#define F0900_P1_DESCRAMB_OFF 0xf4900080 -#define F0900_P1_PN4_SELECT 0xf4900040 -#define F0900_P1_CFR2_STOPDVBS1 0xf4900020 -#define F0900_P1_STOP_CFR2UPDATE 0xf4900010 -#define F0900_P1_STOP_NCO2UPDATE 0xf4900008 -#define F0900_P1_ROTA2ON 0xf4900004 -#define F0900_P1_PH_DET_ALGO2 0xf4900003 +#define R0900_P1_CAR2CFG 0xf490 +#define CAR2CFG REGx(R0900_P1_CAR2CFG) +#define F0900_P1_CARRIER3_DISABLE 0xf4900040 +#define F0900_P1_ROTA2ON 0xf4900004 +#define F0900_P1_PH_DET_ALGO2 0xf4900003 -/*P1_ACLC2*/ -#define R0900_P1_ACLC2 0xf491 -#define F0900_P1_CAR2_PUNCT_ADERAT 0xf4910040 -#define F0900_P1_CAR2_ALPHA_MANT 0xf4910030 -#define F0900_P1_CAR2_ALPHA_EXP 0xf491000f - -/*P1_BCLC2*/ -#define R0900_P1_BCLC2 0xf492 -#define F0900_P1_DVBS2_NIP 0xf4920080 -#define F0900_P1_CAR2_PUNCT_BDERAT 0xf4920040 -#define F0900_P1_CAR2_BETA_MANT 0xf4920030 -#define F0900_P1_CAR2_BETA_EXP 0xf492000f +/*P1_CFR2CFR1*/ +#define R0900_P1_CFR2CFR1 0xf491 +#define CFR2CFR1 REGx(R0900_P1_CFR2CFR1) +#define F0900_P1_CFR2TOCFR1_DVBS1 0xf49100c0 +#define F0900_P1_EN_S2CAR2CENTER 0xf4910020 +#define F0900_P1_DIS_BCHERRCFR2 0xf4910010 +#define F0900_P1_CFR2TOCFR1_BETA 0xf4910007 /*P1_CFR22*/ -#define R0900_P1_CFR22 0xf493 -#define F0900_P1_CAR2_FREQ2 0xf49301ff +#define R0900_P1_CFR22 0xf493 +#define CFR22 REGx(R0900_P1_CFR22) +#define F0900_P1_CAR2_FREQ2 0xf49301ff /*P1_CFR21*/ -#define R0900_P1_CFR21 0xf494 -#define F0900_P1_CAR2_FREQ1 0xf49400ff +#define R0900_P1_CFR21 0xf494 +#define CFR21 REGx(R0900_P1_CFR21) +#define F0900_P1_CAR2_FREQ1 0xf49400ff /*P1_CFR20*/ -#define R0900_P1_CFR20 0xf495 -#define F0900_P1_CAR2_FREQ0 0xf49500ff +#define R0900_P1_CFR20 0xf495 +#define CFR20 REGx(R0900_P1_CFR20) +#define F0900_P1_CAR2_FREQ0 0xf49500ff /*P1_ACLC2S2Q*/ -#define R0900_P1_ACLC2S2Q 0xf497 -#define F0900_P1_ENAB_SPSKSYMB 0xf4970080 -#define F0900_P1_CAR2S2_QADERAT 0xf4970040 -#define F0900_P1_CAR2S2_Q_ALPH_M 0xf4970030 -#define F0900_P1_CAR2S2_Q_ALPH_E 0xf497000f +#define R0900_P1_ACLC2S2Q 0xf497 +#define ACLC2S2Q REGx(R0900_P1_ACLC2S2Q) +#define F0900_P1_ENAB_SPSKSYMB 0xf4970080 +#define F0900_P1_CAR2S2_Q_ALPH_M 0xf4970030 +#define F0900_P1_CAR2S2_Q_ALPH_E 0xf497000f /*P1_ACLC2S28*/ -#define R0900_P1_ACLC2S28 0xf498 -#define F0900_P1_OLDI3Q_MODE 0xf4980080 -#define F0900_P1_CAR2S2_8ADERAT 0xf4980040 -#define F0900_P1_CAR2S2_8_ALPH_M 0xf4980030 -#define F0900_P1_CAR2S2_8_ALPH_E 0xf498000f +#define R0900_P1_ACLC2S28 0xf498 +#define ACLC2S28 REGx(R0900_P1_ACLC2S28) +#define F0900_P1_OLDI3Q_MODE 0xf4980080 +#define F0900_P1_CAR2S2_8_ALPH_M 0xf4980030 +#define F0900_P1_CAR2S2_8_ALPH_E 0xf498000f /*P1_ACLC2S216A*/ -#define R0900_P1_ACLC2S216A 0xf499 -#define F0900_P1_CAR2S2_16ADERAT 0xf4990040 -#define F0900_P1_CAR2S2_16A_ALPH_M 0xf4990030 -#define F0900_P1_CAR2S2_16A_ALPH_E 0xf499000f +#define R0900_P1_ACLC2S216A 0xf499 +#define ACLC2S216A REGx(R0900_P1_ACLC2S216A) +#define F0900_P1_DIS_C3STOPA2 0xf4990080 +#define F0900_P1_CAR2S2_16ADERAT 0xf4990040 +#define F0900_P1_CAR2S2_16A_ALPH_M 0xf4990030 +#define F0900_P1_CAR2S2_16A_ALPH_E 0xf499000f /*P1_ACLC2S232A*/ -#define R0900_P1_ACLC2S232A 0xf49a -#define F0900_P1_CAR2S2_32ADERAT 0xf49a0040 -#define F0900_P1_CAR2S2_32A_ALPH_M 0xf49a0030 -#define F0900_P1_CAR2S2_32A_ALPH_E 0xf49a000f +#define R0900_P1_ACLC2S232A 0xf49a +#define ACLC2S232A REGx(R0900_P1_ACLC2S232A) +#define F0900_P1_CAR2S2_32ADERAT 0xf49a0040 +#define F0900_P1_CAR2S2_32A_ALPH_M 0xf49a0030 +#define F0900_P1_CAR2S2_32A_ALPH_E 0xf49a000f /*P1_BCLC2S2Q*/ -#define R0900_P1_BCLC2S2Q 0xf49c -#define F0900_P1_DVBS2S2Q_NIP 0xf49c0080 -#define F0900_P1_CAR2S2_QBDERAT 0xf49c0040 -#define F0900_P1_CAR2S2_Q_BETA_M 0xf49c0030 -#define F0900_P1_CAR2S2_Q_BETA_E 0xf49c000f +#define R0900_P1_BCLC2S2Q 0xf49c +#define BCLC2S2Q REGx(R0900_P1_BCLC2S2Q) +#define F0900_P1_CAR2S2_Q_BETA_M 0xf49c0030 +#define F0900_P1_CAR2S2_Q_BETA_E 0xf49c000f /*P1_BCLC2S28*/ -#define R0900_P1_BCLC2S28 0xf49d -#define F0900_P1_DVBS2S28_NIP 0xf49d0080 -#define F0900_P1_CAR2S2_8BDERAT 0xf49d0040 -#define F0900_P1_CAR2S2_8_BETA_M 0xf49d0030 -#define F0900_P1_CAR2S2_8_BETA_E 0xf49d000f +#define R0900_P1_BCLC2S28 0xf49d +#define BCLC2S28 REGx(R0900_P1_BCLC2S28) +#define F0900_P1_CAR2S2_8_BETA_M 0xf49d0030 +#define F0900_P1_CAR2S2_8_BETA_E 0xf49d000f /*P1_BCLC2S216A*/ -#define R0900_P1_BCLC2S216A 0xf49e -#define F0900_P1_DVBS2S216A_NIP 0xf49e0080 -#define F0900_P1_CAR2S2_16BDERAT 0xf49e0040 -#define F0900_P1_CAR2S2_16A_BETA_M 0xf49e0030 -#define F0900_P1_CAR2S2_16A_BETA_E 0xf49e000f +#define R0900_P1_BCLC2S216A 0xf49e +#define BCLC2S216A REGx(R0900_P1_BCLC2S216A) /*P1_BCLC2S232A*/ -#define R0900_P1_BCLC2S232A 0xf49f -#define F0900_P1_DVBS2S232A_NIP 0xf49f0080 -#define F0900_P1_CAR2S2_32BDERAT 0xf49f0040 -#define F0900_P1_CAR2S2_32A_BETA_M 0xf49f0030 -#define F0900_P1_CAR2S2_32A_BETA_E 0xf49f000f +#define R0900_P1_BCLC2S232A 0xf49f +#define BCLC2S232A REGx(R0900_P1_BCLC2S232A) /*P1_PLROOT2*/ -#define R0900_P1_PLROOT2 0xf4ac -#define F0900_P1_SHORTFR_DISABLE 0xf4ac0080 -#define F0900_P1_LONGFR_DISABLE 0xf4ac0040 -#define F0900_P1_DUMMYPL_DISABLE 0xf4ac0020 -#define F0900_P1_SHORTFR_AVOID 0xf4ac0010 -#define F0900_P1_PLSCRAMB_MODE 0xf4ac000c -#define F0900_P1_PLSCRAMB_ROOT2 0xf4ac0003 +#define R0900_P1_PLROOT2 0xf4ac +#define PLROOT2 REGx(R0900_P1_PLROOT2) +#define F0900_P1_PLSCRAMB_MODE 0xf4ac000c +#define F0900_P1_PLSCRAMB_ROOT2 0xf4ac0003 /*P1_PLROOT1*/ -#define R0900_P1_PLROOT1 0xf4ad -#define F0900_P1_PLSCRAMB_ROOT1 0xf4ad00ff +#define R0900_P1_PLROOT1 0xf4ad +#define PLROOT1 REGx(R0900_P1_PLROOT1) +#define F0900_P1_PLSCRAMB_ROOT1 0xf4ad00ff /*P1_PLROOT0*/ -#define R0900_P1_PLROOT0 0xf4ae -#define F0900_P1_PLSCRAMB_ROOT0 0xf4ae00ff +#define R0900_P1_PLROOT0 0xf4ae +#define PLROOT0 REGx(R0900_P1_PLROOT0) +#define F0900_P1_PLSCRAMB_ROOT0 0xf4ae00ff /*P1_MODCODLST0*/ -#define R0900_P1_MODCODLST0 0xf4b0 -#define F0900_P1_EN_TOKEN31 0xf4b00080 -#define F0900_P1_SYNCTAG_SELECT 0xf4b00040 -#define F0900_P1_MODCODRQ_MODE 0xf4b00030 +#define R0900_P1_MODCODLST0 0xf4b0 +#define MODCODLST0 REGx(R0900_P1_MODCODLST0) /*P1_MODCODLST1*/ -#define R0900_P1_MODCODLST1 0xf4b1 -#define F0900_P1_DIS_MODCOD29 0xf4b100f0 -#define F0900_P1_DIS_32PSK_9_10 0xf4b1000f +#define R0900_P1_MODCODLST1 0xf4b1 +#define MODCODLST1 REGx(R0900_P1_MODCODLST1) +#define F0900_P1_DIS_MODCOD29 0xf4b100f0 +#define F0900_P1_DIS_32PSK_9_10 0xf4b1000f /*P1_MODCODLST2*/ -#define R0900_P1_MODCODLST2 0xf4b2 -#define F0900_P1_DIS_32PSK_8_9 0xf4b200f0 -#define F0900_P1_DIS_32PSK_5_6 0xf4b2000f +#define R0900_P1_MODCODLST2 0xf4b2 +#define MODCODLST2 REGx(R0900_P1_MODCODLST2) +#define F0900_P1_DIS_32PSK_8_9 0xf4b200f0 +#define F0900_P1_DIS_32PSK_5_6 0xf4b2000f /*P1_MODCODLST3*/ -#define R0900_P1_MODCODLST3 0xf4b3 -#define F0900_P1_DIS_32PSK_4_5 0xf4b300f0 -#define F0900_P1_DIS_32PSK_3_4 0xf4b3000f +#define R0900_P1_MODCODLST3 0xf4b3 +#define MODCODLST3 REGx(R0900_P1_MODCODLST3) +#define F0900_P1_DIS_32PSK_4_5 0xf4b300f0 +#define F0900_P1_DIS_32PSK_3_4 0xf4b3000f /*P1_MODCODLST4*/ -#define R0900_P1_MODCODLST4 0xf4b4 -#define F0900_P1_DIS_16PSK_9_10 0xf4b400f0 -#define F0900_P1_DIS_16PSK_8_9 0xf4b4000f +#define R0900_P1_MODCODLST4 0xf4b4 +#define MODCODLST4 REGx(R0900_P1_MODCODLST4) +#define F0900_P1_DIS_16PSK_9_10 0xf4b400f0 +#define F0900_P1_DIS_16PSK_8_9 0xf4b4000f /*P1_MODCODLST5*/ -#define R0900_P1_MODCODLST5 0xf4b5 -#define F0900_P1_DIS_16PSK_5_6 0xf4b500f0 -#define F0900_P1_DIS_16PSK_4_5 0xf4b5000f +#define R0900_P1_MODCODLST5 0xf4b5 +#define MODCODLST5 REGx(R0900_P1_MODCODLST5) +#define F0900_P1_DIS_16PSK_5_6 0xf4b500f0 +#define F0900_P1_DIS_16PSK_4_5 0xf4b5000f /*P1_MODCODLST6*/ -#define R0900_P1_MODCODLST6 0xf4b6 -#define F0900_P1_DIS_16PSK_3_4 0xf4b600f0 -#define F0900_P1_DIS_16PSK_2_3 0xf4b6000f +#define R0900_P1_MODCODLST6 0xf4b6 +#define MODCODLST6 REGx(R0900_P1_MODCODLST6) +#define F0900_P1_DIS_16PSK_3_4 0xf4b600f0 +#define F0900_P1_DIS_16PSK_2_3 0xf4b6000f /*P1_MODCODLST7*/ -#define R0900_P1_MODCODLST7 0xf4b7 -#define F0900_P1_DIS_8P_9_10 0xf4b700f0 -#define F0900_P1_DIS_8P_8_9 0xf4b7000f +#define R0900_P1_MODCODLST7 0xf4b7 +#define MODCODLST7 REGx(R0900_P1_MODCODLST7) +#define F0900_P1_DIS_8P_9_10 0xf4b700f0 +#define F0900_P1_DIS_8P_8_9 0xf4b7000f /*P1_MODCODLST8*/ -#define R0900_P1_MODCODLST8 0xf4b8 -#define F0900_P1_DIS_8P_5_6 0xf4b800f0 -#define F0900_P1_DIS_8P_3_4 0xf4b8000f +#define R0900_P1_MODCODLST8 0xf4b8 +#define MODCODLST8 REGx(R0900_P1_MODCODLST8) +#define F0900_P1_DIS_8P_5_6 0xf4b800f0 +#define F0900_P1_DIS_8P_3_4 0xf4b8000f /*P1_MODCODLST9*/ -#define R0900_P1_MODCODLST9 0xf4b9 -#define F0900_P1_DIS_8P_2_3 0xf4b900f0 -#define F0900_P1_DIS_8P_3_5 0xf4b9000f +#define R0900_P1_MODCODLST9 0xf4b9 +#define MODCODLST9 REGx(R0900_P1_MODCODLST9) +#define F0900_P1_DIS_8P_2_3 0xf4b900f0 +#define F0900_P1_DIS_8P_3_5 0xf4b9000f /*P1_MODCODLSTA*/ -#define R0900_P1_MODCODLSTA 0xf4ba -#define F0900_P1_DIS_QP_9_10 0xf4ba00f0 -#define F0900_P1_DIS_QP_8_9 0xf4ba000f +#define R0900_P1_MODCODLSTA 0xf4ba +#define MODCODLSTA REGx(R0900_P1_MODCODLSTA) +#define F0900_P1_DIS_QP_9_10 0xf4ba00f0 +#define F0900_P1_DIS_QP_8_9 0xf4ba000f /*P1_MODCODLSTB*/ -#define R0900_P1_MODCODLSTB 0xf4bb -#define F0900_P1_DIS_QP_5_6 0xf4bb00f0 -#define F0900_P1_DIS_QP_4_5 0xf4bb000f +#define R0900_P1_MODCODLSTB 0xf4bb +#define MODCODLSTB REGx(R0900_P1_MODCODLSTB) +#define F0900_P1_DIS_QP_5_6 0xf4bb00f0 +#define F0900_P1_DIS_QP_4_5 0xf4bb000f /*P1_MODCODLSTC*/ -#define R0900_P1_MODCODLSTC 0xf4bc -#define F0900_P1_DIS_QP_3_4 0xf4bc00f0 -#define F0900_P1_DIS_QP_2_3 0xf4bc000f +#define R0900_P1_MODCODLSTC 0xf4bc +#define MODCODLSTC REGx(R0900_P1_MODCODLSTC) +#define F0900_P1_DIS_QP_3_4 0xf4bc00f0 +#define F0900_P1_DIS_QP_2_3 0xf4bc000f /*P1_MODCODLSTD*/ -#define R0900_P1_MODCODLSTD 0xf4bd -#define F0900_P1_DIS_QP_3_5 0xf4bd00f0 -#define F0900_P1_DIS_QP_1_2 0xf4bd000f +#define R0900_P1_MODCODLSTD 0xf4bd +#define MODCODLSTD REGx(R0900_P1_MODCODLSTD) +#define F0900_P1_DIS_QP_3_5 0xf4bd00f0 +#define F0900_P1_DIS_QP_1_2 0xf4bd000f /*P1_MODCODLSTE*/ -#define R0900_P1_MODCODLSTE 0xf4be -#define F0900_P1_DIS_QP_2_5 0xf4be00f0 -#define F0900_P1_DIS_QP_1_3 0xf4be000f +#define R0900_P1_MODCODLSTE 0xf4be +#define MODCODLSTE REGx(R0900_P1_MODCODLSTE) +#define F0900_P1_DIS_QP_2_5 0xf4be00f0 +#define F0900_P1_DIS_QP_1_3 0xf4be000f /*P1_MODCODLSTF*/ -#define R0900_P1_MODCODLSTF 0xf4bf -#define F0900_P1_DIS_QP_1_4 0xf4bf00f0 -#define F0900_P1_DDEMOD_SET 0xf4bf0002 -#define F0900_P1_DDEMOD_MASK 0xf4bf0001 +#define R0900_P1_MODCODLSTF 0xf4bf +#define MODCODLSTF REGx(R0900_P1_MODCODLSTF) +#define F0900_P1_DIS_QP_1_4 0xf4bf00f0 + +/*P1_GAUSSR0*/ +#define R0900_P1_GAUSSR0 0xf4c0 +#define GAUSSR0 REGx(R0900_P1_GAUSSR0) +#define F0900_P1_EN_CCIMODE 0xf4c00080 +#define F0900_P1_R0_GAUSSIEN 0xf4c0007f + +/*P1_CCIR0*/ +#define R0900_P1_CCIR0 0xf4c1 +#define CCIR0 REGx(R0900_P1_CCIR0) +#define F0900_P1_CCIDETECT_PLHONLY 0xf4c10080 +#define F0900_P1_R0_CCI 0xf4c1007f + +/*P1_CCIQUANT*/ +#define R0900_P1_CCIQUANT 0xf4c2 +#define CCIQUANT REGx(R0900_P1_CCIQUANT) +#define F0900_P1_CCI_BETA 0xf4c200e0 +#define F0900_P1_CCI_QUANT 0xf4c2001f + +/*P1_CCITHRES*/ +#define R0900_P1_CCITHRES 0xf4c3 +#define CCITHRES REGx(R0900_P1_CCITHRES) +#define F0900_P1_CCI_THRESHOLD 0xf4c300ff + +/*P1_CCIACC*/ +#define R0900_P1_CCIACC 0xf4c4 +#define CCIACC REGx(R0900_P1_CCIACC) +#define F0900_P1_CCI_VALUE 0xf4c400ff /*P1_DMDRESCFG*/ -#define R0900_P1_DMDRESCFG 0xf4c6 -#define F0900_P1_DMDRES_RESET 0xf4c60080 -#define F0900_P1_DMDRES_NOISESQR 0xf4c60010 -#define F0900_P1_DMDRES_STRALL 0xf4c60008 -#define F0900_P1_DMDRES_NEWONLY 0xf4c60004 -#define F0900_P1_DMDRES_NOSTORE 0xf4c60002 -#define F0900_P1_DMDRES_AGC2MEM 0xf4c60001 +#define R0900_P1_DMDRESCFG 0xf4c6 +#define DMDRESCFG REGx(R0900_P1_DMDRESCFG) +#define F0900_P1_DMDRES_RESET 0xf4c60080 +#define F0900_P1_DMDRES_STRALL 0xf4c60008 +#define F0900_P1_DMDRES_NEWONLY 0xf4c60004 +#define F0900_P1_DMDRES_NOSTORE 0xf4c60002 /*P1_DMDRESADR*/ -#define R0900_P1_DMDRESADR 0xf4c7 -#define F0900_P1_SUSP_PREDCANAL 0xf4c70080 -#define F0900_P1_DMDRES_VALIDCFR 0xf4c70040 -#define F0900_P1_DMDRES_MEMFULL 0xf4c70030 -#define F0900_P1_DMDRES_RESNBR 0xf4c7000f +#define R0900_P1_DMDRESADR 0xf4c7 +#define DMDRESADR REGx(R0900_P1_DMDRESADR) +#define F0900_P1_DMDRES_VALIDCFR 0xf4c70040 +#define F0900_P1_DMDRES_MEMFULL 0xf4c70030 +#define F0900_P1_DMDRES_RESNBR 0xf4c7000f /*P1_DMDRESDATA7*/ -#define R0900_P1_DMDRESDATA7 0xf4c8 -#define F0900_P1_DMDRES_DATA7 0xf4c800ff +#define R0900_P1_DMDRESDATA7 0xf4c8 +#define F0900_P1_DMDRES_DATA7 0xf4c800ff /*P1_DMDRESDATA6*/ -#define R0900_P1_DMDRESDATA6 0xf4c9 -#define F0900_P1_DMDRES_DATA6 0xf4c900ff +#define R0900_P1_DMDRESDATA6 0xf4c9 +#define F0900_P1_DMDRES_DATA6 0xf4c900ff /*P1_DMDRESDATA5*/ -#define R0900_P1_DMDRESDATA5 0xf4ca -#define F0900_P1_DMDRES_DATA5 0xf4ca00ff +#define R0900_P1_DMDRESDATA5 0xf4ca +#define F0900_P1_DMDRES_DATA5 0xf4ca00ff /*P1_DMDRESDATA4*/ -#define R0900_P1_DMDRESDATA4 0xf4cb -#define F0900_P1_DMDRES_DATA4 0xf4cb00ff +#define R0900_P1_DMDRESDATA4 0xf4cb +#define F0900_P1_DMDRES_DATA4 0xf4cb00ff /*P1_DMDRESDATA3*/ -#define R0900_P1_DMDRESDATA3 0xf4cc -#define F0900_P1_DMDRES_DATA3 0xf4cc00ff +#define R0900_P1_DMDRESDATA3 0xf4cc +#define F0900_P1_DMDRES_DATA3 0xf4cc00ff /*P1_DMDRESDATA2*/ -#define R0900_P1_DMDRESDATA2 0xf4cd -#define F0900_P1_DMDRES_DATA2 0xf4cd00ff +#define R0900_P1_DMDRESDATA2 0xf4cd +#define F0900_P1_DMDRES_DATA2 0xf4cd00ff /*P1_DMDRESDATA1*/ -#define R0900_P1_DMDRESDATA1 0xf4ce -#define F0900_P1_DMDRES_DATA1 0xf4ce00ff +#define R0900_P1_DMDRESDATA1 0xf4ce +#define F0900_P1_DMDRES_DATA1 0xf4ce00ff /*P1_DMDRESDATA0*/ -#define R0900_P1_DMDRESDATA0 0xf4cf -#define F0900_P1_DMDRES_DATA0 0xf4cf00ff +#define R0900_P1_DMDRESDATA0 0xf4cf +#define F0900_P1_DMDRES_DATA0 0xf4cf00ff /*P1_FFEI1*/ -#define R0900_P1_FFEI1 0xf4d0 -#define F0900_P1_FFE_ACCI1 0xf4d001ff +#define R0900_P1_FFEI1 0xf4d0 +#define FFEI1 REGx(R0900_P1_FFEI1) +#define F0900_P1_FFE_ACCI1 0xf4d001ff /*P1_FFEQ1*/ -#define R0900_P1_FFEQ1 0xf4d1 -#define F0900_P1_FFE_ACCQ1 0xf4d101ff +#define R0900_P1_FFEQ1 0xf4d1 +#define FFEQ1 REGx(R0900_P1_FFEQ1) +#define F0900_P1_FFE_ACCQ1 0xf4d101ff /*P1_FFEI2*/ -#define R0900_P1_FFEI2 0xf4d2 -#define F0900_P1_FFE_ACCI2 0xf4d201ff +#define R0900_P1_FFEI2 0xf4d2 +#define FFEI2 REGx(R0900_P1_FFEI2) +#define F0900_P1_FFE_ACCI2 0xf4d201ff /*P1_FFEQ2*/ -#define R0900_P1_FFEQ2 0xf4d3 -#define F0900_P1_FFE_ACCQ2 0xf4d301ff +#define R0900_P1_FFEQ2 0xf4d3 +#define FFEQ2 REGx(R0900_P1_FFEQ2) +#define F0900_P1_FFE_ACCQ2 0xf4d301ff /*P1_FFEI3*/ -#define R0900_P1_FFEI3 0xf4d4 -#define F0900_P1_FFE_ACCI3 0xf4d401ff +#define R0900_P1_FFEI3 0xf4d4 +#define FFEI3 REGx(R0900_P1_FFEI3) +#define F0900_P1_FFE_ACCI3 0xf4d401ff /*P1_FFEQ3*/ -#define R0900_P1_FFEQ3 0xf4d5 -#define F0900_P1_FFE_ACCQ3 0xf4d501ff +#define R0900_P1_FFEQ3 0xf4d5 +#define FFEQ3 REGx(R0900_P1_FFEQ3) +#define F0900_P1_FFE_ACCQ3 0xf4d501ff /*P1_FFEI4*/ -#define R0900_P1_FFEI4 0xf4d6 -#define F0900_P1_FFE_ACCI4 0xf4d601ff +#define R0900_P1_FFEI4 0xf4d6 +#define FFEI4 REGx(R0900_P1_FFEI4) +#define F0900_P1_FFE_ACCI4 0xf4d601ff /*P1_FFEQ4*/ -#define R0900_P1_FFEQ4 0xf4d7 -#define F0900_P1_FFE_ACCQ4 0xf4d701ff +#define R0900_P1_FFEQ4 0xf4d7 +#define FFEQ4 REGx(R0900_P1_FFEQ4) +#define F0900_P1_FFE_ACCQ4 0xf4d701ff /*P1_FFECFG*/ -#define R0900_P1_FFECFG 0xf4d8 -#define F0900_P1_EQUALFFE_ON 0xf4d80040 -#define F0900_P1_EQUAL_USEDSYMB 0xf4d80030 -#define F0900_P1_MU_EQUALFFE 0xf4d80007 +#define R0900_P1_FFECFG 0xf4d8 +#define FFECFG REGx(R0900_P1_FFECFG) +#define F0900_P1_EQUALFFE_ON 0xf4d80040 +#define F0900_P1_MU_EQUALFFE 0xf4d80007 /*P1_TNRCFG*/ -#define R0900_P1_TNRCFG 0xf4e0 -#define F0900_P1_TUN_ACKFAIL 0xf4e00080 -#define F0900_P1_TUN_TYPE 0xf4e00070 -#define F0900_P1_TUN_SECSTOP 0xf4e00008 -#define F0900_P1_TUN_VCOSRCH 0xf4e00004 -#define F0900_P1_TUN_MADDRESS 0xf4e00003 +#define R0900_P1_TNRCFG 0xf4e0 +#define TNRCFG REGx(R0900_P1_TNRCFG) +#define F0900_P1_TUN_ACKFAIL 0xf4e00080 +#define F0900_P1_TUN_TYPE 0xf4e00070 +#define F0900_P1_TUN_SECSTOP 0xf4e00008 +#define F0900_P1_TUN_VCOSRCH 0xf4e00004 +#define F0900_P1_TUN_MADDRESS 0xf4e00003 /*P1_TNRCFG2*/ -#define R0900_P1_TNRCFG2 0xf4e1 -#define F0900_P1_TUN_IQSWAP 0xf4e10080 -#define F0900_P1_STB6110_STEP2MHZ 0xf4e10040 -#define F0900_P1_STB6120_DBLI2C 0xf4e10020 -#define F0900_P1_DIS_FCCK 0xf4e10010 -#define F0900_P1_DIS_LPEN 0xf4e10008 -#define F0900_P1_DIS_BWCALC 0xf4e10004 -#define F0900_P1_SHORT_WAITSTATES 0xf4e10002 -#define F0900_P1_DIS_2BWAGC1 0xf4e10001 +#define R0900_P1_TNRCFG2 0xf4e1 +#define TNRCFG2 REGx(R0900_P1_TNRCFG2) +#define F0900_P1_TUN_IQSWAP 0xf4e10080 +#define F0900_P1_DIS_BWCALC 0xf4e10004 +#define F0900_P1_SHORT_WAITSTATES 0xf4e10002 /*P1_TNRXTAL*/ -#define R0900_P1_TNRXTAL 0xf4e4 -#define F0900_P1_TUN_MCLKDECIMAL 0xf4e400e0 -#define F0900_P1_TUN_XTALFREQ 0xf4e4001f +#define R0900_P1_TNRXTAL 0xf4e4 +#define TNRXTAL REGx(R0900_P1_TNRXTAL) +#define F0900_P1_TUN_XTALFREQ 0xf4e4001f /*P1_TNRSTEPS*/ -#define R0900_P1_TNRSTEPS 0xf4e7 -#define F0900_P1_TUNER_BW1P6 0xf4e70080 -#define F0900_P1_BWINC_OFFSET 0xf4e70070 -#define F0900_P1_SOFTSTEP_RNG 0xf4e70008 -#define F0900_P1_TUN_BWOFFSET 0xf4e70107 +#define R0900_P1_TNRSTEPS 0xf4e7 +#define TNRSTEPS REGx(R0900_P1_TNRSTEPS) +#define F0900_P1_TUNER_BW0P125 0xf4e70080 +#define F0900_P1_BWINC_OFFSET 0xf4e70170 +#define F0900_P1_SOFTSTEP_RNG 0xf4e70008 +#define F0900_P1_TUN_BWOFFSET 0xf4e70007 /*P1_TNRGAIN*/ -#define R0900_P1_TNRGAIN 0xf4e8 -#define F0900_P1_TUN_KDIVEN 0xf4e800c0 -#define F0900_P1_STB6X00_OCK 0xf4e80030 -#define F0900_P1_TUN_GAIN 0xf4e8000f +#define R0900_P1_TNRGAIN 0xf4e8 +#define TNRGAIN REGx(R0900_P1_TNRGAIN) +#define F0900_P1_TUN_KDIVEN 0xf4e800c0 +#define F0900_P1_STB6X00_OCK 0xf4e80030 +#define F0900_P1_TUN_GAIN 0xf4e8000f /*P1_TNRRF1*/ -#define R0900_P1_TNRRF1 0xf4e9 -#define F0900_P1_TUN_RFFREQ2 0xf4e900ff +#define R0900_P1_TNRRF1 0xf4e9 +#define TNRRF1 REGx(R0900_P1_TNRRF1) +#define F0900_P1_TUN_RFFREQ2 0xf4e900ff /*P1_TNRRF0*/ -#define R0900_P1_TNRRF0 0xf4ea -#define F0900_P1_TUN_RFFREQ1 0xf4ea00ff +#define R0900_P1_TNRRF0 0xf4ea +#define TNRRF0 REGx(R0900_P1_TNRRF0) +#define F0900_P1_TUN_RFFREQ1 0xf4ea00ff /*P1_TNRBW*/ -#define R0900_P1_TNRBW 0xf4eb -#define F0900_P1_TUN_RFFREQ0 0xf4eb00c0 -#define F0900_P1_TUN_BW 0xf4eb003f +#define R0900_P1_TNRBW 0xf4eb +#define TNRBW REGx(R0900_P1_TNRBW) +#define F0900_P1_TUN_RFFREQ0 0xf4eb00c0 +#define F0900_P1_TUN_BW 0xf4eb003f /*P1_TNRADJ*/ -#define R0900_P1_TNRADJ 0xf4ec -#define F0900_P1_STB61X0_RCLK 0xf4ec0080 -#define F0900_P1_STB61X0_CALTIME 0xf4ec0040 -#define F0900_P1_STB6X00_DLB 0xf4ec0038 -#define F0900_P1_STB6000_FCL 0xf4ec0007 +#define R0900_P1_TNRADJ 0xf4ec +#define TNRADJ REGx(R0900_P1_TNRADJ) +#define F0900_P1_STB61X0_CALTIME 0xf4ec0040 /*P1_TNRCTL2*/ -#define R0900_P1_TNRCTL2 0xf4ed -#define F0900_P1_STB61X0_LCP1_RCCKOFF 0xf4ed0080 -#define F0900_P1_STB61X0_LCP0 0xf4ed0040 -#define F0900_P1_STB61X0_XTOUT_RFOUTS 0xf4ed0020 -#define F0900_P1_STB61X0_XTON_MCKDV 0xf4ed0010 -#define F0900_P1_STB61X0_CALOFF_DCOFF 0xf4ed0008 -#define F0900_P1_STB6110_LPT 0xf4ed0004 -#define F0900_P1_STB6110_RX 0xf4ed0002 -#define F0900_P1_STB6110_SYN 0xf4ed0001 +#define R0900_P1_TNRCTL2 0xf4ed +#define TNRCTL2 REGx(R0900_P1_TNRCTL2) +#define F0900_P1_STB61X0_RCCKOFF 0xf4ed0080 +#define F0900_P1_STB61X0_ICP_SDOFF 0xf4ed0040 +#define F0900_P1_STB61X0_DCLOOPOFF 0xf4ed0020 +#define F0900_P1_STB61X0_REFOUTSEL 0xf4ed0010 +#define F0900_P1_STB61X0_CALOFF 0xf4ed0008 +#define F0900_P1_STB6XX0_LPT_BEN 0xf4ed0004 +#define F0900_P1_STB6XX0_RX_OSCP 0xf4ed0002 +#define F0900_P1_STB6XX0_SYN 0xf4ed0001 /*P1_TNRCFG3*/ -#define R0900_P1_TNRCFG3 0xf4ee -#define F0900_P1_STB6120_DISCTRL1 0xf4ee0080 -#define F0900_P1_STB6120_INVORDER 0xf4ee0040 -#define F0900_P1_STB6120_ENCTRL6 0xf4ee0020 -#define F0900_P1_TUN_PLLFREQ 0xf4ee001c -#define F0900_P1_TUN_I2CFREQ_MODE 0xf4ee0003 +#define R0900_P1_TNRCFG3 0xf4ee +#define TNRCFG3 REGx(R0900_P1_TNRCFG3) +#define F0900_P1_TUN_PLLFREQ 0xf4ee001c +#define F0900_P1_TUN_I2CFREQ_MODE 0xf4ee0003 /*P1_TNRLAUNCH*/ -#define R0900_P1_TNRLAUNCH 0xf4f0 +#define R0900_P1_TNRLAUNCH 0xf4f0 +#define TNRLAUNCH REGx(R0900_P1_TNRLAUNCH) /*P1_TNRLD*/ -#define R0900_P1_TNRLD 0xf4f0 -#define F0900_P1_TUNLD_VCOING 0xf4f00080 -#define F0900_P1_TUN_REG1FAIL 0xf4f00040 -#define F0900_P1_TUN_REG2FAIL 0xf4f00020 -#define F0900_P1_TUN_REG3FAIL 0xf4f00010 -#define F0900_P1_TUN_REG4FAIL 0xf4f00008 -#define F0900_P1_TUN_REG5FAIL 0xf4f00004 -#define F0900_P1_TUN_BWING 0xf4f00002 -#define F0900_P1_TUN_LOCKED 0xf4f00001 +#define R0900_P1_TNRLD 0xf4f0 +#define TNRLD REGx(R0900_P1_TNRLD) +#define F0900_P1_TUNLD_VCOING 0xf4f00080 +#define F0900_P1_TUN_REG1FAIL 0xf4f00040 +#define F0900_P1_TUN_REG2FAIL 0xf4f00020 +#define F0900_P1_TUN_REG3FAIL 0xf4f00010 +#define F0900_P1_TUN_REG4FAIL 0xf4f00008 +#define F0900_P1_TUN_REG5FAIL 0xf4f00004 +#define F0900_P1_TUN_BWING 0xf4f00002 +#define F0900_P1_TUN_LOCKED 0xf4f00001 /*P1_TNROBSL*/ -#define R0900_P1_TNROBSL 0xf4f6 -#define F0900_P1_TUN_I2CABORTED 0xf4f60080 -#define F0900_P1_TUN_LPEN 0xf4f60040 -#define F0900_P1_TUN_FCCK 0xf4f60020 -#define F0900_P1_TUN_I2CLOCKED 0xf4f60010 -#define F0900_P1_TUN_PROGDONE 0xf4f6000c -#define F0900_P1_TUN_RFRESTE1 0xf4f60003 +#define R0900_P1_TNROBSL 0xf4f6 +#define TNROBSL REGx(R0900_P1_TNROBSL) +#define F0900_P1_TUN_I2CABORTED 0xf4f60080 +#define F0900_P1_TUN_LPEN 0xf4f60040 +#define F0900_P1_TUN_FCCK 0xf4f60020 +#define F0900_P1_TUN_I2CLOCKED 0xf4f60010 +#define F0900_P1_TUN_PROGDONE 0xf4f6000c +#define F0900_P1_TUN_RFRESTE1 0xf4f60003 /*P1_TNRRESTE*/ -#define R0900_P1_TNRRESTE 0xf4f7 -#define F0900_P1_TUN_RFRESTE0 0xf4f700ff +#define R0900_P1_TNRRESTE 0xf4f7 +#define TNRRESTE REGx(R0900_P1_TNRRESTE) +#define F0900_P1_TUN_RFRESTE0 0xf4f700ff /*P1_SMAPCOEF7*/ -#define R0900_P1_SMAPCOEF7 0xf500 -#define F0900_P1_DIS_QSCALE 0xf5000080 -#define F0900_P1_SMAPCOEF_Q_LLR12 0xf500017f +#define R0900_P1_SMAPCOEF7 0xf500 +#define SMAPCOEF7 REGx(R0900_P1_SMAPCOEF7) +#define F0900_P1_DIS_QSCALE 0xf5000080 +#define F0900_P1_SMAPCOEF_Q_LLR12 0xf500017f /*P1_SMAPCOEF6*/ -#define R0900_P1_SMAPCOEF6 0xf501 -#define F0900_P1_DIS_NEWSCALE 0xf5010008 -#define F0900_P1_ADJ_8PSKLLR1 0xf5010004 -#define F0900_P1_OLD_8PSKLLR1 0xf5010002 -#define F0900_P1_DIS_AB8PSK 0xf5010001 +#define R0900_P1_SMAPCOEF6 0xf501 +#define SMAPCOEF6 REGx(R0900_P1_SMAPCOEF6) +#define F0900_P1_ADJ_8PSKLLR1 0xf5010004 +#define F0900_P1_OLD_8PSKLLR1 0xf5010002 +#define F0900_P1_DIS_AB8PSK 0xf5010001 /*P1_SMAPCOEF5*/ -#define R0900_P1_SMAPCOEF5 0xf502 -#define F0900_P1_DIS_8SCALE 0xf5020080 -#define F0900_P1_SMAPCOEF_8P_LLR23 0xf502017f +#define R0900_P1_SMAPCOEF5 0xf502 +#define SMAPCOEF5 REGx(R0900_P1_SMAPCOEF5) +#define F0900_P1_DIS_8SCALE 0xf5020080 +#define F0900_P1_SMAPCOEF_8P_LLR23 0xf502017f + +/*P1_NCO2MAX1*/ +#define R0900_P1_NCO2MAX1 0xf514 +#define NCO2MAX1 REGx(R0900_P1_NCO2MAX1) +#define F0900_P1_TETA2_MAXVABS1 0xf51400ff + +/*P1_NCO2MAX0*/ +#define R0900_P1_NCO2MAX0 0xf515 +#define NCO2MAX0 REGx(R0900_P1_NCO2MAX0) +#define F0900_P1_TETA2_MAXVABS0 0xf51500ff + +/*P1_NCO2FR1*/ +#define R0900_P1_NCO2FR1 0xf516 +#define NCO2FR1 REGx(R0900_P1_NCO2FR1) +#define F0900_P1_NCO2FINAL_ANGLE1 0xf51600ff + +/*P1_NCO2FR0*/ +#define R0900_P1_NCO2FR0 0xf517 +#define NCO2FR0 REGx(R0900_P1_NCO2FR0) +#define F0900_P1_NCO2FINAL_ANGLE0 0xf51700ff + +/*P1_CFR2AVRGE1*/ +#define R0900_P1_CFR2AVRGE1 0xf518 +#define CFR2AVRGE1 REGx(R0900_P1_CFR2AVRGE1) +#define F0900_P1_I2C_CFR2AVERAGE1 0xf51800ff + +/*P1_CFR2AVRGE0*/ +#define R0900_P1_CFR2AVRGE0 0xf519 +#define CFR2AVRGE0 REGx(R0900_P1_CFR2AVRGE0) +#define F0900_P1_I2C_CFR2AVERAGE0 0xf51900ff /*P1_DMDPLHSTAT*/ -#define R0900_P1_DMDPLHSTAT 0xf520 -#define F0900_P1_PLH_STATISTIC 0xf52000ff +#define R0900_P1_DMDPLHSTAT 0xf520 +#define DMDPLHSTAT REGx(R0900_P1_DMDPLHSTAT) +#define F0900_P1_PLH_STATISTIC 0xf52000ff /*P1_LOCKTIME3*/ -#define R0900_P1_LOCKTIME3 0xf522 -#define F0900_P1_DEMOD_LOCKTIME3 0xf52200ff +#define R0900_P1_LOCKTIME3 0xf522 +#define LOCKTIME3 REGx(R0900_P1_LOCKTIME3) +#define F0900_P1_DEMOD_LOCKTIME3 0xf52200ff /*P1_LOCKTIME2*/ -#define R0900_P1_LOCKTIME2 0xf523 -#define F0900_P1_DEMOD_LOCKTIME2 0xf52300ff +#define R0900_P1_LOCKTIME2 0xf523 +#define LOCKTIME2 REGx(R0900_P1_LOCKTIME2) +#define F0900_P1_DEMOD_LOCKTIME2 0xf52300ff /*P1_LOCKTIME1*/ -#define R0900_P1_LOCKTIME1 0xf524 -#define F0900_P1_DEMOD_LOCKTIME1 0xf52400ff +#define R0900_P1_LOCKTIME1 0xf524 +#define LOCKTIME1 REGx(R0900_P1_LOCKTIME1) +#define F0900_P1_DEMOD_LOCKTIME1 0xf52400ff /*P1_LOCKTIME0*/ -#define R0900_P1_LOCKTIME0 0xf525 -#define F0900_P1_DEMOD_LOCKTIME0 0xf52500ff +#define R0900_P1_LOCKTIME0 0xf525 +#define LOCKTIME0 REGx(R0900_P1_LOCKTIME0) +#define F0900_P1_DEMOD_LOCKTIME0 0xf52500ff /*P1_VITSCALE*/ -#define R0900_P1_VITSCALE 0xf532 -#define F0900_P1_NVTH_NOSRANGE 0xf5320080 -#define F0900_P1_VERROR_MAXMODE 0xf5320040 -#define F0900_P1_KDIV_MODE 0xf5320030 -#define F0900_P1_NSLOWSN_LOCKED 0xf5320008 -#define F0900_P1_DELOCK_PRFLOSS 0xf5320004 -#define F0900_P1_DIS_RSFLOCK 0xf5320002 +#define R0900_P1_VITSCALE 0xf532 +#define VITSCALE REGx(R0900_P1_VITSCALE) +#define F0900_P1_NVTH_NOSRANGE 0xf5320080 +#define F0900_P1_VERROR_MAXMODE 0xf5320040 +#define F0900_P1_NSLOWSN_LOCKED 0xf5320008 +#define F0900_P1_DIS_RSFLOCK 0xf5320002 /*P1_FECM*/ -#define R0900_P1_FECM 0xf533 -#define F0900_P1_DSS_DVB 0xf5330080 -#define F0900_P1_DEMOD_BYPASS 0xf5330040 -#define F0900_P1_CMP_SLOWMODE 0xf5330020 -#define F0900_P1_DSS_SRCH 0xf5330010 -#define F0900_P1_DIFF_MODEVIT 0xf5330004 -#define F0900_P1_SYNCVIT 0xf5330002 -#define F0900_P1_IQINV 0xf5330001 +#define R0900_P1_FECM 0xf533 +#define FECM REGx(R0900_P1_FECM) +#define F0900_P1_DSS_DVB 0xf5330080 +#define DSS_DVB FLDx(F0900_P1_DSS_DVB) +#define F0900_P1_DSS_SRCH 0xf5330010 +#define F0900_P1_SYNCVIT 0xf5330002 +#define F0900_P1_IQINV 0xf5330001 +#define IQINV FLDx(F0900_P1_IQINV) /*P1_VTH12*/ -#define R0900_P1_VTH12 0xf534 -#define F0900_P1_VTH12 0xf53400ff +#define R0900_P1_VTH12 0xf534 +#define VTH12 REGx(R0900_P1_VTH12) +#define F0900_P1_VTH12 0xf53400ff /*P1_VTH23*/ -#define R0900_P1_VTH23 0xf535 -#define F0900_P1_VTH23 0xf53500ff +#define R0900_P1_VTH23 0xf535 +#define VTH23 REGx(R0900_P1_VTH23) +#define F0900_P1_VTH23 0xf53500ff /*P1_VTH34*/ -#define R0900_P1_VTH34 0xf536 -#define F0900_P1_VTH34 0xf53600ff +#define R0900_P1_VTH34 0xf536 +#define VTH34 REGx(R0900_P1_VTH34) +#define F0900_P1_VTH34 0xf53600ff /*P1_VTH56*/ -#define R0900_P1_VTH56 0xf537 -#define F0900_P1_VTH56 0xf53700ff +#define R0900_P1_VTH56 0xf537 +#define VTH56 REGx(R0900_P1_VTH56) +#define F0900_P1_VTH56 0xf53700ff /*P1_VTH67*/ -#define R0900_P1_VTH67 0xf538 -#define F0900_P1_VTH67 0xf53800ff +#define R0900_P1_VTH67 0xf538 +#define VTH67 REGx(R0900_P1_VTH67) +#define F0900_P1_VTH67 0xf53800ff /*P1_VTH78*/ -#define R0900_P1_VTH78 0xf539 -#define F0900_P1_VTH78 0xf53900ff +#define R0900_P1_VTH78 0xf539 +#define VTH78 REGx(R0900_P1_VTH78) +#define F0900_P1_VTH78 0xf53900ff /*P1_VITCURPUN*/ -#define R0900_P1_VITCURPUN 0xf53a -#define F0900_P1_VIT_MAPPING 0xf53a00e0 -#define F0900_P1_VIT_CURPUN 0xf53a001f +#define R0900_P1_VITCURPUN 0xf53a +#define VITCURPUN REGx(R0900_P1_VITCURPUN) +#define F0900_P1_VIT_CURPUN 0xf53a001f +#define VIT_CURPUN FLDx(F0900_P1_VIT_CURPUN) /*P1_VERROR*/ -#define R0900_P1_VERROR 0xf53b -#define F0900_P1_REGERR_VIT 0xf53b00ff +#define R0900_P1_VERROR 0xf53b +#define VERROR REGx(R0900_P1_VERROR) +#define F0900_P1_REGERR_VIT 0xf53b00ff /*P1_PRVIT*/ -#define R0900_P1_PRVIT 0xf53c -#define F0900_P1_DIS_VTHLOCK 0xf53c0040 -#define F0900_P1_E7_8VIT 0xf53c0020 -#define F0900_P1_E6_7VIT 0xf53c0010 -#define F0900_P1_E5_6VIT 0xf53c0008 -#define F0900_P1_E3_4VIT 0xf53c0004 -#define F0900_P1_E2_3VIT 0xf53c0002 -#define F0900_P1_E1_2VIT 0xf53c0001 +#define R0900_P1_PRVIT 0xf53c +#define PRVIT REGx(R0900_P1_PRVIT) +#define F0900_P1_DIS_VTHLOCK 0xf53c0040 +#define F0900_P1_E7_8VIT 0xf53c0020 +#define F0900_P1_E6_7VIT 0xf53c0010 +#define F0900_P1_E5_6VIT 0xf53c0008 +#define F0900_P1_E3_4VIT 0xf53c0004 +#define F0900_P1_E2_3VIT 0xf53c0002 +#define F0900_P1_E1_2VIT 0xf53c0001 /*P1_VAVSRVIT*/ -#define R0900_P1_VAVSRVIT 0xf53d -#define F0900_P1_AMVIT 0xf53d0080 -#define F0900_P1_FROZENVIT 0xf53d0040 -#define F0900_P1_SNVIT 0xf53d0030 -#define F0900_P1_TOVVIT 0xf53d000c -#define F0900_P1_HYPVIT 0xf53d0003 +#define R0900_P1_VAVSRVIT 0xf53d +#define VAVSRVIT REGx(R0900_P1_VAVSRVIT) +#define F0900_P1_AMVIT 0xf53d0080 +#define F0900_P1_FROZENVIT 0xf53d0040 +#define F0900_P1_SNVIT 0xf53d0030 +#define F0900_P1_TOVVIT 0xf53d000c +#define F0900_P1_HYPVIT 0xf53d0003 /*P1_VSTATUSVIT*/ -#define R0900_P1_VSTATUSVIT 0xf53e -#define F0900_P1_VITERBI_ON 0xf53e0080 -#define F0900_P1_END_LOOPVIT 0xf53e0040 -#define F0900_P1_VITERBI_DEPRF 0xf53e0020 -#define F0900_P1_PRFVIT 0xf53e0010 -#define F0900_P1_LOCKEDVIT 0xf53e0008 -#define F0900_P1_VITERBI_DELOCK 0xf53e0004 -#define F0900_P1_VIT_DEMODSEL 0xf53e0002 -#define F0900_P1_VITERBI_COMPOUT 0xf53e0001 +#define R0900_P1_VSTATUSVIT 0xf53e +#define VSTATUSVIT REGx(R0900_P1_VSTATUSVIT) +#define F0900_P1_PRFVIT 0xf53e0010 +#define PRFVIT FLDx(F0900_P1_PRFVIT) +#define F0900_P1_LOCKEDVIT 0xf53e0008 +#define LOCKEDVIT FLDx(F0900_P1_LOCKEDVIT) /*P1_VTHINUSE*/ -#define R0900_P1_VTHINUSE 0xf53f -#define F0900_P1_VIT_INUSE 0xf53f00ff +#define R0900_P1_VTHINUSE 0xf53f +#define VTHINUSE REGx(R0900_P1_VTHINUSE) +#define F0900_P1_VIT_INUSE 0xf53f00ff /*P1_KDIV12*/ -#define R0900_P1_KDIV12 0xf540 -#define F0900_P1_KDIV12_MANUAL 0xf5400080 -#define F0900_P1_K_DIVIDER_12 0xf540007f +#define R0900_P1_KDIV12 0xf540 +#define KDIV12 REGx(R0900_P1_KDIV12) +#define F0900_P1_K_DIVIDER_12 0xf540007f /*P1_KDIV23*/ -#define R0900_P1_KDIV23 0xf541 -#define F0900_P1_KDIV23_MANUAL 0xf5410080 -#define F0900_P1_K_DIVIDER_23 0xf541007f +#define R0900_P1_KDIV23 0xf541 +#define KDIV23 REGx(R0900_P1_KDIV23) +#define F0900_P1_K_DIVIDER_23 0xf541007f /*P1_KDIV34*/ -#define R0900_P1_KDIV34 0xf542 -#define F0900_P1_KDIV34_MANUAL 0xf5420080 -#define F0900_P1_K_DIVIDER_34 0xf542007f +#define R0900_P1_KDIV34 0xf542 +#define KDIV34 REGx(R0900_P1_KDIV34) +#define F0900_P1_K_DIVIDER_34 0xf542007f /*P1_KDIV56*/ -#define R0900_P1_KDIV56 0xf543 -#define F0900_P1_KDIV56_MANUAL 0xf5430080 -#define F0900_P1_K_DIVIDER_56 0xf543007f +#define R0900_P1_KDIV56 0xf543 +#define KDIV56 REGx(R0900_P1_KDIV56) +#define F0900_P1_K_DIVIDER_56 0xf543007f /*P1_KDIV67*/ -#define R0900_P1_KDIV67 0xf544 -#define F0900_P1_KDIV67_MANUAL 0xf5440080 -#define F0900_P1_K_DIVIDER_67 0xf544007f +#define R0900_P1_KDIV67 0xf544 +#define KDIV67 REGx(R0900_P1_KDIV67) +#define F0900_P1_K_DIVIDER_67 0xf544007f /*P1_KDIV78*/ -#define R0900_P1_KDIV78 0xf545 -#define F0900_P1_KDIV78_MANUAL 0xf5450080 -#define F0900_P1_K_DIVIDER_78 0xf545007f +#define R0900_P1_KDIV78 0xf545 +#define KDIV78 REGx(R0900_P1_KDIV78) +#define F0900_P1_K_DIVIDER_78 0xf545007f /*P1_PDELCTRL1*/ -#define R0900_P1_PDELCTRL1 0xf550 -#define F0900_P1_INV_MISMASK 0xf5500080 -#define F0900_P1_FORCE_ACCEPTED 0xf5500040 -#define F0900_P1_FILTER_EN 0xf5500020 -#define F0900_P1_FORCE_PKTDELINUSE 0xf5500010 -#define F0900_P1_HYSTEN 0xf5500008 -#define F0900_P1_HYSTSWRST 0xf5500004 -#define F0900_P1_EN_MIS00 0xf5500002 -#define F0900_P1_ALGOSWRST 0xf5500001 +#define R0900_P1_PDELCTRL1 0xf550 +#define PDELCTRL1 REGx(R0900_P1_PDELCTRL1) +#define F0900_P1_INV_MISMASK 0xf5500080 +#define F0900_P1_FILTER_EN 0xf5500020 +#define F0900_P1_EN_MIS00 0xf5500002 +#define F0900_P1_ALGOSWRST 0xf5500001 +#define ALGOSWRST FLDx(F0900_P1_ALGOSWRST) /*P1_PDELCTRL2*/ -#define R0900_P1_PDELCTRL2 0xf551 -#define F0900_P1_FORCE_CONTINUOUS 0xf5510080 -#define F0900_P1_RESET_UPKO_COUNT 0xf5510040 -#define F0900_P1_USER_PKTDELIN_NB 0xf5510020 -#define F0900_P1_FORCE_LOCKED 0xf5510010 -#define F0900_P1_DATA_UNBBSCRAM 0xf5510008 -#define F0900_P1_FORCE_LONGPKT 0xf5510004 -#define F0900_P1_FRAME_MODE 0xf5510002 +#define R0900_P1_PDELCTRL2 0xf551 +#define PDELCTRL2 REGx(R0900_P1_PDELCTRL2) +#define F0900_P1_RESET_UPKO_COUNT 0xf5510040 +#define RESET_UPKO_COUNT FLDx(F0900_P1_RESET_UPKO_COUNT) +#define F0900_P1_FRAME_MODE 0xf5510002 +#define F0900_P1_NOBCHERRFLG_USE 0xf5510001 /*P1_HYSTTHRESH*/ -#define R0900_P1_HYSTTHRESH 0xf554 -#define F0900_P1_UNLCK_THRESH 0xf55400f0 -#define F0900_P1_DELIN_LCK_THRESH 0xf554000f +#define R0900_P1_HYSTTHRESH 0xf554 +#define HYSTTHRESH REGx(R0900_P1_HYSTTHRESH) +#define F0900_P1_UNLCK_THRESH 0xf55400f0 +#define F0900_P1_DELIN_LCK_THRESH 0xf554000f /*P1_ISIENTRY*/ -#define R0900_P1_ISIENTRY 0xf55e -#define F0900_P1_ISI_ENTRY 0xf55e00ff +#define R0900_P1_ISIENTRY 0xf55e +#define ISIENTRY REGx(R0900_P1_ISIENTRY) +#define F0900_P1_ISI_ENTRY 0xf55e00ff /*P1_ISIBITENA*/ -#define R0900_P1_ISIBITENA 0xf55f -#define F0900_P1_ISI_BIT_EN 0xf55f00ff +#define R0900_P1_ISIBITENA 0xf55f +#define ISIBITENA REGx(R0900_P1_ISIBITENA) +#define F0900_P1_ISI_BIT_EN 0xf55f00ff /*P1_MATSTR1*/ -#define R0900_P1_MATSTR1 0xf560 -#define F0900_P1_MATYPE_CURRENT1 0xf56000ff +#define R0900_P1_MATSTR1 0xf560 +#define MATSTR1 REGx(R0900_P1_MATSTR1) +#define F0900_P1_MATYPE_CURRENT1 0xf56000ff /*P1_MATSTR0*/ -#define R0900_P1_MATSTR0 0xf561 -#define F0900_P1_MATYPE_CURRENT0 0xf56100ff +#define R0900_P1_MATSTR0 0xf561 +#define MATSTR0 REGx(R0900_P1_MATSTR0) +#define F0900_P1_MATYPE_CURRENT0 0xf56100ff /*P1_UPLSTR1*/ -#define R0900_P1_UPLSTR1 0xf562 -#define F0900_P1_UPL_CURRENT1 0xf56200ff +#define R0900_P1_UPLSTR1 0xf562 +#define UPLSTR1 REGx(R0900_P1_UPLSTR1) +#define F0900_P1_UPL_CURRENT1 0xf56200ff /*P1_UPLSTR0*/ -#define R0900_P1_UPLSTR0 0xf563 -#define F0900_P1_UPL_CURRENT0 0xf56300ff +#define R0900_P1_UPLSTR0 0xf563 +#define UPLSTR0 REGx(R0900_P1_UPLSTR0) +#define F0900_P1_UPL_CURRENT0 0xf56300ff /*P1_DFLSTR1*/ -#define R0900_P1_DFLSTR1 0xf564 -#define F0900_P1_DFL_CURRENT1 0xf56400ff +#define R0900_P1_DFLSTR1 0xf564 +#define DFLSTR1 REGx(R0900_P1_DFLSTR1) +#define F0900_P1_DFL_CURRENT1 0xf56400ff /*P1_DFLSTR0*/ -#define R0900_P1_DFLSTR0 0xf565 -#define F0900_P1_DFL_CURRENT0 0xf56500ff +#define R0900_P1_DFLSTR0 0xf565 +#define DFLSTR0 REGx(R0900_P1_DFLSTR0) +#define F0900_P1_DFL_CURRENT0 0xf56500ff /*P1_SYNCSTR*/ -#define R0900_P1_SYNCSTR 0xf566 -#define F0900_P1_SYNC_CURRENT 0xf56600ff +#define R0900_P1_SYNCSTR 0xf566 +#define SYNCSTR REGx(R0900_P1_SYNCSTR) +#define F0900_P1_SYNC_CURRENT 0xf56600ff /*P1_SYNCDSTR1*/ -#define R0900_P1_SYNCDSTR1 0xf567 -#define F0900_P1_SYNCD_CURRENT1 0xf56700ff +#define R0900_P1_SYNCDSTR1 0xf567 +#define SYNCDSTR1 REGx(R0900_P1_SYNCDSTR1) +#define F0900_P1_SYNCD_CURRENT1 0xf56700ff /*P1_SYNCDSTR0*/ -#define R0900_P1_SYNCDSTR0 0xf568 -#define F0900_P1_SYNCD_CURRENT0 0xf56800ff +#define R0900_P1_SYNCDSTR0 0xf568 +#define SYNCDSTR0 REGx(R0900_P1_SYNCDSTR0) +#define F0900_P1_SYNCD_CURRENT0 0xf56800ff /*P1_PDELSTATUS1*/ -#define R0900_P1_PDELSTATUS1 0xf569 -#define F0900_P1_PKTDELIN_DELOCK 0xf5690080 -#define F0900_P1_SYNCDUPDFL_BADDFL 0xf5690040 -#define F0900_P1_CONTINUOUS_STREAM 0xf5690020 -#define F0900_P1_UNACCEPTED_STREAM 0xf5690010 -#define F0900_P1_BCH_ERROR_FLAG 0xf5690008 -#define F0900_P1_BBHCRCKO 0xf5690004 -#define F0900_P1_PKTDELIN_LOCK 0xf5690002 -#define F0900_P1_FIRST_LOCK 0xf5690001 +#define R0900_P1_PDELSTATUS1 0xf569 +#define F0900_P1_PKTDELIN_DELOCK 0xf5690080 +#define F0900_P1_SYNCDUPDFL_BADDFL 0xf5690040 +#define F0900_P1_CONTINUOUS_STREAM 0xf5690020 +#define F0900_P1_UNACCEPTED_STREAM 0xf5690010 +#define F0900_P1_BCH_ERROR_FLAG 0xf5690008 +#define F0900_P1_PKTDELIN_LOCK 0xf5690002 +#define PKTDELIN_LOCK FLDx(F0900_P1_PKTDELIN_LOCK) +#define F0900_P1_FIRST_LOCK 0xf5690001 /*P1_PDELSTATUS2*/ -#define R0900_P1_PDELSTATUS2 0xf56a -#define F0900_P1_PKTDEL_DEMODSEL 0xf56a0080 -#define F0900_P1_FRAME_MODCOD 0xf56a007c -#define F0900_P1_FRAME_TYPE 0xf56a0003 +#define R0900_P1_PDELSTATUS2 0xf56a +#define F0900_P1_FRAME_MODCOD 0xf56a007c +#define F0900_P1_FRAME_TYPE 0xf56a0003 /*P1_BBFCRCKO1*/ -#define R0900_P1_BBFCRCKO1 0xf56b -#define F0900_P1_BBHCRC_KOCNT1 0xf56b00ff +#define R0900_P1_BBFCRCKO1 0xf56b +#define BBFCRCKO1 REGx(R0900_P1_BBFCRCKO1) +#define F0900_P1_BBHCRC_KOCNT1 0xf56b00ff /*P1_BBFCRCKO0*/ -#define R0900_P1_BBFCRCKO0 0xf56c -#define F0900_P1_BBHCRC_KOCNT0 0xf56c00ff +#define R0900_P1_BBFCRCKO0 0xf56c +#define BBFCRCKO0 REGx(R0900_P1_BBFCRCKO0) +#define F0900_P1_BBHCRC_KOCNT0 0xf56c00ff /*P1_UPCRCKO1*/ -#define R0900_P1_UPCRCKO1 0xf56d -#define F0900_P1_PKTCRC_KOCNT1 0xf56d00ff +#define R0900_P1_UPCRCKO1 0xf56d +#define UPCRCKO1 REGx(R0900_P1_UPCRCKO1) +#define F0900_P1_PKTCRC_KOCNT1 0xf56d00ff /*P1_UPCRCKO0*/ -#define R0900_P1_UPCRCKO0 0xf56e -#define F0900_P1_PKTCRC_KOCNT0 0xf56e00ff +#define R0900_P1_UPCRCKO0 0xf56e +#define UPCRCKO0 REGx(R0900_P1_UPCRCKO0) +#define F0900_P1_PKTCRC_KOCNT0 0xf56e00ff + +/*P1_PDELCTRL3*/ +#define R0900_P1_PDELCTRL3 0xf56f +#define PDELCTRL3 REGx(R0900_P1_PDELCTRL3) +#define F0900_P1_PKTDEL_CONTFAIL 0xf56f0080 +#define F0900_P1_NOFIFO_BCHERR 0xf56f0020 /*P1_TSSTATEM*/ -#define R0900_P1_TSSTATEM 0xf570 -#define F0900_P1_TSDIL_ON 0xf5700080 -#define F0900_P1_TSSKIPRS_ON 0xf5700040 -#define F0900_P1_TSRS_ON 0xf5700020 -#define F0900_P1_TSDESCRAMB_ON 0xf5700010 -#define F0900_P1_TSFRAME_MODE 0xf5700008 -#define F0900_P1_TS_DISABLE 0xf5700004 -#define F0900_P1_TSACM_MODE 0xf5700002 -#define F0900_P1_TSOUT_NOSYNC 0xf5700001 +#define R0900_P1_TSSTATEM 0xf570 +#define TSSTATEM REGx(R0900_P1_TSSTATEM) +#define F0900_P1_TSDIL_ON 0xf5700080 +#define F0900_P1_TSRS_ON 0xf5700020 +#define F0900_P1_TSDESCRAMB_ON 0xf5700010 +#define F0900_P1_TSFRAME_MODE 0xf5700008 +#define F0900_P1_TS_DISABLE 0xf5700004 +#define F0900_P1_TSOUT_NOSYNC 0xf5700001 /*P1_TSCFGH*/ -#define R0900_P1_TSCFGH 0xf572 -#define F0900_P1_TSFIFO_DVBCI 0xf5720080 -#define F0900_P1_TSFIFO_SERIAL 0xf5720040 -#define F0900_P1_TSFIFO_TEIUPDATE 0xf5720020 -#define F0900_P1_TSFIFO_DUTY50 0xf5720010 -#define F0900_P1_TSFIFO_HSGNLOUT 0xf5720008 -#define F0900_P1_TSFIFO_ERRMODE 0xf5720006 -#define F0900_P1_RST_HWARE 0xf5720001 +#define R0900_P1_TSCFGH 0xf572 +#define TSCFGH REGx(R0900_P1_TSCFGH) +#define F0900_P1_TSFIFO_DVBCI 0xf5720080 +#define F0900_P1_TSFIFO_SERIAL 0xf5720040 +#define F0900_P1_TSFIFO_TEIUPDATE 0xf5720020 +#define F0900_P1_TSFIFO_DUTY50 0xf5720010 +#define F0900_P1_TSFIFO_HSGNLOUT 0xf5720008 +#define F0900_P1_TSFIFO_ERRMODE 0xf5720006 +#define F0900_P1_RST_HWARE 0xf5720001 +#define RST_HWARE FLDx(F0900_P1_RST_HWARE) /*P1_TSCFGM*/ -#define R0900_P1_TSCFGM 0xf573 -#define F0900_P1_TSFIFO_MANSPEED 0xf57300c0 -#define F0900_P1_TSFIFO_PERMDATA 0xf5730020 -#define F0900_P1_TSFIFO_NONEWSGNL 0xf5730010 -#define F0900_P1_TSFIFO_BITSPEED 0xf5730008 -#define F0900_P1_NPD_SPECDVBS2 0xf5730004 -#define F0900_P1_TSFIFO_STOPCKDIS 0xf5730002 -#define F0900_P1_TSFIFO_INVDATA 0xf5730001 +#define R0900_P1_TSCFGM 0xf573 +#define TSCFGM REGx(R0900_P1_TSCFGM) +#define F0900_P1_TSFIFO_MANSPEED 0xf57300c0 +#define F0900_P1_TSFIFO_PERMDATA 0xf5730020 +#define F0900_P1_TSFIFO_DPUNACT 0xf5730002 +#define F0900_P1_TSFIFO_INVDATA 0xf5730001 /*P1_TSCFGL*/ -#define R0900_P1_TSCFGL 0xf574 -#define F0900_P1_TSFIFO_BCLKDEL1CK 0xf57400c0 -#define F0900_P1_BCHERROR_MODE 0xf5740030 -#define F0900_P1_TSFIFO_NSGNL2DATA 0xf5740008 -#define F0900_P1_TSFIFO_EMBINDVB 0xf5740004 -#define F0900_P1_TSFIFO_DPUNACT 0xf5740002 -#define F0900_P1_TSFIFO_NPDOFF 0xf5740001 +#define R0900_P1_TSCFGL 0xf574 +#define TSCFGL REGx(R0900_P1_TSCFGL) +#define F0900_P1_TSFIFO_BCLKDEL1CK 0xf57400c0 +#define F0900_P1_BCHERROR_MODE 0xf5740030 +#define F0900_P1_TSFIFO_NSGNL2DATA 0xf5740008 +#define F0900_P1_TSFIFO_EMBINDVB 0xf5740004 +#define F0900_P1_TSFIFO_BITSPEED 0xf5740003 /*P1_TSINSDELH*/ -#define R0900_P1_TSINSDELH 0xf576 -#define F0900_P1_TSDEL_SYNCBYTE 0xf5760080 -#define F0900_P1_TSDEL_XXHEADER 0xf5760040 -#define F0900_P1_TSDEL_BBHEADER 0xf5760020 -#define F0900_P1_TSDEL_DATAFIELD 0xf5760010 -#define F0900_P1_TSINSDEL_ISCR 0xf5760008 -#define F0900_P1_TSINSDEL_NPD 0xf5760004 -#define F0900_P1_TSINSDEL_RSPARITY 0xf5760002 -#define F0900_P1_TSINSDEL_CRC8 0xf5760001 +#define R0900_P1_TSINSDELH 0xf576 +#define TSINSDELH REGx(R0900_P1_TSINSDELH) +#define F0900_P1_TSDEL_SYNCBYTE 0xf5760080 +#define F0900_P1_TSDEL_XXHEADER 0xf5760040 +#define F0900_P1_TSDEL_BBHEADER 0xf5760020 +#define F0900_P1_TSDEL_DATAFIELD 0xf5760010 +#define F0900_P1_TSINSDEL_ISCR 0xf5760008 +#define F0900_P1_TSINSDEL_NPD 0xf5760004 +#define F0900_P1_TSINSDEL_RSPARITY 0xf5760002 +#define F0900_P1_TSINSDEL_CRC8 0xf5760001 + +/*P1_TSDIVN*/ +#define R0900_P1_TSDIVN 0xf579 +#define TSDIVN REGx(R0900_P1_TSDIVN) +#define F0900_P1_TSFIFO_SPEEDMODE 0xf57900c0 + +/*P1_TSCFG4*/ +#define R0900_P1_TSCFG4 0xf57a +#define TSCFG4 REGx(R0900_P1_TSCFG4) +#define F0900_P1_TSFIFO_TSSPEEDMODE 0xf57a00c0 /*P1_TSSPEED*/ -#define R0900_P1_TSSPEED 0xf580 -#define F0900_P1_TSFIFO_OUTSPEED 0xf58000ff +#define R0900_P1_TSSPEED 0xf580 +#define TSSPEED REGx(R0900_P1_TSSPEED) +#define F0900_P1_TSFIFO_OUTSPEED 0xf58000ff /*P1_TSSTATUS*/ -#define R0900_P1_TSSTATUS 0xf581 -#define F0900_P1_TSFIFO_LINEOK 0xf5810080 -#define F0900_P1_TSFIFO_ERROR 0xf5810040 -#define F0900_P1_TSFIFO_DATA7 0xf5810020 -#define F0900_P1_TSFIFO_NOSYNC 0xf5810010 -#define F0900_P1_ISCR_INITIALIZED 0xf5810008 -#define F0900_P1_ISCR_UPDATED 0xf5810004 -#define F0900_P1_SOFFIFO_UNREGUL 0xf5810002 -#define F0900_P1_DIL_READY 0xf5810001 +#define R0900_P1_TSSTATUS 0xf581 +#define TSSTATUS REGx(R0900_P1_TSSTATUS) +#define F0900_P1_TSFIFO_LINEOK 0xf5810080 +#define TSFIFO_LINEOK FLDx(F0900_P1_TSFIFO_LINEOK) +#define F0900_P1_TSFIFO_ERROR 0xf5810040 +#define F0900_P1_DIL_READY 0xf5810001 /*P1_TSSTATUS2*/ -#define R0900_P1_TSSTATUS2 0xf582 -#define F0900_P1_TSFIFO_DEMODSEL 0xf5820080 -#define F0900_P1_TSFIFOSPEED_STORE 0xf5820040 -#define F0900_P1_DILXX_RESET 0xf5820020 -#define F0900_P1_TSSERIAL_IMPOS 0xf5820010 -#define F0900_P1_TSFIFO_LINENOK 0xf5820008 -#define F0900_P1_BITSPEED_EVENT 0xf5820004 -#define F0900_P1_SCRAMBDETECT 0xf5820002 -#define F0900_P1_ULDTV67_FALSELOCK 0xf5820001 +#define R0900_P1_TSSTATUS2 0xf582 +#define TSSTATUS2 REGx(R0900_P1_TSSTATUS2) +#define F0900_P1_TSFIFO_DEMODSEL 0xf5820080 +#define F0900_P1_TSFIFOSPEED_STORE 0xf5820040 +#define F0900_P1_DILXX_RESET 0xf5820020 +#define F0900_P1_TSSERIAL_IMPOS 0xf5820010 +#define F0900_P1_SCRAMBDETECT 0xf5820002 /*P1_TSBITRATE1*/ -#define R0900_P1_TSBITRATE1 0xf583 -#define F0900_P1_TSFIFO_BITRATE1 0xf58300ff +#define R0900_P1_TSBITRATE1 0xf583 +#define TSBITRATE1 REGx(R0900_P1_TSBITRATE1) +#define F0900_P1_TSFIFO_BITRATE1 0xf58300ff /*P1_TSBITRATE0*/ -#define R0900_P1_TSBITRATE0 0xf584 -#define F0900_P1_TSFIFO_BITRATE0 0xf58400ff +#define R0900_P1_TSBITRATE0 0xf584 +#define TSBITRATE0 REGx(R0900_P1_TSBITRATE0) +#define F0900_P1_TSFIFO_BITRATE0 0xf58400ff /*P1_ERRCTRL1*/ -#define R0900_P1_ERRCTRL1 0xf598 -#define F0900_P1_ERR_SOURCE1 0xf59800f0 -#define F0900_P1_NUM_EVENT1 0xf5980007 +#define R0900_P1_ERRCTRL1 0xf598 +#define ERRCTRL1 REGx(R0900_P1_ERRCTRL1) +#define F0900_P1_ERR_SOURCE1 0xf59800f0 +#define F0900_P1_NUM_EVENT1 0xf5980007 /*P1_ERRCNT12*/ -#define R0900_P1_ERRCNT12 0xf599 -#define F0900_P1_ERRCNT1_OLDVALUE 0xf5990080 -#define F0900_P1_ERR_CNT12 0xf599007f +#define R0900_P1_ERRCNT12 0xf599 +#define ERRCNT12 REGx(R0900_P1_ERRCNT12) +#define F0900_P1_ERRCNT1_OLDVALUE 0xf5990080 +#define F0900_P1_ERR_CNT12 0xf599007f +#define ERR_CNT12 FLDx(F0900_P1_ERR_CNT12) /*P1_ERRCNT11*/ -#define R0900_P1_ERRCNT11 0xf59a -#define F0900_P1_ERR_CNT11 0xf59a00ff +#define R0900_P1_ERRCNT11 0xf59a +#define ERRCNT11 REGx(R0900_P1_ERRCNT11) +#define F0900_P1_ERR_CNT11 0xf59a00ff +#define ERR_CNT11 FLDx(F0900_P1_ERR_CNT11) /*P1_ERRCNT10*/ -#define R0900_P1_ERRCNT10 0xf59b -#define F0900_P1_ERR_CNT10 0xf59b00ff +#define R0900_P1_ERRCNT10 0xf59b +#define ERRCNT10 REGx(R0900_P1_ERRCNT10) +#define F0900_P1_ERR_CNT10 0xf59b00ff +#define ERR_CNT10 FLDx(F0900_P1_ERR_CNT10) /*P1_ERRCTRL2*/ -#define R0900_P1_ERRCTRL2 0xf59c -#define F0900_P1_ERR_SOURCE2 0xf59c00f0 -#define F0900_P1_NUM_EVENT2 0xf59c0007 +#define R0900_P1_ERRCTRL2 0xf59c +#define ERRCTRL2 REGx(R0900_P1_ERRCTRL2) +#define F0900_P1_ERR_SOURCE2 0xf59c00f0 +#define F0900_P1_NUM_EVENT2 0xf59c0007 /*P1_ERRCNT22*/ -#define R0900_P1_ERRCNT22 0xf59d -#define F0900_P1_ERRCNT2_OLDVALUE 0xf59d0080 -#define F0900_P1_ERR_CNT22 0xf59d007f +#define R0900_P1_ERRCNT22 0xf59d +#define ERRCNT22 REGx(R0900_P1_ERRCNT22) +#define F0900_P1_ERRCNT2_OLDVALUE 0xf59d0080 +#define F0900_P1_ERR_CNT22 0xf59d007f +#define ERR_CNT22 FLDx(F0900_P1_ERR_CNT22) /*P1_ERRCNT21*/ -#define R0900_P1_ERRCNT21 0xf59e -#define F0900_P1_ERR_CNT21 0xf59e00ff +#define R0900_P1_ERRCNT21 0xf59e +#define ERRCNT21 REGx(R0900_P1_ERRCNT21) +#define F0900_P1_ERR_CNT21 0xf59e00ff +#define ERR_CNT21 FLDx(F0900_P1_ERR_CNT21) /*P1_ERRCNT20*/ -#define R0900_P1_ERRCNT20 0xf59f -#define F0900_P1_ERR_CNT20 0xf59f00ff +#define R0900_P1_ERRCNT20 0xf59f +#define ERRCNT20 REGx(R0900_P1_ERRCNT20) +#define F0900_P1_ERR_CNT20 0xf59f00ff +#define ERR_CNT20 FLDx(F0900_P1_ERR_CNT20) /*P1_FECSPY*/ -#define R0900_P1_FECSPY 0xf5a0 -#define F0900_P1_SPY_ENABLE 0xf5a00080 -#define F0900_P1_NO_SYNCBYTE 0xf5a00040 -#define F0900_P1_SERIAL_MODE 0xf5a00020 -#define F0900_P1_UNUSUAL_PACKET 0xf5a00010 -#define F0900_P1_BER_PACKMODE 0xf5a00008 -#define F0900_P1_BERMETER_LMODE 0xf5a00002 -#define F0900_P1_BERMETER_RESET 0xf5a00001 +#define R0900_P1_FECSPY 0xf5a0 +#define FECSPY REGx(R0900_P1_FECSPY) +#define F0900_P1_SPY_ENABLE 0xf5a00080 +#define F0900_P1_NO_SYNCBYTE 0xf5a00040 +#define F0900_P1_SERIAL_MODE 0xf5a00020 +#define F0900_P1_UNUSUAL_PACKET 0xf5a00010 +#define F0900_P1_BERMETER_DATAMODE 0xf5a00008 +#define F0900_P1_BERMETER_LMODE 0xf5a00002 +#define F0900_P1_BERMETER_RESET 0xf5a00001 /*P1_FSPYCFG*/ -#define R0900_P1_FSPYCFG 0xf5a1 -#define F0900_P1_FECSPY_INPUT 0xf5a100c0 -#define F0900_P1_RST_ON_ERROR 0xf5a10020 -#define F0900_P1_ONE_SHOT 0xf5a10010 -#define F0900_P1_I2C_MODE 0xf5a1000c -#define F0900_P1_SPY_HYSTERESIS 0xf5a10003 +#define R0900_P1_FSPYCFG 0xf5a1 +#define FSPYCFG REGx(R0900_P1_FSPYCFG) +#define F0900_P1_FECSPY_INPUT 0xf5a100c0 +#define F0900_P1_RST_ON_ERROR 0xf5a10020 +#define F0900_P1_ONE_SHOT 0xf5a10010 +#define F0900_P1_I2C_MODE 0xf5a1000c +#define F0900_P1_SPY_HYSTERESIS 0xf5a10003 /*P1_FSPYDATA*/ -#define R0900_P1_FSPYDATA 0xf5a2 -#define F0900_P1_SPY_STUFFING 0xf5a20080 -#define F0900_P1_NOERROR_PKTJITTER 0xf5a20040 -#define F0900_P1_SPY_CNULLPKT 0xf5a20020 -#define F0900_P1_SPY_OUTDATA_MODE 0xf5a2001f +#define R0900_P1_FSPYDATA 0xf5a2 +#define FSPYDATA REGx(R0900_P1_FSPYDATA) +#define F0900_P1_SPY_STUFFING 0xf5a20080 +#define F0900_P1_SPY_CNULLPKT 0xf5a20020 +#define F0900_P1_SPY_OUTDATA_MODE 0xf5a2001f /*P1_FSPYOUT*/ -#define R0900_P1_FSPYOUT 0xf5a3 -#define F0900_P1_FSPY_DIRECT 0xf5a30080 -#define F0900_P1_SPY_OUTDATA_BUS 0xf5a30038 -#define F0900_P1_STUFF_MODE 0xf5a30007 +#define R0900_P1_FSPYOUT 0xf5a3 +#define FSPYOUT REGx(R0900_P1_FSPYOUT) +#define F0900_P1_FSPY_DIRECT 0xf5a30080 +#define F0900_P1_STUFF_MODE 0xf5a30007 /*P1_FSTATUS*/ -#define R0900_P1_FSTATUS 0xf5a4 -#define F0900_P1_SPY_ENDSIM 0xf5a40080 -#define F0900_P1_VALID_SIM 0xf5a40040 -#define F0900_P1_FOUND_SIGNAL 0xf5a40020 -#define F0900_P1_DSS_SYNCBYTE 0xf5a40010 -#define F0900_P1_RESULT_STATE 0xf5a4000f +#define R0900_P1_FSTATUS 0xf5a4 +#define FSTATUS REGx(R0900_P1_FSTATUS) +#define F0900_P1_SPY_ENDSIM 0xf5a40080 +#define F0900_P1_VALID_SIM 0xf5a40040 +#define F0900_P1_FOUND_SIGNAL 0xf5a40020 +#define F0900_P1_DSS_SYNCBYTE 0xf5a40010 +#define F0900_P1_RESULT_STATE 0xf5a4000f /*P1_FBERCPT4*/ -#define R0900_P1_FBERCPT4 0xf5a8 -#define F0900_P1_FBERMETER_CPT4 0xf5a800ff +#define R0900_P1_FBERCPT4 0xf5a8 +#define FBERCPT4 REGx(R0900_P1_FBERCPT4) +#define F0900_P1_FBERMETER_CPT4 0xf5a800ff /*P1_FBERCPT3*/ -#define R0900_P1_FBERCPT3 0xf5a9 -#define F0900_P1_FBERMETER_CPT3 0xf5a900ff +#define R0900_P1_FBERCPT3 0xf5a9 +#define FBERCPT3 REGx(R0900_P1_FBERCPT3) +#define F0900_P1_FBERMETER_CPT3 0xf5a900ff /*P1_FBERCPT2*/ -#define R0900_P1_FBERCPT2 0xf5aa -#define F0900_P1_FBERMETER_CPT2 0xf5aa00ff +#define R0900_P1_FBERCPT2 0xf5aa +#define FBERCPT2 REGx(R0900_P1_FBERCPT2) +#define F0900_P1_FBERMETER_CPT2 0xf5aa00ff /*P1_FBERCPT1*/ -#define R0900_P1_FBERCPT1 0xf5ab -#define F0900_P1_FBERMETER_CPT1 0xf5ab00ff +#define R0900_P1_FBERCPT1 0xf5ab +#define FBERCPT1 REGx(R0900_P1_FBERCPT1) +#define F0900_P1_FBERMETER_CPT1 0xf5ab00ff /*P1_FBERCPT0*/ -#define R0900_P1_FBERCPT0 0xf5ac -#define F0900_P1_FBERMETER_CPT0 0xf5ac00ff +#define R0900_P1_FBERCPT0 0xf5ac +#define FBERCPT0 REGx(R0900_P1_FBERCPT0) +#define F0900_P1_FBERMETER_CPT0 0xf5ac00ff /*P1_FBERERR2*/ -#define R0900_P1_FBERERR2 0xf5ad -#define F0900_P1_FBERMETER_ERR2 0xf5ad00ff +#define R0900_P1_FBERERR2 0xf5ad +#define FBERERR2 REGx(R0900_P1_FBERERR2) +#define F0900_P1_FBERMETER_ERR2 0xf5ad00ff /*P1_FBERERR1*/ -#define R0900_P1_FBERERR1 0xf5ae -#define F0900_P1_FBERMETER_ERR1 0xf5ae00ff +#define R0900_P1_FBERERR1 0xf5ae +#define FBERERR1 REGx(R0900_P1_FBERERR1) +#define F0900_P1_FBERMETER_ERR1 0xf5ae00ff /*P1_FBERERR0*/ -#define R0900_P1_FBERERR0 0xf5af -#define F0900_P1_FBERMETER_ERR0 0xf5af00ff +#define R0900_P1_FBERERR0 0xf5af +#define FBERERR0 REGx(R0900_P1_FBERERR0) +#define F0900_P1_FBERMETER_ERR0 0xf5af00ff /*P1_FSPYBER*/ -#define R0900_P1_FSPYBER 0xf5b2 -#define F0900_P1_FSPYOBS_XORREAD 0xf5b20040 -#define F0900_P1_FSPYBER_OBSMODE 0xf5b20020 -#define F0900_P1_FSPYBER_SYNCBYTE 0xf5b20010 -#define F0900_P1_FSPYBER_UNSYNC 0xf5b20008 -#define F0900_P1_FSPYBER_CTIME 0xf5b20007 +#define R0900_P1_FSPYBER 0xf5b2 +#define FSPYBER REGx(R0900_P1_FSPYBER) +#define F0900_P1_FSPYBER_SYNCBYTE 0xf5b20010 +#define F0900_P1_FSPYBER_UNSYNC 0xf5b20008 +#define F0900_P1_FSPYBER_CTIME 0xf5b20007 -/*RCCFGH*/ -#define R0900_RCCFGH 0xf600 -#define F0900_TSRCFIFO_DVBCI 0xf6000080 -#define F0900_TSRCFIFO_SERIAL 0xf6000040 -#define F0900_TSRCFIFO_DISABLE 0xf6000020 -#define F0900_TSFIFO_2TORC 0xf6000010 -#define F0900_TSRCFIFO_HSGNLOUT 0xf6000008 -#define F0900_TSRCFIFO_ERRMODE 0xf6000006 +/*RCCFG2*/ +#define R0900_RCCFG2 0xf600 /*TSGENERAL*/ -#define R0900_TSGENERAL 0xf630 -#define F0900_TSFIFO_BCLK1ALL 0xf6300020 -#define F0900_MUXSTREAM_OUTMODE 0xf6300008 -#define F0900_TSFIFO_PERMPARAL 0xf6300006 -#define F0900_RST_REEDSOLO 0xf6300001 +#define R0900_TSGENERAL 0xf630 +#define F0900_TSFIFO_DISTS2PAR 0xf6300040 +#define F0900_MUXSTREAM_OUTMODE 0xf6300008 +#define F0900_TSFIFO_PERMPARAL 0xf6300006 /*TSGENERAL1X*/ -#define R0900_TSGENERAL1X 0xf670 -#define F0900_TSFIFO1X_BCLK1ALL 0xf6700020 -#define F0900_MUXSTREAM1X_OUTMODE 0xf6700008 -#define F0900_TSFIFO1X_PERMPARAL 0xf6700006 -#define F0900_RST1X_REEDSOLO 0xf6700001 +#define R0900_TSGENERAL1X 0xf670 /*NBITER_NF4*/ -#define R0900_NBITER_NF4 0xfa03 -#define F0900_NBITER_NF_QP_1_2 0xfa0300ff +#define R0900_NBITER_NF4 0xfa03 +#define F0900_NBITER_NF_QP_1_2 0xfa0300ff /*NBITER_NF5*/ -#define R0900_NBITER_NF5 0xfa04 -#define F0900_NBITER_NF_QP_3_5 0xfa0400ff +#define R0900_NBITER_NF5 0xfa04 +#define F0900_NBITER_NF_QP_3_5 0xfa0400ff /*NBITER_NF6*/ -#define R0900_NBITER_NF6 0xfa05 -#define F0900_NBITER_NF_QP_2_3 0xfa0500ff +#define R0900_NBITER_NF6 0xfa05 +#define F0900_NBITER_NF_QP_2_3 0xfa0500ff /*NBITER_NF7*/ -#define R0900_NBITER_NF7 0xfa06 -#define F0900_NBITER_NF_QP_3_4 0xfa0600ff +#define R0900_NBITER_NF7 0xfa06 +#define F0900_NBITER_NF_QP_3_4 0xfa0600ff /*NBITER_NF8*/ -#define R0900_NBITER_NF8 0xfa07 -#define F0900_NBITER_NF_QP_4_5 0xfa0700ff +#define R0900_NBITER_NF8 0xfa07 +#define F0900_NBITER_NF_QP_4_5 0xfa0700ff /*NBITER_NF9*/ -#define R0900_NBITER_NF9 0xfa08 -#define F0900_NBITER_NF_QP_5_6 0xfa0800ff +#define R0900_NBITER_NF9 0xfa08 +#define F0900_NBITER_NF_QP_5_6 0xfa0800ff /*NBITER_NF10*/ -#define R0900_NBITER_NF10 0xfa09 -#define F0900_NBITER_NF_QP_8_9 0xfa0900ff +#define R0900_NBITER_NF10 0xfa09 +#define F0900_NBITER_NF_QP_8_9 0xfa0900ff /*NBITER_NF11*/ -#define R0900_NBITER_NF11 0xfa0a -#define F0900_NBITER_NF_QP_9_10 0xfa0a00ff +#define R0900_NBITER_NF11 0xfa0a +#define F0900_NBITER_NF_QP_9_10 0xfa0a00ff /*NBITER_NF12*/ -#define R0900_NBITER_NF12 0xfa0b -#define F0900_NBITER_NF_8P_3_5 0xfa0b00ff +#define R0900_NBITER_NF12 0xfa0b +#define F0900_NBITER_NF_8P_3_5 0xfa0b00ff /*NBITER_NF13*/ -#define R0900_NBITER_NF13 0xfa0c -#define F0900_NBITER_NF_8P_2_3 0xfa0c00ff +#define R0900_NBITER_NF13 0xfa0c +#define F0900_NBITER_NF_8P_2_3 0xfa0c00ff /*NBITER_NF14*/ -#define R0900_NBITER_NF14 0xfa0d -#define F0900_NBITER_NF_8P_3_4 0xfa0d00ff +#define R0900_NBITER_NF14 0xfa0d +#define F0900_NBITER_NF_8P_3_4 0xfa0d00ff /*NBITER_NF15*/ -#define R0900_NBITER_NF15 0xfa0e -#define F0900_NBITER_NF_8P_5_6 0xfa0e00ff +#define R0900_NBITER_NF15 0xfa0e +#define F0900_NBITER_NF_8P_5_6 0xfa0e00ff /*NBITER_NF16*/ -#define R0900_NBITER_NF16 0xfa0f -#define F0900_NBITER_NF_8P_8_9 0xfa0f00ff +#define R0900_NBITER_NF16 0xfa0f +#define F0900_NBITER_NF_8P_8_9 0xfa0f00ff /*NBITER_NF17*/ -#define R0900_NBITER_NF17 0xfa10 -#define F0900_NBITER_NF_8P_9_10 0xfa1000ff +#define R0900_NBITER_NF17 0xfa10 +#define F0900_NBITER_NF_8P_9_10 0xfa1000ff /*NBITERNOERR*/ -#define R0900_NBITERNOERR 0xfa3f -#define F0900_NBITER_STOP_CRIT 0xfa3f000f +#define R0900_NBITERNOERR 0xfa3f +#define F0900_NBITER_STOP_CRIT 0xfa3f000f /*GAINLLR_NF4*/ -#define R0900_GAINLLR_NF4 0xfa43 -#define F0900_GAINLLR_NF_QP_1_2 0xfa43007f +#define R0900_GAINLLR_NF4 0xfa43 +#define F0900_GAINLLR_NF_QP_1_2 0xfa43007f /*GAINLLR_NF5*/ -#define R0900_GAINLLR_NF5 0xfa44 -#define F0900_GAINLLR_NF_QP_3_5 0xfa44007f +#define R0900_GAINLLR_NF5 0xfa44 +#define F0900_GAINLLR_NF_QP_3_5 0xfa44007f /*GAINLLR_NF6*/ -#define R0900_GAINLLR_NF6 0xfa45 -#define F0900_GAINLLR_NF_QP_2_3 0xfa45007f +#define R0900_GAINLLR_NF6 0xfa45 +#define F0900_GAINLLR_NF_QP_2_3 0xfa45007f /*GAINLLR_NF7*/ -#define R0900_GAINLLR_NF7 0xfa46 -#define F0900_GAINLLR_NF_QP_3_4 0xfa46007f +#define R0900_GAINLLR_NF7 0xfa46 +#define F0900_GAINLLR_NF_QP_3_4 0xfa46007f /*GAINLLR_NF8*/ -#define R0900_GAINLLR_NF8 0xfa47 -#define F0900_GAINLLR_NF_QP_4_5 0xfa47007f +#define R0900_GAINLLR_NF8 0xfa47 +#define F0900_GAINLLR_NF_QP_4_5 0xfa47007f /*GAINLLR_NF9*/ -#define R0900_GAINLLR_NF9 0xfa48 -#define F0900_GAINLLR_NF_QP_5_6 0xfa48007f +#define R0900_GAINLLR_NF9 0xfa48 +#define F0900_GAINLLR_NF_QP_5_6 0xfa48007f /*GAINLLR_NF10*/ -#define R0900_GAINLLR_NF10 0xfa49 -#define F0900_GAINLLR_NF_QP_8_9 0xfa49007f +#define R0900_GAINLLR_NF10 0xfa49 +#define F0900_GAINLLR_NF_QP_8_9 0xfa49007f /*GAINLLR_NF11*/ -#define R0900_GAINLLR_NF11 0xfa4a -#define F0900_GAINLLR_NF_QP_9_10 0xfa4a007f +#define R0900_GAINLLR_NF11 0xfa4a +#define F0900_GAINLLR_NF_QP_9_10 0xfa4a007f /*GAINLLR_NF12*/ -#define R0900_GAINLLR_NF12 0xfa4b -#define F0900_GAINLLR_NF_8P_3_5 0xfa4b007f +#define R0900_GAINLLR_NF12 0xfa4b +#define F0900_GAINLLR_NF_8P_3_5 0xfa4b007f /*GAINLLR_NF13*/ -#define R0900_GAINLLR_NF13 0xfa4c -#define F0900_GAINLLR_NF_8P_2_3 0xfa4c007f +#define R0900_GAINLLR_NF13 0xfa4c +#define F0900_GAINLLR_NF_8P_2_3 0xfa4c007f /*GAINLLR_NF14*/ -#define R0900_GAINLLR_NF14 0xfa4d -#define F0900_GAINLLR_NF_8P_3_4 0xfa4d007f +#define R0900_GAINLLR_NF14 0xfa4d +#define F0900_GAINLLR_NF_8P_3_4 0xfa4d007f /*GAINLLR_NF15*/ -#define R0900_GAINLLR_NF15 0xfa4e -#define F0900_GAINLLR_NF_8P_5_6 0xfa4e007f +#define R0900_GAINLLR_NF15 0xfa4e +#define F0900_GAINLLR_NF_8P_5_6 0xfa4e007f /*GAINLLR_NF16*/ -#define R0900_GAINLLR_NF16 0xfa4f -#define F0900_GAINLLR_NF_8P_8_9 0xfa4f007f +#define R0900_GAINLLR_NF16 0xfa4f +#define F0900_GAINLLR_NF_8P_8_9 0xfa4f007f /*GAINLLR_NF17*/ -#define R0900_GAINLLR_NF17 0xfa50 -#define F0900_GAINLLR_NF_8P_9_10 0xfa50007f +#define R0900_GAINLLR_NF17 0xfa50 +#define F0900_GAINLLR_NF_8P_9_10 0xfa50007f /*CFGEXT*/ -#define R0900_CFGEXT 0xfa80 -#define F0900_STAGMODE 0xfa800080 -#define F0900_BYPBCH 0xfa800040 -#define F0900_BYPLDPC 0xfa800020 -#define F0900_LDPCMODE 0xfa800010 -#define F0900_INVLLRSIGN 0xfa800008 -#define F0900_SHORTMULT 0xfa800004 -#define F0900_EXTERNTX 0xfa800001 +#define R0900_CFGEXT 0xfa80 +#define F0900_STAGMODE 0xfa800080 +#define F0900_BYPBCH 0xfa800040 +#define F0900_BYPLDPC 0xfa800020 +#define F0900_LDPCMODE 0xfa800010 +#define F0900_INVLLRSIGN 0xfa800008 +#define F0900_SHORTMULT 0xfa800004 +#define F0900_EXTERNTX 0xfa800001 /*GENCFG*/ -#define R0900_GENCFG 0xfa86 -#define F0900_BROADCAST 0xfa860010 -#define F0900_NOSHFRD2 0xfa860008 -#define F0900_BCHERRFLAG 0xfa860004 -#define F0900_PRIORITY 0xfa860002 -#define F0900_DDEMOD 0xfa860001 +#define R0900_GENCFG 0xfa86 +#define F0900_BROADCAST 0xfa860010 +#define F0900_PRIORITY 0xfa860002 +#define F0900_DDEMOD 0xfa860001 /*LDPCERR1*/ -#define R0900_LDPCERR1 0xfa96 -#define F0900_LDPC_ERRORS_COUNTER1 0xfa9600ff +#define R0900_LDPCERR1 0xfa96 +#define F0900_LDPC_ERRORS_COUNTER1 0xfa9600ff /*LDPCERR0*/ -#define R0900_LDPCERR0 0xfa97 -#define F0900_LDPC_ERRORS_COUNTER0 0xfa9700ff +#define R0900_LDPCERR0 0xfa97 +#define F0900_LDPC_ERRORS_COUNTER0 0xfa9700ff /*BCHERR*/ -#define R0900_BCHERR 0xfa98 -#define F0900_ERRORFLAG 0xfa980010 -#define F0900_BCH_ERRORS_COUNTER 0xfa98000f +#define R0900_BCHERR 0xfa98 +#define F0900_ERRORFLAG 0xfa980010 +#define F0900_BCH_ERRORS_COUNTER 0xfa98000f /*TSTRES0*/ -#define R0900_TSTRES0 0xff11 -#define F0900_FRESFEC 0xff110080 -#define F0900_FRESTS 0xff110040 -#define F0900_FRESVIT1 0xff110020 -#define F0900_FRESVIT2 0xff110010 -#define F0900_FRESSYM1 0xff110008 -#define F0900_FRESSYM2 0xff110004 -#define F0900_FRESMAS 0xff110002 -#define F0900_FRESINT 0xff110001 +#define R0900_TSTRES0 0xff11 +#define F0900_FRESFEC 0xff110080 + +/*P2_TCTL4*/ +#define R0900_P2_TCTL4 0xff28 +#define F0900_P2_PN4_SELECT 0xff280020 + +/*P1_TCTL4*/ +#define R0900_P1_TCTL4 0xff48 +#define TCTL4 shiftx(R0900_P1_TCTL4, demod, 0x20) +#define F0900_P1_PN4_SELECT 0xff480020 /*P2_TSTDISRX*/ -#define R0900_P2_TSTDISRX 0xff65 -#define F0900_P2_EN_DISRX 0xff650080 -#define F0900_P2_TST_CURRSRC 0xff650040 -#define F0900_P2_IN_DIGSIGNAL 0xff650020 -#define F0900_P2_HIZ_CURRENTSRC 0xff650010 -#define F0900_TST_P2_PIN_SELECT 0xff650008 -#define F0900_P2_TST_DISRX 0xff650007 +#define R0900_P2_TSTDISRX 0xff65 +#define F0900_P2_PIN_SELECT1 0xff650008 /*P1_TSTDISRX*/ -#define R0900_P1_TSTDISRX 0xff67 -#define F0900_P1_EN_DISRX 0xff670080 -#define F0900_P1_TST_CURRSRC 0xff670040 -#define F0900_P1_IN_DIGSIGNAL 0xff670020 -#define F0900_P1_HIZ_CURRENTSRC 0xff670010 -#define F0900_TST_P1_PIN_SELECT 0xff670008 -#define F0900_P1_TST_DISRX 0xff670007 +#define R0900_P1_TSTDISRX 0xff67 +#define TSTDISRX shiftx(R0900_P1_TSTDISRX, demod, 2) +#define F0900_P1_PIN_SELECT1 0xff670008 +#define PIN_SELECT1 shiftx(F0900_P1_PIN_SELECT1, demod, 0x20000) -#define STV0900_NBREGS 684 -#define STV0900_NBFIELDS 1702 +#define STV0900_NBREGS 723 +#define STV0900_NBFIELDS 1420 #endif From 1e0c397d5ee261b4d855bf38c1e9987caf0e37ca Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 6 Nov 2009 23:42:22 -0300 Subject: [PATCH 204/345] V4L/DVB (13340): stv0900: big rework to support cut 3.0. Patch 3 of 4. Also patch changes logic to prevent code repetitions and big indents. It makes checkpatch silent :) Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_core.c | 1459 +++++++++----------- 1 file changed, 636 insertions(+), 823 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 11dbe942aa41..e2062048f433 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -105,7 +105,8 @@ static struct stv0900_inode *append_internal(struct stv0900_internal *internal) while (new_node->next_inode != NULL) new_node = new_node->next_inode; - new_node->next_inode = kmalloc(sizeof(struct stv0900_inode), GFP_KERNEL); + new_node->next_inode = kmalloc(sizeof(struct stv0900_inode), + GFP_KERNEL); if (new_node->next_inode != NULL) new_node = new_node->next_inode; else @@ -128,13 +129,13 @@ s32 ge2comp(s32 a, s32 width) return (a >= (1 << (width - 1))) ? (a - (1 << width)) : a; } -void stv0900_write_reg(struct stv0900_internal *i_params, u16 reg_addr, +void stv0900_write_reg(struct stv0900_internal *intp, u16 reg_addr, u8 reg_data) { u8 data[3]; int ret; struct i2c_msg i2cmsg = { - .addr = i_params->i2c_addr, + .addr = intp->i2c_addr, .flags = 0, .len = 3, .buf = data, @@ -144,31 +145,31 @@ void stv0900_write_reg(struct stv0900_internal *i_params, u16 reg_addr, data[1] = LSB(reg_addr); data[2] = reg_data; - ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1); + ret = i2c_transfer(intp->i2c_adap, &i2cmsg, 1); if (ret != 1) dprintk("%s: i2c error %d\n", __func__, ret); } -u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg) +u8 stv0900_read_reg(struct stv0900_internal *intp, u16 reg) { int ret; u8 b0[] = { MSB(reg), LSB(reg) }; u8 buf = 0; struct i2c_msg msg[] = { { - .addr = i_params->i2c_addr, + .addr = intp->i2c_addr, .flags = 0, .buf = b0, .len = 2, }, { - .addr = i_params->i2c_addr, + .addr = intp->i2c_addr, .flags = I2C_M_RD, .buf = &buf, .len = 1, }, }; - ret = i2c_transfer(i_params->i2c_adap, msg, 2); + ret = i2c_transfer(intp->i2c_adap, msg, 2); if (ret != 2) dprintk("%s: i2c error %d, reg[0x%02x]\n", __func__, ret, reg); @@ -190,94 +191,103 @@ void extract_mask_pos(u32 label, u8 *mask, u8 *pos) (*pos) = (i - 1); } -void stv0900_write_bits(struct stv0900_internal *i_params, u32 label, u8 val) +void stv0900_write_bits(struct stv0900_internal *intp, u32 label, u8 val) { u8 reg, mask, pos; - reg = stv0900_read_reg(i_params, (label >> 16) & 0xffff); + reg = stv0900_read_reg(intp, (label >> 16) & 0xffff); extract_mask_pos(label, &mask, &pos); val = mask & (val << pos); reg = (reg & (~mask)) | val; - stv0900_write_reg(i_params, (label >> 16) & 0xffff, reg); + stv0900_write_reg(intp, (label >> 16) & 0xffff, reg); } -u8 stv0900_get_bits(struct stv0900_internal *i_params, u32 label) +u8 stv0900_get_bits(struct stv0900_internal *intp, u32 label) { u8 val = 0xff; u8 mask, pos; extract_mask_pos(label, &mask, &pos); - val = stv0900_read_reg(i_params, label >> 16); + val = stv0900_read_reg(intp, label >> 16); val = (val & mask) >> pos; return val; } -enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *i_params) +enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp) { s32 i; - enum fe_stv0900_error error; - if (i_params != NULL) { - i_params->chip_id = stv0900_read_reg(i_params, R0900_MID); - if (i_params->errs == STV0900_NO_ERROR) { - /*Startup sequence*/ - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5c); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5c); - stv0900_write_reg(i_params, R0900_P1_TNRCFG, 0x6c); - stv0900_write_reg(i_params, R0900_P2_TNRCFG, 0x6f); - stv0900_write_reg(i_params, R0900_P1_I2CRPT, 0x20); - stv0900_write_reg(i_params, R0900_P2_I2CRPT, 0x20); - stv0900_write_reg(i_params, R0900_NCOARSE, 0x13); - msleep(3); - stv0900_write_reg(i_params, R0900_I2CCFG, 0x08); + if (intp == NULL) + return STV0900_INVALID_HANDLE; - switch (i_params->clkmode) { - case 0: - case 2: - stv0900_write_reg(i_params, R0900_SYNTCTRL, 0x20 - | i_params->clkmode); - break; - default: - /* preserve SELOSCI bit */ - i = 0x02 & stv0900_read_reg(i_params, R0900_SYNTCTRL); - stv0900_write_reg(i_params, R0900_SYNTCTRL, 0x20 | i); - break; - } + intp->chip_id = stv0900_read_reg(intp, R0900_MID); - msleep(3); - for (i = 0; i < 182; i++) - stv0900_write_reg(i_params, STV0900_InitVal[i][0], STV0900_InitVal[i][1]); + if (intp->errs != STV0900_NO_ERROR) + return intp->errs; - if (stv0900_read_reg(i_params, R0900_MID) >= 0x20) { - stv0900_write_reg(i_params, R0900_TSGENERAL, 0x0c); - for (i = 0; i < 32; i++) - stv0900_write_reg(i_params, STV0900_Cut20_AddOnVal[i][0], STV0900_Cut20_AddOnVal[i][1]); - } + /*Startup sequence*/ + stv0900_write_reg(intp, R0900_P1_DMDISTATE, 0x5c); + stv0900_write_reg(intp, R0900_P2_DMDISTATE, 0x5c); + msleep(3); + stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x6c); + stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x6f); + stv0900_write_reg(intp, R0900_P1_I2CRPT, 0x20); + stv0900_write_reg(intp, R0900_P2_I2CRPT, 0x20); + stv0900_write_reg(intp, R0900_NCOARSE, 0x13); + msleep(3); + stv0900_write_reg(intp, R0900_I2CCFG, 0x08); - stv0900_write_reg(i_params, R0900_P1_FSPYCFG, 0x6c); - stv0900_write_reg(i_params, R0900_P2_FSPYCFG, 0x6c); - stv0900_write_reg(i_params, R0900_TSTRES0, 0x80); - stv0900_write_reg(i_params, R0900_TSTRES0, 0x00); - } - error = i_params->errs; - } else - error = STV0900_INVALID_HANDLE; + switch (intp->clkmode) { + case 0: + case 2: + stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 + | intp->clkmode); + break; + default: + /* preserve SELOSCI bit */ + i = 0x02 & stv0900_read_reg(intp, R0900_SYNTCTRL); + stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | i); + break; + } - return error; + msleep(3); + for (i = 0; i < 181; i++) + stv0900_write_reg(intp, STV0900_InitVal[i][0], + STV0900_InitVal[i][1]); + if (stv0900_read_reg(intp, R0900_MID) >= 0x20) { + stv0900_write_reg(intp, R0900_TSGENERAL, 0x0c); + for (i = 0; i < 32; i++) + stv0900_write_reg(intp, STV0900_Cut20_AddOnVal[i][0], + STV0900_Cut20_AddOnVal[i][1]); + } + + stv0900_write_reg(intp, R0900_P1_FSPYCFG, 0x6c); + stv0900_write_reg(intp, R0900_P2_FSPYCFG, 0x6c); + + stv0900_write_reg(intp, R0900_P1_PDELCTRL2, 0x01); + stv0900_write_reg(intp, R0900_P2_PDELCTRL2, 0x21); + + stv0900_write_reg(intp, R0900_P1_PDELCTRL3, 0x20); + stv0900_write_reg(intp, R0900_P2_PDELCTRL3, 0x20); + + stv0900_write_reg(intp, R0900_TSTRES0, 0x80); + stv0900_write_reg(intp, R0900_TSTRES0, 0x00); + + return STV0900_NO_ERROR; } -u32 stv0900_get_mclk_freq(struct stv0900_internal *i_params, u32 ext_clk) +u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk) { u32 mclk = 90000000, div = 0, ad_div = 0; - div = stv0900_get_bits(i_params, F0900_M_DIV); - ad_div = ((stv0900_get_bits(i_params, F0900_SELX1RATIO) == 1) ? 4 : 6); + div = stv0900_get_bits(intp, F0900_M_DIV); + ad_div = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6); mclk = (div + 1) * ext_clk / ad_div; @@ -286,73 +296,60 @@ u32 stv0900_get_mclk_freq(struct stv0900_internal *i_params, u32 ext_clk) return mclk; } -enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *i_params, u32 mclk) +enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk) { - enum fe_stv0900_error error = STV0900_NO_ERROR; u32 m_div, clk_sel; dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk, - i_params->quartz); + intp->quartz); - if (i_params == NULL) - error = STV0900_INVALID_HANDLE; - else { - if (i_params->errs) - error = STV0900_I2C_ERROR; - else { - clk_sel = ((stv0900_get_bits(i_params, F0900_SELX1RATIO) == 1) ? 4 : 6); - m_div = ((clk_sel * mclk) / i_params->quartz) - 1; - stv0900_write_bits(i_params, F0900_M_DIV, m_div); - i_params->mclk = stv0900_get_mclk_freq(i_params, - i_params->quartz); + if (intp == NULL) + return STV0900_INVALID_HANDLE; - /*Set the DiseqC frequency to 22KHz */ - /* - Formula: - DiseqC_TX_Freq= MasterClock/(32*F22TX_Reg) - DiseqC_RX_Freq= MasterClock/(32*F22RX_Reg) - */ - m_div = i_params->mclk / 704000; - stv0900_write_reg(i_params, R0900_P1_F22TX, m_div); - stv0900_write_reg(i_params, R0900_P1_F22RX, m_div); + if (intp->errs) + return STV0900_I2C_ERROR; - stv0900_write_reg(i_params, R0900_P2_F22TX, m_div); - stv0900_write_reg(i_params, R0900_P2_F22RX, m_div); + clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6); + m_div = ((clk_sel * mclk) / intp->quartz) - 1; + stv0900_write_bits(intp, F0900_M_DIV, m_div); + intp->mclk = stv0900_get_mclk_freq(intp, + intp->quartz); - if ((i_params->errs)) - error = STV0900_I2C_ERROR; - } - } + /*Set the DiseqC frequency to 22KHz */ + /* + Formula: + DiseqC_TX_Freq= MasterClock/(32*F22TX_Reg) + DiseqC_RX_Freq= MasterClock/(32*F22RX_Reg) + */ + m_div = intp->mclk / 704000; + stv0900_write_reg(intp, R0900_P1_F22TX, m_div); + stv0900_write_reg(intp, R0900_P1_F22RX, m_div); - return error; + stv0900_write_reg(intp, R0900_P2_F22TX, m_div); + stv0900_write_reg(intp, R0900_P2_F22RX, m_div); + + if ((intp->errs)) + return STV0900_I2C_ERROR; + + return STV0900_NO_ERROR; } -u32 stv0900_get_err_count(struct stv0900_internal *i_params, int cntr, +u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr, enum fe_stv0900_demod_num demod) { u32 lsb, msb, hsb, err_val; - s32 err1field_hsb, err1field_msb, err1field_lsb; - s32 err2field_hsb, err2field_msb, err2field_lsb; - - dmd_reg(err1field_hsb, F0900_P1_ERR_CNT12, F0900_P2_ERR_CNT12); - dmd_reg(err1field_msb, F0900_P1_ERR_CNT11, F0900_P2_ERR_CNT11); - dmd_reg(err1field_lsb, F0900_P1_ERR_CNT10, F0900_P2_ERR_CNT10); - - dmd_reg(err2field_hsb, F0900_P1_ERR_CNT22, F0900_P2_ERR_CNT22); - dmd_reg(err2field_msb, F0900_P1_ERR_CNT21, F0900_P2_ERR_CNT21); - dmd_reg(err2field_lsb, F0900_P1_ERR_CNT20, F0900_P2_ERR_CNT20); switch (cntr) { case 0: default: - hsb = stv0900_get_bits(i_params, err1field_hsb); - msb = stv0900_get_bits(i_params, err1field_msb); - lsb = stv0900_get_bits(i_params, err1field_lsb); + hsb = stv0900_get_bits(intp, ERR_CNT12); + msb = stv0900_get_bits(intp, ERR_CNT11); + lsb = stv0900_get_bits(intp, ERR_CNT10); break; case 1: - hsb = stv0900_get_bits(i_params, err2field_hsb); - msb = stv0900_get_bits(i_params, err2field_msb); - lsb = stv0900_get_bits(i_params, err2field_lsb); + hsb = stv0900_get_bits(intp, ERR_CNT22); + msb = stv0900_get_bits(intp, ERR_CNT21); + lsb = stv0900_get_bits(intp, ERR_CNT20); break; } @@ -364,26 +361,22 @@ u32 stv0900_get_err_count(struct stv0900_internal *i_params, int cntr, static int stv0900_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - u32 fi2c; - - dmd_reg(fi2c, F0900_P1_I2CT_ON, F0900_P2_I2CT_ON); - - stv0900_write_bits(i_params, fi2c, enable); + stv0900_write_bits(intp, I2CT_ON, enable); return 0; } -static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, +static void stv0900_set_ts_parallel_serial(struct stv0900_internal *intp, enum fe_stv0900_clock_type path1_ts, enum fe_stv0900_clock_type path2_ts) { dprintk("%s\n", __func__); - if (i_params->chip_id >= 0x20) { + if (intp->chip_id >= 0x20) { switch (path1_ts) { case STV0900_PARALLEL_PUNCT_CLOCK: case STV0900_DVBCI_CLOCK: @@ -391,20 +384,20 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, case STV0900_SERIAL_PUNCT_CLOCK: case STV0900_SERIAL_CONT_CLOCK: default: - stv0900_write_reg(i_params, R0900_TSGENERAL, + stv0900_write_reg(intp, R0900_TSGENERAL, 0x00); break; case STV0900_PARALLEL_PUNCT_CLOCK: case STV0900_DVBCI_CLOCK: - stv0900_write_reg(i_params, R0900_TSGENERAL, + stv0900_write_reg(intp, R0900_TSGENERAL, 0x06); - stv0900_write_bits(i_params, + stv0900_write_bits(intp, F0900_P1_TSFIFO_MANSPEED, 3); - stv0900_write_bits(i_params, + stv0900_write_bits(intp, F0900_P2_TSFIFO_MANSPEED, 0); - stv0900_write_reg(i_params, + stv0900_write_reg(intp, R0900_P1_TSSPEED, 0x14); - stv0900_write_reg(i_params, + stv0900_write_reg(intp, R0900_P2_TSSPEED, 0x28); break; } @@ -416,12 +409,12 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, case STV0900_SERIAL_PUNCT_CLOCK: case STV0900_SERIAL_CONT_CLOCK: default: - stv0900_write_reg(i_params, + stv0900_write_reg(intp, R0900_TSGENERAL, 0x0C); break; case STV0900_PARALLEL_PUNCT_CLOCK: case STV0900_DVBCI_CLOCK: - stv0900_write_reg(i_params, + stv0900_write_reg(intp, R0900_TSGENERAL, 0x0A); dprintk("%s: 0x0a\n", __func__); break; @@ -436,20 +429,20 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, case STV0900_SERIAL_PUNCT_CLOCK: case STV0900_SERIAL_CONT_CLOCK: default: - stv0900_write_reg(i_params, R0900_TSGENERAL1X, + stv0900_write_reg(intp, R0900_TSGENERAL1X, 0x10); break; case STV0900_PARALLEL_PUNCT_CLOCK: case STV0900_DVBCI_CLOCK: - stv0900_write_reg(i_params, R0900_TSGENERAL1X, + stv0900_write_reg(intp, R0900_TSGENERAL1X, 0x16); - stv0900_write_bits(i_params, + stv0900_write_bits(intp, F0900_P1_TSFIFO_MANSPEED, 3); - stv0900_write_bits(i_params, + stv0900_write_bits(intp, F0900_P2_TSFIFO_MANSPEED, 0); - stv0900_write_reg(i_params, R0900_P1_TSSPEED, + stv0900_write_reg(intp, R0900_P1_TSSPEED, 0x14); - stv0900_write_reg(i_params, R0900_P2_TSSPEED, + stv0900_write_reg(intp, R0900_P2_TSSPEED, 0x28); break; } @@ -462,12 +455,12 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, case STV0900_SERIAL_PUNCT_CLOCK: case STV0900_SERIAL_CONT_CLOCK: default: - stv0900_write_reg(i_params, R0900_TSGENERAL1X, + stv0900_write_reg(intp, R0900_TSGENERAL1X, 0x14); break; case STV0900_PARALLEL_PUNCT_CLOCK: case STV0900_DVBCI_CLOCK: - stv0900_write_reg(i_params, R0900_TSGENERAL1X, + stv0900_write_reg(intp, R0900_TSGENERAL1X, 0x12); dprintk("%s: 0x12\n", __func__); break; @@ -479,20 +472,20 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, switch (path1_ts) { case STV0900_PARALLEL_PUNCT_CLOCK: - stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x00); - stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x00); + stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x00); + stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x00); break; case STV0900_DVBCI_CLOCK: - stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x00); - stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x01); + stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x00); + stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x01); break; case STV0900_SERIAL_PUNCT_CLOCK: - stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x01); - stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x00); + stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x01); + stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x00); break; case STV0900_SERIAL_CONT_CLOCK: - stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x01); - stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x01); + stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x01); + stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x01); break; default: break; @@ -500,29 +493,29 @@ static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params, switch (path2_ts) { case STV0900_PARALLEL_PUNCT_CLOCK: - stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x00); - stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x00); + stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x00); + stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x00); break; case STV0900_DVBCI_CLOCK: - stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x00); - stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x01); + stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x00); + stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x01); break; case STV0900_SERIAL_PUNCT_CLOCK: - stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x01); - stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x00); + stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x01); + stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x00); break; case STV0900_SERIAL_CONT_CLOCK: - stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x01); - stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x01); + stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x01); + stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x01); break; default: break; } - stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 1); - stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 0); - stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 1); - stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 0); + stv0900_write_bits(intp, F0900_P2_RST_HWARE, 1); + stv0900_write_bits(intp, F0900_P2_RST_HWARE, 0); + stv0900_write_bits(intp, F0900_P1_RST_HWARE, 1); + stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0); } void stv0900_set_tuner(struct dvb_frontend *fe, u32 frequency, @@ -574,7 +567,7 @@ void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) } } -static s32 stv0900_get_rf_level(struct stv0900_internal *i_params, +static s32 stv0900_get_rf_level(struct stv0900_internal *intp, const struct stv0900_table *lookup, enum fe_stv0900_demod_num demod) { @@ -586,43 +579,37 @@ static s32 stv0900_get_rf_level(struct stv0900_internal *i_params, dprintk("%s\n", __func__); - if ((lookup != NULL) && lookup->size) { - switch (demod) { - case STV0900_DEMOD_1: - default: - agc_gain = MAKEWORD(stv0900_get_bits(i_params, F0900_P1_AGCIQ_VALUE1), - stv0900_get_bits(i_params, F0900_P1_AGCIQ_VALUE0)); - break; - case STV0900_DEMOD_2: - agc_gain = MAKEWORD(stv0900_get_bits(i_params, F0900_P2_AGCIQ_VALUE1), - stv0900_get_bits(i_params, F0900_P2_AGCIQ_VALUE0)); - break; + if ((lookup == NULL) || (lookup->size <= 0)) + return 0; + + agc_gain = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1), + stv0900_get_bits(intp, AGCIQ_VALUE0)); + + imin = 0; + imax = lookup->size - 1; + if (INRANGE(lookup->table[imin].regval, agc_gain, + lookup->table[imax].regval)) { + while ((imax - imin) > 1) { + i = (imax + imin) >> 1; + + if (INRANGE(lookup->table[imin].regval, + agc_gain, + lookup->table[i].regval)) + imax = i; + else + imin = i; } - dprintk("%s: AGC Gain = 0x%x\n", __func__, agc_gain); - - imin = 0; - imax = lookup->size - 1; - if (INRANGE(lookup->table[imin].regval, agc_gain, lookup->table[imax].regval)) { - while ((imax - imin) > 1) { - i = (imax + imin) >> 1; - - if (INRANGE(lookup->table[imin].regval, agc_gain, lookup->table[i].regval)) - imax = i; - else - imin = i; - } - - rf_lvl = (((s32)agc_gain - lookup->table[imin].regval) - * (lookup->table[imax].realval - lookup->table[imin].realval) - / (lookup->table[imax].regval - lookup->table[imin].regval)) - + lookup->table[imin].realval; - } else if (agc_gain > lookup->table[0].regval) - rf_lvl = 5; - else if (agc_gain < lookup->table[lookup->size-1].regval) - rf_lvl = -100; - - } + rf_lvl = (s32)agc_gain - lookup->table[imin].regval; + rf_lvl *= (lookup->table[imax].realval - + lookup->table[imin].realval); + rf_lvl /= (lookup->table[imax].regval - + lookup->table[imin].regval); + rf_lvl += lookup->table[imin].realval; + } else if (agc_gain > lookup->table[0].regval) + rf_lvl = 5; + else if (agc_gain < lookup->table[lookup->size-1].regval) + rf_lvl = -100; dprintk("%s: RFLevel = %d\n", __func__, rf_lvl); @@ -648,45 +635,39 @@ static int stv0900_read_signal_strength(struct dvb_frontend *fe, u16 *strength) return 0; } - static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, const struct stv0900_table *lookup) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - s32 c_n = -100, - regval, imin, imax, + s32 c_n = -100, + regval, + imin, + imax, i, - lock_flag_field, noise_field1, noise_field0; dprintk("%s\n", __func__); - dmd_reg(lock_flag_field, F0900_P1_LOCK_DEFINITIF, - F0900_P2_LOCK_DEFINITIF); if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) { - dmd_reg(noise_field1, F0900_P1_NOSPLHT_NORMED1, - F0900_P2_NOSPLHT_NORMED1); - dmd_reg(noise_field0, F0900_P1_NOSPLHT_NORMED0, - F0900_P2_NOSPLHT_NORMED0); + noise_field1 = NOSPLHT_NORMED1; + noise_field0 = NOSPLHT_NORMED0; } else { - dmd_reg(noise_field1, F0900_P1_NOSDATAT_NORMED1, - F0900_P2_NOSDATAT_NORMED1); - dmd_reg(noise_field0, F0900_P1_NOSDATAT_NORMED0, - F0900_P2_NOSDATAT_NORMED0); + noise_field1 = NOSDATAT_NORMED1; + noise_field0 = NOSDATAT_NORMED0; } - if (stv0900_get_bits(i_params, lock_flag_field)) { + if (stv0900_get_bits(intp, LOCK_DEFINITIF)) { if ((lookup != NULL) && lookup->size) { regval = 0; msleep(5); for (i = 0; i < 16; i++) { - regval += MAKEWORD(stv0900_get_bits(i_params, + regval += MAKEWORD(stv0900_get_bits(intp, noise_field1), - stv0900_get_bits(i_params, + stv0900_get_bits(intp, noise_field0)); msleep(1); } @@ -718,18 +699,15 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, } } - dprintk("%s: Quality = %d\n", __func__, c_n); - return c_n; } static int stv0900_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; u8 err_val1, err_val0; - s32 err_field1, err_field0; u32 header_err_val = 0; *ucblocks = 0x0; @@ -737,24 +715,14 @@ static int stv0900_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) /* DVB-S2 delineator errors count */ /* retreiving number for errnous headers */ - dmd_reg(err_field0, R0900_P1_BBFCRCKO0, - R0900_P2_BBFCRCKO0); - dmd_reg(err_field1, R0900_P1_BBFCRCKO1, - R0900_P2_BBFCRCKO1); - - err_val1 = stv0900_read_reg(i_params, err_field1); - err_val0 = stv0900_read_reg(i_params, err_field0); - header_err_val = (err_val1<<8) | err_val0; + err_val1 = stv0900_read_reg(intp, BBFCRCKO1); + err_val0 = stv0900_read_reg(intp, BBFCRCKO0); + header_err_val = (err_val1 << 8) | err_val0; /* retreiving number for errnous packets */ - dmd_reg(err_field0, R0900_P1_UPCRCKO0, - R0900_P2_UPCRCKO0); - dmd_reg(err_field1, R0900_P1_UPCRCKO1, - R0900_P2_UPCRCKO1); - - err_val1 = stv0900_read_reg(i_params, err_field1); - err_val0 = stv0900_read_reg(i_params, err_field0); - *ucblocks = (err_val1<<8) | err_val0; + err_val1 = stv0900_read_reg(intp, UPCRCKO1); + err_val0 = stv0900_read_reg(intp, UPCRCKO0); + *ucblocks = (err_val1 << 8) | err_val0; *ucblocks += header_err_val; } @@ -777,25 +745,13 @@ static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; } -static u32 stv0900_get_ber(struct stv0900_internal *i_params, +static u32 stv0900_get_ber(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { u32 ber = 10000000, i; - s32 dmd_state_reg; s32 demod_state; - s32 vstatus_reg; - s32 prvit_field; - s32 pdel_status_reg; - s32 pdel_lock_field; - dmd_reg(dmd_state_reg, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); - dmd_reg(vstatus_reg, R0900_P1_VSTATUSVIT, R0900_P2_VSTATUSVIT); - dmd_reg(prvit_field, F0900_P1_PRFVIT, F0900_P2_PRFVIT); - dmd_reg(pdel_status_reg, R0900_P1_PDELSTATUS1, R0900_P2_PDELSTATUS1); - dmd_reg(pdel_lock_field, F0900_P1_PKTDELIN_LOCK, - F0900_P2_PKTDELIN_LOCK); - - demod_state = stv0900_get_bits(i_params, dmd_state_reg); + demod_state = stv0900_get_bits(intp, HEADER_MODE); switch (demod_state) { case STV0900_SEARCH: @@ -807,11 +763,11 @@ static u32 stv0900_get_ber(struct stv0900_internal *i_params, ber = 0; for (i = 0; i < 5; i++) { msleep(5); - ber += stv0900_get_err_count(i_params, 0, demod); + ber += stv0900_get_err_count(intp, 0, demod); } ber /= 5; - if (stv0900_get_bits(i_params, prvit_field)) { + if (stv0900_get_bits(intp, PRFVIT)) { ber *= 9766; ber = ber >> 13; } @@ -821,11 +777,11 @@ static u32 stv0900_get_ber(struct stv0900_internal *i_params, ber = 0; for (i = 0; i < 5; i++) { msleep(5); - ber += stv0900_get_err_count(i_params, 0, demod); + ber += stv0900_get_err_count(intp, 0, demod); } ber /= 5; - if (stv0900_get_bits(i_params, pdel_lock_field)) { + if (stv0900_get_bits(intp, PKTDELIN_LOCK)) { ber *= 9766; ber = ber >> 13; } @@ -846,20 +802,16 @@ static int stv0900_read_ber(struct dvb_frontend *fe, u32 *ber) return 0; } -int stv0900_get_demod_lock(struct stv0900_internal *i_params, +int stv0900_get_demod_lock(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod, s32 time_out) { s32 timer = 0, - lock = 0, - header_field, - lock_field; + lock = 0; enum fe_stv0900_search_state dmd_state; - dmd_reg(header_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); - dmd_reg(lock_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF); while ((timer < time_out) && (lock == 0)) { - dmd_state = stv0900_get_bits(i_params, header_field); + dmd_state = stv0900_get_bits(intp, HEADER_MODE); dprintk("Demod State = %d\n", dmd_state); switch (dmd_state) { case STV0900_SEARCH: @@ -869,7 +821,7 @@ int stv0900_get_demod_lock(struct stv0900_internal *i_params, break; case STV0900_DVBS2_FOUND: case STV0900_DVBS_FOUND: - lock = stv0900_get_bits(i_params, lock_field); + lock = stv0900_get_bits(intp, LOCK_DEFINITIF); break; } @@ -887,7 +839,7 @@ int stv0900_get_demod_lock(struct stv0900_internal *i_params, return lock; } -void stv0900_stop_all_s2_modcod(struct stv0900_internal *i_params, +void stv0900_stop_all_s2_modcod(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { s32 regflist, @@ -895,48 +847,32 @@ void stv0900_stop_all_s2_modcod(struct stv0900_internal *i_params, dprintk("%s\n", __func__); - dmd_reg(regflist, R0900_P1_MODCODLST0, R0900_P2_MODCODLST0); + regflist = MODCODLST0; for (i = 0; i < 16; i++) - stv0900_write_reg(i_params, regflist + i, 0xff); + stv0900_write_reg(intp, regflist + i, 0xff); } -void stv0900_activate_s2_modcode(struct stv0900_internal *i_params, +void stv0900_activate_s2_modcod(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { u32 matype, - mod_code, - fmod, - reg_index, - field_index; + mod_code, + fmod, + reg_index, + field_index; dprintk("%s\n", __func__); - if (i_params->chip_id <= 0x11) { + if (intp->chip_id <= 0x11) { msleep(5); - switch (demod) { - case STV0900_DEMOD_1: - default: - mod_code = stv0900_read_reg(i_params, - R0900_P1_PLHMODCOD); - matype = mod_code & 0x3; - mod_code = (mod_code & 0x7f) >> 2; - - reg_index = R0900_P1_MODCODLSTF - mod_code / 2; - field_index = mod_code % 2; - break; - case STV0900_DEMOD_2: - mod_code = stv0900_read_reg(i_params, - R0900_P2_PLHMODCOD); - matype = mod_code & 0x3; - mod_code = (mod_code & 0x7f) >> 2; - - reg_index = R0900_P2_MODCODLSTF - mod_code / 2; - field_index = mod_code % 2; - break; - } + mod_code = stv0900_read_reg(intp, PLHMODCOD); + matype = mod_code & 0x3; + mod_code = (mod_code & 0x7f) >> 2; + reg_index = MODCODLSTF - mod_code / 2; + field_index = mod_code % 2; switch (matype) { case 0: @@ -955,70 +891,41 @@ void stv0900_activate_s2_modcode(struct stv0900_internal *i_params, } if ((INRANGE(STV0900_QPSK_12, mod_code, STV0900_8PSK_910)) - && (matype <= 1)) { + && (matype <= 1)) { if (field_index == 0) - stv0900_write_reg(i_params, reg_index, + stv0900_write_reg(intp, reg_index, 0xf0 | fmod); else - stv0900_write_reg(i_params, reg_index, + stv0900_write_reg(intp, reg_index, (fmod << 4) | 0xf); } - } else if (i_params->chip_id >= 0x12) { - switch (demod) { - case STV0900_DEMOD_1: - default: - for (reg_index = 0; reg_index < 7; reg_index++) - stv0900_write_reg(i_params, R0900_P1_MODCODLST0 + reg_index, 0xff); - stv0900_write_reg(i_params, R0900_P1_MODCODLSTE, 0xff); - stv0900_write_reg(i_params, R0900_P1_MODCODLSTF, 0xcf); - for (reg_index = 0; reg_index < 8; reg_index++) - stv0900_write_reg(i_params, R0900_P1_MODCODLST7 + reg_index, 0xcc); + } else if (intp->chip_id >= 0x12) { + for (reg_index = 0; reg_index < 7; reg_index++) + stv0900_write_reg(intp, MODCODLST0 + reg_index, 0xff); - break; - case STV0900_DEMOD_2: - for (reg_index = 0; reg_index < 7; reg_index++) - stv0900_write_reg(i_params, R0900_P2_MODCODLST0 + reg_index, 0xff); + stv0900_write_reg(intp, MODCODLSTE, 0xff); + stv0900_write_reg(intp, MODCODLSTF, 0xcf); + for (reg_index = 0; reg_index < 8; reg_index++) + stv0900_write_reg(intp, MODCODLST7 + reg_index, 0xcc); - stv0900_write_reg(i_params, R0900_P2_MODCODLSTE, 0xff); - stv0900_write_reg(i_params, R0900_P2_MODCODLSTF, 0xcf); - for (reg_index = 0; reg_index < 8; reg_index++) - stv0900_write_reg(i_params, R0900_P2_MODCODLST7 + reg_index, 0xcc); - - break; - } } } -void stv0900_activate_s2_modcode_single(struct stv0900_internal *i_params, +void stv0900_activate_s2_modcod_single(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { u32 reg_index; dprintk("%s\n", __func__); - switch (demod) { - case STV0900_DEMOD_1: - default: - stv0900_write_reg(i_params, R0900_P1_MODCODLST0, 0xff); - stv0900_write_reg(i_params, R0900_P1_MODCODLST1, 0xf0); - stv0900_write_reg(i_params, R0900_P1_MODCODLSTF, 0x0f); - for (reg_index = 0; reg_index < 13; reg_index++) - stv0900_write_reg(i_params, - R0900_P1_MODCODLST2 + reg_index, 0); + stv0900_write_reg(intp, MODCODLST0, 0xff); + stv0900_write_reg(intp, MODCODLST1, 0xf0); + stv0900_write_reg(intp, MODCODLSTF, 0x0f); + for (reg_index = 0; reg_index < 13; reg_index++) + stv0900_write_reg(intp, MODCODLST2 + reg_index, 0); - break; - case STV0900_DEMOD_2: - stv0900_write_reg(i_params, R0900_P2_MODCODLST0, 0xff); - stv0900_write_reg(i_params, R0900_P2_MODCODLST1, 0xf0); - stv0900_write_reg(i_params, R0900_P2_MODCODLSTF, 0x0f); - for (reg_index = 0; reg_index < 13; reg_index++) - stv0900_write_reg(i_params, - R0900_P2_MODCODLST2 + reg_index, 0); - - break; - } } static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe) @@ -1042,161 +949,118 @@ static int stb0900_get_property(struct dvb_frontend *fe, return 0; } -void stv0900_start_search(struct stv0900_internal *i_params, +void stv0900_start_search(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { + u32 freq; + s16 freq_s16 ; - switch (demod) { - case STV0900_DEMOD_1: - default: - stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x1f); + stv0900_write_bits(intp, DEMOD_MODE, 0x1f); + if (intp->chip_id == 0x10) + stv0900_write_reg(intp, CORRELEXP, 0xaa); - if (i_params->chip_id == 0x10) - stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0xaa); + if (intp->chip_id < 0x20) + stv0900_write_reg(intp, CARHDR, 0x55); - if (i_params->chip_id < 0x20) - stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x55); - - if (i_params->dmd1_symbol_rate <= 5000000) { - stv0900_write_reg(i_params, R0900_P1_CARCFG, 0x44); - stv0900_write_reg(i_params, R0900_P1_CFRUP1, 0x0f); - stv0900_write_reg(i_params, R0900_P1_CFRUP0, 0xff); - stv0900_write_reg(i_params, R0900_P1_CFRLOW1, 0xf0); - stv0900_write_reg(i_params, R0900_P1_CFRLOW0, 0x00); - stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x68); + if (intp->chip_id <= 0x20) { + if (intp->symbol_rate[0] <= 5000000) { + stv0900_write_reg(intp, CARCFG, 0x44); + stv0900_write_reg(intp, CFRUP1, 0x0f); + stv0900_write_reg(intp, CFRUP0, 0xff); + stv0900_write_reg(intp, CFRLOW1, 0xf0); + stv0900_write_reg(intp, CFRLOW0, 0x00); + stv0900_write_reg(intp, RTCS2, 0x68); } else { - stv0900_write_reg(i_params, R0900_P1_CARCFG, 0xc4); - stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x44); + stv0900_write_reg(intp, CARCFG, 0xc4); + stv0900_write_reg(intp, RTCS2, 0x44); } - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0); - - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P1_EQUALCFG, 0x41); - stv0900_write_reg(i_params, R0900_P1_FFECFG, 0x41); - - if ((i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS1) || (i_params->dmd1_srch_standard == STV0900_SEARCH_DSS) || (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH)) { - stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x82); - stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0); - } - } - - stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x00); - stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0xe0); - stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0xc0); - stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); - stv0900_write_bits(i_params, F0900_P1_S1S2_SEQUENTIAL, 0); - stv0900_write_reg(i_params, R0900_P1_RTC, 0x88); - if (i_params->chip_id >= 0x20) { - if (i_params->dmd1_symbol_rate < 2000000) { - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x39); - stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x40); - } - - if (i_params->dmd1_symbol_rate < 10000000) { - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x4c); - stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x20); - } else { - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x4b); - stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x20); - } + } else { /*cut 3.0 above*/ + if (intp->symbol_rate[demod] <= 5000000) + stv0900_write_reg(intp, RTCS2, 0x68); + else + stv0900_write_reg(intp, RTCS2, 0x44); + stv0900_write_reg(intp, CARCFG, 0x46); + if (intp->srch_algo[demod] == STV0900_WARM_START) { + freq = 1000 << 16; + freq /= (intp->mclk / 1000); + freq_s16 = (s16)freq; } else { - if (i_params->dmd1_symbol_rate < 10000000) - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xef); + freq = (intp->srch_range[demod] / 2000); + if (intp->symbol_rate[demod] <= 5000000) + freq += 80; else - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed); + freq += 600; + + freq = freq << 16; + freq /= (intp->mclk / 1000); + freq_s16 = (s16)freq; } - switch (i_params->dmd1_srch_algo) { - case STV0900_WARM_START: - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); - break; - case STV0900_COLD_START: - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15); - break; - default: - break; + stv0900_write_bits(intp, CFR_UP1, MSB(freq_s16)); + stv0900_write_bits(intp, CFR_UP0, LSB(freq_s16)); + freq_s16 *= (-1); + stv0900_write_bits(intp, CFR_LOW1, MSB(freq_s16)); + stv0900_write_bits(intp, CFR_LOW0, LSB(freq_s16)); + } + + stv0900_write_reg(intp, CFRINIT1, 0); + stv0900_write_reg(intp, CFRINIT0, 0); + + if (intp->chip_id >= 0x20) { + stv0900_write_reg(intp, EQUALCFG, 0x41); + stv0900_write_reg(intp, FFECFG, 0x41); + + if ((intp->srch_standard[demod] == STV0900_SEARCH_DVBS1) || + (intp->srch_standard[demod] == STV0900_SEARCH_DSS) || + (intp->srch_standard[demod] == STV0900_AUTO_SEARCH)) { + stv0900_write_reg(intp, VITSCALE, + 0x82); + stv0900_write_reg(intp, VAVSRVIT, 0x0); + } + } + + stv0900_write_reg(intp, SFRSTEP, 0x00); + stv0900_write_reg(intp, TMGTHRISE, 0xe0); + stv0900_write_reg(intp, TMGTHFALL, 0xc0); + stv0900_write_bits(intp, SCAN_ENABLE, 0); + stv0900_write_bits(intp, CFR_AUTOSCAN, 0); + stv0900_write_bits(intp, S1S2_SEQUENTIAL, 0); + stv0900_write_reg(intp, RTC, 0x88); + if (intp->chip_id >= 0x20) { + if (intp->symbol_rate[demod] < 2000000) { + if (intp->chip_id <= 0x20) + stv0900_write_reg(intp, CARFREQ, 0x39); + else /*cut 3.0*/ + stv0900_write_reg(intp, CARFREQ, 0x89); + + stv0900_write_reg(intp, CARHDR, 0x40); + } else if (intp->symbol_rate[demod] < 10000000) { + stv0900_write_reg(intp, CARFREQ, 0x4c); + stv0900_write_reg(intp, CARHDR, 0x20); + } else { + stv0900_write_reg(intp, CARFREQ, 0x4b); + stv0900_write_reg(intp, CARHDR, 0x20); } + } else { + if (intp->symbol_rate[demod] < 10000000) + stv0900_write_reg(intp, CARFREQ, 0xef); + else + stv0900_write_reg(intp, CARFREQ, 0xed); + } + + switch (intp->srch_algo[demod]) { + case STV0900_WARM_START: + stv0900_write_reg(intp, DMDISTATE, 0x1f); + stv0900_write_reg(intp, DMDISTATE, 0x18); break; - case STV0900_DEMOD_2: - stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x1f); - if (i_params->chip_id == 0x10) - stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0xaa); - - if (i_params->chip_id < 0x20) - stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x55); - - if (i_params->dmd2_symbol_rate <= 5000000) { - stv0900_write_reg(i_params, R0900_P2_CARCFG, 0x44); - stv0900_write_reg(i_params, R0900_P2_CFRUP1, 0x0f); - stv0900_write_reg(i_params, R0900_P2_CFRUP0, 0xff); - stv0900_write_reg(i_params, R0900_P2_CFRLOW1, 0xf0); - stv0900_write_reg(i_params, R0900_P2_CFRLOW0, 0x00); - stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x68); - } else { - stv0900_write_reg(i_params, R0900_P2_CARCFG, 0xc4); - stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x44); - } - - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0); - - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P2_EQUALCFG, 0x41); - stv0900_write_reg(i_params, R0900_P2_FFECFG, 0x41); - if ((i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS1) || (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DSS) || (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH)) { - stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x82); - stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0); - } - } - - stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x00); - stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0xe0); - stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0xc0); - stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); - stv0900_write_bits(i_params, F0900_P2_S1S2_SEQUENTIAL, 0); - stv0900_write_reg(i_params, R0900_P2_RTC, 0x88); - if (i_params->chip_id >= 0x20) { - if (i_params->dmd2_symbol_rate < 2000000) { - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x39); - stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x40); - } - - if (i_params->dmd2_symbol_rate < 10000000) { - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x4c); - stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x20); - } else { - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x4b); - stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x20); - } - - } else { - if (i_params->dmd2_symbol_rate < 10000000) - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xef); - else - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed); - } - - switch (i_params->dmd2_srch_algo) { - case STV0900_WARM_START: - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); - break; - case STV0900_COLD_START: - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15); - break; - default: - break; - } - + case STV0900_COLD_START: + stv0900_write_reg(intp, DMDISTATE, 0x1f); + stv0900_write_reg(intp, DMDISTATE, 0x15); + break; + default: break; } } @@ -1205,33 +1069,40 @@ u8 stv0900_get_optim_carr_loop(s32 srate, enum fe_stv0900_modcode modcode, s32 pilot, u8 chip_id) { u8 aclc_value = 0x29; - s32 i; - const struct stv0900_car_loop_optim *car_loop_s2; + s32 i; + const struct stv0900_car_loop_optim *cls2, *cllqs2, *cllas2; dprintk("%s\n", __func__); - if (chip_id <= 0x12) - car_loop_s2 = FE_STV0900_S2CarLoop; - else if (chip_id == 0x20) - car_loop_s2 = FE_STV0900_S2CarLoopCut20; - else - car_loop_s2 = FE_STV0900_S2CarLoop; + if (chip_id <= 0x12) { + cls2 = FE_STV0900_S2CarLoop; + cllqs2 = FE_STV0900_S2LowQPCarLoopCut30; + cllas2 = FE_STV0900_S2APSKCarLoopCut30; + } else if (chip_id == 0x20) { + cls2 = FE_STV0900_S2CarLoopCut20; + cllqs2 = FE_STV0900_S2LowQPCarLoopCut20; + cllas2 = FE_STV0900_S2APSKCarLoopCut20; + } else { + cls2 = FE_STV0900_S2CarLoopCut30; + cllqs2 = FE_STV0900_S2LowQPCarLoopCut30; + cllas2 = FE_STV0900_S2APSKCarLoopCut30; + } if (modcode < STV0900_QPSK_12) { i = 0; - while ((i < 3) && (modcode != FE_STV0900_S2LowQPCarLoopCut20[i].modcode)) + while ((i < 3) && (modcode != cllqs2[i].modcode)) i++; if (i >= 3) i = 2; } else { i = 0; - while ((i < 14) && (modcode != car_loop_s2[i].modcode)) + while ((i < 14) && (modcode != cls2[i].modcode)) i++; if (i >= 14) { i = 0; - while ((i < 11) && (modcode != FE_STV0900_S2APSKCarLoopCut20[i].modcode)) + while ((i < 11) && (modcode != cllas2[i].modcode)) i++; if (i >= 11) @@ -1242,77 +1113,83 @@ u8 stv0900_get_optim_carr_loop(s32 srate, enum fe_stv0900_modcode modcode, if (modcode <= STV0900_QPSK_25) { if (pilot) { if (srate <= 3000000) - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_2; + aclc_value = cllqs2[i].car_loop_pilots_on_2; else if (srate <= 7000000) - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_5; + aclc_value = cllqs2[i].car_loop_pilots_on_5; else if (srate <= 15000000) - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_10; + aclc_value = cllqs2[i].car_loop_pilots_on_10; else if (srate <= 25000000) - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_20; + aclc_value = cllqs2[i].car_loop_pilots_on_20; else - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_30; + aclc_value = cllqs2[i].car_loop_pilots_on_30; } else { if (srate <= 3000000) - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_2; + aclc_value = cllqs2[i].car_loop_pilots_off_2; else if (srate <= 7000000) - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_5; + aclc_value = cllqs2[i].car_loop_pilots_off_5; else if (srate <= 15000000) - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_10; + aclc_value = cllqs2[i].car_loop_pilots_off_10; else if (srate <= 25000000) - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_20; + aclc_value = cllqs2[i].car_loop_pilots_off_20; else - aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_30; + aclc_value = cllqs2[i].car_loop_pilots_off_30; } } else if (modcode <= STV0900_8PSK_910) { if (pilot) { if (srate <= 3000000) - aclc_value = car_loop_s2[i].car_loop_pilots_on_2; + aclc_value = cls2[i].car_loop_pilots_on_2; else if (srate <= 7000000) - aclc_value = car_loop_s2[i].car_loop_pilots_on_5; + aclc_value = cls2[i].car_loop_pilots_on_5; else if (srate <= 15000000) - aclc_value = car_loop_s2[i].car_loop_pilots_on_10; + aclc_value = cls2[i].car_loop_pilots_on_10; else if (srate <= 25000000) - aclc_value = car_loop_s2[i].car_loop_pilots_on_20; + aclc_value = cls2[i].car_loop_pilots_on_20; else - aclc_value = car_loop_s2[i].car_loop_pilots_on_30; + aclc_value = cls2[i].car_loop_pilots_on_30; } else { if (srate <= 3000000) - aclc_value = car_loop_s2[i].car_loop_pilots_off_2; + aclc_value = cls2[i].car_loop_pilots_off_2; else if (srate <= 7000000) - aclc_value = car_loop_s2[i].car_loop_pilots_off_5; + aclc_value = cls2[i].car_loop_pilots_off_5; else if (srate <= 15000000) - aclc_value = car_loop_s2[i].car_loop_pilots_off_10; + aclc_value = cls2[i].car_loop_pilots_off_10; else if (srate <= 25000000) - aclc_value = car_loop_s2[i].car_loop_pilots_off_20; + aclc_value = cls2[i].car_loop_pilots_off_20; else - aclc_value = car_loop_s2[i].car_loop_pilots_off_30; + aclc_value = cls2[i].car_loop_pilots_off_30; } } else { if (srate <= 3000000) - aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_2; + aclc_value = cllas2[i].car_loop_pilots_on_2; else if (srate <= 7000000) - aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_5; + aclc_value = cllas2[i].car_loop_pilots_on_5; else if (srate <= 15000000) - aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_10; + aclc_value = cllas2[i].car_loop_pilots_on_10; else if (srate <= 25000000) - aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_20; + aclc_value = cllas2[i].car_loop_pilots_on_20; else - aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_30; + aclc_value = cllas2[i].car_loop_pilots_on_30; } return aclc_value; } -u8 stv0900_get_optim_short_carr_loop(s32 srate, enum fe_stv0900_modulation modulation, u8 chip_id) +u8 stv0900_get_optim_short_carr_loop(s32 srate, + enum fe_stv0900_modulation modulation, + u8 chip_id) { + const struct stv0900_short_frames_car_loop_optim *s2scl; + const struct stv0900_short_frames_car_loop_optim_vs_mod *s2sclc30; s32 mod_index = 0; - u8 aclc_value = 0x0b; dprintk("%s\n", __func__); + s2scl = FE_STV0900_S2ShortCarLoop; + s2sclc30 = FE_STV0900_S2ShortCarLoopCut30; + switch (modulation) { case STV0900_QPSK: default: @@ -1329,75 +1206,116 @@ u8 stv0900_get_optim_short_carr_loop(s32 srate, enum fe_stv0900_modulation modul break; } - switch (chip_id) { - case 0x20: + if (chip_id >= 0x30) { if (srate <= 3000000) - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_2; + aclc_value = s2sclc30[mod_index].car_loop_2; else if (srate <= 7000000) - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_5; + aclc_value = s2sclc30[mod_index].car_loop_5; else if (srate <= 15000000) - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_10; + aclc_value = s2sclc30[mod_index].car_loop_10; else if (srate <= 25000000) - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_20; + aclc_value = s2sclc30[mod_index].car_loop_20; else - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_30; + aclc_value = s2sclc30[mod_index].car_loop_30; - break; - case 0x12: - default: + } else if (chip_id >= 0x20) { if (srate <= 3000000) - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_2; + aclc_value = s2scl[mod_index].car_loop_cut20_2; else if (srate <= 7000000) - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_5; + aclc_value = s2scl[mod_index].car_loop_cut20_5; else if (srate <= 15000000) - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_10; + aclc_value = s2scl[mod_index].car_loop_cut20_10; else if (srate <= 25000000) - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_20; + aclc_value = s2scl[mod_index].car_loop_cut20_20; else - aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_30; + aclc_value = s2scl[mod_index].car_loop_cut20_30; + + } else { + if (srate <= 3000000) + aclc_value = s2scl[mod_index].car_loop_cut12_2; + else if (srate <= 7000000) + aclc_value = s2scl[mod_index].car_loop_cut12_5; + else if (srate <= 15000000) + aclc_value = s2scl[mod_index].car_loop_cut12_10; + else if (srate <= 25000000) + aclc_value = s2scl[mod_index].car_loop_cut12_20; + else + aclc_value = s2scl[mod_index].car_loop_cut12_30; - break; } return aclc_value; } -static enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *i_params, +static +enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp, enum fe_stv0900_demod_mode LDPC_Mode, enum fe_stv0900_demod_num demod) { enum fe_stv0900_error error = STV0900_NO_ERROR; + s32 reg_ind; dprintk("%s\n", __func__); switch (LDPC_Mode) { case STV0900_DUAL: default: - if ((i_params->demod_mode != STV0900_DUAL) - || (stv0900_get_bits(i_params, F0900_DDEMOD) != 1)) { - stv0900_write_reg(i_params, R0900_GENCFG, 0x1d); + if ((intp->demod_mode != STV0900_DUAL) + || (stv0900_get_bits(intp, F0900_DDEMOD) != 1)) { + stv0900_write_reg(intp, R0900_GENCFG, 0x1d); - i_params->demod_mode = STV0900_DUAL; + intp->demod_mode = STV0900_DUAL; - stv0900_write_bits(i_params, F0900_FRESFEC, 1); - stv0900_write_bits(i_params, F0900_FRESFEC, 0); + stv0900_write_bits(intp, F0900_FRESFEC, 1); + stv0900_write_bits(intp, F0900_FRESFEC, 0); + + for (reg_ind = 0; reg_ind < 7; reg_ind++) + stv0900_write_reg(intp, + R0900_P1_MODCODLST0 + reg_ind, + 0xff); + for (reg_ind = 0; reg_ind < 8; reg_ind++) + stv0900_write_reg(intp, + R0900_P1_MODCODLST7 + reg_ind, + 0xcc); + + stv0900_write_reg(intp, R0900_P1_MODCODLSTE, 0xff); + stv0900_write_reg(intp, R0900_P1_MODCODLSTF, 0xcf); + + for (reg_ind = 0; reg_ind < 7; reg_ind++) + stv0900_write_reg(intp, + R0900_P2_MODCODLST0 + reg_ind, + 0xff); + for (reg_ind = 0; reg_ind < 8; reg_ind++) + stv0900_write_reg(intp, + R0900_P2_MODCODLST7 + reg_ind, + 0xcc); + + stv0900_write_reg(intp, R0900_P2_MODCODLSTE, 0xff); + stv0900_write_reg(intp, R0900_P2_MODCODLSTF, 0xcf); } break; case STV0900_SINGLE: - if (demod == STV0900_DEMOD_2) - stv0900_write_reg(i_params, R0900_GENCFG, 0x06); - else - stv0900_write_reg(i_params, R0900_GENCFG, 0x04); + if (demod == STV0900_DEMOD_2) { + stv0900_stop_all_s2_modcod(intp, STV0900_DEMOD_1); + stv0900_activate_s2_modcod_single(intp, + STV0900_DEMOD_2); + stv0900_write_reg(intp, R0900_GENCFG, 0x06); + } else { + stv0900_stop_all_s2_modcod(intp, STV0900_DEMOD_2); + stv0900_activate_s2_modcod_single(intp, + STV0900_DEMOD_1); + stv0900_write_reg(intp, R0900_GENCFG, 0x04); + } - i_params->demod_mode = STV0900_SINGLE; + intp->demod_mode = STV0900_SINGLE; - stv0900_write_bits(i_params, F0900_FRESFEC, 1); - stv0900_write_bits(i_params, F0900_FRESFEC, 0); - stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 1); - stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 0); - stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 1); - stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 0); + stv0900_write_bits(intp, F0900_FRESFEC, 1); + stv0900_write_bits(intp, F0900_FRESFEC, 0); + stv0900_write_bits(intp, F0900_P1_ALGOSWRST, 1); + stv0900_write_bits(intp, F0900_P1_ALGOSWRST, 0); + stv0900_write_bits(intp, F0900_P2_ALGOSWRST, 1); + stv0900_write_bits(intp, F0900_P2_ALGOSWRST, 0); break; } @@ -1410,6 +1328,8 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, struct stv0900_state *state = fe->demodulator_priv; enum fe_stv0900_error error = STV0900_NO_ERROR; enum fe_stv0900_error demodError = STV0900_NO_ERROR; + struct stv0900_internal *intp = NULL; + int selosci, i; struct stv0900_inode *temp_int = find_inode(state->i2c_adap, @@ -1423,7 +1343,8 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, dprintk("%s: Find Internal Structure!\n", __func__); return STV0900_NO_ERROR; } else { - state->internal = kmalloc(sizeof(struct stv0900_internal), GFP_KERNEL); + state->internal = kmalloc(sizeof(struct stv0900_internal), + GFP_KERNEL); temp_int = append_internal(state->internal); state->internal->dmds_used = 1; state->internal->i2c_adap = state->i2c_adap; @@ -1433,108 +1354,105 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, dprintk("%s: Create New Internal Structure!\n", __func__); } - if (state->internal != NULL) { - demodError = stv0900_initialize(state->internal); - if (demodError == STV0900_NO_ERROR) { - error = STV0900_NO_ERROR; - } else { - if (demodError == STV0900_INVALID_HANDLE) - error = STV0900_INVALID_HANDLE; - else - error = STV0900_I2C_ERROR; - } - - if (state->internal != NULL) { - if (error == STV0900_NO_ERROR) { - state->internal->demod_mode = p_init->demod_mode; - - stv0900_st_dvbs2_single(state->internal, state->internal->demod_mode, STV0900_DEMOD_1); - - state->internal->chip_id = stv0900_read_reg(state->internal, R0900_MID); - state->internal->rolloff = p_init->rolloff; - state->internal->quartz = p_init->dmd_ref_clk; - - stv0900_write_bits(state->internal, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff); - stv0900_write_bits(state->internal, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff); - - state->internal->ts_config = p_init->ts_config; - if (state->internal->ts_config == NULL) - stv0900_set_ts_parallel_serial(state->internal, - p_init->path1_ts_clock, - p_init->path2_ts_clock); - else { - for (i = 0; state->internal->ts_config[i].addr != 0xffff; i++) - stv0900_write_reg(state->internal, - state->internal->ts_config[i].addr, - state->internal->ts_config[i].val); - - stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 1); - stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 0); - stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 1); - stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 0); - } - - stv0900_write_bits(state->internal, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); - switch (p_init->tuner1_adc) { - case 1: - stv0900_write_reg(state->internal, R0900_TSTTNR1, 0x26); - break; - default: - break; - } - - stv0900_write_bits(state->internal, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress); - switch (p_init->tuner2_adc) { - case 1: - stv0900_write_reg(state->internal, R0900_TSTTNR3, 0x26); - break; - default: - break; - } - - stv0900_write_bits(state->internal, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inversion); - stv0900_write_bits(state->internal, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inversion); - stv0900_set_mclk(state->internal, 135000000); - msleep(3); - - switch (state->internal->clkmode) { - case 0: - case 2: - stv0900_write_reg(state->internal, R0900_SYNTCTRL, 0x20 | state->internal->clkmode); - break; - default: - selosci = 0x02 & stv0900_read_reg(state->internal, R0900_SYNTCTRL); - stv0900_write_reg(state->internal, R0900_SYNTCTRL, 0x20 | selosci); - break; - } - msleep(3); - - state->internal->mclk = stv0900_get_mclk_freq(state->internal, state->internal->quartz); - if (state->internal->errs) - error = STV0900_I2C_ERROR; - } - } else { - error = STV0900_INVALID_HANDLE; - } + if (state->internal == NULL) { + error = STV0900_INVALID_HANDLE; + return error; } + demodError = stv0900_initialize(state->internal); + if (demodError == STV0900_NO_ERROR) { + error = STV0900_NO_ERROR; + } else { + if (demodError == STV0900_INVALID_HANDLE) + error = STV0900_INVALID_HANDLE; + else + error = STV0900_I2C_ERROR; + + return error; + } + + if (state->internal == NULL) { + error = STV0900_INVALID_HANDLE; + return error; + } + + intp = state->internal; + + intp->demod_mode = p_init->demod_mode; + stv0900_st_dvbs2_single(intp, intp->demod_mode, STV0900_DEMOD_1); + intp->chip_id = stv0900_read_reg(intp, R0900_MID); + intp->rolloff = p_init->rolloff; + intp->quartz = p_init->dmd_ref_clk; + + stv0900_write_bits(intp, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff); + stv0900_write_bits(intp, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff); + + intp->ts_config = p_init->ts_config; + if (intp->ts_config == NULL) + stv0900_set_ts_parallel_serial(intp, + p_init->path1_ts_clock, + p_init->path2_ts_clock); + else { + for (i = 0; intp->ts_config[i].addr != 0xffff; i++) + stv0900_write_reg(intp, + intp->ts_config[i].addr, + intp->ts_config[i].val); + + stv0900_write_bits(intp, F0900_P2_RST_HWARE, 1); + stv0900_write_bits(intp, F0900_P2_RST_HWARE, 0); + stv0900_write_bits(intp, F0900_P1_RST_HWARE, 1); + stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0); + } + + stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); + switch (p_init->tuner1_adc) { + case 1: + stv0900_write_reg(intp, R0900_TSTTNR1, 0x26); + break; + default: + break; + } + + stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress); + switch (p_init->tuner2_adc) { + case 1: + stv0900_write_reg(intp, R0900_TSTTNR3, 0x26); + break; + default: + break; + } + + stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv); + stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv); + stv0900_set_mclk(intp, 135000000); + msleep(3); + + switch (intp->clkmode) { + case 0: + case 2: + stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | intp->clkmode); + break; + default: + selosci = 0x02 & stv0900_read_reg(intp, R0900_SYNTCTRL); + stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | selosci); + break; + } + msleep(3); + + intp->mclk = stv0900_get_mclk_freq(intp, intp->quartz); + if (intp->errs) + error = STV0900_I2C_ERROR; + return error; } -static int stv0900_status(struct stv0900_internal *i_params, +static int stv0900_status(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { enum fe_stv0900_search_state demod_state; - s32 mode_field, delin_field, lock_field, fifo_field, lockedvit_field; int locked = FALSE; - dmd_reg(mode_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); - dmd_reg(lock_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF); - dmd_reg(delin_field, F0900_P1_PKTDELIN_LOCK, F0900_P2_PKTDELIN_LOCK); - dmd_reg(fifo_field, F0900_P1_TSFIFO_LINEOK, F0900_P2_TSFIFO_LINEOK); - dmd_reg(lockedvit_field, F0900_P1_LOCKEDVIT, F0900_P2_LOCKEDVIT); - - demod_state = stv0900_get_bits(i_params, mode_field); + demod_state = stv0900_get_bits(intp, HEADER_MODE); switch (demod_state) { case STV0900_SEARCH: case STV0900_PLH_DETECTED: @@ -1542,17 +1460,19 @@ static int stv0900_status(struct stv0900_internal *i_params, locked = FALSE; break; case STV0900_DVBS2_FOUND: - locked = stv0900_get_bits(i_params, lock_field) && - stv0900_get_bits(i_params, delin_field) && - stv0900_get_bits(i_params, fifo_field); + locked = stv0900_get_bits(intp, LOCK_DEFINITIF) && + stv0900_get_bits(intp, PKTDELIN_LOCK) && + stv0900_get_bits(intp, TSFIFO_LINEOK); break; case STV0900_DVBS_FOUND: - locked = stv0900_get_bits(i_params, lock_field) && - stv0900_get_bits(i_params, lockedvit_field) && - stv0900_get_bits(i_params, fifo_field); + locked = stv0900_get_bits(intp, LOCK_DEFINITIF) && + stv0900_get_bits(intp, LOCKEDVIT) && + stv0900_get_bits(intp, TSFIFO_LINEOK); break; } + dprintk("%s: locked = %d\n", __func__, locked); + return locked; } @@ -1560,7 +1480,8 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; + enum fe_stv0900_demod_num demod = state->demod; struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct stv0900_search_params p_search; @@ -1570,8 +1491,11 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, dprintk("%s: ", __func__); + if (!(INRANGE(100000, c->symbol_rate, 70000000))) + return DVBFE_ALGO_SEARCH_FAILED; + p_result.locked = FALSE; - p_search.path = state->demod; + p_search.path = demod; p_search.frequency = c->frequency; p_search.symbol_rate = c->symbol_rate; p_search.search_range = 10000000; @@ -1580,93 +1504,38 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, p_search.iq_inversion = STV0900_IQ_AUTO; p_search.search_algo = STV0900_BLIND_SEARCH; - if ((INRANGE(100000, p_search.symbol_rate, 70000000)) && - (INRANGE(100000, p_search.search_range, 50000000))) { - switch (p_search.path) { - case STV0900_DEMOD_1: + intp->srch_standard[demod] = p_search.standard; + intp->symbol_rate[demod] = p_search.symbol_rate; + intp->srch_range[demod] = p_search.search_range; + intp->freq[demod] = p_search.frequency; + intp->srch_algo[demod] = p_search.search_algo; + intp->srch_iq_inv[demod] = p_search.iq_inversion; + intp->fec[demod] = p_search.fec; + if ((stv0900_algo(fe) == STV0900_RANGEOK) && + (intp->errs == STV0900_NO_ERROR)) { + p_result.locked = intp->result[demod].locked; + p_result.standard = intp->result[demod].standard; + p_result.frequency = intp->result[demod].frequency; + p_result.symbol_rate = intp->result[demod].symbol_rate; + p_result.fec = intp->result[demod].fec; + p_result.modcode = intp->result[demod].modcode; + p_result.pilot = intp->result[demod].pilot; + p_result.frame_len = intp->result[demod].frame_len; + p_result.spectrum = intp->result[demod].spectrum; + p_result.rolloff = intp->result[demod].rolloff; + p_result.modulation = intp->result[demod].modulation; + } else { + p_result.locked = FALSE; + switch (intp->err[demod]) { + case STV0900_I2C_ERROR: + error = STV0900_I2C_ERROR; + break; + case STV0900_NO_ERROR: default: - i_params->dmd1_srch_standard = p_search.standard; - i_params->dmd1_symbol_rate = p_search.symbol_rate; - i_params->dmd1_srch_range = p_search.search_range; - i_params->tuner1_freq = p_search.frequency; - i_params->dmd1_srch_algo = p_search.search_algo; - i_params->dmd1_srch_iq_inv = p_search.iq_inversion; - i_params->dmd1_fec = p_search.fec; - break; - - case STV0900_DEMOD_2: - i_params->dmd2_srch_stndrd = p_search.standard; - i_params->dmd2_symbol_rate = p_search.symbol_rate; - i_params->dmd2_srch_range = p_search.search_range; - i_params->tuner2_freq = p_search.frequency; - i_params->dmd2_srch_algo = p_search.search_algo; - i_params->dmd2_srch_iq_inv = p_search.iq_inversion; - i_params->dmd2_fec = p_search.fec; + error = STV0900_SEARCH_FAILED; break; } - - if ((stv0900_algo(fe) == STV0900_RANGEOK) && - (i_params->errs == STV0900_NO_ERROR)) { - switch (p_search.path) { - case STV0900_DEMOD_1: - default: - p_result.locked = i_params->dmd1_rslts.locked; - p_result.standard = i_params->dmd1_rslts.standard; - p_result.frequency = i_params->dmd1_rslts.frequency; - p_result.symbol_rate = i_params->dmd1_rslts.symbol_rate; - p_result.fec = i_params->dmd1_rslts.fec; - p_result.modcode = i_params->dmd1_rslts.modcode; - p_result.pilot = i_params->dmd1_rslts.pilot; - p_result.frame_length = i_params->dmd1_rslts.frame_length; - p_result.spectrum = i_params->dmd1_rslts.spectrum; - p_result.rolloff = i_params->dmd1_rslts.rolloff; - p_result.modulation = i_params->dmd1_rslts.modulation; - break; - case STV0900_DEMOD_2: - p_result.locked = i_params->dmd2_rslts.locked; - p_result.standard = i_params->dmd2_rslts.standard; - p_result.frequency = i_params->dmd2_rslts.frequency; - p_result.symbol_rate = i_params->dmd2_rslts.symbol_rate; - p_result.fec = i_params->dmd2_rslts.fec; - p_result.modcode = i_params->dmd2_rslts.modcode; - p_result.pilot = i_params->dmd2_rslts.pilot; - p_result.frame_length = i_params->dmd2_rslts.frame_length; - p_result.spectrum = i_params->dmd2_rslts.spectrum; - p_result.rolloff = i_params->dmd2_rslts.rolloff; - p_result.modulation = i_params->dmd2_rslts.modulation; - break; - } - - } else { - p_result.locked = FALSE; - switch (p_search.path) { - case STV0900_DEMOD_1: - switch (i_params->dmd1_err) { - case STV0900_I2C_ERROR: - error = STV0900_I2C_ERROR; - break; - case STV0900_NO_ERROR: - default: - error = STV0900_SEARCH_FAILED; - break; - } - break; - case STV0900_DEMOD_2: - switch (i_params->dmd2_err) { - case STV0900_I2C_ERROR: - error = STV0900_I2C_ERROR; - break; - case STV0900_NO_ERROR: - default: - error = STV0900_SEARCH_FAILED; - break; - } - break; - } - } - - } else - error = STV0900_BAD_PARAMETER; + } if ((p_result.locked == TRUE) && (error == STV0900_NO_ERROR)) { dprintk("Search Success\n"); @@ -1676,7 +1545,6 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, return DVBFE_ALGO_SEARCH_FAILED; } - return DVBFE_ALGO_SEARCH_ERROR; } static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status) @@ -1707,16 +1575,13 @@ static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - s32 rst_field; - - dmd_reg(rst_field, F0900_P1_RST_HWARE, F0900_P2_RST_HWARE); if (stop_ts == TRUE) - stv0900_write_bits(i_params, rst_field, 1); + stv0900_write_bits(intp, RST_HWARE, 1); else - stv0900_write_bits(i_params, rst_field, 0); + stv0900_write_bits(intp, RST_HWARE, 0); return 0; } @@ -1724,16 +1589,12 @@ static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts) static int stv0900_diseqc_init(struct dvb_frontend *fe) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - s32 mode_field, reset_field; - dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); - dmd_reg(reset_field, F0900_P1_DISEQC_RESET, F0900_P2_DISEQC_RESET); - - stv0900_write_bits(i_params, mode_field, state->config->diseqc_mode); - stv0900_write_bits(i_params, reset_field, 1); - stv0900_write_bits(i_params, reset_field, 0); + stv0900_write_bits(intp, DISTX_MODE, state->config->diseqc_mode); + stv0900_write_bits(intp, DISEQC_RESET, 1); + stv0900_write_bits(intp, DISEQC_RESET, 0); return 0; } @@ -1748,47 +1609,24 @@ static int stv0900_init(struct dvb_frontend *fe) return 0; } -static int stv0900_diseqc_send(struct stv0900_internal *i_params , u8 *Data, +static int stv0900_diseqc_send(struct stv0900_internal *intp , u8 *data, u32 NbData, enum fe_stv0900_demod_num demod) { s32 i = 0; - switch (demod) { - case STV0900_DEMOD_1: - default: - stv0900_write_bits(i_params, F0900_P1_DIS_PRECHARGE, 1); - while (i < NbData) { - while (stv0900_get_bits(i_params, F0900_P1_FIFO_FULL)) - ;/* checkpatch complains */ - stv0900_write_reg(i_params, R0900_P1_DISTXDATA, Data[i]); - i++; - } + stv0900_write_bits(intp, DIS_PRECHARGE, 1); + while (i < NbData) { + while (stv0900_get_bits(intp, FIFO_FULL)) + ;/* checkpatch complains */ + stv0900_write_reg(intp, DISTXDATA, data[i]); + i++; + } - stv0900_write_bits(i_params, F0900_P1_DIS_PRECHARGE, 0); - i = 0; - while ((stv0900_get_bits(i_params, F0900_P1_TX_IDLE) != 1) && (i < 10)) { - msleep(10); - i++; - } - - break; - case STV0900_DEMOD_2: - stv0900_write_bits(i_params, F0900_P2_DIS_PRECHARGE, 1); - - while (i < NbData) { - while (stv0900_get_bits(i_params, F0900_P2_FIFO_FULL)) - ;/* checkpatch complains */ - stv0900_write_reg(i_params, R0900_P2_DISTXDATA, Data[i]); - i++; - } - - stv0900_write_bits(i_params, F0900_P2_DIS_PRECHARGE, 0); - i = 0; - while ((stv0900_get_bits(i_params, F0900_P2_TX_IDLE) != 1) && (i < 10)) { - msleep(10); - i++; - } - break; + stv0900_write_bits(intp, DIS_PRECHARGE, 0); + i = 0; + while ((stv0900_get_bits(intp, TX_IDLE) != 1) && (i < 10)) { + msleep(10); + i++; } return 0; @@ -1808,23 +1646,21 @@ static int stv0900_send_master_cmd(struct dvb_frontend *fe, static int stv0900_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - s32 mode_field; u8 data; - dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); switch (burst) { case SEC_MINI_A: - stv0900_write_bits(i_params, mode_field, 3);/* Unmodulated */ + stv0900_write_bits(intp, DISTX_MODE, 3);/* Unmodulated */ data = 0x00; - stv0900_diseqc_send(state->internal, &data, 1, state->demod); + stv0900_diseqc_send(intp, &data, 1, state->demod); break; case SEC_MINI_B: - stv0900_write_bits(i_params, mode_field, 2);/* Modulated */ + stv0900_write_bits(intp, DISTX_MODE, 2);/* Modulated */ data = 0xff; - stv0900_diseqc_send(state->internal, &data, 1, state->demod); + stv0900_diseqc_send(intp, &data, 1, state->demod); break; } @@ -1835,41 +1671,22 @@ static int stv0900_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; + enum fe_stv0900_demod_num demod = state->demod; s32 i = 0; - switch (state->demod) { - case STV0900_DEMOD_1: - default: - reply->msg_len = 0; + reply->msg_len = 0; - while ((stv0900_get_bits(i_params, F0900_P1_RX_END) != 1) && (i < 10)) { - msleep(10); - i++; - } + while ((stv0900_get_bits(intp, RX_END) != 1) && (i < 10)) { + msleep(10); + i++; + } - if (stv0900_get_bits(i_params, F0900_P1_RX_END)) { - reply->msg_len = stv0900_get_bits(i_params, F0900_P1_FIFO_BYTENBR); + if (stv0900_get_bits(intp, RX_END)) { + reply->msg_len = stv0900_get_bits(intp, FIFO_BYTENBR); - for (i = 0; i < reply->msg_len; i++) - reply->msg[i] = stv0900_read_reg(i_params, R0900_P1_DISRXDATA); - } - break; - case STV0900_DEMOD_2: - reply->msg_len = 0; - - while ((stv0900_get_bits(i_params, F0900_P2_RX_END) != 1) && (i < 10)) { - msleep(10); - i++; - } - - if (stv0900_get_bits(i_params, F0900_P2_RX_END)) { - reply->msg_len = stv0900_get_bits(i_params, F0900_P2_FIFO_BYTENBR); - - for (i = 0; i < reply->msg_len; i++) - reply->msg[i] = stv0900_read_reg(i_params, R0900_P2_DISRXDATA); - } - break; + for (i = 0; i < reply->msg_len; i++) + reply->msg[i] = stv0900_read_reg(intp, DISRXDATA); } return 0; @@ -1878,31 +1695,27 @@ static int stv0900_recv_slave_reply(struct dvb_frontend *fe, static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t toneoff) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - s32 mode_field, reset_field; dprintk("%s: %s\n", __func__, ((toneoff == 0) ? "On" : "Off")); - dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE); - dmd_reg(reset_field, F0900_P1_DISEQC_RESET, F0900_P2_DISEQC_RESET); - switch (toneoff) { case SEC_TONE_ON: /*Set the DiseqC mode to 22Khz _continues_ tone*/ - stv0900_write_bits(i_params, mode_field, 0); - stv0900_write_bits(i_params, reset_field, 1); + stv0900_write_bits(intp, DISTX_MODE, 0); + stv0900_write_bits(intp, DISEQC_RESET, 1); /*release DiseqC reset to enable the 22KHz tone*/ - stv0900_write_bits(i_params, reset_field, 0); + stv0900_write_bits(intp, DISEQC_RESET, 0); break; case SEC_TONE_OFF: /*return diseqc mode to config->diseqc_mode. Usually it's without _continues_ tone */ - stv0900_write_bits(i_params, mode_field, + stv0900_write_bits(intp, DISTX_MODE, state->config->diseqc_mode); /*maintain the DiseqC reset to disable the 22KHz tone*/ - stv0900_write_bits(i_params, reset_field, 1); - stv0900_write_bits(i_params, reset_field, 0); + stv0900_write_bits(intp, DISEQC_RESET, 1); + stv0900_write_bits(intp, DISEQC_RESET, 0); break; default: return -EINVAL; @@ -1993,13 +1806,13 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, init_params.rolloff = STV0900_35; init_params.path1_ts_clock = config->path1_mode; init_params.tun1_maddress = config->tun1_maddress; - init_params.tun1_iq_inversion = STV0900_IQ_NORMAL; + init_params.tun1_iq_inv = STV0900_IQ_NORMAL; init_params.tuner1_adc = config->tun1_adc; init_params.path2_ts_clock = config->path2_mode; init_params.ts_config = config->ts_config_regs; init_params.tun2_maddress = config->tun2_maddress; init_params.tuner2_adc = config->tun2_adc; - init_params.tun2_iq_inversion = STV0900_IQ_SWAPPED; + init_params.tun2_iq_inv = STV0900_IQ_SWAPPED; err_stv0900 = stv0900_init_internal(&state->frontend, &init_params); From a3a4f7e167e77066b0b98b8f056efcda2d302f97 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 6 Nov 2009 23:46:32 -0300 Subject: [PATCH 205/345] V4L/DVB (13341): stv0900: big rework to support cut 3.0. Patch 4 of 4. Also patch changes logic to prevent code repetitions and big indents. It makes checkpatch silent :) Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_sw.c | 3446 ++++++++-------------- 1 file changed, 1299 insertions(+), 2147 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c index 8c83c8b306a6..b8da87fa637f 100644 --- a/drivers/media/dvb/frontends/stv0900_sw.c +++ b/drivers/media/dvb/frontends/stv0900_sw.c @@ -27,56 +27,45 @@ #include "stv0900_reg.h" #include "stv0900_priv.h" -int stv0900_check_signal_presence(struct stv0900_internal *i_params, +s32 shiftx(s32 x, int demod, s32 shift) +{ + if (demod == 1) + return x - shift; + + return x; +} + +int stv0900_check_signal_presence(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { - s32 carr_offset, - agc2_integr, - max_carrier; + s32 carr_offset, + agc2_integr, + max_carrier; - int no_signal; + int no_signal = FALSE; - switch (demod) { - case STV0900_DEMOD_1: - default: - carr_offset = (stv0900_read_reg(i_params, R0900_P1_CFR2) << 8) - | stv0900_read_reg(i_params, - R0900_P1_CFR1); - carr_offset = ge2comp(carr_offset, 16); - agc2_integr = (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) - | stv0900_read_reg(i_params, - R0900_P1_AGC2I0); - max_carrier = i_params->dmd1_srch_range / 1000; - break; - case STV0900_DEMOD_2: - carr_offset = (stv0900_read_reg(i_params, R0900_P2_CFR2) << 8) - | stv0900_read_reg(i_params, - R0900_P2_CFR1); - carr_offset = ge2comp(carr_offset, 16); - agc2_integr = (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8) - | stv0900_read_reg(i_params, - R0900_P2_AGC2I0); - max_carrier = i_params->dmd2_srch_range / 1000; - break; - } + carr_offset = (stv0900_read_reg(intp, CFR2) << 8) + | stv0900_read_reg(intp, CFR1); + carr_offset = ge2comp(carr_offset, 16); + agc2_integr = (stv0900_read_reg(intp, AGC2I1) << 8) + | stv0900_read_reg(intp, AGC2I0); + max_carrier = intp->srch_range[demod] / 1000; max_carrier += (max_carrier / 10); max_carrier = 65536 * (max_carrier / 2); - max_carrier /= i_params->mclk / 1000; + max_carrier /= intp->mclk / 1000; if (max_carrier > 0x4000) max_carrier = 0x4000; if ((agc2_integr > 0x2000) - || (carr_offset > + 2*max_carrier) - || (carr_offset < -2*max_carrier)) + || (carr_offset > (2 * max_carrier)) + || (carr_offset < (-2 * max_carrier))) no_signal = TRUE; - else - no_signal = FALSE; return no_signal; } -static void stv0900_get_sw_loop_params(struct stv0900_internal *i_params, +static void stv0900_get_sw_loop_params(struct stv0900_internal *intp, s32 *frequency_inc, s32 *sw_timeout, s32 *steps, enum fe_stv0900_demod_num demod) @@ -85,30 +74,19 @@ static void stv0900_get_sw_loop_params(struct stv0900_internal *i_params, enum fe_stv0900_search_standard standard; - switch (demod) { - case STV0900_DEMOD_1: - default: - srate = i_params->dmd1_symbol_rate; - max_carrier = i_params->dmd1_srch_range / 1000; - max_carrier += max_carrier / 10; - standard = i_params->dmd1_srch_standard; - break; - case STV0900_DEMOD_2: - srate = i_params->dmd2_symbol_rate; - max_carrier = i_params->dmd2_srch_range / 1000; - max_carrier += max_carrier / 10; - standard = i_params->dmd2_srch_stndrd; - break; - } + srate = intp->symbol_rate[demod]; + max_carrier = intp->srch_range[demod] / 1000; + max_carrier += max_carrier / 10; + standard = intp->srch_standard[demod]; max_carrier = 65536 * (max_carrier / 2); - max_carrier /= i_params->mclk / 1000; + max_carrier /= intp->mclk / 1000; if (max_carrier > 0x4000) max_carrier = 0x4000; freq_inc = srate; - freq_inc /= i_params->mclk >> 10; + freq_inc /= intp->mclk >> 10; freq_inc = freq_inc << 6; switch (standard) { @@ -154,7 +132,7 @@ static void stv0900_get_sw_loop_params(struct stv0900_internal *i_params, } -static int stv0900_search_carr_sw_loop(struct stv0900_internal *i_params, +static int stv0900_search_carr_sw_loop(struct stv0900_internal *intp, s32 FreqIncr, s32 Timeout, int zigzag, s32 MaxStep, enum fe_stv0900_demod_num demod) { @@ -164,20 +142,11 @@ static int stv0900_search_carr_sw_loop(struct stv0900_internal *i_params, freqOffset, max_carrier; - switch (demod) { - case STV0900_DEMOD_1: - default: - max_carrier = i_params->dmd1_srch_range / 1000; - max_carrier += (max_carrier / 10); - break; - case STV0900_DEMOD_2: - max_carrier = i_params->dmd2_srch_range / 1000; - max_carrier += (max_carrier / 10); - break; - } + max_carrier = intp->srch_range[demod] / 1000; + max_carrier += (max_carrier / 10); max_carrier = 65536 * (max_carrier / 2); - max_carrier /= i_params->mclk / 1000; + max_carrier /= intp->mclk / 1000; if (max_carrier > 0x4000) max_carrier = 0x4000; @@ -190,40 +159,15 @@ static int stv0900_search_carr_sw_loop(struct stv0900_internal *i_params, stepCpt = 0; do { - switch (demod) { - case STV0900_DEMOD_1: - default: - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C); - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, - (freqOffset / 256) & 0xFF); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, - freqOffset & 0xFF); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); - stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 1); + stv0900_write_reg(intp, DMDISTATE, 0x1c); + stv0900_write_reg(intp, CFRINIT1, (freqOffset / 256) & 0xff); + stv0900_write_reg(intp, CFRINIT0, freqOffset & 0xff); + stv0900_write_reg(intp, DMDISTATE, 0x18); + stv0900_write_bits(intp, ALGOSWRST, 1); - if (i_params->chip_id == 0x12) { - stv0900_write_bits(i_params, - F0900_P1_RST_HWARE, 1); - stv0900_write_bits(i_params, - F0900_P1_RST_HWARE, 0); - } - break; - case STV0900_DEMOD_2: - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C); - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, - (freqOffset / 256) & 0xFF); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, - freqOffset & 0xFF); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); - stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 1); - - if (i_params->chip_id == 0x12) { - stv0900_write_bits(i_params, - F0900_P2_RST_HWARE, 1); - stv0900_write_bits(i_params, - F0900_P2_RST_HWARE, 0); - } - break; + if (intp->chip_id == 0x12) { + stv0900_write_bits(intp, RST_HWARE, 1); + stv0900_write_bits(intp, RST_HWARE, 0); } if (zigzag == TRUE) { @@ -235,8 +179,8 @@ static int stv0900_search_carr_sw_loop(struct stv0900_internal *i_params, freqOffset += + 2 * FreqIncr; stepCpt++; - lock = stv0900_get_demod_lock(i_params, demod, Timeout); - no_signal = stv0900_check_signal_presence(i_params, demod); + lock = stv0900_get_demod_lock(intp, demod, Timeout); + no_signal = stv0900_check_signal_presence(intp, demod); } while ((lock == FALSE) && (no_signal == FALSE) @@ -244,269 +188,138 @@ static int stv0900_search_carr_sw_loop(struct stv0900_internal *i_params, && ((freqOffset + FreqIncr) > -max_carrier) && (stepCpt < MaxStep)); - switch (demod) { - case STV0900_DEMOD_1: - default: - stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 0); - break; - case STV0900_DEMOD_2: - stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 0); - break; - } + stv0900_write_bits(intp, ALGOSWRST, 0); return lock; } -int stv0900_sw_algo(struct stv0900_internal *i_params, +int stv0900_sw_algo(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { - int lock = FALSE; + int lock = FALSE, + no_signal, + zigzag; + s32 s2fw, + fqc_inc, + sft_stp_tout, + trial_cntr, + max_steps; - int no_signal, - zigzag; - s32 dvbs2_fly_wheel; - - s32 freqIncrement, softStepTimeout, trialCounter, max_steps; - - stv0900_get_sw_loop_params(i_params, &freqIncrement, &softStepTimeout, + stv0900_get_sw_loop_params(intp, &fqc_inc, &sft_stp_tout, &max_steps, demod); - switch (demod) { - case STV0900_DEMOD_1: - default: - switch (i_params->dmd1_srch_standard) { - case STV0900_SEARCH_DVBS1: - case STV0900_SEARCH_DSS: - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P1_CARFREQ, - 0x3B); - else - stv0900_write_reg(i_params, R0900_P1_CARFREQ, - 0xef); - - stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, 0x49); - zigzag = FALSE; - break; - case STV0900_SEARCH_DVBS2: - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P1_CORRELABS, - 0x79); - else - stv0900_write_reg(i_params, R0900_P1_CORRELABS, - 0x68); - - stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, - 0x89); - - zigzag = TRUE; - break; - case STV0900_AUTO_SEARCH: - default: - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P1_CARFREQ, - 0x3B); - stv0900_write_reg(i_params, R0900_P1_CORRELABS, - 0x79); - } else { - stv0900_write_reg(i_params, R0900_P1_CARFREQ, - 0xef); - stv0900_write_reg(i_params, R0900_P1_CORRELABS, - 0x68); - } - - stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, - 0xc9); - zigzag = FALSE; - break; - } - - trialCounter = 0; - do { - lock = stv0900_search_carr_sw_loop(i_params, - freqIncrement, - softStepTimeout, - zigzag, - max_steps, - demod); - no_signal = stv0900_check_signal_presence(i_params, - demod); - trialCounter++; - if ((lock == TRUE) - || (no_signal == TRUE) - || (trialCounter == 2)) { - - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, - R0900_P1_CARFREQ, - 0x49); - stv0900_write_reg(i_params, - R0900_P1_CORRELABS, - 0x9e); - } else { - stv0900_write_reg(i_params, - R0900_P1_CARFREQ, - 0xed); - stv0900_write_reg(i_params, - R0900_P1_CORRELABS, - 0x88); - } - - if ((lock == TRUE) && (stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS2_FOUND)) { - msleep(softStepTimeout); - dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P1_FLYWHEEL_CPT); - - if (dvbs2_fly_wheel < 0xd) { - msleep(softStepTimeout); - dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P1_FLYWHEEL_CPT); - } - - if (dvbs2_fly_wheel < 0xd) { - lock = FALSE; - - if (trialCounter < 2) { - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x79); - else - stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x68); - - stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, 0x89); - } - } - } - } - - } while ((lock == FALSE) - && (trialCounter < 2) - && (no_signal == FALSE)); + switch (intp->srch_standard[demod]) { + case STV0900_SEARCH_DVBS1: + case STV0900_SEARCH_DSS: + if (intp->chip_id >= 0x20) + stv0900_write_reg(intp, CARFREQ, 0x3b); + else + stv0900_write_reg(intp, CARFREQ, 0xef); + stv0900_write_reg(intp, DMDCFGMD, 0x49); + zigzag = FALSE; break; - case STV0900_DEMOD_2: - switch (i_params->dmd2_srch_stndrd) { - case STV0900_SEARCH_DVBS1: - case STV0900_SEARCH_DSS: - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P2_CARFREQ, - 0x3b); - else - stv0900_write_reg(i_params, R0900_P2_CARFREQ, - 0xef); + case STV0900_SEARCH_DVBS2: + if (intp->chip_id >= 0x20) + stv0900_write_reg(intp, CORRELABS, 0x79); + else + stv0900_write_reg(intp, CORRELABS, 0x68); - stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, - 0x49); - zigzag = FALSE; - break; - case STV0900_SEARCH_DVBS2: - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P2_CORRELABS, - 0x79); - else - stv0900_write_reg(i_params, R0900_P2_CORRELABS, - 0x68); + stv0900_write_reg(intp, DMDCFGMD, 0x89); - stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0x89); - zigzag = TRUE; - break; - case STV0900_AUTO_SEARCH: - default: - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P2_CARFREQ, - 0x3b); - stv0900_write_reg(i_params, R0900_P2_CORRELABS, - 0x79); - } else { - stv0900_write_reg(i_params, R0900_P2_CARFREQ, - 0xef); - stv0900_write_reg(i_params, R0900_P2_CORRELABS, - 0x68); - } - - stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0xc9); - - zigzag = FALSE; - break; + zigzag = TRUE; + break; + case STV0900_AUTO_SEARCH: + default: + if (intp->chip_id >= 0x20) { + stv0900_write_reg(intp, CARFREQ, 0x3b); + stv0900_write_reg(intp, CORRELABS, 0x79); + } else { + stv0900_write_reg(intp, CARFREQ, 0xef); + stv0900_write_reg(intp, CORRELABS, 0x68); } - trialCounter = 0; - - do { - lock = stv0900_search_carr_sw_loop(i_params, - freqIncrement, - softStepTimeout, - zigzag, - max_steps, - demod); - no_signal = stv0900_check_signal_presence(i_params, - demod); - trialCounter++; - if ((lock == TRUE) - || (no_signal == TRUE) - || (trialCounter == 2)) { - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, - R0900_P2_CARFREQ, - 0x49); - stv0900_write_reg(i_params, - R0900_P2_CORRELABS, - 0x9e); - } else { - stv0900_write_reg(i_params, - R0900_P2_CARFREQ, - 0xed); - stv0900_write_reg(i_params, - R0900_P2_CORRELABS, - 0x88); - } - - if ((lock == TRUE) && (stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS2_FOUND)) { - msleep(softStepTimeout); - dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P2_FLYWHEEL_CPT); - if (dvbs2_fly_wheel < 0xd) { - msleep(softStepTimeout); - dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P2_FLYWHEEL_CPT); - } - - if (dvbs2_fly_wheel < 0xd) { - lock = FALSE; - if (trialCounter < 2) { - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x79); - else - stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x68); - - stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0x89); - } - } - } - } - - } while ((lock == FALSE) && (trialCounter < 2) && (no_signal == FALSE)); - + stv0900_write_reg(intp, DMDCFGMD, 0xc9); + zigzag = FALSE; break; } + trial_cntr = 0; + do { + lock = stv0900_search_carr_sw_loop(intp, + fqc_inc, + sft_stp_tout, + zigzag, + max_steps, + demod); + no_signal = stv0900_check_signal_presence(intp, demod); + trial_cntr++; + if ((lock == TRUE) + || (no_signal == TRUE) + || (trial_cntr == 2)) { + + if (intp->chip_id >= 0x20) { + stv0900_write_reg(intp, CARFREQ, 0x49); + stv0900_write_reg(intp, CORRELABS, 0x9e); + } else { + stv0900_write_reg(intp, CARFREQ, 0xed); + stv0900_write_reg(intp, CORRELABS, 0x88); + } + + if ((stv0900_get_bits(intp, HEADER_MODE) == + STV0900_DVBS2_FOUND) && + (lock == TRUE)) { + msleep(sft_stp_tout); + s2fw = stv0900_get_bits(intp, FLYWHEEL_CPT); + + if (s2fw < 0xd) { + msleep(sft_stp_tout); + s2fw = stv0900_get_bits(intp, + FLYWHEEL_CPT); + } + + if (s2fw < 0xd) { + lock = FALSE; + + if (trial_cntr < 2) { + if (intp->chip_id >= 0x20) + stv0900_write_reg(intp, + CORRELABS, + 0x79); + else + stv0900_write_reg(intp, + CORRELABS, + 0x68); + + stv0900_write_reg(intp, + DMDCFGMD, + 0x89); + } + } + } + } + + } while ((lock == FALSE) + && (trial_cntr < 2) + && (no_signal == FALSE)); + return lock; } -static u32 stv0900_get_symbol_rate(struct stv0900_internal *i_params, +static u32 stv0900_get_symbol_rate(struct stv0900_internal *intp, u32 mclk, enum fe_stv0900_demod_num demod) { - s32 sfr_field3, sfr_field2, sfr_field1, sfr_field0, - rem1, rem2, intval1, intval2, srate; + s32 rem1, rem2, intval1, intval2, srate; - dmd_reg(sfr_field3, F0900_P1_SYMB_FREQ3, F0900_P2_SYMB_FREQ3); - dmd_reg(sfr_field2, F0900_P1_SYMB_FREQ2, F0900_P2_SYMB_FREQ2); - dmd_reg(sfr_field1, F0900_P1_SYMB_FREQ1, F0900_P2_SYMB_FREQ1); - dmd_reg(sfr_field0, F0900_P1_SYMB_FREQ0, F0900_P2_SYMB_FREQ0); - - srate = (stv0900_get_bits(i_params, sfr_field3) << 24) + - (stv0900_get_bits(i_params, sfr_field2) << 16) + - (stv0900_get_bits(i_params, sfr_field1) << 8) + - (stv0900_get_bits(i_params, sfr_field0)); + srate = (stv0900_get_bits(intp, SYMB_FREQ3) << 24) + + (stv0900_get_bits(intp, SYMB_FREQ2) << 16) + + (stv0900_get_bits(intp, SYMB_FREQ1) << 8) + + (stv0900_get_bits(intp, SYMB_FREQ0)); dprintk("lock: srate=%d r0=0x%x r1=0x%x r2=0x%x r3=0x%x \n", - srate, stv0900_get_bits(i_params, sfr_field0), - stv0900_get_bits(i_params, sfr_field1), - stv0900_get_bits(i_params, sfr_field2), - stv0900_get_bits(i_params, sfr_field3)); + srate, stv0900_get_bits(intp, SYMB_FREQ0), + stv0900_get_bits(intp, SYMB_FREQ1), + stv0900_get_bits(intp, SYMB_FREQ2), + stv0900_get_bits(intp, SYMB_FREQ3)); intval1 = (mclk) >> 16; intval2 = (srate) >> 16; @@ -520,18 +333,15 @@ static u32 stv0900_get_symbol_rate(struct stv0900_internal *i_params, return srate; } -static void stv0900_set_symbol_rate(struct stv0900_internal *i_params, +static void stv0900_set_symbol_rate(struct stv0900_internal *intp, u32 mclk, u32 srate, enum fe_stv0900_demod_num demod) { - s32 sfr_init_reg; u32 symb; dprintk("%s: Mclk %d, SR %d, Dmd %d\n", __func__, mclk, srate, demod); - dmd_reg(sfr_init_reg, R0900_P1_SFRINIT1, R0900_P2_SFRINIT1); - if (srate > 60000000) { symb = srate << 4; symb /= (mclk >> 12); @@ -543,19 +353,16 @@ static void stv0900_set_symbol_rate(struct stv0900_internal *i_params, symb /= (mclk >> 7); } - stv0900_write_reg(i_params, sfr_init_reg, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, sfr_init_reg + 1, (symb & 0xFF)); + stv0900_write_reg(intp, SFRINIT1, (symb >> 8) & 0x7f); + stv0900_write_reg(intp, SFRINIT1 + 1, (symb & 0xff)); } -static void stv0900_set_max_symbol_rate(struct stv0900_internal *i_params, +static void stv0900_set_max_symbol_rate(struct stv0900_internal *intp, u32 mclk, u32 srate, enum fe_stv0900_demod_num demod) { - s32 sfr_max_reg; u32 symb; - dmd_reg(sfr_max_reg, R0900_P1_SFRUP1, R0900_P2_SFRUP1); - srate = 105 * (srate / 100); if (srate > 60000000) { @@ -570,23 +377,20 @@ static void stv0900_set_max_symbol_rate(struct stv0900_internal *i_params, } if (symb < 0x7fff) { - stv0900_write_reg(i_params, sfr_max_reg, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, sfr_max_reg + 1, (symb & 0xFF)); + stv0900_write_reg(intp, SFRUP1, (symb >> 8) & 0x7f); + stv0900_write_reg(intp, SFRUP1 + 1, (symb & 0xff)); } else { - stv0900_write_reg(i_params, sfr_max_reg, 0x7F); - stv0900_write_reg(i_params, sfr_max_reg + 1, 0xFF); + stv0900_write_reg(intp, SFRUP1, 0x7f); + stv0900_write_reg(intp, SFRUP1 + 1, 0xff); } } -static void stv0900_set_min_symbol_rate(struct stv0900_internal *i_params, +static void stv0900_set_min_symbol_rate(struct stv0900_internal *intp, u32 mclk, u32 srate, enum fe_stv0900_demod_num demod) { - s32 sfr_min_reg; u32 symb; - dmd_reg(sfr_min_reg, R0900_P1_SFRLOW1, R0900_P2_SFRLOW1); - srate = 95 * (srate / 100); if (srate > 60000000) { symb = srate << 4; @@ -601,22 +405,20 @@ static void stv0900_set_min_symbol_rate(struct stv0900_internal *i_params, symb /= (mclk >> 7); } - stv0900_write_reg(i_params, sfr_min_reg, (symb >> 8) & 0xFF); - stv0900_write_reg(i_params, sfr_min_reg + 1, (symb & 0xFF)); + stv0900_write_reg(intp, SFRLOW1, (symb >> 8) & 0xff); + stv0900_write_reg(intp, SFRLOW1 + 1, (symb & 0xff)); } -static s32 stv0900_get_timing_offst(struct stv0900_internal *i_params, +static s32 stv0900_get_timing_offst(struct stv0900_internal *intp, u32 srate, enum fe_stv0900_demod_num demod) { - s32 tmgreg, - timingoffset; + s32 timingoffset; - dmd_reg(tmgreg, R0900_P1_TMGREG2, R0900_P2_TMGREG2); - timingoffset = (stv0900_read_reg(i_params, tmgreg) << 16) + - (stv0900_read_reg(i_params, tmgreg + 1) << 8) + - (stv0900_read_reg(i_params, tmgreg + 2)); + timingoffset = (stv0900_read_reg(intp, TMGREG2) << 16) + + (stv0900_read_reg(intp, TMGREG2 + 1) << 8) + + (stv0900_read_reg(intp, TMGREG2 + 2)); timingoffset = ge2comp(timingoffset, 24); @@ -630,22 +432,19 @@ static s32 stv0900_get_timing_offst(struct stv0900_internal *i_params, return timingoffset; } -static void stv0900_set_dvbs2_rolloff(struct stv0900_internal *i_params, +static void stv0900_set_dvbs2_rolloff(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { - s32 rolloff, man_fld, matstr_reg, rolloff_ctl_fld; + s32 rolloff; - dmd_reg(man_fld, F0900_P1_MANUAL_ROLLOFF, F0900_P2_MANUAL_ROLLOFF); - dmd_reg(matstr_reg, R0900_P1_MATSTR1, R0900_P2_MATSTR1); - dmd_reg(rolloff_ctl_fld, F0900_P1_ROLLOFF_CONTROL, - F0900_P2_ROLLOFF_CONTROL); - - if (i_params->chip_id == 0x10) { - stv0900_write_bits(i_params, man_fld, 1); - rolloff = stv0900_read_reg(i_params, matstr_reg) & 0x03; - stv0900_write_bits(i_params, rolloff_ctl_fld, rolloff); - } else - stv0900_write_bits(i_params, man_fld, 0); + if (intp->chip_id == 0x10) { + stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1); + rolloff = stv0900_read_reg(intp, MATSTR1) & 0x03; + stv0900_write_bits(intp, ROLLOFF_CONTROL, rolloff); + } else if (intp->chip_id <= 0x20) + stv0900_write_bits(intp, MANUALSX_ROLLOFF, 0); + else /* cut 3.0 */ + stv0900_write_bits(intp, MANUALS2_ROLLOFF, 0); } static u32 stv0900_carrier_width(u32 srate, enum fe_stv0900_rolloff ro) @@ -668,85 +467,48 @@ static u32 stv0900_carrier_width(u32 srate, enum fe_stv0900_rolloff ro) return srate + (srate * rolloff) / 100; } -static int stv0900_check_timing_lock(struct stv0900_internal *i_params, +static int stv0900_check_timing_lock(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { int timingLock = FALSE; - s32 i, - timingcpt = 0; - u8 carFreq, - tmgTHhigh, - tmgTHLow; + s32 i, + timingcpt = 0; + u8 car_freq, + tmg_th_high, + tmg_th_low; - switch (demod) { - case STV0900_DEMOD_1: - default: - carFreq = stv0900_read_reg(i_params, R0900_P1_CARFREQ); - tmgTHhigh = stv0900_read_reg(i_params, R0900_P1_TMGTHRISE); - tmgTHLow = stv0900_read_reg(i_params, R0900_P1_TMGTHFALL); - stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0x20); - stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0x0); - stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); - stv0900_write_reg(i_params, R0900_P1_RTC, 0x80); - stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x40); - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x0); - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0x0); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0x0); - stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x65); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); - msleep(7); + car_freq = stv0900_read_reg(intp, CARFREQ); + tmg_th_high = stv0900_read_reg(intp, TMGTHRISE); + tmg_th_low = stv0900_read_reg(intp, TMGTHFALL); + stv0900_write_reg(intp, TMGTHRISE, 0x20); + stv0900_write_reg(intp, TMGTHFALL, 0x0); + stv0900_write_bits(intp, CFR_AUTOSCAN, 0); + stv0900_write_reg(intp, RTC, 0x80); + stv0900_write_reg(intp, RTCS2, 0x40); + stv0900_write_reg(intp, CARFREQ, 0x0); + stv0900_write_reg(intp, CFRINIT1, 0x0); + stv0900_write_reg(intp, CFRINIT0, 0x0); + stv0900_write_reg(intp, AGC2REF, 0x65); + stv0900_write_reg(intp, DMDISTATE, 0x18); + msleep(7); - for (i = 0; i < 10; i++) { - if (stv0900_get_bits(i_params, F0900_P1_TMGLOCK_QUALITY) >= 2) - timingcpt++; + for (i = 0; i < 10; i++) { + if (stv0900_get_bits(intp, TMGLOCK_QUALITY) >= 2) + timingcpt++; - msleep(1); - } - - if (timingcpt >= 3) - timingLock = TRUE; - - stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38); - stv0900_write_reg(i_params, R0900_P1_RTC, 0x88); - stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x68); - stv0900_write_reg(i_params, R0900_P1_CARFREQ, carFreq); - stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, tmgTHhigh); - stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, tmgTHLow); - break; - case STV0900_DEMOD_2: - carFreq = stv0900_read_reg(i_params, R0900_P2_CARFREQ); - tmgTHhigh = stv0900_read_reg(i_params, R0900_P2_TMGTHRISE); - tmgTHLow = stv0900_read_reg(i_params, R0900_P2_TMGTHFALL); - stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0x20); - stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0); - stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); - stv0900_write_reg(i_params, R0900_P2_RTC, 0x80); - stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x40); - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x0); - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0x0); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0x0); - stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x65); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); - msleep(5); - for (i = 0; i < 10; i++) { - if (stv0900_get_bits(i_params, F0900_P2_TMGLOCK_QUALITY) >= 2) - timingcpt++; - - msleep(1); - } - - if (timingcpt >= 3) - timingLock = TRUE; - - stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38); - stv0900_write_reg(i_params, R0900_P2_RTC, 0x88); - stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x68); - stv0900_write_reg(i_params, R0900_P2_CARFREQ, carFreq); - stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, tmgTHhigh); - stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, tmgTHLow); - break; + msleep(1); } + if (timingcpt >= 3) + timingLock = TRUE; + + stv0900_write_reg(intp, AGC2REF, 0x38); + stv0900_write_reg(intp, RTC, 0x88); + stv0900_write_reg(intp, RTCS2, 0x68); + stv0900_write_reg(intp, CARFREQ, car_freq); + stv0900_write_reg(intp, TMGTHRISE, tmg_th_high); + stv0900_write_reg(intp, TMGTHFALL, tmg_th_low); + return timingLock; } @@ -754,142 +516,114 @@ static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe, s32 demod_timeout) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; + int lock = FALSE, + d = demod; + s32 srate, + search_range, + locktimeout, + currier_step, + nb_steps, + current_step, + direction, + tuner_freq, + timeout, + freq; - int lock = FALSE; - s32 srate, search_range, locktimeout, - currier_step, nb_steps, current_step, - direction, tuner_freq, timeout; - - switch (demod) { - case STV0900_DEMOD_1: - default: - srate = i_params->dmd1_symbol_rate; - search_range = i_params->dmd1_srch_range; - break; - - case STV0900_DEMOD_2: - srate = i_params->dmd2_symbol_rate; - search_range = i_params->dmd2_srch_range; - break; - } + srate = intp->symbol_rate[d]; + search_range = intp->srch_range[d]; if (srate >= 10000000) locktimeout = demod_timeout / 3; else locktimeout = demod_timeout / 2; - lock = stv0900_get_demod_lock(i_params, demod, locktimeout); + lock = stv0900_get_demod_lock(intp, d, locktimeout); - if (lock == FALSE) { - if (srate >= 10000000) { - if (stv0900_check_timing_lock(i_params, demod) == TRUE) { - switch (demod) { - case STV0900_DEMOD_1: - default: - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15); - break; - case STV0900_DEMOD_2: - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15); - break; - } + if (lock != FALSE) + return lock; - lock = stv0900_get_demod_lock(i_params, demod, demod_timeout); - } else - lock = FALSE; - } else { - if (srate <= 4000000) - currier_step = 1000; - else if (srate <= 7000000) - currier_step = 2000; - else if (srate <= 10000000) - currier_step = 3000; - else - currier_step = 5000; + if (srate >= 10000000) { + if (stv0900_check_timing_lock(intp, d) == TRUE) { + stv0900_write_reg(intp, DMDISTATE, 0x1f); + stv0900_write_reg(intp, DMDISTATE, 0x15); + lock = stv0900_get_demod_lock(intp, d, demod_timeout); + } else + lock = FALSE; - nb_steps = ((search_range / 1000) / currier_step); - nb_steps /= 2; - nb_steps = (2 * (nb_steps + 1)); - if (nb_steps < 0) - nb_steps = 2; - else if (nb_steps > 12) - nb_steps = 12; + return lock; + } - current_step = 1; - direction = 1; + if (intp->chip_id <= 0x20) { + if (srate <= 1000000) + currier_step = 500; + else if (srate <= 4000000) + currier_step = 1000; + else if (srate <= 7000000) + currier_step = 2000; + else if (srate <= 10000000) + currier_step = 3000; + else + currier_step = 5000; + + if (srate >= 2000000) { timeout = (demod_timeout / 3); if (timeout > 1000) timeout = 1000; + } else + timeout = (demod_timeout / 2); + } else { + /*cut 3.0 */ + currier_step = srate / 4000; + timeout = (demod_timeout * 3) / 4; + } - switch (demod) { - case STV0900_DEMOD_1: - default: - if (lock == FALSE) { - tuner_freq = i_params->tuner1_freq; - i_params->tuner1_bw = stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + i_params->dmd1_symbol_rate; + nb_steps = ((search_range / 1000) / currier_step); - while ((current_step <= nb_steps) && (lock == FALSE)) { + if ((nb_steps % 2) != 0) + nb_steps += 1; - if (direction > 0) - tuner_freq += (current_step * currier_step); - else - tuner_freq -= (current_step * currier_step); + if (nb_steps <= 0) + nb_steps = 2; + else if (nb_steps > 12) + nb_steps = 12; - stv0900_set_tuner(fe, tuner_freq, i_params->tuner1_bw); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C); - if (i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS2) { - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); - } + current_step = 1; + direction = 1; - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15); - lock = stv0900_get_demod_lock(i_params, demod, timeout); - direction *= -1; - current_step++; - } - } - break; - case STV0900_DEMOD_2: - if (lock == FALSE) { - tuner_freq = i_params->tuner2_freq; - i_params->tuner2_bw = stv0900_carrier_width(srate, i_params->rolloff) + srate; + if (intp->chip_id <= 0x20) { + tuner_freq = intp->freq[d]; + intp->bw[d] = stv0900_carrier_width(intp->symbol_rate[d], + intp->rolloff) + intp->symbol_rate[d]; + } else + tuner_freq = 0; - while ((current_step <= nb_steps) && (lock == FALSE)) { + while ((current_step <= nb_steps) && (lock == FALSE)) { + if (direction > 0) + tuner_freq += (current_step * currier_step); + else + tuner_freq -= (current_step * currier_step); - if (direction > 0) - tuner_freq += (current_step * currier_step); - else - tuner_freq -= (current_step * currier_step); - - stv0900_set_tuner(fe, tuner_freq, i_params->tuner2_bw); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C); - if (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS2) { - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); - } - - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15); - lock = stv0900_get_demod_lock(i_params, demod, timeout); - direction *= -1; - current_step++; - } - } - break; - } + if (intp->chip_id <= 0x20) { + stv0900_set_tuner(fe, tuner_freq, intp->bw[d]); + stv0900_write_reg(intp, DMDISTATE, 0x1c); + stv0900_write_reg(intp, CFRINIT1, 0); + stv0900_write_reg(intp, CFRINIT0, 0); + stv0900_write_reg(intp, DMDISTATE, 0x1f); + stv0900_write_reg(intp, DMDISTATE, 0x15); + } else { + stv0900_write_reg(intp, DMDISTATE, 0x1c); + freq = (tuner_freq * 65536) / (intp->mclk / 1000); + stv0900_write_bits(intp, CFR_INIT1, MSB(freq)); + stv0900_write_bits(intp, CFR_INIT0, LSB(freq)); + stv0900_write_reg(intp, DMDISTATE, 0x1f); + stv0900_write_reg(intp, DMDISTATE, 0x05); } + + lock = stv0900_get_demod_lock(intp, d, timeout); + direction *= -1; + current_step++; } return lock; @@ -931,9 +665,7 @@ static void stv0900_get_lock_timeout(s32 *demod_timeout, s32 *fec_timeout, } else if (srate <= 20000000) { (*demod_timeout) = 400; (*fec_timeout) = 130; - } - - else { + } else { (*demod_timeout) = 300; (*fec_timeout) = 100; } @@ -946,95 +678,77 @@ static void stv0900_get_lock_timeout(s32 *demod_timeout, s32 *fec_timeout, (*demod_timeout) /= 2; } -static void stv0900_set_viterbi_tracq(struct stv0900_internal *i_params, +static void stv0900_set_viterbi_tracq(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { - s32 vth_reg; + s32 vth_reg = VTH12; dprintk("%s\n", __func__); - dmd_reg(vth_reg, R0900_P1_VTH12, R0900_P2_VTH12); - - stv0900_write_reg(i_params, vth_reg++, 0xd0); - stv0900_write_reg(i_params, vth_reg++, 0x7d); - stv0900_write_reg(i_params, vth_reg++, 0x53); - stv0900_write_reg(i_params, vth_reg++, 0x2F); - stv0900_write_reg(i_params, vth_reg++, 0x24); - stv0900_write_reg(i_params, vth_reg++, 0x1F); + stv0900_write_reg(intp, vth_reg++, 0xd0); + stv0900_write_reg(intp, vth_reg++, 0x7d); + stv0900_write_reg(intp, vth_reg++, 0x53); + stv0900_write_reg(intp, vth_reg++, 0x2f); + stv0900_write_reg(intp, vth_reg++, 0x24); + stv0900_write_reg(intp, vth_reg++, 0x1f); } -static void stv0900_set_viterbi_standard(struct stv0900_internal *i_params, - enum fe_stv0900_search_standard Standard, - enum fe_stv0900_fec PunctureRate, +static void stv0900_set_viterbi_standard(struct stv0900_internal *intp, + enum fe_stv0900_search_standard standard, + enum fe_stv0900_fec fec, enum fe_stv0900_demod_num demod) { - - s32 fecmReg, - prvitReg; - dprintk("%s: ViterbiStandard = ", __func__); - switch (demod) { - case STV0900_DEMOD_1: - default: - fecmReg = R0900_P1_FECM; - prvitReg = R0900_P1_PRVIT; - break; - case STV0900_DEMOD_2: - fecmReg = R0900_P2_FECM; - prvitReg = R0900_P2_PRVIT; - break; - } - - switch (Standard) { + switch (standard) { case STV0900_AUTO_SEARCH: dprintk("Auto\n"); - stv0900_write_reg(i_params, fecmReg, 0x10); - stv0900_write_reg(i_params, prvitReg, 0x3F); + stv0900_write_reg(intp, FECM, 0x10); + stv0900_write_reg(intp, PRVIT, 0x3f); break; case STV0900_SEARCH_DVBS1: dprintk("DVBS1\n"); - stv0900_write_reg(i_params, fecmReg, 0x00); - switch (PunctureRate) { + stv0900_write_reg(intp, FECM, 0x00); + switch (fec) { case STV0900_FEC_UNKNOWN: default: - stv0900_write_reg(i_params, prvitReg, 0x2F); + stv0900_write_reg(intp, PRVIT, 0x2f); break; case STV0900_FEC_1_2: - stv0900_write_reg(i_params, prvitReg, 0x01); + stv0900_write_reg(intp, PRVIT, 0x01); break; case STV0900_FEC_2_3: - stv0900_write_reg(i_params, prvitReg, 0x02); + stv0900_write_reg(intp, PRVIT, 0x02); break; case STV0900_FEC_3_4: - stv0900_write_reg(i_params, prvitReg, 0x04); + stv0900_write_reg(intp, PRVIT, 0x04); break; case STV0900_FEC_5_6: - stv0900_write_reg(i_params, prvitReg, 0x08); + stv0900_write_reg(intp, PRVIT, 0x08); break; case STV0900_FEC_7_8: - stv0900_write_reg(i_params, prvitReg, 0x20); + stv0900_write_reg(intp, PRVIT, 0x20); break; } break; case STV0900_SEARCH_DSS: dprintk("DSS\n"); - stv0900_write_reg(i_params, fecmReg, 0x80); - switch (PunctureRate) { + stv0900_write_reg(intp, FECM, 0x80); + switch (fec) { case STV0900_FEC_UNKNOWN: default: - stv0900_write_reg(i_params, prvitReg, 0x13); + stv0900_write_reg(intp, PRVIT, 0x13); break; case STV0900_FEC_1_2: - stv0900_write_reg(i_params, prvitReg, 0x01); + stv0900_write_reg(intp, PRVIT, 0x01); break; case STV0900_FEC_2_3: - stv0900_write_reg(i_params, prvitReg, 0x02); + stv0900_write_reg(intp, PRVIT, 0x02); break; case STV0900_FEC_6_7: - stv0900_write_reg(i_params, prvitReg, 0x10); + stv0900_write_reg(intp, PRVIT, 0x10); break; } break; @@ -1043,496 +757,11 @@ static void stv0900_set_viterbi_standard(struct stv0900_internal *i_params, } } -static void stv0900_track_optimization(struct dvb_frontend *fe) -{ - struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; - enum fe_stv0900_demod_num demod = state->demod; - - s32 srate, pilots, aclc, freq1, freq0, - i = 0, timed, timef, blindTunSw = 0; - - enum fe_stv0900_rolloff rolloff; - enum fe_stv0900_modcode foundModcod; - - dprintk("%s\n", __func__); - - srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - srate += stv0900_get_timing_offst(i_params, srate, demod); - - switch (demod) { - case STV0900_DEMOD_1: - default: - switch (i_params->dmd1_rslts.standard) { - case STV0900_DVBS1_STANDARD: - if (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH) { - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); - } - - stv0900_write_bits(i_params, F0900_P1_ROLLOFF_CONTROL, i_params->rolloff); - stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1); - stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75); - break; - case STV0900_DSS_STANDARD: - if (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH) { - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); - } - - stv0900_write_bits(i_params, F0900_P1_ROLLOFF_CONTROL, i_params->rolloff); - stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1); - stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75); - break; - case STV0900_DVBS2_STANDARD: - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); - stv0900_write_reg(i_params, R0900_P1_ACLC, 0); - stv0900_write_reg(i_params, R0900_P1_BCLC, 0); - if (i_params->dmd1_rslts.frame_length == STV0900_LONG_FRAME) { - foundModcod = stv0900_get_bits(i_params, F0900_P1_DEMOD_MODCOD); - pilots = stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE) & 0x01; - aclc = stv0900_get_optim_carr_loop(srate, foundModcod, pilots, i_params->chip_id); - if (foundModcod <= STV0900_QPSK_910) - stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, aclc); - else if (foundModcod <= STV0900_8PSK_910) { - stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P1_ACLC2S28, aclc); - } - - if ((i_params->demod_mode == STV0900_SINGLE) && (foundModcod > STV0900_8PSK_910)) { - if (foundModcod <= STV0900_16APSK_910) { - stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P1_ACLC2S216A, aclc); - } else if (foundModcod <= STV0900_32APSK_910) { - stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P1_ACLC2S232A, aclc); - } - } - - } else { - aclc = stv0900_get_optim_short_carr_loop(srate, i_params->dmd1_rslts.modulation, i_params->chip_id); - if (i_params->dmd1_rslts.modulation == STV0900_QPSK) - stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, aclc); - - else if (i_params->dmd1_rslts.modulation == STV0900_8PSK) { - stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P1_ACLC2S28, aclc); - } else if (i_params->dmd1_rslts.modulation == STV0900_16APSK) { - stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P1_ACLC2S216A, aclc); - } else if (i_params->dmd1_rslts.modulation == STV0900_32APSK) { - stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P1_ACLC2S232A, aclc); - } - - } - - if (i_params->chip_id <= 0x11) { - if (i_params->demod_mode != STV0900_SINGLE) - stv0900_activate_s2_modcode(i_params, demod); - - } - - stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x67); - break; - case STV0900_UNKNOWN_STANDARD: - default: - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); - break; - } - - freq1 = stv0900_read_reg(i_params, R0900_P1_CFR2); - freq0 = stv0900_read_reg(i_params, R0900_P1_CFR1); - rolloff = stv0900_get_bits(i_params, F0900_P1_ROLLOFF_STATUS); - if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) { - stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x00); - stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); - stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01); - stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod); - stv0900_set_max_symbol_rate(i_params, i_params->mclk, srate, demod); - stv0900_set_min_symbol_rate(i_params, i_params->mclk, srate, demod); - blindTunSw = 1; - } - - if (i_params->chip_id >= 0x20) { - if ((i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS1) || (i_params->dmd1_srch_standard == STV0900_SEARCH_DSS) || (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH)) { - stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0a); - stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x0); - } - } - - if (i_params->chip_id < 0x20) - stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x08); - - if (i_params->chip_id == 0x10) - stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0x0A); - - stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38); - - if ((i_params->chip_id >= 0x20) || (blindTunSw == 1) || (i_params->dmd1_symbol_rate < 10000000)) { - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); - i_params->tuner1_bw = stv0900_carrier_width(srate, i_params->rolloff) + 10000000; - - if ((i_params->chip_id >= 0x20) || (blindTunSw == 1)) { - if (i_params->dmd1_srch_algo != STV0900_WARM_START) - stv0900_set_bandwidth(fe, i_params->tuner1_bw); - } - - if ((i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd1_symbol_rate < 10000000)) - msleep(50); - else - msleep(5); - - stv0900_get_lock_timeout(&timed, &timef, srate, STV0900_WARM_START); - - if (stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) { - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F); - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); - i = 0; - while ((stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) && (i <= 2)) { - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F); - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); - i++; - } - } - - } - - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x49); - - if ((i_params->dmd1_rslts.standard == STV0900_DVBS1_STANDARD) || (i_params->dmd1_rslts.standard == STV0900_DSS_STANDARD)) - stv0900_set_viterbi_tracq(i_params, demod); - - break; - - case STV0900_DEMOD_2: - switch (i_params->dmd2_rslts.standard) { - case STV0900_DVBS1_STANDARD: - - if (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH) { - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); - } - - stv0900_write_bits(i_params, F0900_P2_ROLLOFF_CONTROL, i_params->rolloff); - stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1); - stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75); - break; - case STV0900_DSS_STANDARD: - if (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH) { - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); - } - - stv0900_write_bits(i_params, F0900_P2_ROLLOFF_CONTROL, i_params->rolloff); - stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1); - stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75); - break; - case STV0900_DVBS2_STANDARD: - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); - stv0900_write_reg(i_params, R0900_P2_ACLC, 0); - stv0900_write_reg(i_params, R0900_P2_BCLC, 0); - if (i_params->dmd2_rslts.frame_length == STV0900_LONG_FRAME) { - foundModcod = stv0900_get_bits(i_params, F0900_P2_DEMOD_MODCOD); - pilots = stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE) & 0x01; - aclc = stv0900_get_optim_carr_loop(srate, foundModcod, pilots, i_params->chip_id); - if (foundModcod <= STV0900_QPSK_910) - stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, aclc); - else if (foundModcod <= STV0900_8PSK_910) { - stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P2_ACLC2S28, aclc); - } - - if ((i_params->demod_mode == STV0900_SINGLE) && (foundModcod > STV0900_8PSK_910)) { - if (foundModcod <= STV0900_16APSK_910) { - stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P2_ACLC2S216A, aclc); - } else if (foundModcod <= STV0900_32APSK_910) { - stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P2_ACLC2S232A, aclc); - } - - } - - } else { - aclc = stv0900_get_optim_short_carr_loop(srate, - i_params->dmd2_rslts.modulation, - i_params->chip_id); - - if (i_params->dmd2_rslts.modulation == STV0900_QPSK) - stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, aclc); - - else if (i_params->dmd2_rslts.modulation == STV0900_8PSK) { - stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P2_ACLC2S28, aclc); - } else if (i_params->dmd2_rslts.modulation == STV0900_16APSK) { - stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P2_ACLC2S216A, aclc); - } else if (i_params->dmd2_rslts.modulation == STV0900_32APSK) { - stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a); - stv0900_write_reg(i_params, R0900_P2_ACLC2S232A, aclc); - } - } - - stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x67); - - break; - case STV0900_UNKNOWN_STANDARD: - default: - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); - break; - } - - freq1 = stv0900_read_reg(i_params, R0900_P2_CFR2); - freq0 = stv0900_read_reg(i_params, R0900_P2_CFR1); - rolloff = stv0900_get_bits(i_params, F0900_P2_ROLLOFF_STATUS); - if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) { - stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x00); - stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); - stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01); - stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod); - stv0900_set_max_symbol_rate(i_params, i_params->mclk, srate, demod); - stv0900_set_min_symbol_rate(i_params, i_params->mclk, srate, demod); - blindTunSw = 1; - } - - if (i_params->chip_id >= 0x20) { - if ((i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS1) || (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DSS) || (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH)) { - stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0a); - stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x0); - } - } - - if (i_params->chip_id < 0x20) - stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x08); - - if (i_params->chip_id == 0x10) - stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0x0a); - - stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38); - if ((i_params->chip_id >= 0x20) || (blindTunSw == 1) || (i_params->dmd2_symbol_rate < 10000000)) { - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); - i_params->tuner2_bw = stv0900_carrier_width(srate, i_params->rolloff) + 10000000; - - if ((i_params->chip_id >= 0x20) || (blindTunSw == 1)) { - if (i_params->dmd2_srch_algo != STV0900_WARM_START) - stv0900_set_bandwidth(fe, i_params->tuner2_bw); - } - - if ((i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd2_symbol_rate < 10000000)) - msleep(50); - else - msleep(5); - - stv0900_get_lock_timeout(&timed, &timef, srate, STV0900_WARM_START); - if (stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) { - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F); - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); - i = 0; - while ((stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) && (i <= 2)) { - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F); - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); - i++; - } - } - } - - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x49); - - if ((i_params->dmd2_rslts.standard == STV0900_DVBS1_STANDARD) || (i_params->dmd2_rslts.standard == STV0900_DSS_STANDARD)) - stv0900_set_viterbi_tracq(i_params, demod); - - break; - } -} - -static int stv0900_get_fec_lock(struct stv0900_internal *i_params, enum fe_stv0900_demod_num demod, s32 time_out) -{ - s32 timer = 0, lock = 0, header_field, pktdelin_field, lock_vit_field; - - enum fe_stv0900_search_state dmd_state; - - dprintk("%s\n", __func__); - - dmd_reg(header_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); - dmd_reg(pktdelin_field, F0900_P1_PKTDELIN_LOCK, F0900_P2_PKTDELIN_LOCK); - dmd_reg(lock_vit_field, F0900_P1_LOCKEDVIT, F0900_P2_LOCKEDVIT); - - dmd_state = stv0900_get_bits(i_params, header_field); - - while ((timer < time_out) && (lock == 0)) { - switch (dmd_state) { - case STV0900_SEARCH: - case STV0900_PLH_DETECTED: - default: - lock = 0; - break; - case STV0900_DVBS2_FOUND: - lock = stv0900_get_bits(i_params, pktdelin_field); - break; - case STV0900_DVBS_FOUND: - lock = stv0900_get_bits(i_params, lock_vit_field); - break; - } - - if (lock == 0) { - msleep(10); - timer += 10; - } - } - - if (lock) - dprintk("DEMOD FEC LOCK OK\n"); - else - dprintk("DEMOD FEC LOCK FAIL\n"); - - return lock; -} - -static int stv0900_wait_for_lock(struct stv0900_internal *i_params, - enum fe_stv0900_demod_num demod, - s32 dmd_timeout, s32 fec_timeout) -{ - - s32 timer = 0, lock = 0, str_merg_rst_fld, str_merg_lock_fld; - - dprintk("%s\n", __func__); - - dmd_reg(str_merg_rst_fld, F0900_P1_RST_HWARE, F0900_P2_RST_HWARE); - dmd_reg(str_merg_lock_fld, F0900_P1_TSFIFO_LINEOK, F0900_P2_TSFIFO_LINEOK); - - lock = stv0900_get_demod_lock(i_params, demod, dmd_timeout); - - if (lock) - lock = lock && stv0900_get_fec_lock(i_params, demod, fec_timeout); - - if (lock) { - lock = 0; - - dprintk("%s: Timer = %d, time_out = %d\n", __func__, timer, - fec_timeout); - - while ((timer < fec_timeout) && (lock == 0)) { - lock = stv0900_get_bits(i_params, str_merg_lock_fld); - msleep(1); - timer++; - } - } - - if (lock) - dprintk("%s: DEMOD LOCK OK\n", __func__); - else - dprintk("%s: DEMOD LOCK FAIL\n", __func__); - - if (lock) - return TRUE; - else - return FALSE; -} - -enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, +static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { - struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; - enum fe_stv0900_tracking_standard fnd_standard; - s32 state_field, - dss_dvb_field; - - dprintk("%s\n", __func__); - - dmd_reg(state_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE); - dmd_reg(dss_dvb_field, F0900_P1_DSS_DVB, F0900_P2_DSS_DVB); - - if (stv0900_get_bits(i_params, state_field) == 2) - fnd_standard = STV0900_DVBS2_STANDARD; - - else if (stv0900_get_bits(i_params, state_field) == 3) { - if (stv0900_get_bits(i_params, dss_dvb_field) == 1) - fnd_standard = STV0900_DSS_STANDARD; - else - fnd_standard = STV0900_DVBS1_STANDARD; - } else - fnd_standard = STV0900_UNKNOWN_STANDARD; - - return fnd_standard; -} - -static s32 stv0900_get_carr_freq(struct stv0900_internal *i_params, u32 mclk, - enum fe_stv0900_demod_num demod) -{ - s32 cfr_field2, cfr_field1, cfr_field0, - derot, rem1, rem2, intval1, intval2; - - dmd_reg(cfr_field2, F0900_P1_CAR_FREQ2, F0900_P2_CAR_FREQ2); - dmd_reg(cfr_field1, F0900_P1_CAR_FREQ1, F0900_P2_CAR_FREQ1); - dmd_reg(cfr_field0, F0900_P1_CAR_FREQ0, F0900_P2_CAR_FREQ0); - - derot = (stv0900_get_bits(i_params, cfr_field2) << 16) + - (stv0900_get_bits(i_params, cfr_field1) << 8) + - (stv0900_get_bits(i_params, cfr_field0)); - - derot = ge2comp(derot, 24); - intval1 = mclk >> 12; - intval2 = derot >> 12; - rem1 = mclk % 0x1000; - rem2 = derot % 0x1000; - derot = (intval1 * intval2) + - ((intval1 * rem2) >> 12) + - ((intval2 * rem1) >> 12); - - return derot; -} - -static u32 stv0900_get_tuner_freq(struct dvb_frontend *fe) -{ - struct dvb_frontend_ops *frontend_ops = NULL; - struct dvb_tuner_ops *tuner_ops = NULL; - u32 frequency = 0; - - if (&fe->ops) - frontend_ops = &fe->ops; - - if (&frontend_ops->tuner_ops) - tuner_ops = &frontend_ops->tuner_ops; - - if (tuner_ops->get_frequency) { - if ((tuner_ops->get_frequency(fe, &frequency)) < 0) - dprintk("%s: Invalid parameter\n", __func__); - else - dprintk("%s: Frequency=%d\n", __func__, frequency); - - } - - return frequency; -} - -static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *i_params, - enum fe_stv0900_demod_num demod) -{ - s32 rate_fld, vit_curpun_fld; enum fe_stv0900_fec prate; - - dmd_reg(vit_curpun_fld, F0900_P1_VIT_CURPUN, F0900_P2_VIT_CURPUN); - rate_fld = stv0900_get_bits(i_params, vit_curpun_fld); + s32 rate_fld = stv0900_get_bits(intp, VIT_CURPUN); switch (rate_fld) { case 13: @@ -1561,258 +790,532 @@ static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *i_params return prate; } -static enum fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) +void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp, + enum fe_stv0900_demod_num demod, + u32 srate) +{ + if (intp->chip_id >= 0x30) { + if (srate >= 15000000) { + stv0900_write_reg(intp, ACLC, 0x2b); + stv0900_write_reg(intp, BCLC, 0x1a); + } else if ((srate >= 7000000) && (15000000 > srate)) { + stv0900_write_reg(intp, ACLC, 0x0c); + stv0900_write_reg(intp, BCLC, 0x1b); + } else if (srate < 7000000) { + stv0900_write_reg(intp, ACLC, 0x2c); + stv0900_write_reg(intp, BCLC, 0x1c); + } + + } else { /*cut 2.0 and 1.x*/ + stv0900_write_reg(intp, ACLC, 0x1a); + stv0900_write_reg(intp, BCLC, 0x09); + } + +} + +static void stv0900_track_optimization(struct dvb_frontend *fe) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + + s32 srate, + pilots, + aclc, + freq1, + freq0, + i = 0, + timed, + timef, + blind_tun_sw = 0, + modulation; + + enum fe_stv0900_rolloff rolloff; + enum fe_stv0900_modcode foundModcod; + + dprintk("%s\n", __func__); + + srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); + srate += stv0900_get_timing_offst(intp, srate, demod); + + switch (intp->result[demod].standard) { + case STV0900_DVBS1_STANDARD: + case STV0900_DSS_STANDARD: + dprintk("%s: found DVB-S or DSS\n", __func__); + if (intp->srch_standard[demod] == STV0900_AUTO_SEARCH) { + stv0900_write_bits(intp, DVBS1_ENABLE, 1); + stv0900_write_bits(intp, DVBS2_ENABLE, 0); + } + + stv0900_write_bits(intp, ROLLOFF_CONTROL, intp->rolloff); + stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1); + + if (intp->chip_id < 0x30) { + stv0900_write_reg(intp, ERRCTRL1, 0x75); + break; + } + + if (stv0900_get_vit_fec(intp, demod) == STV0900_FEC_1_2) { + stv0900_write_reg(intp, GAUSSR0, 0x98); + stv0900_write_reg(intp, CCIR0, 0x18); + } else { + stv0900_write_reg(intp, GAUSSR0, 0x18); + stv0900_write_reg(intp, CCIR0, 0x18); + } + + stv0900_write_reg(intp, ERRCTRL1, 0x75); + break; + case STV0900_DVBS2_STANDARD: + dprintk("%s: found DVB-S2\n", __func__); + stv0900_write_bits(intp, DVBS1_ENABLE, 0); + stv0900_write_bits(intp, DVBS2_ENABLE, 1); + stv0900_write_reg(intp, ACLC, 0); + stv0900_write_reg(intp, BCLC, 0); + if (intp->result[demod].frame_len == STV0900_LONG_FRAME) { + foundModcod = stv0900_get_bits(intp, DEMOD_MODCOD); + pilots = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01; + aclc = stv0900_get_optim_carr_loop(srate, + foundModcod, + pilots, + intp->chip_id); + if (foundModcod <= STV0900_QPSK_910) + stv0900_write_reg(intp, ACLC2S2Q, aclc); + else if (foundModcod <= STV0900_8PSK_910) { + stv0900_write_reg(intp, ACLC2S2Q, 0x2a); + stv0900_write_reg(intp, ACLC2S28, aclc); + } + + if ((intp->demod_mode == STV0900_SINGLE) && + (foundModcod > STV0900_8PSK_910)) { + if (foundModcod <= STV0900_16APSK_910) { + stv0900_write_reg(intp, ACLC2S2Q, 0x2a); + stv0900_write_reg(intp, ACLC2S216A, + aclc); + } else if (foundModcod <= STV0900_32APSK_910) { + stv0900_write_reg(intp, ACLC2S2Q, 0x2a); + stv0900_write_reg(intp, ACLC2S232A, + aclc); + } + } + + } else { + modulation = intp->result[demod].modulation; + aclc = stv0900_get_optim_short_carr_loop(srate, + modulation, intp->chip_id); + if (modulation == STV0900_QPSK) + stv0900_write_reg(intp, ACLC2S2Q, aclc); + else if (modulation == STV0900_8PSK) { + stv0900_write_reg(intp, ACLC2S2Q, 0x2a); + stv0900_write_reg(intp, ACLC2S28, aclc); + } else if (modulation == STV0900_16APSK) { + stv0900_write_reg(intp, ACLC2S2Q, 0x2a); + stv0900_write_reg(intp, ACLC2S216A, aclc); + } else if (modulation == STV0900_32APSK) { + stv0900_write_reg(intp, ACLC2S2Q, 0x2a); + stv0900_write_reg(intp, ACLC2S232A, aclc); + } + + } + + if (intp->chip_id <= 0x11) { + if (intp->demod_mode != STV0900_SINGLE) + stv0900_activate_s2_modcod(intp, demod); + + } + + stv0900_write_reg(intp, ERRCTRL1, 0x67); + break; + case STV0900_UNKNOWN_STANDARD: + default: + dprintk("%s: found unknown standard\n", __func__); + stv0900_write_bits(intp, DVBS1_ENABLE, 1); + stv0900_write_bits(intp, DVBS2_ENABLE, 1); + break; + } + + freq1 = stv0900_read_reg(intp, CFR2); + freq0 = stv0900_read_reg(intp, CFR1); + rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS); + if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) { + stv0900_write_reg(intp, SFRSTEP, 0x00); + stv0900_write_bits(intp, SCAN_ENABLE, 0); + stv0900_write_bits(intp, CFR_AUTOSCAN, 0); + stv0900_write_reg(intp, TMGCFG2, 0xc1); + stv0900_set_symbol_rate(intp, intp->mclk, srate, demod); + blind_tun_sw = 1; + if (intp->result[demod].standard != STV0900_DVBS2_STANDARD) + stv0900_set_dvbs1_track_car_loop(intp, demod, srate); + + } + + if (intp->chip_id >= 0x20) { + if ((intp->srch_standard[demod] == STV0900_SEARCH_DVBS1) || + (intp->srch_standard[demod] == + STV0900_SEARCH_DSS) || + (intp->srch_standard[demod] == + STV0900_AUTO_SEARCH)) { + stv0900_write_reg(intp, VAVSRVIT, 0x0a); + stv0900_write_reg(intp, VITSCALE, 0x0); + } + } + + if (intp->chip_id < 0x20) + stv0900_write_reg(intp, CARHDR, 0x08); + + if (intp->chip_id == 0x10) + stv0900_write_reg(intp, CORRELEXP, 0x0a); + + stv0900_write_reg(intp, AGC2REF, 0x38); + + if ((intp->chip_id >= 0x20) || + (blind_tun_sw == 1) || + (intp->symbol_rate[demod] < 10000000)) { + stv0900_write_reg(intp, CFRINIT1, freq1); + stv0900_write_reg(intp, CFRINIT0, freq0); + intp->bw[demod] = stv0900_carrier_width(srate, + intp->rolloff) + 10000000; + + if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) { + if (intp->srch_algo[demod] != STV0900_WARM_START) + stv0900_set_bandwidth(fe, intp->bw[demod]); + } + + if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) || + (intp->symbol_rate[demod] < 10000000)) + msleep(50); + else + msleep(5); + + stv0900_get_lock_timeout(&timed, &timef, srate, + STV0900_WARM_START); + + if (stv0900_get_demod_lock(intp, demod, timed / 2) == FALSE) { + stv0900_write_reg(intp, DMDISTATE, 0x1f); + stv0900_write_reg(intp, CFRINIT1, freq1); + stv0900_write_reg(intp, CFRINIT0, freq0); + stv0900_write_reg(intp, DMDISTATE, 0x18); + i = 0; + while ((stv0900_get_demod_lock(intp, + demod, + timed / 2) == FALSE) && + (i <= 2)) { + stv0900_write_reg(intp, DMDISTATE, 0x1f); + stv0900_write_reg(intp, CFRINIT1, freq1); + stv0900_write_reg(intp, CFRINIT0, freq0); + stv0900_write_reg(intp, DMDISTATE, 0x18); + i++; + } + } + + } + + if (intp->chip_id >= 0x20) + stv0900_write_reg(intp, CARFREQ, 0x49); + + if ((intp->result[demod].standard == STV0900_DVBS1_STANDARD) || + (intp->result[demod].standard == STV0900_DSS_STANDARD)) + stv0900_set_viterbi_tracq(intp, demod); + +} + +static int stv0900_get_fec_lock(struct stv0900_internal *intp, + enum fe_stv0900_demod_num demod, s32 time_out) +{ + s32 timer = 0, lock = 0; + + enum fe_stv0900_search_state dmd_state; + + dprintk("%s\n", __func__); + + dmd_state = stv0900_get_bits(intp, HEADER_MODE); + + while ((timer < time_out) && (lock == 0)) { + switch (dmd_state) { + case STV0900_SEARCH: + case STV0900_PLH_DETECTED: + default: + lock = 0; + break; + case STV0900_DVBS2_FOUND: + lock = stv0900_get_bits(intp, PKTDELIN_LOCK); + break; + case STV0900_DVBS_FOUND: + lock = stv0900_get_bits(intp, LOCKEDVIT); + break; + } + + if (lock == 0) { + msleep(10); + timer += 10; + } + } + + if (lock) + dprintk("%s: DEMOD FEC LOCK OK\n", __func__); + else + dprintk("%s: DEMOD FEC LOCK FAIL\n", __func__); + + return lock; +} + +static int stv0900_wait_for_lock(struct stv0900_internal *intp, + enum fe_stv0900_demod_num demod, + s32 dmd_timeout, s32 fec_timeout) +{ + + s32 timer = 0, lock = 0; + + dprintk("%s\n", __func__); + + lock = stv0900_get_demod_lock(intp, demod, dmd_timeout); + + if (lock) + lock = lock && stv0900_get_fec_lock(intp, demod, fec_timeout); + + if (lock) { + lock = 0; + + dprintk("%s: Timer = %d, time_out = %d\n", + __func__, timer, fec_timeout); + + while ((timer < fec_timeout) && (lock == 0)) { + lock = stv0900_get_bits(intp, TSFIFO_LINEOK); + msleep(1); + timer++; + } + } + + if (lock) + dprintk("%s: DEMOD LOCK OK\n", __func__); + else + dprintk("%s: DEMOD LOCK FAIL\n", __func__); + + if (lock) + return TRUE; + else + return FALSE; +} + +enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, + enum fe_stv0900_demod_num demod) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *intp = state->internal; + enum fe_stv0900_tracking_standard fnd_standard; + + int hdr_mode = stv0900_get_bits(intp, HEADER_MODE); + + switch (hdr_mode) { + case 2: + fnd_standard = STV0900_DVBS2_STANDARD; + break; + case 3: + if (stv0900_get_bits(intp, DSS_DVB) == 1) + fnd_standard = STV0900_DSS_STANDARD; + else + fnd_standard = STV0900_DVBS1_STANDARD; + + break; + default: + fnd_standard = STV0900_UNKNOWN_STANDARD; + } + + dprintk("%s: standard %d\n", __func__, fnd_standard); + + return fnd_standard; +} + +static s32 stv0900_get_carr_freq(struct stv0900_internal *intp, u32 mclk, + enum fe_stv0900_demod_num demod) +{ + s32 derot, + rem1, + rem2, + intval1, + intval2; + + derot = (stv0900_get_bits(intp, CAR_FREQ2) << 16) + + (stv0900_get_bits(intp, CAR_FREQ1) << 8) + + (stv0900_get_bits(intp, CAR_FREQ0)); + + derot = ge2comp(derot, 24); + intval1 = mclk >> 12; + intval2 = derot >> 12; + rem1 = mclk % 0x1000; + rem2 = derot % 0x1000; + derot = (intval1 * intval2) + + ((intval1 * rem2) >> 12) + + ((intval2 * rem1) >> 12); + + return derot; +} + +static u32 stv0900_get_tuner_freq(struct dvb_frontend *fe) +{ + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + u32 freq = 0; + + if (&fe->ops) + frontend_ops = &fe->ops; + + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + + if (tuner_ops->get_frequency) { + if ((tuner_ops->get_frequency(fe, &freq)) < 0) + dprintk("%s: Invalid parameter\n", __func__); + else + dprintk("%s: Frequency=%d\n", __func__, freq); + + } + + return freq; +} + +static enum +fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; enum fe_stv0900_signal_type range = STV0900_OUTOFRANGE; - s32 offsetFreq, - srate_offset, - i = 0; + struct stv0900_signal_info *result = &intp->result[demod]; + s32 offsetFreq, + srate_offset; + int i = 0, + d = demod; u8 timing; msleep(5); - switch (demod) { - case STV0900_DEMOD_1: - default: - if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) { - timing = stv0900_read_reg(i_params, R0900_P1_TMGREG2); - i = 0; - stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x5c); + if (intp->srch_algo[d] == STV0900_BLIND_SEARCH) { + timing = stv0900_read_reg(intp, TMGREG2); + i = 0; + stv0900_write_reg(intp, SFRSTEP, 0x5c); - while ((i <= 50) && (timing != 0) && (timing != 0xFF)) { - timing = stv0900_read_reg(i_params, R0900_P1_TMGREG2); - msleep(5); - i += 5; - } + while ((i <= 50) && (timing != 0) && (timing != 0xff)) { + timing = stv0900_read_reg(intp, TMGREG2); + msleep(5); + i += 5; } + } - i_params->dmd1_rslts.standard = stv0900_get_standard(fe, demod); - i_params->dmd1_rslts.frequency = stv0900_get_tuner_freq(fe); - offsetFreq = stv0900_get_carr_freq(i_params, i_params->mclk, demod) / 1000; - i_params->dmd1_rslts.frequency += offsetFreq; - i_params->dmd1_rslts.symbol_rate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - srate_offset = stv0900_get_timing_offst(i_params, i_params->dmd1_rslts.symbol_rate, demod); - i_params->dmd1_rslts.symbol_rate += srate_offset; - i_params->dmd1_rslts.fec = stv0900_get_vit_fec(i_params, demod); - i_params->dmd1_rslts.modcode = stv0900_get_bits(i_params, F0900_P1_DEMOD_MODCOD); - i_params->dmd1_rslts.pilot = stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE) & 0x01; - i_params->dmd1_rslts.frame_length = ((u32)stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE)) >> 1; - i_params->dmd1_rslts.rolloff = stv0900_get_bits(i_params, F0900_P1_ROLLOFF_STATUS); - switch (i_params->dmd1_rslts.standard) { - case STV0900_DVBS2_STANDARD: - i_params->dmd1_rslts.spectrum = stv0900_get_bits(i_params, F0900_P1_SPECINV_DEMOD); - if (i_params->dmd1_rslts.modcode <= STV0900_QPSK_910) - i_params->dmd1_rslts.modulation = STV0900_QPSK; - else if (i_params->dmd1_rslts.modcode <= STV0900_8PSK_910) - i_params->dmd1_rslts.modulation = STV0900_8PSK; - else if (i_params->dmd1_rslts.modcode <= STV0900_16APSK_910) - i_params->dmd1_rslts.modulation = STV0900_16APSK; - else if (i_params->dmd1_rslts.modcode <= STV0900_32APSK_910) - i_params->dmd1_rslts.modulation = STV0900_32APSK; - else - i_params->dmd1_rslts.modulation = STV0900_UNKNOWN; - break; - case STV0900_DVBS1_STANDARD: - case STV0900_DSS_STANDARD: - i_params->dmd1_rslts.spectrum = stv0900_get_bits(i_params, F0900_P1_IQINV); - i_params->dmd1_rslts.modulation = STV0900_QPSK; - break; - default: - break; - } - - if ((i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd1_symbol_rate < 10000000)) { - offsetFreq = i_params->dmd1_rslts.frequency - i_params->tuner1_freq; - i_params->tuner1_freq = stv0900_get_tuner_freq(fe); - if (ABS(offsetFreq) <= ((i_params->dmd1_srch_range / 2000) + 500)) - range = STV0900_RANGEOK; - else - if (ABS(offsetFreq) <= (stv0900_carrier_width(i_params->dmd1_rslts.symbol_rate, i_params->dmd1_rslts.rolloff) / 2000)) - range = STV0900_RANGEOK; - else - range = STV0900_OUTOFRANGE; - - } else { - if (ABS(offsetFreq) <= ((i_params->dmd1_srch_range / 2000) + 500)) - range = STV0900_RANGEOK; - else - range = STV0900_OUTOFRANGE; - } + result->standard = stv0900_get_standard(fe, d); + result->frequency = stv0900_get_tuner_freq(fe); + offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000; + result->frequency += offsetFreq; + result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d); + srate_offset = stv0900_get_timing_offst(intp, result->symbol_rate, d); + result->symbol_rate += srate_offset; + result->fec = stv0900_get_vit_fec(intp, d); + result->modcode = stv0900_get_bits(intp, DEMOD_MODCOD); + result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01; + result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1; + result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS); + switch (result->standard) { + case STV0900_DVBS2_STANDARD: + result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD); + if (result->modcode <= STV0900_QPSK_910) + result->modulation = STV0900_QPSK; + else if (result->modcode <= STV0900_8PSK_910) + result->modulation = STV0900_8PSK; + else if (result->modcode <= STV0900_16APSK_910) + result->modulation = STV0900_16APSK; + else if (result->modcode <= STV0900_32APSK_910) + result->modulation = STV0900_32APSK; + else + result->modulation = STV0900_UNKNOWN; break; - case STV0900_DEMOD_2: - if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) { - timing = stv0900_read_reg(i_params, R0900_P2_TMGREG2); - i = 0; - stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x5c); - - while ((i <= 50) && (timing != 0) && (timing != 0xff)) { - timing = stv0900_read_reg(i_params, R0900_P2_TMGREG2); - msleep(5); - i += 5; - } - } - - i_params->dmd2_rslts.standard = stv0900_get_standard(fe, demod); - i_params->dmd2_rslts.frequency = stv0900_get_tuner_freq(fe); - offsetFreq = stv0900_get_carr_freq(i_params, i_params->mclk, demod) / 1000; - i_params->dmd2_rslts.frequency += offsetFreq; - i_params->dmd2_rslts.symbol_rate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - srate_offset = stv0900_get_timing_offst(i_params, i_params->dmd2_rslts.symbol_rate, demod); - i_params->dmd2_rslts.symbol_rate += srate_offset; - i_params->dmd2_rslts.fec = stv0900_get_vit_fec(i_params, demod); - i_params->dmd2_rslts.modcode = stv0900_get_bits(i_params, F0900_P2_DEMOD_MODCOD); - i_params->dmd2_rslts.pilot = stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE) & 0x01; - i_params->dmd2_rslts.frame_length = ((u32)stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE)) >> 1; - i_params->dmd2_rslts.rolloff = stv0900_get_bits(i_params, F0900_P2_ROLLOFF_STATUS); - switch (i_params->dmd2_rslts.standard) { - case STV0900_DVBS2_STANDARD: - i_params->dmd2_rslts.spectrum = stv0900_get_bits(i_params, F0900_P2_SPECINV_DEMOD); - if (i_params->dmd2_rslts.modcode <= STV0900_QPSK_910) - i_params->dmd2_rslts.modulation = STV0900_QPSK; - else if (i_params->dmd2_rslts.modcode <= STV0900_8PSK_910) - i_params->dmd2_rslts.modulation = STV0900_8PSK; - else if (i_params->dmd2_rslts.modcode <= STV0900_16APSK_910) - i_params->dmd2_rslts.modulation = STV0900_16APSK; - else if (i_params->dmd2_rslts.modcode <= STV0900_32APSK_910) - i_params->dmd2_rslts.modulation = STV0900_32APSK; - else - i_params->dmd2_rslts.modulation = STV0900_UNKNOWN; - break; - case STV0900_DVBS1_STANDARD: - case STV0900_DSS_STANDARD: - i_params->dmd2_rslts.spectrum = stv0900_get_bits(i_params, F0900_P2_IQINV); - i_params->dmd2_rslts.modulation = STV0900_QPSK; - break; - default: - break; - } - - if ((i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd2_symbol_rate < 10000000)) { - offsetFreq = i_params->dmd2_rslts.frequency - i_params->tuner2_freq; - i_params->tuner2_freq = stv0900_get_tuner_freq(fe); - - if (ABS(offsetFreq) <= ((i_params->dmd2_srch_range / 2000) + 500)) - range = STV0900_RANGEOK; - else - if (ABS(offsetFreq) <= (stv0900_carrier_width(i_params->dmd2_rslts.symbol_rate, i_params->dmd2_rslts.rolloff) / 2000)) - range = STV0900_RANGEOK; - else - range = STV0900_OUTOFRANGE; - } else { - if (ABS(offsetFreq) <= ((i_params->dmd2_srch_range / 2000) + 500)) - range = STV0900_RANGEOK; - else - range = STV0900_OUTOFRANGE; - } - + case STV0900_DVBS1_STANDARD: + case STV0900_DSS_STANDARD: + result->spectrum = stv0900_get_bits(intp, IQINV); + result->modulation = STV0900_QPSK; + break; + default: break; } + if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) || + (intp->symbol_rate[d] < 10000000)) { + offsetFreq = result->frequency - intp->freq[d]; + intp->freq[d] = stv0900_get_tuner_freq(fe); + if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500)) + range = STV0900_RANGEOK; + else if (ABS(offsetFreq) <= + (stv0900_carrier_width(result->symbol_rate, + result->rolloff) / 2000)) + range = STV0900_RANGEOK; + + } else if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500)) + range = STV0900_RANGEOK; + + dprintk("%s: range %d\n", __func__, range); + return range; } -static enum fe_stv0900_signal_type stv0900_dvbs1_acq_workaround(struct dvb_frontend *fe) +static enum +fe_stv0900_signal_type stv0900_dvbs1_acq_workaround(struct dvb_frontend *fe) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - - s32 srate, demod_timeout, - fec_timeout, freq1, freq0; enum fe_stv0900_signal_type signal_type = STV0900_NODATA; - switch (demod) { - case STV0900_DEMOD_1: - default: - i_params->dmd1_rslts.locked = FALSE; - if (stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS_FOUND) { - srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - srate += stv0900_get_timing_offst(i_params, srate, demod); - if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) - stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod); + s32 srate, + demod_timeout, + fec_timeout, + freq1, + freq0; - stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, srate, STV0900_WARM_START); - freq1 = stv0900_read_reg(i_params, R0900_P1_CFR2); - freq0 = stv0900_read_reg(i_params, R0900_P1_CFR1); - stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); - stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, STV0900_IQ_FORCE_SWAPPED); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C); - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); - if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) { - i_params->dmd1_rslts.locked = TRUE; + intp->result[demod].locked = FALSE; + + if (stv0900_get_bits(intp, HEADER_MODE) == STV0900_DVBS_FOUND) { + srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); + srate += stv0900_get_timing_offst(intp, srate, demod); + if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) + stv0900_set_symbol_rate(intp, intp->mclk, srate, demod); + + stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, + srate, STV0900_WARM_START); + freq1 = stv0900_read_reg(intp, CFR2); + freq0 = stv0900_read_reg(intp, CFR1); + stv0900_write_bits(intp, CFR_AUTOSCAN, 0); + stv0900_write_bits(intp, SPECINV_CONTROL, + STV0900_IQ_FORCE_SWAPPED); + stv0900_write_reg(intp, DMDISTATE, 0x1c); + stv0900_write_reg(intp, CFRINIT1, freq1); + stv0900_write_reg(intp, CFRINIT0, freq0); + stv0900_write_reg(intp, DMDISTATE, 0x18); + if (stv0900_wait_for_lock(intp, demod, + demod_timeout, fec_timeout) == TRUE) { + intp->result[demod].locked = TRUE; + signal_type = stv0900_get_signal_params(fe); + stv0900_track_optimization(fe); + } else { + stv0900_write_bits(intp, SPECINV_CONTROL, + STV0900_IQ_FORCE_NORMAL); + stv0900_write_reg(intp, DMDISTATE, 0x1c); + stv0900_write_reg(intp, CFRINIT1, freq1); + stv0900_write_reg(intp, CFRINIT0, freq0); + stv0900_write_reg(intp, DMDISTATE, 0x18); + if (stv0900_wait_for_lock(intp, demod, + demod_timeout, fec_timeout) == TRUE) { + intp->result[demod].locked = TRUE; signal_type = stv0900_get_signal_params(fe); stv0900_track_optimization(fe); - } else { - stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, STV0900_IQ_FORCE_NORMAL); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1c); - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18); - if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) { - i_params->dmd1_rslts.locked = TRUE; - signal_type = stv0900_get_signal_params(fe); - stv0900_track_optimization(fe); - } - } - } else - i_params->dmd1_rslts.locked = FALSE; + } - break; - case STV0900_DEMOD_2: - i_params->dmd2_rslts.locked = FALSE; - if (stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS_FOUND) { - srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - srate += stv0900_get_timing_offst(i_params, srate, demod); - - if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) - stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod); - - stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, srate, STV0900_WARM_START); - freq1 = stv0900_read_reg(i_params, R0900_P2_CFR2); - freq0 = stv0900_read_reg(i_params, R0900_P2_CFR1); - stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); - stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, STV0900_IQ_FORCE_SWAPPED); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C); - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); - - if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) { - i_params->dmd2_rslts.locked = TRUE; - signal_type = stv0900_get_signal_params(fe); - stv0900_track_optimization(fe); - } else { - stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, STV0900_IQ_FORCE_NORMAL); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1c); - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18); - - if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) { - i_params->dmd2_rslts.locked = TRUE; - signal_type = stv0900_get_signal_params(fe); - stv0900_track_optimization(fe); - } - - } - - } else - i_params->dmd1_rslts.locked = FALSE; - - break; - } + } else + intp->result[demod].locked = FALSE; return signal_type; } -static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *i_params, +static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { u32 minagc2level = 0xffff, @@ -1823,103 +1326,52 @@ static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *i_params, dprintk("%s\n", __func__); - switch (demod) { - case STV0900_DEMOD_1: - default: - stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38); - stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 1); + stv0900_write_reg(intp, AGC2REF, 0x38); + stv0900_write_bits(intp, SCAN_ENABLE, 0); + stv0900_write_bits(intp, CFR_AUTOSCAN, 0); - stv0900_write_reg(i_params, R0900_P1_SFRUP1, 0x83); - stv0900_write_reg(i_params, R0900_P1_SFRUP0, 0xc0); + stv0900_write_bits(intp, AUTO_GUP, 1); + stv0900_write_bits(intp, AUTO_GLOW, 1); - stv0900_write_reg(i_params, R0900_P1_SFRLOW1, 0x82); - stv0900_write_reg(i_params, R0900_P1_SFRLOW0, 0xa0); - stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x0); + stv0900_write_reg(intp, DMDT0M, 0x0); - stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod); - nb_steps = -1 + (i_params->dmd1_srch_range / 1000000); - nb_steps /= 2; - nb_steps = (2 * nb_steps) + 1; + stv0900_set_symbol_rate(intp, intp->mclk, 1000000, demod); + nb_steps = -1 + (intp->srch_range[demod] / 1000000); + nb_steps /= 2; + nb_steps = (2 * nb_steps) + 1; - if (nb_steps < 0) - nb_steps = 1; + if (nb_steps < 0) + nb_steps = 1; - direction = 1; + direction = 1; - freq_step = (1000000 << 8) / (i_params->mclk >> 8); + freq_step = (1000000 << 8) / (intp->mclk >> 8); - init_freq = 0; + init_freq = 0; - for (i = 0; i < nb_steps; i++) { - if (direction > 0) - init_freq = init_freq + (freq_step * i); - else - init_freq = init_freq - (freq_step * i); + for (i = 0; i < nb_steps; i++) { + if (direction > 0) + init_freq = init_freq + (freq_step * i); + else + init_freq = init_freq - (freq_step * i); - direction *= -1; - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5C); - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, (init_freq >> 8) & 0xff); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, init_freq & 0xff); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x58); - msleep(10); - agc2level = 0; + direction *= -1; + stv0900_write_reg(intp, DMDISTATE, 0x5C); + stv0900_write_reg(intp, CFRINIT1, (init_freq >> 8) & 0xff); + stv0900_write_reg(intp, CFRINIT0, init_freq & 0xff); + stv0900_write_reg(intp, DMDISTATE, 0x58); + msleep(10); + agc2level = 0; - for (j = 0; j < 10; j++) - agc2level += (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) - | stv0900_read_reg(i_params, R0900_P1_AGC2I0); + for (j = 0; j < 10; j++) + agc2level += (stv0900_read_reg(intp, AGC2I1) << 8) + | stv0900_read_reg(intp, AGC2I0); - agc2level /= 10; + agc2level /= 10; - if (agc2level < minagc2level) - minagc2level = agc2level; - } - break; - case STV0900_DEMOD_2: - stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38); - stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 1); - stv0900_write_reg(i_params, R0900_P2_SFRUP1, 0x83); - stv0900_write_reg(i_params, R0900_P2_SFRUP0, 0xc0); - stv0900_write_reg(i_params, R0900_P2_SFRLOW1, 0x82); - stv0900_write_reg(i_params, R0900_P2_SFRLOW0, 0xa0); - stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x0); - stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod); - nb_steps = -1 + (i_params->dmd2_srch_range / 1000000); - nb_steps /= 2; - nb_steps = (2 * nb_steps) + 1; + if (agc2level < minagc2level) + minagc2level = agc2level; - if (nb_steps < 0) - nb_steps = 1; - - direction = 1; - freq_step = (1000000 << 8) / (i_params->mclk >> 8); - init_freq = 0; - for (i = 0; i < nb_steps; i++) { - if (direction > 0) - init_freq = init_freq + (freq_step * i); - else - init_freq = init_freq - (freq_step * i); - - direction *= -1; - - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5C); - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, (init_freq >> 8) & 0xff); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, init_freq & 0xff); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x58); - - msleep(10); - agc2level = 0; - for (j = 0; j < 10; j++) - agc2level += (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8) - | stv0900_read_reg(i_params, R0900_P2_AGC2I0); - - agc2level /= 10; - - if (agc2level < minagc2level) - minagc2level = agc2level; - } - break; } return (u16)minagc2level; @@ -1928,336 +1380,192 @@ static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *i_params, static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - int timingLock = FALSE; + int timing_lck = FALSE; s32 i, timingcpt = 0, direction = 1, nb_steps, current_step = 0, tuner_freq; + u32 agc2_th, + coarse_srate = 0, + agc2_integr = 0, + currier_step = 1200; - u32 coarse_srate = 0, agc2_integr = 0, currier_step = 1200; + if (intp->chip_id >= 0x30) + agc2_th = 0x2e00; + else + agc2_th = 0x1f00; - switch (demod) { - case STV0900_DEMOD_1: - default: - stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x1F); - stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0x12); - stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0xf0); - stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0xe0); - stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 1); - stv0900_write_reg(i_params, R0900_P1_SFRUP1, 0x83); - stv0900_write_reg(i_params, R0900_P1_SFRUP0, 0xc0); - stv0900_write_reg(i_params, R0900_P1_SFRLOW1, 0x82); - stv0900_write_reg(i_params, R0900_P1_SFRLOW0, 0xa0); - stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x0); - stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x50); + stv0900_write_bits(intp, DEMOD_MODE, 0x1f); + stv0900_write_reg(intp, TMGCFG, 0x12); + stv0900_write_reg(intp, TMGTHRISE, 0xf0); + stv0900_write_reg(intp, TMGTHFALL, 0xe0); + stv0900_write_bits(intp, SCAN_ENABLE, 1); + stv0900_write_bits(intp, CFR_AUTOSCAN, 1); + stv0900_write_reg(intp, SFRUP1, 0x83); + stv0900_write_reg(intp, SFRUP0, 0xc0); + stv0900_write_reg(intp, SFRLOW1, 0x82); + stv0900_write_reg(intp, SFRLOW0, 0xa0); + stv0900_write_reg(intp, DMDT0M, 0x0); + stv0900_write_reg(intp, AGC2REF, 0x50); - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x6a); - stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x95); - } else { - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed); - stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x73); - } - - if (i_params->dmd1_symbol_rate <= 2000000) - currier_step = 1000; - else if (i_params->dmd1_symbol_rate <= 5000000) - currier_step = 2000; - else if (i_params->dmd1_symbol_rate <= 12000000) - currier_step = 3000; - else - currier_step = 5000; - - nb_steps = -1 + ((i_params->dmd1_srch_range / 1000) / currier_step); - nb_steps /= 2; - nb_steps = (2 * nb_steps) + 1; - - if (nb_steps < 0) - nb_steps = 1; - - else if (nb_steps > 10) { - nb_steps = 11; - currier_step = (i_params->dmd1_srch_range / 1000) / 10; - } - - current_step = 0; - - direction = 1; - tuner_freq = i_params->tuner1_freq; - - while ((timingLock == FALSE) && (current_step < nb_steps)) { - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5F); - stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x0); - - msleep(50); - - for (i = 0; i < 10; i++) { - if (stv0900_get_bits(i_params, F0900_P1_TMGLOCK_QUALITY) >= 2) - timingcpt++; - - agc2_integr += (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) | stv0900_read_reg(i_params, R0900_P1_AGC2I0); - - } - - agc2_integr /= 10; - coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - current_step++; - direction *= -1; - - dprintk("lock: I2C_DEMOD_MODE_FIELD =0. Search started. tuner freq=%d agc2=0x%x srate_coarse=%d tmg_cpt=%d\n", tuner_freq, agc2_integr, coarse_srate, timingcpt); - - if ((timingcpt >= 5) && (agc2_integr < 0x1F00) && (coarse_srate < 55000000) && (coarse_srate > 850000)) { - timingLock = TRUE; - } - - else if (current_step < nb_steps) { - if (direction > 0) - tuner_freq += (current_step * currier_step); - else - tuner_freq -= (current_step * currier_step); - - stv0900_set_tuner(fe, tuner_freq, i_params->tuner1_bw); - } - } - - if (timingLock == FALSE) - coarse_srate = 0; - else - coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - break; - case STV0900_DEMOD_2: - stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x1F); - stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0x12); - stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0xf0); - stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0xe0); - stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 1); - stv0900_write_reg(i_params, R0900_P2_SFRUP1, 0x83); - stv0900_write_reg(i_params, R0900_P2_SFRUP0, 0xc0); - stv0900_write_reg(i_params, R0900_P2_SFRLOW1, 0x82); - stv0900_write_reg(i_params, R0900_P2_SFRLOW0, 0xa0); - stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x0); - stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x50); - - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x6a); - stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x95); - } else { - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed); - stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x73); - } - - if (i_params->dmd2_symbol_rate <= 2000000) - currier_step = 1000; - else if (i_params->dmd2_symbol_rate <= 5000000) - currier_step = 2000; - else if (i_params->dmd2_symbol_rate <= 12000000) - currier_step = 3000; - else - currier_step = 5000; - - - nb_steps = -1 + ((i_params->dmd2_srch_range / 1000) / currier_step); - nb_steps /= 2; - nb_steps = (2 * nb_steps) + 1; - - if (nb_steps < 0) - nb_steps = 1; - else if (nb_steps > 10) { - nb_steps = 11; - currier_step = (i_params->dmd2_srch_range / 1000) / 10; - } - - current_step = 0; - direction = 1; - tuner_freq = i_params->tuner2_freq; - - while ((timingLock == FALSE) && (current_step < nb_steps)) { - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5F); - stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x0); - - msleep(50); - timingcpt = 0; - - for (i = 0; i < 20; i++) { - if (stv0900_get_bits(i_params, F0900_P2_TMGLOCK_QUALITY) >= 2) - timingcpt++; - agc2_integr += (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8) - | stv0900_read_reg(i_params, R0900_P2_AGC2I0); - } - - agc2_integr /= 20; - coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - if ((timingcpt >= 10) && (agc2_integr < 0x1F00) && (coarse_srate < 55000000) && (coarse_srate > 850000)) - timingLock = TRUE; - else { - current_step++; - direction *= -1; - - if (direction > 0) - tuner_freq += (current_step * currier_step); - else - tuner_freq -= (current_step * currier_step); - - stv0900_set_tuner(fe, tuner_freq, i_params->tuner2_bw); - } - } - - if (timingLock == FALSE) - coarse_srate = 0; - else - coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); - break; + if (intp->chip_id >= 0x30) { + stv0900_write_reg(intp, CARFREQ, 0x99); + stv0900_write_reg(intp, SFRSTEP, 0x98); + } else if (intp->chip_id >= 0x20) { + stv0900_write_reg(intp, CARFREQ, 0x6a); + stv0900_write_reg(intp, SFRSTEP, 0x95); + } else { + stv0900_write_reg(intp, CARFREQ, 0xed); + stv0900_write_reg(intp, SFRSTEP, 0x73); } + if (intp->symbol_rate[demod] <= 2000000) + currier_step = 1000; + else if (intp->symbol_rate[demod] <= 5000000) + currier_step = 2000; + else if (intp->symbol_rate[demod] <= 12000000) + currier_step = 3000; + else + currier_step = 5000; + + nb_steps = -1 + ((intp->srch_range[demod] / 1000) / currier_step); + nb_steps /= 2; + nb_steps = (2 * nb_steps) + 1; + + if (nb_steps < 0) + nb_steps = 1; + else if (nb_steps > 10) { + nb_steps = 11; + currier_step = (intp->srch_range[demod] / 1000) / 10; + } + + current_step = 0; + direction = 1; + + tuner_freq = intp->freq[demod]; + + while ((timing_lck == FALSE) && (current_step < nb_steps)) { + stv0900_write_reg(intp, DMDISTATE, 0x5f); + stv0900_write_bits(intp, DEMOD_MODE, 0); + + msleep(50); + + for (i = 0; i < 10; i++) { + if (stv0900_get_bits(intp, TMGLOCK_QUALITY) >= 2) + timingcpt++; + + agc2_integr += (stv0900_read_reg(intp, AGC2I1) << 8) | + stv0900_read_reg(intp, AGC2I0); + } + + agc2_integr /= 10; + coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); + current_step++; + direction *= -1; + + dprintk("lock: I2C_DEMOD_MODE_FIELD =0. Search started." + " tuner freq=%d agc2=0x%x srate_coarse=%d tmg_cpt=%d\n", + tuner_freq, agc2_integr, coarse_srate, timingcpt); + + if ((timingcpt >= 5) && + (agc2_integr < agc2_th) && + (coarse_srate < 55000000) && + (coarse_srate > 850000)) + timing_lck = TRUE; + else if (current_step < nb_steps) { + if (direction > 0) + tuner_freq += (current_step * currier_step); + else + tuner_freq -= (current_step * currier_step); + + stv0900_set_tuner(fe, tuner_freq, intp->bw[demod]); + } + } + + if (timing_lck == FALSE) + coarse_srate = 0; + else + coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); + return coarse_srate; } static u32 stv0900_search_srate_fine(struct dvb_frontend *fe) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - u32 coarse_srate, - coarse_freq, - symb; + u32 coarse_srate, + coarse_freq, + symb, + symbmax, + symbmin, + symbcomp; - coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod); + coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod); - switch (demod) { - case STV0900_DEMOD_1: - default: - coarse_freq = (stv0900_read_reg(i_params, R0900_P1_CFR2) << 8) - | stv0900_read_reg(i_params, R0900_P1_CFR1); - symb = 13 * (coarse_srate / 10); + if (coarse_srate > 3000000) { + symbmax = 13 * (coarse_srate / 10); + symbmax = (symbmax / 1000) * 65536; + symbmax /= (intp->mclk / 1000); - if (symb < i_params->dmd1_symbol_rate) - coarse_srate = 0; - else { - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F); - stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01); - stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0x20); - stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0x00); - stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0xd2); - stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0); + symbmin = 10 * (coarse_srate / 13); + symbmin = (symbmin / 1000)*65536; + symbmin /= (intp->mclk / 1000); - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x49); - else - stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed); + symb = (coarse_srate / 1000) * 65536; + symb /= (intp->mclk / 1000); + } else { + symbmax = 13 * (coarse_srate / 10); + symbmax = (symbmax / 100) * 65536; + symbmax /= (intp->mclk / 100); - if (coarse_srate > 3000000) { - symb = 13 * (coarse_srate / 10); - symb = (symb / 1000) * 65536; - symb /= (i_params->mclk / 1000); - stv0900_write_reg(i_params, R0900_P1_SFRUP1, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, R0900_P1_SFRUP0, (symb & 0xFF)); + symbmin = 10 * (coarse_srate / 14); + symbmin = (symbmin / 100) * 65536; + symbmin /= (intp->mclk / 100); - symb = 10 * (coarse_srate / 13); - symb = (symb / 1000) * 65536; - symb /= (i_params->mclk / 1000); + symb = (coarse_srate / 100) * 65536; + symb /= (intp->mclk / 100); + } - stv0900_write_reg(i_params, R0900_P1_SFRLOW1, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, R0900_P1_SFRLOW0, (symb & 0xFF)); + symbcomp = 13 * (coarse_srate / 10); + coarse_freq = (stv0900_read_reg(intp, CFR2) << 8) + | stv0900_read_reg(intp, CFR1); - symb = (coarse_srate / 1000) * 65536; - symb /= (i_params->mclk / 1000); - stv0900_write_reg(i_params, R0900_P1_SFRINIT1, (symb >> 8) & 0xFF); - stv0900_write_reg(i_params, R0900_P1_SFRINIT0, (symb & 0xFF)); - } else { - symb = 13 * (coarse_srate / 10); - symb = (symb / 100) * 65536; - symb /= (i_params->mclk / 100); - stv0900_write_reg(i_params, R0900_P1_SFRUP1, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, R0900_P1_SFRUP0, (symb & 0xFF)); + if (symbcomp < intp->symbol_rate[demod]) + coarse_srate = 0; + else { + stv0900_write_reg(intp, DMDISTATE, 0x1f); + stv0900_write_reg(intp, TMGCFG2, 0xc1); + stv0900_write_reg(intp, TMGTHRISE, 0x20); + stv0900_write_reg(intp, TMGTHFALL, 0x00); + stv0900_write_reg(intp, TMGCFG, 0xd2); + stv0900_write_bits(intp, CFR_AUTOSCAN, 0); + stv0900_write_reg(intp, AGC2REF, 0x38); - symb = 10 * (coarse_srate / 14); - symb = (symb / 100) * 65536; - symb /= (i_params->mclk / 100); - stv0900_write_reg(i_params, R0900_P1_SFRLOW1, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, R0900_P1_SFRLOW0, (symb & 0xFF)); + if (intp->chip_id >= 0x30) + stv0900_write_reg(intp, CARFREQ, 0x79); + else if (intp->chip_id >= 0x20) + stv0900_write_reg(intp, CARFREQ, 0x49); + else + stv0900_write_reg(intp, CARFREQ, 0xed); - symb = (coarse_srate / 100) * 65536; - symb /= (i_params->mclk / 100); - stv0900_write_reg(i_params, R0900_P1_SFRINIT1, (symb >> 8) & 0xFF); - stv0900_write_reg(i_params, R0900_P1_SFRINIT0, (symb & 0xFF)); - } + stv0900_write_reg(intp, SFRUP1, (symbmax >> 8) & 0x7f); + stv0900_write_reg(intp, SFRUP0, (symbmax & 0xff)); - stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x20); - stv0900_write_reg(i_params, R0900_P1_CFRINIT1, (coarse_freq >> 8) & 0xff); - stv0900_write_reg(i_params, R0900_P1_CFRINIT0, coarse_freq & 0xff); - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15); - } - break; - case STV0900_DEMOD_2: - coarse_freq = (stv0900_read_reg(i_params, R0900_P2_CFR2) << 8) - | stv0900_read_reg(i_params, R0900_P2_CFR1); + stv0900_write_reg(intp, SFRLOW1, (symbmin >> 8) & 0x7f); + stv0900_write_reg(intp, SFRLOW0, (symbmin & 0xff)); - symb = 13 * (coarse_srate / 10); + stv0900_write_reg(intp, SFRINIT1, (symb >> 8) & 0xff); + stv0900_write_reg(intp, SFRINIT0, (symb & 0xff)); - if (symb < i_params->dmd2_symbol_rate) - coarse_srate = 0; - else { - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F); - stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01); - stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0x20); - stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0x00); - stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0xd2); - stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0); - - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x49); - else - stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed); - - if (coarse_srate > 3000000) { - symb = 13 * (coarse_srate / 10); - symb = (symb / 1000) * 65536; - symb /= (i_params->mclk / 1000); - stv0900_write_reg(i_params, R0900_P2_SFRUP1, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, R0900_P2_SFRUP0, (symb & 0xFF)); - - symb = 10 * (coarse_srate / 13); - symb = (symb / 1000) * 65536; - symb /= (i_params->mclk / 1000); - - stv0900_write_reg(i_params, R0900_P2_SFRLOW1, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, R0900_P2_SFRLOW0, (symb & 0xFF)); - - symb = (coarse_srate / 1000) * 65536; - symb /= (i_params->mclk / 1000); - stv0900_write_reg(i_params, R0900_P2_SFRINIT1, (symb >> 8) & 0xFF); - stv0900_write_reg(i_params, R0900_P2_SFRINIT0, (symb & 0xFF)); - } else { - symb = 13 * (coarse_srate / 10); - symb = (symb / 100) * 65536; - symb /= (i_params->mclk / 100); - stv0900_write_reg(i_params, R0900_P2_SFRUP1, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, R0900_P2_SFRUP0, (symb & 0xFF)); - - symb = 10 * (coarse_srate / 14); - symb = (symb / 100) * 65536; - symb /= (i_params->mclk / 100); - stv0900_write_reg(i_params, R0900_P2_SFRLOW1, (symb >> 8) & 0x7F); - stv0900_write_reg(i_params, R0900_P2_SFRLOW0, (symb & 0xFF)); - - symb = (coarse_srate / 100) * 65536; - symb /= (i_params->mclk / 100); - stv0900_write_reg(i_params, R0900_P2_SFRINIT1, (symb >> 8) & 0xFF); - stv0900_write_reg(i_params, R0900_P2_SFRINIT0, (symb & 0xFF)); - } - - stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x20); - stv0900_write_reg(i_params, R0900_P2_CFRINIT1, (coarse_freq >> 8) & 0xff); - stv0900_write_reg(i_params, R0900_P2_CFRINIT0, coarse_freq & 0xff); - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15); - } - - break; + stv0900_write_reg(intp, DMDT0M, 0x20); + stv0900_write_reg(intp, CFRINIT1, (coarse_freq >> 8) & 0xff); + stv0900_write_reg(intp, CFRINIT0, coarse_freq & 0xff); + stv0900_write_reg(intp, DMDISTATE, 0x15); } return coarse_srate; @@ -2266,163 +1574,135 @@ static u32 stv0900_search_srate_fine(struct dvb_frontend *fe) static int stv0900_blind_search_algo(struct dvb_frontend *fe) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - u8 k_ref_tmg, k_ref_tmg_max, k_ref_tmg_min; - u32 coarse_srate; - int lock = FALSE, coarse_fail = FALSE; - s32 demod_timeout = 500, fec_timeout = 50, kref_tmg_reg, fail_cpt, i, agc2_overflow; - u16 agc2_integr; - u8 dstatus2; + u8 k_ref_tmg, + k_ref_tmg_max, + k_ref_tmg_min; + u32 coarse_srate, + agc2_th; + int lock = FALSE, + coarse_fail = FALSE; + s32 demod_timeout = 500, + fec_timeout = 50, + fail_cpt, + i, + agc2_overflow; + u16 agc2_int; + u8 dstatus2; dprintk("%s\n", __func__); - if (i_params->chip_id < 0x20) { + if (intp->chip_id < 0x20) { k_ref_tmg_max = 233; k_ref_tmg_min = 143; } else { - k_ref_tmg_max = 120; - k_ref_tmg_min = 30; + k_ref_tmg_max = 110; + k_ref_tmg_min = 10; } - agc2_integr = stv0900_blind_check_agc2_min_level(i_params, demod); + if (intp->chip_id <= 0x20) + agc2_th = STV0900_BLIND_SEARCH_AGC2_TH; + else + agc2_th = STV0900_BLIND_SEARCH_AGC2_TH_CUT30; - if (agc2_integr > STV0900_BLIND_SEARCH_AGC2_TH) { - lock = FALSE; + agc2_int = stv0900_blind_check_agc2_min_level(intp, demod); - } else { - switch (demod) { - case STV0900_DEMOD_1: - default: - if (i_params->chip_id == 0x10) - stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0xAA); + if (agc2_int > STV0900_BLIND_SEARCH_AGC2_TH) + return FALSE; - if (i_params->chip_id < 0x20) - stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x55); + if (intp->chip_id == 0x10) + stv0900_write_reg(intp, CORRELEXP, 0xaa); - stv0900_write_reg(i_params, R0900_P1_CARCFG, 0xC4); - stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x44); + if (intp->chip_id < 0x20) + stv0900_write_reg(intp, CARHDR, 0x55); + else + stv0900_write_reg(intp, CARHDR, 0x20); - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P1_EQUALCFG, 0x41); - stv0900_write_reg(i_params, R0900_P1_FFECFG, 0x41); - stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x82); - stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0); - } + if (intp->chip_id <= 0x20) + stv0900_write_reg(intp, CARCFG, 0xc4); + else + stv0900_write_reg(intp, CARCFG, 0x6); - kref_tmg_reg = R0900_P1_KREFTMG; - break; - case STV0900_DEMOD_2: - if (i_params->chip_id == 0x10) - stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0xAA); + stv0900_write_reg(intp, RTCS2, 0x44); - if (i_params->chip_id < 0x20) - stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x55); + if (intp->chip_id >= 0x20) { + stv0900_write_reg(intp, EQUALCFG, 0x41); + stv0900_write_reg(intp, FFECFG, 0x41); + stv0900_write_reg(intp, VITSCALE, 0x82); + stv0900_write_reg(intp, VAVSRVIT, 0x0); + } - stv0900_write_reg(i_params, R0900_P2_CARCFG, 0xC4); - stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x44); + k_ref_tmg = k_ref_tmg_max; - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P2_EQUALCFG, 0x41); - stv0900_write_reg(i_params, R0900_P2_FFECFG, 0x41); - stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x82); - stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0); - } - - kref_tmg_reg = R0900_P2_KREFTMG; - break; - } - - k_ref_tmg = k_ref_tmg_max; - - do { - stv0900_write_reg(i_params, kref_tmg_reg, k_ref_tmg); - if (stv0900_search_srate_coarse(fe) != 0) { - coarse_srate = stv0900_search_srate_fine(fe); - - if (coarse_srate != 0) { - stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, coarse_srate, STV0900_BLIND_SEARCH); - lock = stv0900_get_demod_lock(i_params, demod, demod_timeout); - } else - lock = FALSE; - } else { - fail_cpt = 0; - agc2_overflow = 0; - - switch (demod) { - case STV0900_DEMOD_1: - default: - for (i = 0; i < 10; i++) { - agc2_integr = (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) - | stv0900_read_reg(i_params, R0900_P1_AGC2I0); - - if (agc2_integr >= 0xff00) - agc2_overflow++; - - dstatus2 = stv0900_read_reg(i_params, R0900_P1_DSTATUS2); - - if (((dstatus2 & 0x1) == 0x1) && ((dstatus2 >> 7) == 1)) - fail_cpt++; - } - break; - case STV0900_DEMOD_2: - for (i = 0; i < 10; i++) { - agc2_integr = (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8) - | stv0900_read_reg(i_params, R0900_P2_AGC2I0); - - if (agc2_integr >= 0xff00) - agc2_overflow++; - - dstatus2 = stv0900_read_reg(i_params, R0900_P2_DSTATUS2); - - if (((dstatus2 & 0x1) == 0x1) && ((dstatus2 >> 7) == 1)) - fail_cpt++; - } - break; - } - - if ((fail_cpt > 7) || (agc2_overflow > 7)) - coarse_fail = TRUE; + do { + stv0900_write_reg(intp, KREFTMG, k_ref_tmg); + if (stv0900_search_srate_coarse(fe) != 0) { + coarse_srate = stv0900_search_srate_fine(fe); + if (coarse_srate != 0) { + stv0900_get_lock_timeout(&demod_timeout, + &fec_timeout, + coarse_srate, + STV0900_BLIND_SEARCH); + lock = stv0900_get_demod_lock(intp, + demod, + demod_timeout); + } else lock = FALSE; + } else { + fail_cpt = 0; + agc2_overflow = 0; + + for (i = 0; i < 10; i++) { + agc2_int = (stv0900_read_reg(intp, AGC2I1) << 8) + | stv0900_read_reg(intp, AGC2I0); + + if (agc2_int >= 0xff00) + agc2_overflow++; + + dstatus2 = stv0900_read_reg(intp, DSTATUS2); + + if (((dstatus2 & 0x1) == 0x1) && + ((dstatus2 >> 7) == 1)) + fail_cpt++; } - k_ref_tmg -= 30; - } while ((k_ref_tmg >= k_ref_tmg_min) && (lock == FALSE) && (coarse_fail == FALSE)); - } + + if ((fail_cpt > 7) || (agc2_overflow > 7)) + coarse_fail = TRUE; + + lock = FALSE; + } + k_ref_tmg -= 30; + } while ((k_ref_tmg >= k_ref_tmg_min) && + (lock == FALSE) && + (coarse_fail == FALSE)); return lock; } -static void stv0900_set_viterbi_acq(struct stv0900_internal *i_params, +static void stv0900_set_viterbi_acq(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { - s32 vth_reg; + s32 vth_reg = VTH12; dprintk("%s\n", __func__); - dmd_reg(vth_reg, R0900_P1_VTH12, R0900_P2_VTH12); - - stv0900_write_reg(i_params, vth_reg++, 0x96); - stv0900_write_reg(i_params, vth_reg++, 0x64); - stv0900_write_reg(i_params, vth_reg++, 0x36); - stv0900_write_reg(i_params, vth_reg++, 0x23); - stv0900_write_reg(i_params, vth_reg++, 0x1E); - stv0900_write_reg(i_params, vth_reg++, 0x19); + stv0900_write_reg(intp, vth_reg++, 0x96); + stv0900_write_reg(intp, vth_reg++, 0x64); + stv0900_write_reg(intp, vth_reg++, 0x36); + stv0900_write_reg(intp, vth_reg++, 0x23); + stv0900_write_reg(intp, vth_reg++, 0x1e); + stv0900_write_reg(intp, vth_reg++, 0x19); } -static void stv0900_set_search_standard(struct stv0900_internal *i_params, +static void stv0900_set_search_standard(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { - int sstndrd; - dprintk("%s\n", __func__); - sstndrd = i_params->dmd1_srch_standard; - if (demod == 1) - sstndrd = i_params->dmd2_srch_stndrd; - - switch (sstndrd) { + switch (intp->srch_standard[demod]) { case STV0900_SEARCH_DVBS1: dprintk("Search Standard = DVBS1\n"); break; @@ -2437,129 +1717,74 @@ static void stv0900_set_search_standard(struct stv0900_internal *i_params, break; } - switch (demod) { - case STV0900_DEMOD_1: - default: - switch (i_params->dmd1_srch_standard) { - case STV0900_SEARCH_DVBS1: - case STV0900_SEARCH_DSS: - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); + switch (intp->srch_standard[demod]) { + case STV0900_SEARCH_DVBS1: + case STV0900_SEARCH_DSS: + stv0900_write_bits(intp, DVBS1_ENABLE, 1); + stv0900_write_bits(intp, DVBS2_ENABLE, 0); + stv0900_write_bits(intp, STOP_CLKVIT, 0); + stv0900_set_dvbs1_track_car_loop(intp, + demod, + intp->symbol_rate[demod]); + stv0900_write_reg(intp, CAR2CFG, 0x22); - stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 0); - stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a); - stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09); - stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x22); + stv0900_set_viterbi_acq(intp, demod); + stv0900_set_viterbi_standard(intp, + intp->srch_standard[demod], + intp->fec[demod], demod); - stv0900_set_viterbi_acq(i_params, demod); - stv0900_set_viterbi_standard(i_params, - i_params->dmd1_srch_standard, - i_params->dmd1_fec, demod); - - break; - case STV0900_SEARCH_DVBS2: - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); - stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 1); - stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a); - stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09); - stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x26); - if (i_params->demod_mode != STV0900_SINGLE) { - if (i_params->chip_id <= 0x11) - stv0900_stop_all_s2_modcod(i_params, demod); - else - stv0900_activate_s2_modcode(i_params, demod); - - } else - stv0900_activate_s2_modcode_single(i_params, demod); - - stv0900_set_viterbi_tracq(i_params, demod); - - break; - case STV0900_AUTO_SEARCH: - default: - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1); - stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 0); - stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a); - stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09); - stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x26); - if (i_params->demod_mode != STV0900_SINGLE) { - if (i_params->chip_id <= 0x11) - stv0900_stop_all_s2_modcod(i_params, demod); - else - stv0900_activate_s2_modcode(i_params, demod); - - } else - stv0900_activate_s2_modcode_single(i_params, demod); - - if (i_params->dmd1_symbol_rate >= 2000000) - stv0900_set_viterbi_acq(i_params, demod); - else - stv0900_set_viterbi_tracq(i_params, demod); - - stv0900_set_viterbi_standard(i_params, i_params->dmd1_srch_standard, i_params->dmd1_fec, demod); - - break; - } break; - case STV0900_DEMOD_2: - switch (i_params->dmd2_srch_stndrd) { - case STV0900_SEARCH_DVBS1: - case STV0900_SEARCH_DSS: - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); - stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 0); - stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a); - stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09); - stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x22); - stv0900_set_viterbi_acq(i_params, demod); - stv0900_set_viterbi_standard(i_params, i_params->dmd2_srch_stndrd, i_params->dmd2_fec, demod); - break; - case STV0900_SEARCH_DVBS2: - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); - stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 1); - stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a); - stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09); - stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x26); - if (i_params->demod_mode != STV0900_SINGLE) - stv0900_activate_s2_modcode(i_params, demod); + case STV0900_SEARCH_DVBS2: + stv0900_write_bits(intp, DVBS1_ENABLE, 0); + stv0900_write_bits(intp, DVBS2_ENABLE, 1); + stv0900_write_bits(intp, STOP_CLKVIT, 1); + stv0900_write_reg(intp, ACLC, 0x1a); + stv0900_write_reg(intp, BCLC, 0x09); + if (intp->chip_id <= 0x20) /*cut 1.x and 2.0*/ + stv0900_write_reg(intp, CAR2CFG, 0x26); + else + stv0900_write_reg(intp, CAR2CFG, 0x66); + + if (intp->demod_mode != STV0900_SINGLE) { + if (intp->chip_id <= 0x11) + stv0900_stop_all_s2_modcod(intp, demod); else - stv0900_activate_s2_modcode_single(i_params, demod); + stv0900_activate_s2_modcod(intp, demod); - stv0900_set_viterbi_tracq(i_params, demod); - break; - case STV0900_AUTO_SEARCH: - default: - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0); - stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1); - stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1); - stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 0); - stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a); - stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09); - stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x26); - if (i_params->demod_mode != STV0900_SINGLE) - stv0900_activate_s2_modcode(i_params, demod); + } else + stv0900_activate_s2_modcod_single(intp, demod); + + stv0900_set_viterbi_tracq(intp, demod); + + break; + case STV0900_AUTO_SEARCH: + default: + stv0900_write_bits(intp, DVBS1_ENABLE, 1); + stv0900_write_bits(intp, DVBS2_ENABLE, 1); + stv0900_write_bits(intp, STOP_CLKVIT, 0); + stv0900_write_reg(intp, ACLC, 0x1a); + stv0900_write_reg(intp, BCLC, 0x09); + stv0900_set_dvbs1_track_car_loop(intp, + demod, + intp->symbol_rate[demod]); + if (intp->chip_id <= 0x20) /*cut 1.x and 2.0*/ + stv0900_write_reg(intp, CAR2CFG, 0x26); + else + stv0900_write_reg(intp, CAR2CFG, 0x66); + + if (intp->demod_mode != STV0900_SINGLE) { + if (intp->chip_id <= 0x11) + stv0900_stop_all_s2_modcod(intp, demod); else - stv0900_activate_s2_modcode_single(i_params, demod); + stv0900_activate_s2_modcod(intp, demod); - if (i_params->dmd2_symbol_rate >= 2000000) - stv0900_set_viterbi_acq(i_params, demod); - else - stv0900_set_viterbi_tracq(i_params, demod); + } else + stv0900_activate_s2_modcod_single(intp, demod); - stv0900_set_viterbi_standard(i_params, i_params->dmd2_srch_stndrd, i_params->dmd2_fec, demod); - - break; - } + stv0900_set_viterbi_tracq(intp, demod); + stv0900_set_viterbi_standard(intp, + intp->srch_standard[demod], + intp->fec[demod], demod); break; } @@ -2568,10 +1793,11 @@ static void stv0900_set_search_standard(struct stv0900_internal *i_params, enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) { struct stv0900_state *state = fe->demodulator_priv; - struct stv0900_internal *i_params = state->internal; + struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; - s32 demod_timeout = 500, fec_timeout = 50, stream_merger_field; + s32 demod_timeout = 500, fec_timeout = 50; + s32 aq_power, agc1_power, i; int lock = FALSE, low_sr = FALSE; @@ -2581,155 +1807,115 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) dprintk("%s\n", __func__); - switch (demod) { - case STV0900_DEMOD_1: - default: - algo = i_params->dmd1_srch_algo; - - stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 1); - stream_merger_field = F0900_P1_RST_HWARE; - - stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5C); - - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x9e); + algo = intp->srch_algo[demod]; + stv0900_write_bits(intp, RST_HWARE, 1); + stv0900_write_reg(intp, DMDISTATE, 0x5c); + if (intp->chip_id >= 0x20) { + if (intp->symbol_rate[demod] > 5000000) + stv0900_write_reg(intp, CORRELABS, 0x9e); else - stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x88); + stv0900_write_reg(intp, CORRELABS, 0x82); + } else + stv0900_write_reg(intp, CORRELABS, 0x88); - stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, i_params->dmd1_symbol_rate, i_params->dmd1_srch_algo); + stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, + intp->symbol_rate[demod], + intp->srch_algo[demod]); - if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) { - i_params->tuner1_bw = 2 * 36000000; + if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) { + intp->bw[demod] = 2 * 36000000; - stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x00); - stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x70); + stv0900_write_reg(intp, TMGCFG2, 0xc0); + stv0900_write_reg(intp, CORRELMANT, 0x70); + + stv0900_set_symbol_rate(intp, intp->mclk, 1000000, demod); + } else { + stv0900_write_reg(intp, DMDT0M, 0x20); + stv0900_write_reg(intp, TMGCFG, 0xd2); + + if (intp->symbol_rate[demod] < 2000000) + stv0900_write_reg(intp, CORRELMANT, 0x63); + else + stv0900_write_reg(intp, CORRELMANT, 0x70); + + stv0900_write_reg(intp, AGC2REF, 0x38); + + intp->bw[demod] = + stv0900_carrier_width(intp->symbol_rate[demod], + intp->rolloff); + if (intp->chip_id >= 0x20) { + stv0900_write_reg(intp, KREFTMG, 0x5a); + + if (intp->srch_algo[demod] == STV0900_COLD_START) { + intp->bw[demod] += 10000000; + intp->bw[demod] *= 15; + intp->bw[demod] /= 10; + } else if (intp->srch_algo[demod] == STV0900_WARM_START) + intp->bw[demod] += 10000000; - stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod); } else { - stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x20); - stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0xd2); - - if (i_params->dmd1_symbol_rate < 2000000) - stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x63); - else - stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x70); - - stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38); - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P1_KREFTMG, 0x5a); - - if (i_params->dmd1_srch_algo == STV0900_COLD_START) - i_params->tuner1_bw = (15 * (stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000)) / 10; - else if (i_params->dmd1_srch_algo == STV0900_WARM_START) - i_params->tuner1_bw = stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000; - } else { - stv0900_write_reg(i_params, R0900_P1_KREFTMG, 0xc1); - i_params->tuner1_bw = (15 * (stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000)) / 10; - } - - stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01); - - stv0900_set_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod); - stv0900_set_max_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod); - stv0900_set_min_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod); - if (i_params->dmd1_symbol_rate >= 10000000) - low_sr = FALSE; - else - low_sr = TRUE; - + stv0900_write_reg(intp, KREFTMG, 0xc1); + intp->bw[demod] += 10000000; + intp->bw[demod] *= 15; + intp->bw[demod] /= 10; } - stv0900_set_tuner(fe, i_params->tuner1_freq, i_params->tuner1_bw); + stv0900_write_reg(intp, TMGCFG2, 0xc1); - stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, i_params->dmd1_srch_iq_inv); - stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1); - - stv0900_set_search_standard(i_params, demod); - - if (i_params->dmd1_srch_algo != STV0900_BLIND_SEARCH) - stv0900_start_search(i_params, demod); - break; - case STV0900_DEMOD_2: - algo = i_params->dmd2_srch_algo; - - stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 1); - - stream_merger_field = F0900_P2_RST_HWARE; - - stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5C); - - if (i_params->chip_id >= 0x20) - stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x9e); + stv0900_set_symbol_rate(intp, intp->mclk, + intp->symbol_rate[demod], demod); + stv0900_set_max_symbol_rate(intp, intp->mclk, + intp->symbol_rate[demod], demod); + stv0900_set_min_symbol_rate(intp, intp->mclk, + intp->symbol_rate[demod], demod); + if (intp->symbol_rate[demod] >= 10000000) + low_sr = FALSE; else - stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x88); + low_sr = TRUE; - stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, i_params->dmd2_symbol_rate, i_params->dmd2_srch_algo); - - if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) { - i_params->tuner2_bw = 2 * 36000000; - - stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x00); - stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x70); - - stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod); - } else { - stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x20); - stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0xd2); - - if (i_params->dmd2_symbol_rate < 2000000) - stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x63); - else - stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x70); - - if (i_params->dmd2_symbol_rate >= 10000000) - stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38); - else - stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x60); - - if (i_params->chip_id >= 0x20) { - stv0900_write_reg(i_params, R0900_P2_KREFTMG, 0x5a); - - if (i_params->dmd2_srch_algo == STV0900_COLD_START) - i_params->tuner2_bw = (15 * (stv0900_carrier_width(i_params->dmd2_symbol_rate, - i_params->rolloff) + 10000000)) / 10; - else if (i_params->dmd2_srch_algo == STV0900_WARM_START) - i_params->tuner2_bw = stv0900_carrier_width(i_params->dmd2_symbol_rate, - i_params->rolloff) + 10000000; - } else { - stv0900_write_reg(i_params, R0900_P2_KREFTMG, 0xc1); - i_params->tuner2_bw = (15 * (stv0900_carrier_width(i_params->dmd2_symbol_rate, - i_params->rolloff) + 10000000)) / 10; - } - - stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01); - - stv0900_set_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod); - stv0900_set_max_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod); - stv0900_set_min_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod); - if (i_params->dmd2_symbol_rate >= 10000000) - low_sr = FALSE; - else - low_sr = TRUE; - - } - - stv0900_set_tuner(fe, i_params->tuner2_freq, i_params->tuner2_bw); - - stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, i_params->dmd2_srch_iq_inv); - stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1); - - stv0900_set_search_standard(i_params, demod); - - if (i_params->dmd2_srch_algo != STV0900_BLIND_SEARCH) - stv0900_start_search(i_params, demod); - break; } - if (i_params->chip_id == 0x12) { - stv0900_write_bits(i_params, stream_merger_field, 0); + stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]); + + agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1), + stv0900_get_bits(intp, AGCIQ_VALUE0)); + + aq_power = 0; + + if (agc1_power == 0) { + for (i = 0; i < 5; i++) + aq_power += (stv0900_get_bits(intp, POWER_I) + + stv0900_get_bits(intp, POWER_Q)) / 2; + + aq_power /= 5; + } + + if ((agc1_power == 0) && (aq_power < IQPOWER_THRESHOLD)) { + intp->result[demod].locked = FALSE; + signal_type = STV0900_NOAGC1; + dprintk("%s: NO AGC1, POWERI, POWERQ\n", __func__); + } else { + stv0900_write_bits(intp, SPECINV_CONTROL, + intp->srch_iq_inv[demod]); + if (intp->chip_id <= 0x20) /*cut 2.0*/ + stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1); + else /*cut 3.0*/ + stv0900_write_bits(intp, MANUALS2_ROLLOFF, 1); + + stv0900_set_search_standard(intp, demod); + + if (intp->srch_algo[demod] != STV0900_BLIND_SEARCH) + stv0900_start_search(intp, demod); + } + + if (signal_type == STV0900_NOAGC1) + return signal_type; + + if (intp->chip_id == 0x12) { + stv0900_write_bits(intp, RST_HWARE, 0); msleep(3); - stv0900_write_bits(i_params, stream_merger_field, 1); - stv0900_write_bits(i_params, stream_merger_field, 0); + stv0900_write_bits(intp, RST_HWARE, 1); + stv0900_write_bits(intp, RST_HWARE, 0); } if (algo == STV0900_BLIND_SEARCH) @@ -2737,12 +1923,12 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) else if (algo == STV0900_COLD_START) lock = stv0900_get_demod_cold_lock(fe, demod_timeout); else if (algo == STV0900_WARM_START) - lock = stv0900_get_demod_lock(i_params, demod, demod_timeout); + lock = stv0900_get_demod_lock(intp, demod, demod_timeout); if ((lock == FALSE) && (algo == STV0900_COLD_START)) { if (low_sr == FALSE) { - if (stv0900_check_timing_lock(i_params, demod) == TRUE) - lock = stv0900_sw_algo(i_params, demod); + if (stv0900_check_timing_lock(intp, demod) == TRUE) + lock = stv0900_sw_algo(intp, demod); } } @@ -2751,98 +1937,64 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) if ((lock == TRUE) && (signal_type == STV0900_RANGEOK)) { stv0900_track_optimization(fe); - if (i_params->chip_id <= 0x11) { - if ((stv0900_get_standard(fe, STV0900_DEMOD_1) == STV0900_DVBS1_STANDARD) && (stv0900_get_standard(fe, STV0900_DEMOD_2) == STV0900_DVBS1_STANDARD)) { + if (intp->chip_id <= 0x11) { + if ((stv0900_get_standard(fe, 0) == + STV0900_DVBS1_STANDARD) && + (stv0900_get_standard(fe, 1) == + STV0900_DVBS1_STANDARD)) { msleep(20); - stv0900_write_bits(i_params, stream_merger_field, 0); + stv0900_write_bits(intp, RST_HWARE, 0); } else { - stv0900_write_bits(i_params, stream_merger_field, 0); + stv0900_write_bits(intp, RST_HWARE, 0); msleep(3); - stv0900_write_bits(i_params, stream_merger_field, 1); - stv0900_write_bits(i_params, stream_merger_field, 0); + stv0900_write_bits(intp, RST_HWARE, 1); + stv0900_write_bits(intp, RST_HWARE, 0); } - } else if (i_params->chip_id == 0x20) { - stv0900_write_bits(i_params, stream_merger_field, 0); + + } else if (intp->chip_id >= 0x20) { + stv0900_write_bits(intp, RST_HWARE, 0); msleep(3); - stv0900_write_bits(i_params, stream_merger_field, 1); - stv0900_write_bits(i_params, stream_merger_field, 0); + stv0900_write_bits(intp, RST_HWARE, 1); + stv0900_write_bits(intp, RST_HWARE, 0); } - if (stv0900_wait_for_lock(i_params, demod, fec_timeout, fec_timeout) == TRUE) { + if (stv0900_wait_for_lock(intp, demod, + fec_timeout, fec_timeout) == TRUE) { lock = TRUE; - switch (demod) { - case STV0900_DEMOD_1: - default: - i_params->dmd1_rslts.locked = TRUE; - if (i_params->dmd1_rslts.standard == STV0900_DVBS2_STANDARD) { - stv0900_set_dvbs2_rolloff(i_params, demod); - stv0900_write_reg(i_params, R0900_P1_PDELCTRL2, 0x40); - stv0900_write_reg(i_params, R0900_P1_PDELCTRL2, 0); - stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x67); - } else { - stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75); - } - - stv0900_write_reg(i_params, R0900_P1_FBERCPT4, 0); - stv0900_write_reg(i_params, R0900_P1_ERRCTRL2, 0xc1); - break; - case STV0900_DEMOD_2: - i_params->dmd2_rslts.locked = TRUE; - - if (i_params->dmd2_rslts.standard == STV0900_DVBS2_STANDARD) { - stv0900_set_dvbs2_rolloff(i_params, demod); - stv0900_write_reg(i_params, R0900_P2_PDELCTRL2, 0x60); - stv0900_write_reg(i_params, R0900_P2_PDELCTRL2, 0x20); - stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x67); - } else { - stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75); - } - - stv0900_write_reg(i_params, R0900_P2_FBERCPT4, 0); - - stv0900_write_reg(i_params, R0900_P2_ERRCTRL2, 0xc1); - break; + intp->result[demod].locked = TRUE; + if (intp->result[demod].standard == + STV0900_DVBS2_STANDARD) { + stv0900_set_dvbs2_rolloff(intp, demod); + stv0900_write_bits(intp, RESET_UPKO_COUNT, 1); + stv0900_write_bits(intp, RESET_UPKO_COUNT, 0); + stv0900_write_reg(intp, ERRCTRL1, 0x67); + } else { + stv0900_write_reg(intp, ERRCTRL1, 0x75); } + + stv0900_write_reg(intp, FBERCPT4, 0); + stv0900_write_reg(intp, ERRCTRL2, 0xc1); } else { lock = FALSE; signal_type = STV0900_NODATA; - no_signal = stv0900_check_signal_presence(i_params, demod); + no_signal = stv0900_check_signal_presence(intp, demod); - switch (demod) { - case STV0900_DEMOD_1: - default: - i_params->dmd1_rslts.locked = FALSE; - break; - case STV0900_DEMOD_2: - i_params->dmd2_rslts.locked = FALSE; - break; - } + intp->result[demod].locked = FALSE; } } - if ((signal_type == STV0900_NODATA) && (no_signal == FALSE)) { - switch (demod) { - case STV0900_DEMOD_1: - default: - if (i_params->chip_id <= 0x11) { - if ((stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS_FOUND) && - (i_params->dmd1_srch_iq_inv <= STV0900_IQ_AUTO_NORMAL_FIRST)) - signal_type = stv0900_dvbs1_acq_workaround(fe); - } else - i_params->dmd1_rslts.locked = FALSE; + if ((signal_type != STV0900_NODATA) || (no_signal != FALSE)) + return signal_type; - break; - case STV0900_DEMOD_2: - if (i_params->chip_id <= 0x11) { - if ((stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS_FOUND) && - (i_params->dmd2_srch_iq_inv <= STV0900_IQ_AUTO_NORMAL_FIRST)) - signal_type = stv0900_dvbs1_acq_workaround(fe); - } else - i_params->dmd2_rslts.locked = FALSE; - break; - } + if (intp->chip_id > 0x11) { + intp->result[demod].locked = FALSE; + return signal_type; } + if ((stv0900_get_bits(intp, HEADER_MODE) == STV0900_DVBS_FOUND) && + (intp->srch_iq_inv[demod] <= STV0900_IQ_AUTO_NORMAL_FIRST)) + signal_type = stv0900_dvbs1_acq_workaround(fe); + return signal_type; } From aee0b24c05f6e9615115748a8ea5042d8ee0e6a0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 11 Nov 2009 01:52:45 -0300 Subject: [PATCH 206/345] V4L/DVB (13347): cx23885: add digital television support for Hauppauge WinTV-HVR1290 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 12 ++++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 1 + drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 15 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 5f33d8486102..be293346ffe1 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -24,3 +24,4 @@ 23 -> Magic-Pro ProHDTV Extreme 2 [14f1:8657] 24 -> Hauppauge WinTV-HVR1850 [0070:8541] 25 -> Compro VideoMate E800 [1858:e800] + 26 -> Hauppauge WinTV-HVR1290 [0070:8551] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 2cbac93866be..2f4db970152e 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -265,6 +265,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Compro VideoMate E800", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1290] = { + .name = "Hauppauge WinTV-HVR1290", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -400,6 +404,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x1858, .subdevice = 0xe800, .card = CX23885_BOARD_COMPRO_VIDEOMATE_E800, + }, { + .subvendor = 0x0070, + .subdevice = 0x8551, + .card = CX23885_BOARD_HAUPPAUGE_HVR1290, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -819,6 +827,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) mdelay(100); break; case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: /* GPIO-0 656_CLK */ /* GPIO-1 656_D0 */ /* GPIO-2 Wake# */ @@ -934,6 +943,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1255: case CX23885_BOARD_HAUPPAUGE_HVR1210: case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -1003,6 +1013,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1210: case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: + case CX23885_BOARD_HAUPPAUGE_HVR1290: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ @@ -1023,6 +1034,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_MYGICA_X8506: case CX23885_BOARD_MAGICPRO_PROHDTVE2: + case CX23885_BOARD_HAUPPAUGE_HVR1290: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, "cx25840", "cx25840", 0x88 >> 1, NULL); diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 44e5fade0488..133e80290711 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -898,6 +898,7 @@ static int dvb_register(struct cx23885_tsport *port) } break; case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 813eaf7c5e94..12d1a344a8ab 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -79,6 +79,7 @@ #define CX23885_BOARD_MAGICPRO_PROHDTVE2 23 #define CX23885_BOARD_HAUPPAUGE_HVR1850 24 #define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 +#define CX23885_BOARD_HAUPPAUGE_HVR1290 26 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 From 73a5f4196dcdf1f5b0bcfa208cb485c4fde840cc Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 11 Nov 2009 10:46:40 -0300 Subject: [PATCH 207/345] V4L/DVB (13348): cx23885: update model matrix for models 85021 and 85721 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 2f4db970152e..632d76a432af 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -568,9 +568,13 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) * DVB-T and MPEG2 HW Encoder */ break; case 85021: - /* WinTV-HVR1850 (PCIe, OEM, RCA in, IR, FM, + /* WinTV-HVR1850 (PCIe, Retail, 3.5mm in, IR, FM, Dual channel ATSC and MPEG2 HW Encoder */ break; + case 85721: + /* WinTV-HVR1290 (PCIe, OEM, RCA in, IR, + Dual channel ATSC and Basic analog */ + break; default: printk(KERN_WARNING "%s: warning: " "unknown hauppauge model #%d\n", From 7fec6fee56def62a53e3bc4db5baf6bca12c3474 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 11 Nov 2009 15:46:09 -0300 Subject: [PATCH 208/345] V4L/DVB (13349): cx23885: Enable IR input keypress handling for the Hauppauge WinTV HVR-1290 The IR on the HVR-1290 is identical to that of the HVR-1850 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 3 +++ drivers/media/video/cx23885/cx23885-input.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 632d76a432af..d9d71c8c7941 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -881,6 +881,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) /* FIXME: Implement me */ break; case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: ret = cx23888_ir_probe(dev); if (ret) break; @@ -899,6 +900,7 @@ void cx23885_ir_fini(struct cx23885_dev *dev) { switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: dev->pci_irqmask &= ~PCI_MSK_IR; cx_clear(PCI_INT_MSK, PCI_MSK_IR); cx23888_ir_remove(dev); @@ -911,6 +913,7 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev) { switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR)) cx_set(PCI_INT_MSK, PCI_MSK_IR); break; diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index c208079f4e9d..f000ed787d4e 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -202,6 +202,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: /* * The only board we handle right now. However other boards * using the CX2388x integrated IR controller should be similar @@ -252,6 +253,7 @@ static void cx23885_input_ir_start(struct cx23885_dev *dev) /* keyup timer set up, if needed */ switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: setup_timer(&ir_input->timer_keyup, ir_rc5_timer_keyup, /* Not actually RC-5 specific */ (unsigned long) ir_input); @@ -268,6 +270,7 @@ static void cx23885_input_ir_start(struct cx23885_dev *dev) v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: /* * The IR controller on this board only returns pulse widths. * Any other mode setting will fail to set up the device. @@ -325,6 +328,7 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev) switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: del_timer_sync(&ir_input->timer_keyup); break; } @@ -347,6 +351,7 @@ int cx23885_input_init(struct cx23885_dev *dev) switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: /* Parameters for the grey Hauppauge remote for the HVR-1850 */ ir_codes = &ir_codes_hauppauge_new_table; ir_type = IR_TYPE_RC5; From c879d8cef4c5fc31ff2ab6e5b83bf4a537e77844 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:11:26 -0300 Subject: [PATCH 209/345] V4L/DVB (13351): stv090x: increases search range based on symbol rate Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 488bdfb34fb3..6c99a86c8efd 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3296,7 +3296,13 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron state->search_mode = STV090x_SEARCH_AUTO; state->algo = STV090x_COLD_SEARCH; state->fec = STV090x_PRERR; - state->search_range = 2000000; + if (state->srate > 10000000) { + dprintk(FE_DEBUG, 1, "Search range: 10 MHz"); + state->search_range = 10000000; + } else { + dprintk(FE_DEBUG, 1, "Search range: 5 MHz"); + state->search_range = 5000000; + } if (stv090x_algo(state) == STV090x_RANGEOK) { dprintk(FE_DEBUG, 1, "Search success!"); From 45433d3f8dec42179ebe0f27966073a71fd1c612 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:12:48 -0300 Subject: [PATCH 210/345] V4L/DVB (13352): stv090x: fixes errors and typos in register definitions Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x_reg.h | 70 +++++++++++------------ 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x_reg.h b/drivers/media/dvb/frontends/stv090x_reg.h index 57b6abbbd32d..2502855dd784 100644 --- a/drivers/media/dvb/frontends/stv090x_reg.h +++ b/drivers/media/dvb/frontends/stv090x_reg.h @@ -44,7 +44,7 @@ #define STV090x_OFFST_OUTSERRS2_HZ_FIELD 5 #define STV090x_WIDTH_OUTSERRS2_HZ_FIELD 1 #define STV090x_OFFST_OUTSERRS3_HZ_FIELD 4 -#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD 1 +#define STV090x_WIDTH_OUTSERRS3_HZ_FIELD 1 #define STV090x_OFFST_OUTPARRS3_HZ_FIELD 3 #define STV090x_WIDTH_OUTPARRS3_HZ_FIELD 1 @@ -113,24 +113,24 @@ #define STV090x_IRQMASK3 0xf124 #define STV090x_OFFST_MPLL_LOCK_FIELD 5 #define STV090x_WIDTH_MPLL_LOCK_FIELD 1 -#define STV090x_OFFST_MSTREAM_LCK_3_FIELD 2 -#define STV090x_WIDTH_MSTREAM_LCK_3_FIELD 3 -#define STV090x_OFFST_MSTREAM_LCK_2_FIELD 2 -#define STV090x_WIDTH_MSTREAM_LCK_2_FIELD 3 +#define STV090x_OFFST_MSTREAM_LCK_3_FIELD 4 +#define STV090x_WIDTH_MSTREAM_LCK_3_FIELD 1 +#define STV090x_OFFST_MSTREAM_LCK_2_FIELD 3 +#define STV090x_WIDTH_MSTREAM_LCK_2_FIELD 1 #define STV090x_OFFST_MSTREAM_LCK_1_FIELD 2 -#define STV090x_WIDTH_MSTREAM_LCK_1_FIELD 3 +#define STV090x_WIDTH_MSTREAM_LCK_1_FIELD 1 #define STV090x_OFFST_MDVBS1_PRF_2_FIELD 1 #define STV090x_WIDTH_MDVBS1_PRF_2_FIELD 1 #define STV090x_OFFST_MDVBS1_PRF_1_FIELD 0 #define STV090x_WIDTH_MDVBS1_PRF_1_FIELD 1 #define STV090x_IRQMASK2 0xf125 -#define STV090x_OFFST_MSPY_ENDSIM_3_FIELD 5 -#define STV090x_WIDTH_MSPY_ENDSIM_3_FIELD 3 -#define STV090x_OFFST_MSPY_ENDSIM_2_FIELD 5 -#define STV090x_WIDTH_MSPY_ENDSIM_2_FIELD 3 +#define STV090x_OFFST_MSPY_ENDSIM_3_FIELD 7 +#define STV090x_WIDTH_MSPY_ENDSIM_3_FIELD 1 +#define STV090x_OFFST_MSPY_ENDSIM_2_FIELD 6 +#define STV090x_WIDTH_MSPY_ENDSIM_2_FIELD 1 #define STV090x_OFFST_MSPY_ENDSIM_1_FIELD 5 -#define STV090x_WIDTH_MSPY_ENDSIM_1_FIELD 3 +#define STV090x_WIDTH_MSPY_ENDSIM_1_FIELD 1 #define STV090x_OFFST_MPKTDEL_ERROR_2_FIELD 4 #define STV090x_WIDTH_MPKTDEL_ERROR_2_FIELD 1 #define STV090x_OFFST_MPKTDEL_LOCKB_2_FIELD 3 @@ -370,7 +370,7 @@ #define STV090x_OFFST_SELX1RATIO_FIELD 5 #define STV090x_WIDTH_SELX1RATIO_FIELD 1 #define STV090x_OFFST_STOP_PLL_FIELD 3 -#define STV090x_WIDTH_SELX1RATIO_FIELD 1 +#define STV090x_WIDTH_STOP_PLL_FIELD 1 #define STV090x_OFFST_BYPASSPLLFSK_FIELD 2 #define STV090x_WIDTH_BYPASSPLLFSK_FIELD 1 #define STV090x_OFFST_SELOSCI_FIELD 1 @@ -616,7 +616,7 @@ #define STV090x_OFFST_Px_CONT_TONE_FIELD 4 #define STV090x_WIDTH_Px_CONT_TONE_FIELD 1 #define STV090x_OFFST_Px_FIFO_4BREADY_FIELD 3 -#define STV090x_WIDTH_Px_FIFO_4BREADY_FIELD 2 +#define STV090x_WIDTH_Px_FIFO_4BREADY_FIELD 1 #define STV090x_OFFST_Px_FIFO_EMPTY_FIELD 2 #define STV090x_WIDTH_Px_FIFO_EMPTY_FIELD 1 #define STV090x_OFFST_Px_ABORT_DISRX_FIELD 0 @@ -847,12 +847,10 @@ #define STV090x_WIDTH_Px_DVBS2_ENABLE_FIELD 1 #define STV090x_OFFST_Px_DVBS1_ENABLE_FIELD 6 #define STV090x_WIDTH_Px_DVBS1_ENABLE_FIELD 1 -#define STV090x_OFFST_Px_CFR_AUTOSCAN_FIELD 5 /* check */ -#define STV090x_WIDTH_Px_CFR_AUTOSCAN_FIELD 1 -#define STV090x_OFFST_Px_SCAN_ENABLE_FIELD 4 /* check */ +#define STV090x_OFFST_Px_SCAN_ENABLE_FIELD 4 #define STV090x_WIDTH_Px_SCAN_ENABLE_FIELD 1 -#define STV090x_OFFST_Px_TUN_AUTOSCAN_FIELD 3 -#define STV090x_WIDTH_Px_TUN_AUTOSCAN_FIELD 1 +#define STV090x_OFFST_Px_CFR_AUTOSCAN_FIELD 3 +#define STV090x_WIDTH_Px_CFR_AUTOSCAN_FIELD 1 #define STV090x_OFFST_Px_NOFORCE_RELOCK_FIELD 2 #define STV090x_WIDTH_Px_NOFORCE_RELOCK_FIELD 1 #define STV090x_OFFST_Px_TUN_RNG_FIELD 0 @@ -885,7 +883,7 @@ #define STV090x_P2_DMDFLYW STV090x_Px_DMDFLYW(2) #define STV090x_OFFST_Px_I2C_IRQVAL_FIELD 4 #define STV090x_WIDTH_Px_I2C_IRQVAL_FIELD 4 -#define STV090x_OFFST_Px_FLYWHEEL_CPT_FIELD 0 /* check */ +#define STV090x_OFFST_Px_FLYWHEEL_CPT_FIELD 0 #define STV090x_WIDTH_Px_FLYWHEEL_CPT_FIELD 4 #define STV090x_Px_DSTATUS3(__x) (0xF41D - (__x - 1) * 0x200) @@ -1048,12 +1046,12 @@ #define STV090x_P1_CFRINC1 STV090x_Px_CFRINC1(1) #define STV090x_P2_CFRINC1 STV090x_Px_CFRINC1(2) #define STV090x_OFFST_Px_CFR_INC1_FIELD 0 -#define STV090x_WIDTH_Px_CFR_INC1_FIELD 7 +#define STV090x_WIDTH_Px_CFR_INC1_FIELD 7 /* check */ #define STV090x_Px_CFRINC0(__x) (0xF44B - (__x - 1) * 0x200) #define STV090x_P1_CFRINC0 STV090x_Px_CFRINC0(1) #define STV090x_P2_CFRINC0 STV090x_Px_CFRINC0(2) -#define STV090x_OFFST_Px_CFR_INC0_FIELD 4 +#define STV090x_OFFST_Px_CFR_INC0_FIELD 4 /* check */ #define STV090x_WIDTH_Px_CFR_INC0_FIELD 4 #define STV090x_Pn_CFRy(__x, __y) (0xF44E - (__x - 1) * 0x200 - __y * 0x1) @@ -1145,14 +1143,14 @@ #define STV090x_Px_SFRINIT1(__x) (0xF45E - (__x - 1) * 0x200) #define STV090x_P1_SFRINIT1 STV090x_Px_SFRINIT1(1) #define STV090x_P2_SFRINIT1 STV090x_Px_SFRINIT1(2) -#define STV090x_OFFST_Px_SFR_INIT_FIELD 0 -#define STV090x_WIDTH_Px_SFR_INIT_FIELD 8 +#define STV090x_OFFST_Px_SFR_INIT1_FIELD 0 +#define STV090x_WIDTH_Px_SFR_INIT1_FIELD 7 #define STV090x_Px_SFRINIT0(__x) (0xF45F - (__x - 1) * 0x200) #define STV090x_P1_SFRINIT0 STV090x_Px_SFRINIT0(1) #define STV090x_P2_SFRINIT0 STV090x_Px_SFRINIT0(2) -#define STV090x_OFFST_Px_SFR_INIT_FIELD 0 -#define STV090x_WIDTH_Px_SFR_INIT_FIELD 8 +#define STV090x_OFFST_Px_SFR_INIT0_FIELD 0 +#define STV090x_WIDTH_Px_SFR_INIT0_FIELD 8 #define STV090x_Px_SFRUP1(__x) (0xF460 - (__x - 1) * 0x200) #define STV090x_P1_SFRUP1 STV090x_Px_SFRUP1(1) @@ -1178,7 +1176,7 @@ #define STV090x_OFFST_Px_SYMB_FREQ_LOW0_FIELD 0 #define STV090x_WIDTH_Px_SYMB_FREQ_LOW0_FIELD 8 -#define STV090x_Px_SFRy(__x, __y) (0xF464 - (__x-1) * 0x200 + (3 - __y)) +#define STV090x_Px_SFRy(__x, __y) (0xF467 - (__x-1) * 0x200 - __y) #define STV090x_P1_SFR0 STV090x_Px_SFRy(1, 0) #define STV090x_P1_SFR1 STV090x_Px_SFRy(1, 1) #define STV090x_P1_SFR2 STV090x_Px_SFRy(1, 2) @@ -1188,7 +1186,7 @@ #define STV090x_P2_SFR2 STV090x_Px_SFRy(2, 2) #define STV090x_P2_SFR3 STV090x_Px_SFRy(2, 3) #define STV090x_OFFST_Px_SYMB_FREQ_FIELD 0 -#define STV090x_WIDTH_Px_SYMB_FREQ_FIELD 32 +#define STV090x_WIDTH_Px_SYMB_FREQ_FIELD 8 #define STV090x_Px_TMGREG2(__x) (0xF468 - (__x - 1) * 0x200) #define STV090x_P1_TMGREG2 STV090x_Px_TMGREG2(1) @@ -1198,7 +1196,7 @@ #define STV090x_Px_TMGREG1(__x) (0xF469 - (__x - 1) * 0x200) #define STV090x_P1_TMGREG1 STV090x_Px_TMGREG1(1) -#define STV090x_P2_TMGREG1 STV090x_Px_TMGREG1(2) +#define STV090x_P2_TMGREG1 STV090x_Px_TMGREG1(2) #define STV090x_OFFST_Px_TMGREG_FIELD 0 #define STV090x_WIDTH_Px_TMGREG_FIELD 8 @@ -1230,7 +1228,7 @@ #define STV090x_OFFST_Px_MU_EQUALDFE_FIELD 0 #define STV090x_WIDTH_Px_MU_EQUALDFE_FIELD 3 -#define STV090x_Px_EQUAIy(__x, __y) (0xf470 - (__x - 1) * 0x200 + (__y - 1)) +#define STV090x_Px_EQUAIy(__x, __y) (0xf470 - (__x-1) * 0x200 + 2 * (__y-1)) #define STV090x_P1_EQUAI1 STV090x_Px_EQUAIy(1, 1) #define STV090x_P1_EQUAI2 STV090x_Px_EQUAIy(1, 2) #define STV090x_P1_EQUAI3 STV090x_Px_EQUAIy(1, 3) @@ -1251,7 +1249,7 @@ #define STV090x_OFFST_Px_EQUA_ACCIy_FIELD 0 #define STV090x_WIDTH_Px_EQUA_ACCIy_FIELD 8 -#define STV090x_Px_EQUAQy(__x, __y) (0xf471 - (__x - 1) * 0x200 + (__y - 1)) +#define STV090x_Px_EQUAQy(__x, __y) (0xf471 - (__x-1) * 0x200 + 2 * (__y-1)) #define STV090x_P1_EQUAQ1 STV090x_Px_EQUAQy(1, 1) #define STV090x_P1_EQUAQ2 STV090x_Px_EQUAQy(1, 2) #define STV090x_P1_EQUAQ3 STV090x_Px_EQUAQy(1, 3) @@ -1390,7 +1388,7 @@ #define STV090x_OFFST_Px_CAR2S2_16A_ALPH_E_FIELD 0 #define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_E_FIELD 4 -#define STV090x_Px_ACLC2S232A(__x) (0xf499 - (__x - 1) * 0x200) +#define STV090x_Px_ACLC2S232A(__x) (0xf49A - (__x - 1) * 0x200) #define STV090x_P1_ACLC2S232A STV090x_Px_ACLC2S232A(1) #define STV090x_P2_ACLC2S232A STV090x_Px_ACLC2S232A(2) #define STV090x_OFFST_Px_CAR2S2_32A_ALPH_M_FIELD 4 @@ -1414,7 +1412,7 @@ #define STV090x_OFFST_Px_CAR2S2_8_BETA_E_FIELD 0 #define STV090x_WIDTH_Px_CAR2S2_8_BETA_E_FIELD 4 -#define STV090x_Px_BCLC2S216A(__x) (0xf49d - (__x - 1) * 0x200) +#define STV090x_Px_BCLC2S216A(__x) (0xf49e - (__x - 1) * 0x200) #define STV090x_P1_BCLC2S216A STV090x_Px_BCLC2S216A(1) #define STV090x_P2_BCLC2S216A STV090x_Px_BCLC2S216A(1) #define STV090x_OFFST_Px_CAR2S2_16A_BETA_M_FIELD 4 @@ -1422,7 +1420,7 @@ #define STV090x_OFFST_Px_CAR2S2_16A_BETA_E_FIELD 0 #define STV090x_WIDTH_Px_CAR2S2_16A_BETA_E_FIELD 4 -#define STV090x_Px_BCLC2S232A(__x) (0xf49d - (__x - 1) * 0x200) +#define STV090x_Px_BCLC2S232A(__x) (0xf49f - (__x - 1) * 0x200) #define STV090x_P1_BCLC2S232A STV090x_Px_BCLC2S232A(1) #define STV090x_P2_BCLC2S232A STV090x_Px_BCLC2S232A(1) #define STV090x_OFFST_Px_CAR2S2_32A_BETA_M_FIELD 4 @@ -1458,7 +1456,7 @@ #define STV090x_P1_MODCODLST1 STV090x_Px_MODCODLST1(1) #define STV090x_P2_MODCODLST1 STV090x_Px_MODCODLST1(2) #define STV090x_OFFST_Px_DIS_MODCOD29_FIELD 4 -#define STV090x_WIDTH_Px_DIS_MODCOD29T_FIELD 4 +#define STV090x_WIDTH_Px_DIS_MODCOD29_FIELD 4 #define STV090x_OFFST_Px_DIS_32PSK_9_10_FIELD 0 #define STV090x_WIDTH_Px_DIS_32PSK_9_10_FIELD 4 @@ -2180,7 +2178,7 @@ #define STV090x_WIDTH_Px_TSFIFOSPEED_STORE_FIELD 1 #define STV090x_OFFST_Px_DILXX_RESET_FIELD 5 #define STV090x_WIDTH_Px_DILXX_RESET_FIELD 1 -#define STV090x_OFFST_Px_TSSERIAL_IMPOS_FIELD 5 +#define STV090x_OFFST_Px_TSSERIAL_IMPOS_FIELD 4 #define STV090x_WIDTH_Px_TSSERIAL_IMPOS_FIELD 1 #define STV090x_OFFST_Px_SCRAMBDETECT_FIELD 1 #define STV090x_WIDTH_Px_SCRAMBDETECT_FIELD 1 @@ -2190,7 +2188,7 @@ #define STV090x_P1_TSBITRATE1 STV090x_Px_TSBITRATEy(1, 1) #define STV090x_P2_TSBITRATE0 STV090x_Px_TSBITRATEy(2, 0) #define STV090x_P2_TSBITRATE1 STV090x_Px_TSBITRATEy(2, 1) -#define STV090x_OFFST_Px_TSFIFO_BITRATE_FIELD 7 +#define STV090x_OFFST_Px_TSFIFO_BITRATE_FIELD 0 #define STV090x_WIDTH_Px_TSFIFO_BITRATE_FIELD 8 #define STV090x_Px_ERRCTRL1(__x) (0xF598 - (__x - 1) * 0x200) From dbeb7dbf867dc976c66332e6f2c3e24bf87df258 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:14:00 -0300 Subject: [PATCH 211/345] V4L/DVB (13353): stv090x: fixes STR and SNR calculation and normalizes the value into the 0..0xFFFF range Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 58 ++++++++++++++++++--------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 6c99a86c8efd..e74419b682d3 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3418,14 +3418,12 @@ static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val) int res = 0; int min = 0, med; - if (val < tab[min].read) - res = tab[min].real; - else if (val >= tab[max].read) - res = tab[max].real; - else { + if ((val >= tab[min].read && val < tab[max].read) || + (val >= tab[max].read && val < tab[min].read)) { while ((max - min) > 1) { med = (max + min) / 2; - if (val >= tab[min].read && val < tab[med].read) + if ((val >= tab[min].read && val < tab[med].read) || + (val >= tab[med].read && val < tab[min].read)) max = med; else min = med; @@ -3434,6 +3432,18 @@ static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val) (tab[max].real - tab[min].real) / (tab[max].read - tab[min].read)) + tab[min].real; + } else { + if (tab[min].read < tab[max].read) { + if (val < tab[min].read) + res = tab[min].real; + else if (val >= tab[max].read) + res = tab[max].real; + } else { + if (val >= tab[min].read) + res = tab[min].real; + else if (val < tab[max].read) + res = tab[max].real; + } } return res; @@ -3443,16 +3453,22 @@ static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct stv090x_state *state = fe->demodulator_priv; u32 reg; - s32 agc; + s32 agc_0, agc_1, agc; + s32 str; reg = STV090x_READ_DEMOD(state, AGCIQIN1); - agc = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); + agc_1 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); + reg = STV090x_READ_DEMOD(state, AGCIQIN0); + agc_0 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); + agc = MAKEWORD16(agc_1, agc_0); - *strength = stv090x_table_lookup(stv090x_rf_tab, ARRAY_SIZE(stv090x_rf_tab) - 1, agc); + str = stv090x_table_lookup(stv090x_rf_tab, + ARRAY_SIZE(stv090x_rf_tab) - 1, agc); if (agc > stv090x_rf_tab[0].read) - *strength = 5; + str = 0; else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read) - *strength = -100; + str = -100; + *strength = (str + 100) * 0xFFFF / 100; return 0; } @@ -3463,6 +3479,8 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) u32 reg_0, reg_1, reg, i; s32 val_0, val_1, val = 0; u8 lock_f; + s32 div; + u32 last; switch (state->delsys) { case STV090x_DVBS2: @@ -3474,14 +3492,15 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) reg_1 = STV090x_READ_DEMOD(state, NNOSPLHT1); val_1 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD); reg_0 = STV090x_READ_DEMOD(state, NNOSPLHT0); - val_0 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD); + val_0 = STV090x_GETFIELD_Px(reg_0, NOSPLHT_NORMED_FIELD); val += MAKEWORD16(val_1, val_0); msleep(1); } val /= 16; - *cnr = stv090x_table_lookup(stv090x_s2cn_tab, ARRAY_SIZE(stv090x_s2cn_tab) - 1, val); - if (val < stv090x_s2cn_tab[ARRAY_SIZE(stv090x_s2cn_tab) - 1].read) - *cnr = 1000; + last = ARRAY_SIZE(stv090x_s2cn_tab) - 1; + div = stv090x_s2cn_tab[0].read - + stv090x_s2cn_tab[last].read; + *cnr = 0xFFFF - ((val * 0xFFFF) / div); } break; @@ -3495,14 +3514,15 @@ static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) reg_1 = STV090x_READ_DEMOD(state, NOSDATAT1); val_1 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD); reg_0 = STV090x_READ_DEMOD(state, NOSDATAT0); - val_0 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD); + val_0 = STV090x_GETFIELD_Px(reg_0, NOSDATAT_UNNORMED_FIELD); val += MAKEWORD16(val_1, val_0); msleep(1); } val /= 16; - *cnr = stv090x_table_lookup(stv090x_s1cn_tab, ARRAY_SIZE(stv090x_s1cn_tab) - 1, val); - if (val < stv090x_s2cn_tab[ARRAY_SIZE(stv090x_s1cn_tab) - 1].read) - *cnr = 1000; + last = ARRAY_SIZE(stv090x_s1cn_tab) - 1; + div = stv090x_s1cn_tab[0].read - + stv090x_s1cn_tab[last].read; + *cnr = 0xFFFF - ((val * 0xFFFF) / div); } break; default: From b671a8d4b68626142a9a34da59c55396d2cf0ce9 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:15:27 -0300 Subject: [PATCH 212/345] V4L/DVB (13354): stv090x: fixes some typos like wrong register or variable names Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index e74419b682d3..fe03bac5b2e4 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -825,7 +825,7 @@ static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate sym /= (state->mclk >> 7); } - if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0xff)) < 0) /* MSB */ + if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */ goto err; if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */ goto err; @@ -1317,7 +1317,7 @@ static int stv090x_start_search(struct stv090x_state *state) goto err; if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, CFRUP1, 0xff) < 0) + if (STV090x_WRITE_DEMOD(state, CFRUP0, 0xff) < 0) goto err; if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0) goto err; @@ -1371,7 +1371,7 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, CFRUP1, LSB(freq)) < 0) + if (STV090x_WRITE_DEMOD(state, CFRUP0, LSB(freq)) < 0) goto err; freq *= -1; @@ -1525,7 +1525,7 @@ static int stv090x_get_agc2_min_level(struct stv090x_state *state) else freq_init = freq_init - (freq_step * i); - dir = -1; + dir *= -1; if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */ goto err; @@ -2425,7 +2425,7 @@ static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk) derot = (int_1 * int_2) + ((int_1 * tmp_2) >> 12) + - ((int_1 * tmp_1) >> 12); + ((int_2 * tmp_1) >> 12); return derot; } @@ -2732,7 +2732,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) switch (state->delsys) { case STV090x_DVBS1: case STV090x_DSS: - if (state->algo == STV090x_SEARCH_AUTO) { + if (state->search_mode == STV090x_SEARCH_AUTO) { reg = STV090x_READ_DEMOD(state, DMDCFGMD); STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); From b4a4248d56a6985f5d37fc5a219ba0675fc6f503 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:16:44 -0300 Subject: [PATCH 213/345] V4L/DVB (13355): stv090x: fixes calculation of AGC2 and uses a different AGC2 threshold for cut 3 chips Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 33 ++++++++++++++-------- drivers/media/dvb/frontends/stv090x_priv.h | 2 +- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index fe03bac5b2e4..8c0d351405f3 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1485,7 +1485,7 @@ static int stv090x_start_search(struct stv090x_state *state) static int stv090x_get_agc2_min_level(struct stv090x_state *state) { - u32 agc2_min = 0, agc2 = 0, freq_init, freq_step, reg; + u32 agc2_min = 0xffff, agc2 = 0, freq_init, freq_step, reg; s32 i, j, steps, dir; if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) @@ -1536,13 +1536,14 @@ static int stv090x_get_agc2_min_level(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */ goto err; msleep(10); + + agc2 = 0; for (j = 0; j < 10; j++) { - agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8; - agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) | + STV090x_READ_DEMOD(state, AGC2I0); } agc2 /= 10; - agc2_min = 0xffff; - if (agc2 < 0xffff) + if (agc2 < agc2_min) agc2_min = agc2; } @@ -1584,6 +1585,12 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) int tmg_lock = 0, i; s32 tmg_cpt = 0, dir = 1, steps, cur_step = 0, freq; u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg; + u32 agc2th; + + if (state->dev_ver >= 0x30) + agc2th = 0x2e00; + else + agc2th = 0x1f00; reg = STV090x_READ_DEMOD(state, DMDISTATE); STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */ @@ -1611,7 +1618,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) goto err; if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x60) < 0) + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0) goto err; if (state->dev_ver >= 0x30) { @@ -1661,14 +1668,15 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) reg = STV090x_READ_DEMOD(state, DSTATUS); if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2) tmg_cpt++; - agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8; - agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) | + STV090x_READ_DEMOD(state, AGC2I0); } agc2 /= 10; srate_coarse = stv090x_get_srate(state, state->mclk); cur_step++; dir *= -1; - if ((tmg_cpt >= 5) && (agc2 < 0x1f00) && (srate_coarse < 55000000) && (srate_coarse > 850000)) + if ((tmg_cpt >= 5) && (agc2 < agc2th) && + (srate_coarse < 50000000) && (srate_coarse > 850000)) tmg_lock = 1; else if (cur_step < steps) { if (dir > 0) @@ -1751,6 +1759,9 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) goto err; + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) + goto err; + if (state->dev_ver >= 0x30) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0) goto err; @@ -1908,8 +1919,8 @@ static int stv090x_blind_search(struct stv090x_state *state) cpt_fail = 0; agc2_ovflw = 0; for (i = 0; i < 10; i++) { - agc2 = STV090x_READ_DEMOD(state, AGC2I1) << 8; - agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) | + STV090x_READ_DEMOD(state, AGC2I0); if (agc2 >= 0xff00) agc2_ovflw++; reg = STV090x_READ_DEMOD(state, DSTATUS2); diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h index 5a4a01740d88..5696816b88a4 100644 --- a/drivers/media/dvb/frontends/stv090x_priv.h +++ b/drivers/media/dvb/frontends/stv090x_priv.h @@ -83,7 +83,7 @@ #define STV090x_IQPOWER_THRESHOLD 30 #define STV090x_SEARCH_AGC2_TH_CUT20 700 -#define STV090x_SEARCH_AGC2_TH_CUT30 1200 +#define STV090x_SEARCH_AGC2_TH_CUT30 1400 #define STV090x_SEARCH_AGC2_TH(__ver) \ ((__ver <= 0x20) ? \ From a4978a83e51324aed08b1f1105a58f7e6491b751 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:17:45 -0300 Subject: [PATCH 214/345] V4L/DVB (13356): stv090x: fixes signal lock logic This patch contains several fixes for the stv090x driver: - added missing else - use calculated timeout instead of fixed one - use correct frequency when doing zigzag scan - added missing read of GENCFG register Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 8c0d351405f3..a2ec0ed48832 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1436,9 +1436,7 @@ static int stv090x_start_search(struct stv090x_state *state) } if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0) goto err; - } - - if (state->srate < 10000000) { + } else if (state->srate < 10000000) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0) goto err; } else { @@ -1689,7 +1687,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) goto err; if (state->config->tuner_set_frequency) { - if (state->config->tuner_set_frequency(fe, state->frequency) < 0) + if (state->config->tuner_set_frequency(fe, freq) < 0) goto err; } @@ -1867,7 +1865,7 @@ static int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout) static int stv090x_blind_search(struct stv090x_state *state) { u32 agc2, reg, srate_coarse; - s32 timeout_dmd = 500, cpt_fail, agc2_ovflw, i; + s32 cpt_fail, agc2_ovflw, i; u8 k_ref, k_max, k_min; int coarse_fail, lock; @@ -1911,7 +1909,8 @@ static int stv090x_blind_search(struct stv090x_state *state) srate_coarse = stv090x_srate_srch_fine(state); if (srate_coarse != 0) { stv090x_get_lock_tmg(state); - lock = stv090x_get_dmdlock(state, timeout_dmd); + lock = stv090x_get_dmdlock(state, + state->DemodTimeout); } else { lock = 0; } @@ -2073,7 +2072,7 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) goto err; if (state->config->tuner_set_frequency) { - if (state->config->tuner_set_frequency(fe, state->frequency) < 0) + if (state->config->tuner_set_frequency(fe, freq) < 0) goto err; } @@ -3053,7 +3052,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) struct dvb_frontend *fe = &state->frontend; enum stv090x_signal_state signal_state = STV090x_NOCARRIER; u32 reg; - s32 timeout_dmd = 500, timeout_fec = 50, agc1_power, power_iq = 0, i; + s32 agc1_power, power_iq = 0, i; int lock = 0, low_sr = 0, no_signal = 0; reg = STV090x_READ_DEMOD(state, TSCFGH); @@ -3218,10 +3217,10 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) lock = stv090x_blind_search(state); else if (state->algo == STV090x_COLD_SEARCH) - lock = stv090x_get_coldlock(state, timeout_dmd); + lock = stv090x_get_coldlock(state, state->DemodTimeout); else if (state->algo == STV090x_WARM_SEARCH) - lock = stv090x_get_dmdlock(state, timeout_dmd); + lock = stv090x_get_dmdlock(state, state->DemodTimeout); if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) { if (!low_sr) { @@ -3256,8 +3255,9 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) goto err; } - if (stv090x_get_lock(state, timeout_fec, timeout_fec)) { - lock = 1; + lock = stv090x_get_lock(state, state->FecTimeout, + state->FecTimeout); + if (lock) { if (state->delsys == STV090x_DVBS2) { stv090x_set_s2rolloff(state); @@ -3284,7 +3284,6 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) goto err; } else { - lock = 0; signal_state = STV090x_NODATA; no_signal = stv090x_chk_signal(state); } @@ -3769,6 +3768,8 @@ static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc { u32 reg = 0; + reg = stv090x_read_reg(state, STV090x_GENCFG); + switch (ldpc_mode) { case STV090x_DUAL: default: From c4fa649a3beca1e311d7f244de67306673f4c285 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:18:53 -0300 Subject: [PATCH 215/345] V4L/DVB (13357): stv090x: adds an additional check for signal presence based on AGC1 Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 7 +++---- drivers/media/dvb/frontends/stv090x_priv.h | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index a2ec0ed48832..647c5354300f 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3185,7 +3185,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) { dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq); lock = 0; - + signal_state = STV090x_NOAGC1; } else { reg = STV090x_READ_DEMOD(state, DEMOD); STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); @@ -3209,9 +3209,8 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) } } - /* need to check for AGC1 state */ - - + if (signal_state == STV090x_NOAGC1) + return signal_state; if (state->algo == STV090x_BLIND_SEARCH) lock = stv090x_blind_search(state); diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h index 5696816b88a4..5921a8d6c89f 100644 --- a/drivers/media/dvb/frontends/stv090x_priv.h +++ b/drivers/media/dvb/frontends/stv090x_priv.h @@ -91,6 +91,7 @@ STV090x_SEARCH_AGC2_TH_CUT30) enum stv090x_signal_state { + STV090x_NOAGC1, STV090x_NOCARRIER, STV090x_NODATA, STV090x_DATAOK, From 1d4361718a47fba3b51f6e155524b5473a5b8d18 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:19:54 -0300 Subject: [PATCH 216/345] V4L/DVB (13358): stv090x: add an additional check for packet delineator lock in stv090x_read_status in case of a tuned DVB-S2 signal Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 647c5354300f..65ae677015e4 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3324,7 +3324,6 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron return DVBFE_ALGO_SEARCH_ERROR; } -/* FIXME! */ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct stv090x_state *state = fe->demodulator_priv; @@ -3346,9 +3345,15 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2"); reg = STV090x_READ_DEMOD(state, DSTATUS); if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) { - reg = STV090x_READ_DEMOD(state, TSSTATUS); - if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { - *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + reg = STV090x_READ_DEMOD(state, PDELSTATUS1); + if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) { + reg = STV090x_READ_DEMOD(state, TSSTATUS); + if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { + *status = FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC | + FE_HAS_LOCK; + } } } break; From 7b035da93eb6ba839b39c61c5d993365ae308684 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:20:54 -0300 Subject: [PATCH 217/345] V4L/DVB (13359): stv090x: adds corrections of some register values While here, also do some blind scan related fixes. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 84 ++++++++++++++------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 65ae677015e4..48edd542242e 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1238,6 +1238,8 @@ static int stv090x_delivery_search(struct stv090x_state *state) goto err; } + if (stv090x_set_vit_thtracq(state) < 0) + goto err; break; case STV090x_SEARCH_AUTO: @@ -1278,17 +1280,8 @@ static int stv090x_delivery_search(struct stv090x_state *state) goto err; } - if (state->srate >= 2000000) { - /* Srate >= 2MSPS, Viterbi threshold to acquire */ - if (stv090x_set_vit_thacq(state) < 0) - goto err; - } else { - /* Srate < 2MSPS, Reset Viterbi thresholdto track - * and then re-acquire - */ - if (stv090x_set_vit_thtracq(state) < 0) - goto err; - } + if (stv090x_set_vit_thacq(state) < 0) + goto err; if (stv090x_set_viterbi(state) < 0) goto err; @@ -1422,6 +1415,9 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0) goto err; + if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) + goto err; + if (state->dev_ver >= 0x20) { /*Frequency offset detector setting*/ if (state->srate < 2000000) { @@ -1430,7 +1426,7 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0) goto err; } else { - /* Cut 2 */ + /* Cut 3 */ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0) goto err; } @@ -1439,9 +1435,13 @@ static int stv090x_start_search(struct stv090x_state *state) } else if (state->srate < 10000000) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0) goto err; + if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0) + goto err; } else { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0) goto err; + if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0) + goto err; } } else { if (state->srate < 10000000) { @@ -1489,8 +1489,8 @@ static int stv090x_get_agc2_min_level(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) goto err; reg = STV090x_READ_DEMOD(state, DMDCFGMD); - STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1); - STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 1); + STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0); if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) goto err; @@ -1507,10 +1507,8 @@ static int stv090x_get_agc2_min_level(struct stv090x_state *state) if (stv090x_set_srate(state, 1000000) < 0) goto err; - steps = -1 + state->search_range / 1000000; - steps /= 2; - steps = (2 * steps) + 1; - if (steps < 0) + steps = state->search_range / 1000000; + if (steps <= 0) steps = 1; dir = 1; @@ -1596,13 +1594,15 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) goto err; if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 0) goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) + goto err; if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xf0) < 0) goto err; if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xe0) < 0) goto err; reg = STV090x_READ_DEMOD(state, DMDCFGMD); STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1); - STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 1); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0); if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) goto err; @@ -1622,7 +1622,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) if (state->dev_ver >= 0x30) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) + if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0) goto err; } else if (state->dev_ver >= 0x20) { @@ -1657,9 +1657,16 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) while ((!tmg_lock) && (cur_step < steps)) { if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5f) < 0) /* Demod RESET */ goto err; - reg = STV090x_READ_DEMOD(state, DMDISTATE); - STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x00); /* trigger acquisition */ - if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) + if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRINIT1, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRINIT0, 0x00) < 0) + goto err; + /* trigger acquisition */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x40) < 0) goto err; msleep(50); for (i = 0; i < 10; i++) { @@ -1744,7 +1751,7 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) else { if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */ goto err; - if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0) + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) goto err; if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0) goto err; @@ -1869,8 +1876,8 @@ static int stv090x_blind_search(struct stv090x_state *state) u8 k_ref, k_max, k_min; int coarse_fail, lock; - k_max = 120; - k_min = 30; + k_max = 110; + k_min = 10; agc2 = stv090x_get_agc2_min_level(state); @@ -1933,7 +1940,7 @@ static int stv090x_blind_search(struct stv090x_state *state) lock = 0; } - k_ref -= 30; + k_ref -= 20; } while ((k_ref >= k_min) && (!lock) && (!coarse_fail)); } @@ -2103,17 +2110,6 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) goto err; STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c); - if (state->delsys == STV090x_DVBS2) { - reg = STV090x_READ_DEMOD(state, DMDCFGMD); - STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); - STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); - if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) - goto err; - STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); - STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); - if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) - goto err; - } if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) goto err; if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0) @@ -2867,6 +2863,9 @@ static int stv090x_optimize_track(struct stv090x_state *state) if (stv090x_set_srate(state, srate) < 0) goto err; blind_tune = 1; + + if (stv090x_dvbs_track_crl(state) < 0) + goto err; } if (state->dev_ver >= 0x20) { @@ -3064,8 +3063,13 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) goto err; if (state->dev_ver >= 0x20) { - if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) /* cut 2.0 */ - goto err; + if (state->srate > 5000000) { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x82) < 0) + goto err; + } } stv090x_get_lock_tmg(state); From 7c236e37dd027c0bf35ffbda8de03cbe0c6a750d Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Fri, 13 Nov 2009 18:22:02 -0300 Subject: [PATCH 218/345] V4L/DVB (13360): stv090x: fix the calculation of the r divider in stv6110x_set_frequency It had always the value 3 no matter what frequency was given. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv6110x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c index 3d8a2e01c9c4..bcfcb652464c 100644 --- a/drivers/media/dvb/frontends/stv6110x.c +++ b/drivers/media/dvb/frontends/stv6110x.c @@ -95,7 +95,7 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency) { struct stv6110x_state *stv6110x = fe->tuner_priv; u32 rDiv, divider; - s32 pVal, pCalc, rDivOpt = 0; + s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000; u8 i; STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16)); @@ -121,8 +121,10 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency) for (rDiv = 0; rDiv <= 3; rDiv++) { pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv); - if ((abs((s32)(pCalc - pVal))) < (abs((s32)(1000 - pVal)))) + if ((abs((s32)(pCalc - pVal))) < (abs((s32)(pCalcOpt - pVal)))) rDivOpt = rDiv; + + pCalcOpt = (REFCLOCK_kHz / 100) / R_DIV(rDivOpt); } divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz; From c1426df678c5e9a095ff40285ff3d698d0d25658 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 13 Nov 2009 18:51:39 -0300 Subject: [PATCH 219/345] V4L/DVB (13361): stv090x: fix TS corruption with High Symbol Rate streams With a lower bandwidth setup, the Transport Stream gets corrupted due to TSFIFO overrun. The patch fixes the issue. The issue is seen with Transport Streams having a Symbol Rate of 22MSPS and/or greater. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 8ea915227674..983672aa2450 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1055,7 +1055,7 @@ static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = { { STB0899_TSCFGH , 0x0c }, { STB0899_TSCFGM , 0x00 }, { STB0899_TSCFGL , 0x0c }, - { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */ + { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */ { STB0899_RSSYNCDEL , 0x00 }, { STB0899_TSINHDELH , 0x02 }, { STB0899_TSINHDELM , 0x00 }, diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index b5c681372b6c..88a0a5670ccf 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -1248,7 +1248,7 @@ static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = { { STB0899_TSCFGH , 0x0c }, { STB0899_TSCFGM , 0x00 }, { STB0899_TSCFGL , 0x0c }, - { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */ + { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */ { STB0899_RSSYNCDEL , 0x00 }, { STB0899_TSINHDELH , 0x02 }, { STB0899_TSINHDELM , 0x00 }, From a15c7b42b2b8eda719920e93b81be031f2e0b01b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 13 Nov 2009 22:33:45 -0300 Subject: [PATCH 220/345] V4L/DVB (13363): ec100: add new driver for E3C EC100 DVB-T demodulator E3C EC100 DVB-T demodulator driver Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/ec100.c | 335 +++++++++++++++++++++++ drivers/media/dvb/frontends/ec100.h | 46 ++++ drivers/media/dvb/frontends/ec100_priv.h | 39 +++ 5 files changed, 428 insertions(+) create mode 100644 drivers/media/dvb/frontends/ec100.c create mode 100644 drivers/media/dvb/frontends/ec100.h create mode 100644 drivers/media/dvb/frontends/ec100_priv.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index d7c4837fa71c..4f785f549d02 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -342,6 +342,13 @@ config DVB_AF9013 help Say Y when you want to support this frontend. +config DVB_EC100 + tristate "E3C EC100" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Say Y when you want to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 3523767e7a76..1ca758eeff59 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -76,3 +76,4 @@ obj-$(CONFIG_DVB_STV0900) += stv0900.o obj-$(CONFIG_DVB_STV090x) += stv090x.o obj-$(CONFIG_DVB_STV6110x) += stv6110x.o obj-$(CONFIG_DVB_ISL6423) += isl6423.o +obj-$(CONFIG_DVB_EC100) += ec100.o diff --git a/drivers/media/dvb/frontends/ec100.c b/drivers/media/dvb/frontends/ec100.c new file mode 100644 index 000000000000..2414dc6ee5d9 --- /dev/null +++ b/drivers/media/dvb/frontends/ec100.c @@ -0,0 +1,335 @@ +/* + * E3C EC100 demodulator driver + * + * Copyright (C) 2009 Antti Palosaari + * + * 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 "dvb_frontend.h" +#include "ec100_priv.h" +#include "ec100.h" + +int ec100_debug; +module_param_named(debug, ec100_debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +struct ec100_state { + struct i2c_adapter *i2c; + struct dvb_frontend frontend; + struct ec100_config config; + + u16 ber; +}; + +/* write single register */ +static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val) +{ + u8 buf[2] = {reg, val}; + struct i2c_msg msg = { + .addr = state->config.demod_address, + .flags = 0, + .len = 2, + .buf = buf}; + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + warn("I2C write failed reg:%02x", reg); + return -EREMOTEIO; + } + return 0; +} + +/* read single register */ +static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val) +{ + struct i2c_msg msg[2] = { + { + .addr = state->config.demod_address, + .flags = 0, + .len = 1, + .buf = ® + }, { + .addr = state->config.demod_address, + .flags = I2C_M_RD, + .len = 1, + .buf = val + } + }; + + if (i2c_transfer(state->i2c, msg, 2) != 2) { + warn("I2C read failed reg:%02x", reg); + return -EREMOTEIO; + } + return 0; +} + +static int ec100_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct ec100_state *state = fe->demodulator_priv; + int ret; + u8 tmp, tmp2; + + deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency, + params->u.ofdm.bandwidth); + + /* program tuner */ + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, params); + + ret = ec100_write_reg(state, 0x04, 0x06); + if (ret) + goto error; + ret = ec100_write_reg(state, 0x67, 0x58); + if (ret) + goto error; + ret = ec100_write_reg(state, 0x05, 0x18); + if (ret) + goto error; + + /* reg/bw | 6 | 7 | 8 + -------+------+------+------ + A 0x1b | 0xa1 | 0xe7 | 0x2c + A 0x1c | 0x55 | 0x63 | 0x72 + -------+------+------+------ + B 0x1b | 0xb7 | 0x00 | 0x49 + B 0x1c | 0x55 | 0x64 | 0x72 */ + + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + tmp = 0xb7; + tmp2 = 0x55; + break; + case BANDWIDTH_7_MHZ: + tmp = 0x00; + tmp2 = 0x64; + break; + case BANDWIDTH_8_MHZ: + default: + tmp = 0x49; + tmp2 = 0x72; + } + + ret = ec100_write_reg(state, 0x1b, tmp); + if (ret) + goto error; + ret = ec100_write_reg(state, 0x1c, tmp2); + if (ret) + goto error; + + ret = ec100_write_reg(state, 0x0c, 0xbb); /* if freq */ + if (ret) + goto error; + ret = ec100_write_reg(state, 0x0d, 0x31); /* if freq */ + if (ret) + goto error; + + ret = ec100_write_reg(state, 0x08, 0x24); + if (ret) + goto error; + + ret = ec100_write_reg(state, 0x00, 0x00); /* go */ + if (ret) + goto error; + ret = ec100_write_reg(state, 0x00, 0x20); /* go */ + if (ret) + goto error; + + return ret; +error: + deb_info("%s: failed:%d\n", __func__, ret); + return ret; +} + +static int ec100_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *fesettings) +{ + fesettings->min_delay_ms = 300; + fesettings->step_size = 0; + fesettings->max_drift = 0; + + return 0; +} + +static int ec100_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct ec100_state *state = fe->demodulator_priv; + int ret; + u8 tmp; + *status = 0; + + ret = ec100_read_reg(state, 0x42, &tmp); + if (ret) + goto error; + + if (tmp & 0x80) { + /* bit7 set - have lock */ + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_LOCK; + } else { + ret = ec100_read_reg(state, 0x01, &tmp); + if (ret) + goto error; + + if (tmp & 0x10) { + /* bit4 set - have signal */ + *status |= FE_HAS_SIGNAL; + if (!(tmp & 0x01)) { + /* bit0 clear - have ~valid signal */ + *status |= FE_HAS_CARRIER | FE_HAS_VITERBI; + } + } + } + + return ret; +error: + deb_info("%s: failed:%d\n", __func__, ret); + return ret; +} + +static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct ec100_state *state = fe->demodulator_priv; + int ret; + u8 tmp, tmp2; + u16 ber2; + + *ber = 0; + + ret = ec100_read_reg(state, 0x65, &tmp); + if (ret) + goto error; + ret = ec100_read_reg(state, 0x66, &tmp2); + if (ret) + goto error; + + ber2 = (tmp2 << 8) | tmp; + + /* if counter overflow or clear */ + if (ber2 < state->ber) + *ber = ber2; + else + *ber = ber2 - state->ber; + + state->ber = ber2; + + return ret; +error: + deb_info("%s: failed:%d\n", __func__, ret); + return ret; +} + +static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct ec100_state *state = fe->demodulator_priv; + int ret; + u8 tmp; + + ret = ec100_read_reg(state, 0x24, &tmp); + if (ret) { + *strength = 0; + goto error; + } + + *strength = ((tmp << 8) | tmp); + + return ret; +error: + deb_info("%s: failed:%d\n", __func__, ret); + return ret; +} + +static int ec100_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + *snr = 0; + return 0; +} + +static int ec100_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + *ucblocks = 0; + return 0; +} + +static void ec100_release(struct dvb_frontend *fe) +{ + struct ec100_state *state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops ec100_ops; + +struct dvb_frontend *ec100_attach(const struct ec100_config *config, + struct i2c_adapter *i2c) +{ + int ret; + struct ec100_state *state = NULL; + u8 tmp; + + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct ec100_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->i2c = i2c; + memcpy(&state->config, config, sizeof(struct ec100_config)); + + /* check if the demod is there */ + ret = ec100_read_reg(state, 0x33, &tmp); + if (ret || tmp != 0x0b) + goto error; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &ec100_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + return &state->frontend; +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(ec100_attach); + +static struct dvb_frontend_ops ec100_ops = { + .info = { + .name = "E3C EC100 DVB-T", + .type = FE_OFDM, + .caps = + 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_QAM_16 | + FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | + FE_CAN_MUTE_TS + }, + + .release = ec100_release, + .set_frontend = ec100_set_frontend, + .get_tune_settings = ec100_get_tune_settings, + .read_status = ec100_read_status, + .read_ber = ec100_read_ber, + .read_signal_strength = ec100_read_signal_strength, + .read_snr = ec100_read_snr, + .read_ucblocks = ec100_read_ucblocks, +}; + +MODULE_AUTHOR("Antti Palosaari "); +MODULE_DESCRIPTION("E3C EC100 DVB-T demodulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/ec100.h b/drivers/media/dvb/frontends/ec100.h new file mode 100644 index 000000000000..ee8e52417958 --- /dev/null +++ b/drivers/media/dvb/frontends/ec100.h @@ -0,0 +1,46 @@ +/* + * E3C EC100 demodulator driver + * + * Copyright (C) 2009 Antti Palosaari + * + * 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. + * + */ + +#ifndef EC100_H +#define EC100_H + +#include + +struct ec100_config { + /* demodulator's I2C address */ + u8 demod_address; +}; + + +#if defined(CONFIG_DVB_EC100) || \ + (defined(CONFIG_DVB_EC100_MODULE) && defined(MODULE)) +extern struct dvb_frontend *ec100_attach(const struct ec100_config *config, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *ec100_attach( + const struct ec100_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif /* EC100_H */ diff --git a/drivers/media/dvb/frontends/ec100_priv.h b/drivers/media/dvb/frontends/ec100_priv.h new file mode 100644 index 000000000000..5c990144bc47 --- /dev/null +++ b/drivers/media/dvb/frontends/ec100_priv.h @@ -0,0 +1,39 @@ +/* + * E3C EC100 demodulator driver + * + * Copyright (C) 2009 Antti Palosaari + * + * 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. + * + */ + +#ifndef EC100_PRIV +#define EC100_PRIV + +#define LOG_PREFIX "ec100" + +#define dprintk(var, level, args...) \ + do { if ((var & level)) printk(args); } while (0) + +#define deb_info(args...) dprintk(ec100_debug, 0x01, args) + +#undef err +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) +#undef info +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef warn +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) + +#endif /* EC100_PRIV */ From 2bf290be4f3ef11889026d750244cc3bd1164974 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 13 Nov 2009 22:38:55 -0300 Subject: [PATCH 221/345] V4L/DVB (13364): ec168: add new driver for E3C EC168 DVB USB E3C EC168 DVB USB driver Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 8 + drivers/media/dvb/dvb-usb/Makefile | 3 + drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 6 + drivers/media/dvb/dvb-usb/ec168.c | 440 ++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/ec168.h | 73 ++++ 5 files changed, 530 insertions(+) create mode 100644 drivers/media/dvb/dvb-usb/ec168.c create mode 100644 drivers/media/dvb/dvb-usb/ec168.h diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 0e4b97fba384..2dee1bf73577 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -322,3 +322,11 @@ config DVB_USB_FRIIO depends on DVB_USB help Say Y here to support the Japanese DTV receiver Friio. + +config DVB_USB_EC168 + tristate "E3C EC168 DVB-T USB2.0 support" + depends on DVB_USB && EXPERIMENTAL + select DVB_EC100 + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE + help + Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 85b83a43d55d..72c92cb69a22 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -82,6 +82,9 @@ obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o dvb-usb-friio-objs = friio.o friio-fe.o obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o +dvb-usb-ec168-objs = ec168.o +obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ # due to tuner-xc3028 EXTRA_CFLAGS += -Idrivers/media/common/tuners diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 128fca63df95..491440d6e652 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -27,6 +27,7 @@ #define USB_VID_DIBCOM 0x10b8 #define USB_VID_DPOSH 0x1498 #define USB_VID_DVICO 0x0fe9 +#define USB_VID_E3C 0x18b4 #define USB_VID_ELGATO 0x0fd9 #define USB_VID_EMPIA 0xeb1a #define USB_VID_GENPIX 0x09c0 @@ -104,6 +105,11 @@ #define USB_PID_DIBCOM_STK7770P 0x1e80 #define USB_PID_DPOSH_M9206_COLD 0x9206 #define USB_PID_DPOSH_M9206_WARM 0xa090 +#define USB_PID_E3C_EC168 0x1689 +#define USB_PID_E3C_EC168_2 0xfffa +#define USB_PID_E3C_EC168_3 0xfffb +#define USB_PID_E3C_EC168_4 0x1001 +#define USB_PID_E3C_EC168_5 0x1002 #define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 diff --git a/drivers/media/dvb/dvb-usb/ec168.c b/drivers/media/dvb/dvb-usb/ec168.c new file mode 100644 index 000000000000..52f5d4f0f230 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ec168.c @@ -0,0 +1,440 @@ +/* + * E3C EC168 DVB USB driver + * + * Copyright (C) 2009 Antti Palosaari + * + * 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 "ec168.h" +#include "ec100.h" +#include "mxl5005s.h" + +/* debug */ +static int dvb_usb_ec168_debug; +module_param_named(debug, dvb_usb_ec168_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static struct ec100_config ec168_ec100_config; + +static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) +{ + int ret; + unsigned int pipe; + u8 request, requesttype; + u8 buf[req->size]; + + switch (req->cmd) { + case DOWNLOAD_FIRMWARE: + case GPIO: + case WRITE_I2C: + case STREAMING_CTRL: + requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); + request = req->cmd; + break; + case READ_I2C: + requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); + request = req->cmd; + break; + case GET_CONFIG: + requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); + request = CONFIG; + break; + case SET_CONFIG: + requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); + request = CONFIG; + break; + case WRITE_DEMOD: + requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); + request = DEMOD_RW; + break; + case READ_DEMOD: + requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); + request = DEMOD_RW; + break; + default: + err("unknown command:%02x", req->cmd); + ret = -EPERM; + goto error; + } + + if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { + /* write */ + memcpy(buf, req->data, req->size); + pipe = usb_sndctrlpipe(udev, 0); + } else { + /* read */ + pipe = usb_rcvctrlpipe(udev, 0); + } + + msleep(1); /* avoid I2C errors */ + + ret = usb_control_msg(udev, pipe, request, requesttype, req->value, + req->index, buf, sizeof(buf), EC168_USB_TIMEOUT); + + ec168_debug_dump(request, requesttype, req->value, req->index, buf, + req->size, deb_xfer); + + if (ret < 0) + goto error; + else + ret = 0; + + /* read request, copy returned data to return buf */ + if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) + memcpy(req->data, buf, req->size); + + return ret; +error: + deb_info("%s: failed:%d\n", __func__, ret); + return ret; +} + +static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req) +{ + return ec168_rw_udev(d->udev, req); +} + +/* I2C */ +static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct ec168_req req; + int i = 0; + int ret; + + if (num > 2) + return -EINVAL; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + while (i < num) { + if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { + if (msg[i].addr == ec168_ec100_config.demod_address) { + req.cmd = READ_DEMOD; + req.value = 0; + req.index = 0xff00 + msg[i].buf[0]; /* reg */ + req.size = msg[i+1].len; /* bytes to read */ + req.data = &msg[i+1].buf[0]; + ret = ec168_ctrl_msg(d, &req); + i += 2; + } else { + err("I2C read not implemented"); + ret = -ENOSYS; + i += 2; + } + } else { + if (msg[i].addr == ec168_ec100_config.demod_address) { + req.cmd = WRITE_DEMOD; + req.value = msg[i].buf[1]; /* val */ + req.index = 0xff00 + msg[i].buf[0]; /* reg */ + req.size = 0; + req.data = NULL; + ret = ec168_ctrl_msg(d, &req); + i += 1; + } else { + req.cmd = WRITE_I2C; + req.value = msg[i].buf[0]; /* val */ + req.index = 0x0100 + msg[i].addr; /* I2C addr */ + req.size = msg[i].len-1; + req.data = &msg[i].buf[1]; + ret = ec168_ctrl_msg(d, &req); + i += 1; + } + } + if (ret) + goto error; + + } + ret = i; + +error: + mutex_unlock(&d->i2c_mutex); + return i; +} + + +static u32 ec168_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm ec168_i2c_algo = { + .master_xfer = ec168_i2c_xfer, + .functionality = ec168_i2c_func, +}; + +/* Callbacks for DVB USB */ +static struct ec100_config ec168_ec100_config = { + .demod_address = 0xff, /* not real address, demod is integrated */ +}; + +static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap) +{ + deb_info("%s:\n", __func__); + adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config, + &adap->dev->i2c_adap); + if (adap->fe == NULL) + return -ENODEV; + + return 0; +} + +static struct mxl5005s_config ec168_mxl5003s_config = { + .i2c_address = 0xc6, + .if_freq = IF_FREQ_4570000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_OFF, + .rssi_enable = MXL_RSSI_ENABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; + +static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) +{ + deb_info("%s:\n", __func__); + return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap, + &ec168_mxl5003s_config) == NULL ? -ENODEV : 0; +} + +static int ec168_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL}; + deb_info("%s: onoff:%d\n", __func__, onoff); + if (onoff) + req.index = 0x0102; + return ec168_ctrl_msg(adap->dev, &req); +} + +static int ec168_download_firmware(struct usb_device *udev, + const struct firmware *fw) +{ + int i, len, packets, remainder, ret; + u16 addr = 0x0000; /* firmware start address */ + struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL}; + deb_info("%s:\n", __func__); + + #define FW_PACKET_MAX_DATA 2048 + packets = fw->size / FW_PACKET_MAX_DATA; + remainder = fw->size % FW_PACKET_MAX_DATA; + len = FW_PACKET_MAX_DATA; + for (i = 0; i <= packets; i++) { + if (i == packets) /* set size of the last packet */ + len = remainder; + + req.size = len; + req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA); + req.index = addr; + addr += FW_PACKET_MAX_DATA; + + ret = ec168_rw_udev(udev, &req); + if (ret) { + err("firmware download failed:%d packet:%d", ret, i); + goto error; + } + } + req.size = 0; + + /* set "warm"? */ + req.cmd = SET_CONFIG; + req.value = 0; + req.index = 0x0001; + ret = ec168_rw_udev(udev, &req); + if (ret) + goto error; + + /* really needed - no idea what does */ + req.cmd = GPIO; + req.value = 0; + req.index = 0x0206; + ret = ec168_rw_udev(udev, &req); + if (ret) + goto error; + + /* activate tuner I2C? */ + req.cmd = WRITE_I2C; + req.value = 0; + req.index = 0x00c6; + ret = ec168_rw_udev(udev, &req); + if (ret) + goto error; + + return ret; +error: + deb_info("%s: failed:%d\n", __func__, ret); + return ret; +} + +static int ec168_identify_state(struct usb_device *udev, + struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, int *cold) +{ + int ret; + u8 reply; + struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply}; + deb_info("%s:\n", __func__); + + ret = ec168_rw_udev(udev, &req); + if (ret) + goto error; + + deb_info("%s: reply:%02x\n", __func__, reply); + + if (reply == 0x01) + *cold = 0; + else + *cold = 1; + + return ret; +error: + deb_info("%s: failed:%d\n", __func__, ret); + return ret; +} + +/* DVB USB Driver stuff */ +static struct dvb_usb_device_properties ec168_properties; + +static int ec168_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret; + deb_info("%s: interface:%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + + ret = dvb_usb_device_init(intf, &ec168_properties, THIS_MODULE, NULL, + adapter_nr); + if (ret) + goto error; + + return ret; +error: + deb_info("%s: failed:%d\n", __func__, ret); + return ret; +} + +#define E3C_EC168_1689 0 +#define E3C_EC168_FFFA 1 +#define E3C_EC168_FFFB 2 +#define E3C_EC168_1001 3 +#define E3C_EC168_1002 4 + +static struct usb_device_id ec168_id[] = { + [E3C_EC168_1689] = + {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168)}, + [E3C_EC168_FFFA] = + {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2)}, + [E3C_EC168_FFFB] = + {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3)}, + [E3C_EC168_1001] = + {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4)}, + [E3C_EC168_1002] = + {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5)}, + {} /* terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, ec168_id); + +static struct dvb_usb_device_properties ec168_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .download_firmware = ec168_download_firmware, + .firmware = "dvb-usb-ec168.fw", + .no_reconnect = 1, + + .size_of_priv = 0, + + .num_adapters = 1, + .adapter = { + { + .streaming_ctrl = ec168_streaming_ctrl, + .frontend_attach = ec168_ec100_frontend_attach, + .tuner_attach = ec168_mxl5003s_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = (32*512), + } + } + }, + } + }, + + .identify_state = ec168_identify_state, + + .i2c_algo = &ec168_i2c_algo, + + .num_device_descs = 1, + .devices = { + { + .name = "E3C EC168 DVB-T USB2.0 reference design", + .cold_ids = { + &ec168_id[E3C_EC168_1689], + &ec168_id[E3C_EC168_FFFA], + &ec168_id[E3C_EC168_FFFB], + &ec168_id[E3C_EC168_1001], + &ec168_id[E3C_EC168_1002], + NULL}, + .warm_ids = {NULL}, + }, + } +}; + +static struct usb_driver ec168_driver = { + .name = "dvb_usb_ec168", + .probe = ec168_probe, + .disconnect = dvb_usb_device_exit, + .id_table = ec168_id, +}; + +/* module stuff */ +static int __init ec168_module_init(void) +{ + int ret; + deb_info("%s:\n", __func__); + ret = usb_register(&ec168_driver); + if (ret) + err("module init failed:%d", ret); + + return ret; +} + +static void __exit ec168_module_exit(void) +{ + deb_info("%s:\n", __func__); + /* deregister this driver from the USB subsystem */ + usb_deregister(&ec168_driver); +} + +module_init(ec168_module_init); +module_exit(ec168_module_exit); + +MODULE_AUTHOR("Antti Palosaari "); +MODULE_DESCRIPTION("E3C EC168 DVB-T USB2.0 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/ec168.h b/drivers/media/dvb/dvb-usb/ec168.h new file mode 100644 index 000000000000..e7e0b831314e --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ec168.h @@ -0,0 +1,73 @@ +/* + * E3C EC168 DVB USB driver + * + * Copyright (C) 2009 Antti Palosaari + * + * 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. + * + */ + +#ifndef EC168_H +#define EC168_H + +#define DVB_USB_LOG_PREFIX "ec168" +#include "dvb-usb.h" + +#define deb_info(args...) dprintk(dvb_usb_ec168_debug, 0x01, args) +#define deb_rc(args...) dprintk(dvb_usb_ec168_debug, 0x02, args) +#define deb_xfer(args...) dprintk(dvb_usb_ec168_debug, 0x04, args) +#define deb_reg(args...) dprintk(dvb_usb_ec168_debug, 0x08, args) +#define deb_i2c(args...) dprintk(dvb_usb_ec168_debug, 0x10, args) +#define deb_fw(args...) dprintk(dvb_usb_ec168_debug, 0x20, args) + +#define ec168_debug_dump(r, t, v, i, b, l, func) { \ + int loop_; \ + func("%02x %02x %02x %02x %02x %02x %02x %02x", \ + t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ + if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ + func(" >>> "); \ + else \ + func(" <<< "); \ + for (loop_ = 0; loop_ < l; loop_++) \ + func("%02x ", b[loop_]); \ + func("\n");\ +} + +#define EC168_USB_TIMEOUT 1000 + +struct ec168_req { + u8 cmd; /* [1] */ + u16 value; /* [2|3] */ + u16 index; /* [4|5] */ + u16 size; /* [6|7] */ + u8 *data; +}; + +enum ec168_cmd { + DOWNLOAD_FIRMWARE = 0x00, + CONFIG = 0x01, + DEMOD_RW = 0x03, + GPIO = 0x04, + STREAMING_CTRL = 0x10, + READ_I2C = 0x20, + WRITE_I2C = 0x21, + HID_DOWNLOAD = 0x30, + GET_CONFIG, + SET_CONFIG, + READ_DEMOD, + WRITE_DEMOD, +}; + +#endif From 5232263a7daa1247fe4a30579c296ddccfeeb7e6 Mon Sep 17 00:00:00 2001 From: Ignacio de Miguel Diaz Date: Fri, 13 Nov 2009 23:13:34 -0300 Subject: [PATCH 222/345] V4L/DVB (13368): af9015: support for Sveon STV20 Tuner USB DVB-T HDTV Add USB ID 1b80:e39d for Sveon STV20 Tuner USB DVB-T HDTV. Signed-off-by: Ignacio de Miguel Diaz Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 8 +++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index bad3e10f3724..8b60a601fb82 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1294,6 +1294,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, /* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1565,7 +1566,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 5, /* max 9 */ + .num_device_descs = 6, /* max 9 */ .devices = { { .name = "AverMedia AVerTV Volar GPS 805 (A805)", @@ -1594,6 +1595,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[26], NULL}, .warm_ids = {NULL}, }, + { + .name = "Sveon STV20 Tuner USB DVB-T HDTV", + .cold_ids = {&af9015_usb_table[27], NULL}, + .warm_ids = {NULL}, + }, } }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 491440d6e652..dc57fe1b6f0f 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -285,5 +285,6 @@ #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 #define USB_PID_FRIIO_WHITE 0x0001 #define USB_PID_TVWAY_PLUS 0x0002 +#define USB_PID_SVEON_STV20 0xe39d #endif From 95963cbcd0ee00026cc34ba84906ee4aa2029f4d Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Mon, 26 Oct 2009 06:42:34 -0300 Subject: [PATCH 223/345] V4L/DVB (13373): Maxium MAX2165 silicon tuner Adds support for Maxim MAX2165 silicon tuner. It is tested on Mygica X8558Pro, which has MAX2165, ATBM8830 and CX23885 Signed-off-by: David T. L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 7 + drivers/media/common/tuners/Makefile | 1 + drivers/media/common/tuners/max2165.c | 442 +++++++++++++++++++++ drivers/media/common/tuners/max2165.h | 48 +++ drivers/media/common/tuners/max2165_priv.h | 60 +++ 5 files changed, 558 insertions(+) create mode 100644 drivers/media/common/tuners/max2165.c create mode 100644 drivers/media/common/tuners/max2165.h create mode 100644 drivers/media/common/tuners/max2165_priv.h diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 607d319ce8ed..409a4261e5b5 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -172,4 +172,11 @@ config MEDIA_TUNER_MC44S803 help Say Y here to support the Freescale MC44S803 based tuners +config MEDIA_TUNER_MAX2165 + tristate "Maxim MAX2165 silicon tuner" + depends on VIDEO_MEDIA && I2C + default m if MEDIA_TUNER_CUSTOMISE + help + A driver for the silicon tuner MAX2165 from Maxim. + endif # MEDIA_TUNER_CUSTOMISE diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile index 4132b2be79e5..a5438523f30d 100644 --- a/drivers/media/common/tuners/Makefile +++ b/drivers/media/common/tuners/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o +obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/common/tuners/max2165.c b/drivers/media/common/tuners/max2165.c new file mode 100644 index 000000000000..1b486cfb8ed9 --- /dev/null +++ b/drivers/media/common/tuners/max2165.c @@ -0,0 +1,442 @@ +/* + * Driver for Maxim MAX2165 silicon tuner + * + * Copyright (c) 2009 David T. L. Wong + * + * 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 +#include + +#include "dvb_frontend.h" + +#include "max2165.h" +#include "max2165_priv.h" +#include "tuner-i2c.h" + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "max2165: " args); \ + } while (0) + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); + +static int max2165_write_reg(struct max2165_priv *priv, u8 reg, u8 data) +{ + int ret; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; + + msg.addr = priv->config->i2c_address; + + if (debug >= 2) + printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", + __func__, reg, data); + + ret = i2c_transfer(priv->i2c, &msg, 1); + + if (ret != 1) + dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n", + __func__, reg, data, ret); + + return (ret != 1) ? -EIO : 0; +} + +static int max2165_read_reg(struct max2165_priv *priv, u8 reg, u8 *p_data) +{ + int ret; + u8 dev_addr = priv->config->i2c_address; + + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { .addr = dev_addr, .flags = 0, .buf = b0, .len = 1 }, + { .addr = dev_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }, + }; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret != 2) { + dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n", + __func__, reg, ret); + return -EIO; + } + + *p_data = b1[0]; + if (debug >= 2) + printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", + __func__, reg, b1[0]); + return 0; +} + +static int max2165_mask_write_reg(struct max2165_priv *priv, u8 reg, + u8 mask, u8 data) +{ + int ret; + u8 v; + + data &= mask; + ret = max2165_read_reg(priv, reg, &v); + if (ret != 0) + return ret; + v &= ~mask; + v |= data; + ret = max2165_write_reg(priv, reg, v); + + return ret; +} + +static int max2165_read_rom_table(struct max2165_priv *priv) +{ + u8 dat[3]; + int i; + + for (i = 0; i < 3; i++) { + max2165_write_reg(priv, REG_ROM_TABLE_ADDR, i + 1); + max2165_read_reg(priv, REG_ROM_TABLE_DATA, &dat[i]); + } + + priv->tf_ntch_low_cfg = dat[0] >> 4; + priv->tf_ntch_hi_cfg = dat[0] & 0x0F; + priv->tf_balun_low_ref = dat[1] & 0x0F; + priv->tf_balun_hi_ref = dat[1] >> 4; + priv->bb_filter_7mhz_cfg = dat[2] & 0x0F; + priv->bb_filter_8mhz_cfg = dat[2] >> 4; + + dprintk("tf_ntch_low_cfg = 0x%X\n", priv->tf_ntch_low_cfg); + dprintk("tf_ntch_hi_cfg = 0x%X\n", priv->tf_ntch_hi_cfg); + dprintk("tf_balun_low_ref = 0x%X\n", priv->tf_balun_low_ref); + dprintk("tf_balun_hi_ref = 0x%X\n", priv->tf_balun_hi_ref); + dprintk("bb_filter_7mhz_cfg = 0x%X\n", priv->bb_filter_7mhz_cfg); + dprintk("bb_filter_8mhz_cfg = 0x%X\n", priv->bb_filter_8mhz_cfg); + + return 0; +} + +static int max2165_set_osc(struct max2165_priv *priv, u8 osc /*MHz*/) +{ + u8 v; + + v = (osc / 2); + if (v == 2) + v = 0x7; + else + v -= 8; + + max2165_mask_write_reg(priv, REG_PLL_CFG, 0x07, v); + + return 0; +} + +static int max2165_set_bandwidth(struct max2165_priv *priv, u32 bw) +{ + u8 val; + + if (bw == BANDWIDTH_8_MHZ) + val = priv->bb_filter_8mhz_cfg; + else + val = priv->bb_filter_7mhz_cfg; + + max2165_mask_write_reg(priv, REG_BASEBAND_CTRL, 0xF0, val << 4); + + return 0; +} + +int fixpt_div32(u32 dividend, u32 divisor, u32 *quotient, u32 *fraction) +{ + u32 remainder; + u32 q, f = 0; + int i; + + if (0 == divisor) + return -1; + + q = dividend / divisor; + remainder = dividend - q * divisor; + + for (i = 0; i < 31; i++) { + remainder <<= 1; + if (remainder >= divisor) { + f += 1; + remainder -= divisor; + } + f <<= 1; + } + + *quotient = q; + *fraction = f; + + return 0; +} + +static int max2165_set_rf(struct max2165_priv *priv, u32 freq) +{ + u8 tf; + u8 tf_ntch; + double t; + u32 quotient, fraction; + + /* Set PLL divider according to RF frequency */ + fixpt_div32(freq / 1000, priv->config->osc_clk * 1000, + "ient, &fraction); + + /* 20-bit fraction */ + fraction >>= 12; + + max2165_write_reg(priv, REG_NDIV_INT, quotient); + max2165_mask_write_reg(priv, REG_NDIV_FRAC2, 0x0F, fraction >> 16); + max2165_write_reg(priv, REG_NDIV_FRAC1, fraction >> 8); + max2165_write_reg(priv, REG_NDIV_FRAC0, fraction); + + /* Norch Filter */ + tf_ntch = (freq < 725000000) ? + priv->tf_ntch_low_cfg : priv->tf_ntch_hi_cfg; + + /* Tracking filter balun */ + t = priv->tf_balun_low_ref; + t += (priv->tf_balun_hi_ref - priv->tf_balun_low_ref) + * (freq / 1000 - 470000) / (780000 - 470000); + + tf = t; + dprintk("tf = %X\n", tf); + tf |= tf_ntch << 4; + + max2165_write_reg(priv, REG_TRACK_FILTER, tf); + + return 0; +} + +static void max2165_debug_status(struct max2165_priv *priv) +{ + u8 status, autotune; + u8 auto_vco_success, auto_vco_active; + u8 pll_locked; + u8 dc_offset_low, dc_offset_hi; + u8 signal_lv_over_threshold; + u8 vco, vco_sub_band, adc; + + max2165_read_reg(priv, REG_STATUS, &status); + max2165_read_reg(priv, REG_AUTOTUNE, &autotune); + + auto_vco_success = (status >> 6) & 0x01; + auto_vco_active = (status >> 5) & 0x01; + pll_locked = (status >> 4) & 0x01; + dc_offset_low = (status >> 3) & 0x01; + dc_offset_hi = (status >> 2) & 0x01; + signal_lv_over_threshold = status & 0x01; + + vco = autotune >> 6; + vco_sub_band = (autotune >> 3) & 0x7; + adc = autotune & 0x7; + + dprintk("auto VCO active: %d, auto VCO success: %d\n", + auto_vco_active, auto_vco_success); + dprintk("PLL locked: %d\n", pll_locked); + dprintk("DC offset low: %d, DC offset high: %d\n", + dc_offset_low, dc_offset_hi); + dprintk("Signal lvl over threshold: %d\n", signal_lv_over_threshold); + dprintk("VCO: %d, VCO Sub-band: %d, ADC: %d\n", vco, vco_sub_band, adc); +} + +static int max2165_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct max2165_priv *priv = fe->tuner_priv; + int ret; + + dprintk("%s() frequency=%d (Hz)\n", __func__, params->frequency); + if (fe->ops.info.type == FE_ATSC) { + return -EINVAL; + } else if (fe->ops.info.type == FE_OFDM) { + dprintk("%s() OFDM\n", __func__); + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + return -EINVAL; + case BANDWIDTH_7_MHZ: + case BANDWIDTH_8_MHZ: + priv->frequency = params->frequency; + priv->bandwidth = params->u.ofdm.bandwidth; + break; + default: + printk(KERN_ERR "MAX2165 bandwidth not set!\n"); + return -EINVAL; + } + } else { + printk(KERN_ERR "MAX2165 modulation type not supported!\n"); + return -EINVAL; + } + + dprintk("%s() frequency=%d\n", __func__, priv->frequency); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + max2165_set_bandwidth(priv, priv->bandwidth); + ret = max2165_set_rf(priv, priv->frequency); + mdelay(50); + max2165_debug_status(priv); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret != 0) + return -EREMOTEIO; + + return 0; +} + +static int max2165_get_frequency(struct dvb_frontend *fe, u32 *freq) +{ + struct max2165_priv *priv = fe->tuner_priv; + dprintk("%s()\n", __func__); + *freq = priv->frequency; + return 0; +} + +static int max2165_get_bandwidth(struct dvb_frontend *fe, u32 *bw) +{ + struct max2165_priv *priv = fe->tuner_priv; + dprintk("%s()\n", __func__); + + *bw = priv->bandwidth; + return 0; +} + +static int max2165_get_status(struct dvb_frontend *fe, u32 *status) +{ + struct max2165_priv *priv = fe->tuner_priv; + u16 lock_status = 0; + + dprintk("%s()\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + max2165_debug_status(priv); + *status = lock_status; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int max2165_sleep(struct dvb_frontend *fe) +{ + dprintk("%s()\n", __func__); + return 0; +} + +static int max2165_init(struct dvb_frontend *fe) +{ + struct max2165_priv *priv = fe->tuner_priv; + dprintk("%s()\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* Setup initial values */ + /* Fractional Mode on */ + max2165_write_reg(priv, REG_NDIV_FRAC2, 0x18); + /* LNA on */ + max2165_write_reg(priv, REG_LNA, 0x01); + max2165_write_reg(priv, REG_PLL_CFG, 0x7A); + max2165_write_reg(priv, REG_TEST, 0x08); + max2165_write_reg(priv, REG_SHUTDOWN, 0x40); + max2165_write_reg(priv, REG_VCO_CTRL, 0x84); + max2165_write_reg(priv, REG_BASEBAND_CTRL, 0xC3); + max2165_write_reg(priv, REG_DC_OFFSET_CTRL, 0x75); + max2165_write_reg(priv, REG_DC_OFFSET_DAC, 0x00); + max2165_write_reg(priv, REG_ROM_TABLE_ADDR, 0x00); + + max2165_set_osc(priv, priv->config->osc_clk); + + max2165_read_rom_table(priv); + + max2165_set_bandwidth(priv, BANDWIDTH_8_MHZ); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int max2165_release(struct dvb_frontend *fe) +{ + struct max2165_priv *priv = fe->tuner_priv; + dprintk("%s()\n", __func__); + + kfree(priv); + fe->tuner_priv = NULL; + + return 0; +} + +static const struct dvb_tuner_ops max2165_tuner_ops = { + .info = { + .name = "Maxim MAX2165", + .frequency_min = 470000000, + .frequency_max = 780000000, + .frequency_step = 50000, + }, + + .release = max2165_release, + .init = max2165_init, + .sleep = max2165_sleep, + + .set_params = max2165_set_params, + .set_analog_params = NULL, + .get_frequency = max2165_get_frequency, + .get_bandwidth = max2165_get_bandwidth, + .get_status = max2165_get_status +}; + +struct dvb_frontend *max2165_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct max2165_config *cfg) +{ + struct max2165_priv *priv = NULL; + + dprintk("%s(%d-%04x)\n", __func__, + i2c ? i2c_adapter_id(i2c) : -1, + cfg ? cfg->i2c_address : -1); + + priv = kzalloc(sizeof(struct max2165_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + memcpy(&fe->ops.tuner_ops, &max2165_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + priv->config = cfg; + priv->i2c = i2c; + fe->tuner_priv = priv; + + max2165_init(fe); + max2165_debug_status(priv); + + return fe; +} +EXPORT_SYMBOL(max2165_attach); + +MODULE_AUTHOR("David T. L. Wong "); +MODULE_DESCRIPTION("Maxim MAX2165 silicon tuner driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/tuners/max2165.h b/drivers/media/common/tuners/max2165.h new file mode 100644 index 000000000000..c063c36a93d3 --- /dev/null +++ b/drivers/media/common/tuners/max2165.h @@ -0,0 +1,48 @@ +/* + * Driver for Maxim MAX2165 silicon tuner + * + * Copyright (c) 2009 David T. L. Wong + * + * 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. + */ + +#ifndef __MAX2165_H__ +#define __MAX2165_H__ + +struct dvb_frontend; +struct i2c_adapter; + +struct max2165_config { + u8 i2c_address; + u8 osc_clk; /* in MHz, selectable values: 4,16,18,20,22,24,26,28 */ +}; + +#if defined(CONFIG_MEDIA_TUNER_MAX2165) || \ + (defined(CONFIG_MEDIA_TUNER_MAX2165_MODULE) && defined(MODULE)) +extern struct dvb_frontend *max2165_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct max2165_config *cfg); +#else +static inline struct dvb_frontend *max2165_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct max2165_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif diff --git a/drivers/media/common/tuners/max2165_priv.h b/drivers/media/common/tuners/max2165_priv.h new file mode 100644 index 000000000000..91bbe021a08d --- /dev/null +++ b/drivers/media/common/tuners/max2165_priv.h @@ -0,0 +1,60 @@ +/* + * Driver for Maxim MAX2165 silicon tuner + * + * Copyright (c) 2009 David T. L. Wong + * + * 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. + */ + +#ifndef __MAX2165_PRIV_H__ +#define __MAX2165_PRIV_H__ + +#define REG_NDIV_INT 0x00 +#define REG_NDIV_FRAC2 0x01 +#define REG_NDIV_FRAC1 0x02 +#define REG_NDIV_FRAC0 0x03 +#define REG_TRACK_FILTER 0x04 +#define REG_LNA 0x05 +#define REG_PLL_CFG 0x06 +#define REG_TEST 0x07 +#define REG_SHUTDOWN 0x08 +#define REG_VCO_CTRL 0x09 +#define REG_BASEBAND_CTRL 0x0A +#define REG_DC_OFFSET_CTRL 0x0B +#define REG_DC_OFFSET_DAC 0x0C +#define REG_ROM_TABLE_ADDR 0x0D + +/* Read Only Registers */ +#define REG_ROM_TABLE_DATA 0x10 +#define REG_STATUS 0x11 +#define REG_AUTOTUNE 0x12 + +struct max2165_priv { + struct max2165_config *config; + struct i2c_adapter *i2c; + + u32 frequency; + u32 bandwidth; + + u8 tf_ntch_low_cfg; + u8 tf_ntch_hi_cfg; + u8 tf_balun_low_ref; + u8 tf_balun_hi_ref; + u8 bb_filter_7mhz_cfg; + u8 bb_filter_8mhz_cfg; +}; + +#endif From ec27b6aafb1796a09aad401143f70ad079421ca4 Mon Sep 17 00:00:00 2001 From: "David T.L. Wong" Date: Mon, 26 Oct 2009 07:08:17 -0300 Subject: [PATCH 224/345] V4L/DVB (13374): AltoBeam ATBM8830 GB20600-2006(DMB-TH) demodulator Adds support for Maxim MAX2165 silicon tuner. It was tested on Mygica X8558Pro, which has MAX2165, ATBM8830 and CX23885. Signed-off-by: David T. L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/atbm8830.c | 495 ++++++++++++++++++++ drivers/media/dvb/frontends/atbm8830.h | 76 +++ drivers/media/dvb/frontends/atbm8830_priv.h | 75 +++ 5 files changed, 654 insertions(+) create mode 100644 drivers/media/dvb/frontends/atbm8830.c create mode 100644 drivers/media/dvb/frontends/atbm8830.h create mode 100644 drivers/media/dvb/frontends/atbm8830_priv.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 4f785f549d02..fdc7926cb2db 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -564,6 +564,13 @@ config DVB_LGS8GXX help A DMB-TH tuner module. Say Y when you want to support this frontend. +config DVB_ATBM8830 + tristate "AltoBeam ATBM8830/8831 DMB-TH demodulator" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DMB-TH tuner module. Say Y when you want to support this frontend. + comment "Tools to develop new frontends" config DVB_DUMMY_FE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 1ca758eeff59..390eec6d5d84 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o +obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o obj-$(CONFIG_DVB_AF9013) += af9013.o obj-$(CONFIG_DVB_CX24116) += cx24116.o diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c new file mode 100644 index 000000000000..87fb3c23b80f --- /dev/null +++ b/drivers/media/dvb/frontends/atbm8830.c @@ -0,0 +1,495 @@ +/* + * Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator + * ATBM8830, ATBM8831 + * + * Copyright (C) 2009 David T.L. Wong + * + * 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 "dvb_frontend.h" + +#include "atbm8830.h" +#include "atbm8830_priv.h" + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "atbm8830: " args); \ + } while (0) + +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +static int atbm8830_write_reg(struct atbm_state *priv, u16 reg, u8 data) +{ + int ret = 0; + u8 dev_addr; + u8 buf1[] = { reg >> 8, reg & 0xFF }; + u8 buf2[] = { data }; + struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 }; + struct i2c_msg msg2 = { .flags = 0, .buf = buf2, .len = 1 }; + + dev_addr = priv->config->demod_address; + msg1.addr = dev_addr; + msg2.addr = dev_addr; + + if (debug >= 2) + printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n", + __func__, reg, data); + + ret = i2c_transfer(priv->i2c, &msg1, 1); + if (ret != 1) + return -EIO; + + ret = i2c_transfer(priv->i2c, &msg2, 1); + return (ret != 1) ? -EIO : 0; +} + +static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data) +{ + int ret; + u8 dev_addr; + + u8 buf1[] = { reg >> 8, reg & 0xFF }; + u8 buf2[] = { 0 }; + struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 }; + struct i2c_msg msg2 = { .flags = I2C_M_RD, .buf = buf2, .len = 1 }; + + dev_addr = priv->config->demod_address; + msg1.addr = dev_addr; + msg2.addr = dev_addr; + + ret = i2c_transfer(priv->i2c, &msg1, 1); + if (ret != 1) { + dprintk(KERN_DEBUG "%s: error reg=0x%04x, ret=%i\n", + __func__, reg, ret); + return -EIO; + } + + ret = i2c_transfer(priv->i2c, &msg2, 1); + if (ret != 1) + return -EIO; + + *p_data = buf2[0]; + if (debug >= 2) + printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n", + __func__, reg, buf2[0]); + + return 0; +} + +/* Lock register latch so that multi-register read is atomic */ +static inline int atbm8830_reglatch_lock(struct atbm_state *priv, int lock) +{ + return atbm8830_write_reg(priv, REG_READ_LATCH, lock ? 1 : 0); +} + +static int set_osc_freq(struct atbm_state *priv, u32 freq /*in kHz*/) +{ + u32 val; + + val = (u64)0x100000 * freq / 30400; + + atbm8830_write_reg(priv, REG_OSC_CLK, val); + atbm8830_write_reg(priv, REG_OSC_CLK + 1, val >> 8); + atbm8830_write_reg(priv, REG_OSC_CLK + 2, val >> 16); + + return 0; +} + +static int set_if_freq(struct atbm_state *priv, u32 freq /*in kHz*/) +{ + + u32 fs = priv->config->osc_clk_freq; + double t; + u32 val; + u8 dat; + + t = 2 * 3.141593 * (freq - fs) / fs * (1 << 22); + val = t; + + if (freq != 0) { + atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 1); + atbm8830_write_reg(priv, REG_IF_FREQ, val); + atbm8830_write_reg(priv, REG_IF_FREQ+1, val >> 8); + atbm8830_write_reg(priv, REG_IF_FREQ+2, val >> 16); + + atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat); + dat &= 0xFC; + atbm8830_write_reg(priv, REG_ADC_CONFIG, dat); + } else { + /* Zero IF */ + atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 0); + + atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat); + dat &= 0xFC; + dat |= 0x02; + atbm8830_write_reg(priv, REG_ADC_CONFIG, dat); + + if (priv->config->zif_swap_iq) + atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x03); + else + atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x01); + } + + return 0; +} + +static int is_locked(struct atbm_state *priv, u8 *locked) +{ + u8 status; + + atbm8830_read_reg(priv, REG_LOCK_STATUS, &status); + + if (locked != NULL) + *locked = (status == 1); + return 0; +} + +static int set_agc_config(struct atbm_state *priv, + u8 min, u8 max, u8 hold_loop) +{ + atbm8830_write_reg(priv, REG_AGC_MIN, min); + atbm8830_write_reg(priv, REG_AGC_MAX, max); + atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop); + + return 0; +} + +static int set_static_channel_mode(struct atbm_state *priv) +{ + int i; + + for (i = 0; i < 5; i++) + atbm8830_write_reg(priv, 0x099B + i, 0x08); + + atbm8830_write_reg(priv, 0x095B, 0x7F); + atbm8830_write_reg(priv, 0x09CB, 0x01); + atbm8830_write_reg(priv, 0x09CC, 0x7F); + atbm8830_write_reg(priv, 0x09CD, 0x7F); + atbm8830_write_reg(priv, 0x0E01, 0x20); + + /* For single carrier */ + atbm8830_write_reg(priv, 0x0B03, 0x0A); + atbm8830_write_reg(priv, 0x0935, 0x10); + atbm8830_write_reg(priv, 0x0936, 0x08); + atbm8830_write_reg(priv, 0x093E, 0x08); + atbm8830_write_reg(priv, 0x096E, 0x06); + + /* frame_count_max0 */ + atbm8830_write_reg(priv, 0x0B09, 0x00); + /* frame_count_max1 */ + atbm8830_write_reg(priv, 0x0B0A, 0x08); + + return 0; +} + +static int set_ts_config(struct atbm_state *priv) +{ + const struct atbm8830_config *cfg = priv->config; + + /*Set parallel/serial ts mode*/ + atbm8830_write_reg(priv, REG_TS_SERIAL, cfg->serial_ts ? 1 : 0); + atbm8830_write_reg(priv, REG_TS_CLK_MODE, cfg->serial_ts ? 1 : 0); + /*Set ts sampling edge*/ + atbm8830_write_reg(priv, REG_TS_SAMPLE_EDGE, + cfg->ts_sampling_edge ? 1 : 0); + /*Set ts clock freerun*/ + atbm8830_write_reg(priv, REG_TS_CLK_FREERUN, + cfg->ts_clk_gated ? 0 : 1); + + return 0; +} + +static int atbm8830_init(struct dvb_frontend *fe) +{ + struct atbm_state *priv = fe->demodulator_priv; + const struct atbm8830_config *cfg = priv->config; + + /*Set oscillator frequency*/ + set_osc_freq(priv, cfg->osc_clk_freq); + + /*Set IF frequency*/ + set_if_freq(priv, cfg->if_freq); + + + /*Set static channel mode*/ + set_static_channel_mode(priv); + + set_ts_config(priv); + /*Turn off DSP reset*/ + atbm8830_write_reg(priv, 0x000A, 0); + + /*SW version test*/ + atbm8830_write_reg(priv, 0x020C, 11); + + /* Run */ + atbm8830_write_reg(priv, REG_DEMOD_RUN, 1); + + return 0; +} + + +static void atbm8830_release(struct dvb_frontend *fe) +{ + struct atbm_state *state = fe->demodulator_priv; + dprintk("%s\n", __func__); + + kfree(state); +} + +static int atbm8830_set_fe(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fe_params) +{ + struct atbm_state *priv = fe->demodulator_priv; + int i; + u8 locked = 0; + dprintk("%s\n", __func__); + + /* set frequency */ + if (fe->ops.tuner_ops.set_params) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + fe->ops.tuner_ops.set_params(fe, fe_params); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + /* start auto lock */ + for (i = 0; i < 10; i++) { + mdelay(100); + dprintk("Try %d\n", i); + is_locked(priv, &locked); + if (locked != 0) { + dprintk("ATBM8830 locked!\n"); + break; + } + } + + return 0; +} + +static int atbm8830_get_fe(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fe_params) +{ + dprintk("%s\n", __func__); + + /* TODO: get real readings from device */ + /* inversion status */ + fe_params->inversion = INVERSION_OFF; + + /* bandwidth */ + fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + + fe_params->u.ofdm.code_rate_HP = FEC_AUTO; + fe_params->u.ofdm.code_rate_LP = FEC_AUTO; + + fe_params->u.ofdm.constellation = QAM_AUTO; + + /* transmission mode */ + fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + + /* guard interval */ + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + + /* hierarchy */ + fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; + + return 0; +} + +static int atbm8830_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *fesettings) +{ + fesettings->min_delay_ms = 0; + fesettings->step_size = 0; + fesettings->max_drift = 0; + return 0; +} + +static int atbm8830_read_status(struct dvb_frontend *fe, fe_status_t *fe_status) +{ + struct atbm_state *priv = fe->demodulator_priv; + u8 locked = 0; + u8 agc_locked = 0; + + dprintk("%s\n", __func__); + *fe_status = 0; + + is_locked(priv, &locked); + if (locked) { + *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } + dprintk("%s: fe_status=0x%x\n", __func__, *fe_status); + + atbm8830_read_reg(priv, REG_AGC_LOCK, &agc_locked); + dprintk("AGC Lock: %d\n", agc_locked); + + return 0; +} + +static int atbm8830_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct atbm_state *priv = fe->demodulator_priv; + u32 frame_err; + u8 t; + + dprintk("%s\n", __func__); + + atbm8830_reglatch_lock(priv, 1); + + atbm8830_read_reg(priv, REG_FRAME_ERR_CNT + 1, &t); + frame_err = t & 0x7F; + frame_err <<= 8; + atbm8830_read_reg(priv, REG_FRAME_ERR_CNT, &t); + frame_err |= t; + + atbm8830_reglatch_lock(priv, 0); + + *ber = frame_err * 100 / 32767; + + dprintk("%s: ber=0x%x\n", __func__, *ber); + return 0; +} + +static int atbm8830_read_signal_strength(struct dvb_frontend *fe, u16 *signal) +{ + struct atbm_state *priv = fe->demodulator_priv; + u32 pwm; + u8 t; + + dprintk("%s\n", __func__); + atbm8830_reglatch_lock(priv, 1); + + atbm8830_read_reg(priv, REG_AGC_PWM_VAL + 1, &t); + pwm = t & 0x03; + pwm <<= 8; + atbm8830_read_reg(priv, REG_AGC_PWM_VAL, &t); + pwm |= t; + + atbm8830_reglatch_lock(priv, 0); + + dprintk("AGC PWM = 0x%02X\n", pwm); + pwm = 0x400 - pwm; + + *signal = pwm * 0x10000 / 0x400; + + return 0; +} + +static int atbm8830_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + dprintk("%s\n", __func__); + *snr = 0; + return 0; +} + +static int atbm8830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + dprintk("%s\n", __func__); + *ucblocks = 0; + return 0; +} + +static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct atbm_state *priv = fe->demodulator_priv; + + return atbm8830_write_reg(priv, REG_I2C_GATE, enable ? 1 : 0); +} + +static struct dvb_frontend_ops atbm8830_ops = { + .info = { + .name = "AltoBeam ATBM8830/8831 DMB-TH", + .type = FE_OFDM, + .frequency_min = 474000000, + .frequency_max = 858000000, + .frequency_stepsize = 10000, + .caps = + FE_CAN_FEC_AUTO | + FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO + }, + + .release = atbm8830_release, + + .init = atbm8830_init, + .sleep = NULL, + .write = NULL, + .i2c_gate_ctrl = atbm8830_i2c_gate_ctrl, + + .set_frontend = atbm8830_set_fe, + .get_frontend = atbm8830_get_fe, + .get_tune_settings = atbm8830_get_tune_settings, + + .read_status = atbm8830_read_status, + .read_ber = atbm8830_read_ber, + .read_signal_strength = atbm8830_read_signal_strength, + .read_snr = atbm8830_read_snr, + .read_ucblocks = atbm8830_read_ucblocks, +}; + +struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config, + struct i2c_adapter *i2c) +{ + struct atbm_state *priv = NULL; + u8 data = 0; + + dprintk("%s()\n", __func__); + + if (config == NULL || i2c == NULL) + return NULL; + + priv = kzalloc(sizeof(struct atbm_state), GFP_KERNEL); + if (priv == NULL) + goto error_out; + + priv->config = config; + priv->i2c = i2c; + + /* check if the demod is there */ + if (atbm8830_read_reg(priv, REG_CHIP_ID, &data) != 0) { + dprintk("%s atbm8830/8831 not found at i2c addr 0x%02X\n", + __func__, priv->config->demod_address); + goto error_out; + } + dprintk("atbm8830 chip id: 0x%02X\n", data); + + memcpy(&priv->frontend.ops, &atbm8830_ops, + sizeof(struct dvb_frontend_ops)); + priv->frontend.demodulator_priv = priv; + + atbm8830_init(&priv->frontend); + + atbm8830_i2c_gate_ctrl(&priv->frontend, 1); + + return &priv->frontend; + +error_out: + dprintk("%s() error_out\n", __func__); + kfree(priv); + return NULL; + +} +EXPORT_SYMBOL(atbm8830_attach); + +MODULE_DESCRIPTION("AltoBeam ATBM8830/8831 GB20600 demodulator driver"); +MODULE_AUTHOR("David T. L. Wong "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/atbm8830.h b/drivers/media/dvb/frontends/atbm8830.h new file mode 100644 index 000000000000..e8149f393300 --- /dev/null +++ b/drivers/media/dvb/frontends/atbm8830.h @@ -0,0 +1,76 @@ +/* + * Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator + * ATBM8830, ATBM8831 + * + * Copyright (C) 2009 David T.L. Wong + * + * 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. + */ + +#ifndef __ATBM8830_H__ +#define __ATBM8830_H__ + +#include +#include + +#define ATBM8830_PROD_8830 0 +#define ATBM8830_PROD_8831 1 + +struct atbm8830_config { + + /* product type */ + u8 prod; + + /* the demodulator's i2c address */ + u8 demod_address; + + /* parallel or serial transport stream */ + u8 serial_ts; + + /* transport stream clock output only when receving valid stream */ + u8 ts_clk_gated; + + /* Decoder sample TS data at rising edge of clock */ + u8 ts_sampling_edge; + + /* Oscillator clock frequency */ + u32 osc_clk_freq; /* in kHz */ + + /* IF frequency */ + u32 if_freq; /* in kHz */ + + /* Swap I/Q for zero IF */ + u8 zif_swap_iq; + + /* Tuner AGC settings */ + u8 agc_min; + u8 agc_max; + u8 agc_hold_loop; +}; + +#if defined(CONFIG_DVB_ATBM8830) || \ + (defined(CONFIG_DVB_ATBM8830_MODULE) && defined(MODULE)) +extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config, + struct i2c_adapter *i2c); +#else +static inline +struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config, + struct i2c_adapter *i2c) { + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_ATBM8830 */ + +#endif /* __ATBM8830_H__ */ diff --git a/drivers/media/dvb/frontends/atbm8830_priv.h b/drivers/media/dvb/frontends/atbm8830_priv.h new file mode 100644 index 000000000000..ce960f76092a --- /dev/null +++ b/drivers/media/dvb/frontends/atbm8830_priv.h @@ -0,0 +1,75 @@ +/* + * Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator + * ATBM8830, ATBM8831 + * + * Copyright (C) 2009 David T.L. Wong + * + * 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. + */ + +#ifndef __ATBM8830_PRIV_H +#define __ATBM8830_PRIV_H + +struct atbm_state { + struct i2c_adapter *i2c; + /* configuration settings */ + const struct atbm8830_config *config; + struct dvb_frontend frontend; +}; + +#define REG_CHIP_ID 0x0000 +#define REG_TUNER_BASEBAND 0x0001 +#define REG_DEMOD_RUN 0x0004 +#define REG_DSP_RESET 0x0005 +#define REG_RAM_RESET 0x0006 +#define REG_ADC_RESET 0x0007 +#define REG_TSPORT_RESET 0x0008 +#define REG_BLKERR_POL 0x000C +#define REG_I2C_GATE 0x0103 +#define REG_TS_SAMPLE_EDGE 0x0301 +#define REG_TS_PKT_LEN_204 0x0302 +#define REG_TS_PKT_LEN_AUTO 0x0303 +#define REG_TS_SERIAL 0x0305 +#define REG_TS_CLK_FREERUN 0x0306 +#define REG_TS_VALID_MODE 0x0307 +#define REG_TS_CLK_MODE 0x030B /* 1 for serial, 0 for parallel */ + +#define REG_TS_ERRBIT_USE 0x030C +#define REG_LOCK_STATUS 0x030D +#define REG_ADC_CONFIG 0x0602 +#define REG_CARRIER_OFFSET 0x0827 /* 0x0827-0x0829 little endian */ +#define REG_DETECTED_PN_MODE 0x082D +#define REG_READ_LATCH 0x084D +#define REG_IF_FREQ 0x0A00 /* 0x0A00-0x0A02 little endian */ +#define REG_OSC_CLK 0x0A03 /* 0x0A03-0x0A05 little endian */ +#define REG_BYPASS_CCI 0x0A06 +#define REG_ANALOG_LUMA_DETECTED 0x0A25 +#define REG_ANALOG_AUDIO_DETECTED 0x0A26 +#define REG_ANALOG_CHROMA_DETECTED 0x0A39 +#define REG_FRAME_ERR_CNT 0x0B04 +#define REG_USE_EXT_ADC 0x0C00 +#define REG_SWAP_I_Q 0x0C01 +#define REG_TPS_MANUAL 0x0D01 +#define REG_TPS_CONFIG 0x0D02 +#define REG_BYPASS_DEINTERLEAVER 0x0E00 +#define REG_AGC_TARGET 0x1003 /* 0x1003-0x1005 little endian */ +#define REG_AGC_MIN 0x1020 +#define REG_AGC_MAX 0x1023 +#define REG_AGC_LOCK 0x1027 +#define REG_AGC_PWM_VAL 0x1028 /* 0x1028-0x1029 little endian */ +#define REG_AGC_HOLD_LOOP 0x1031 + +#endif + From ea5697fe9ed6a1d534de436eff3138041e3c8aa9 Mon Sep 17 00:00:00 2001 From: "David T. L. Wong" Date: Mon, 26 Oct 2009 08:54:04 -0300 Subject: [PATCH 225/345] V4L/DVB (13375): cx23885: Add support for Mygica X8558Pro DMB-TH Adds support for cx23885 card Mygica X8558 Pro DMB-TH Signed-off-by: David T. L. Wong Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 26 +++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 64 +++++++++++++++++++++ drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 92 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index be293346ffe1..7539e8fa1ffd 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -25,3 +25,4 @@ 24 -> Hauppauge WinTV-HVR1850 [0070:8541] 25 -> Compro VideoMate E800 [1858:e800] 26 -> Hauppauge WinTV-HVR1290 [0070:8551] + 27 -> Mygica X8558 PRO DMB-TH [14f1:8578] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index d9d71c8c7941..23302ddf4187 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -269,6 +269,11 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1290", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_MYGICA_X8558PRO] = { + .name = "Mygica X8558 PRO DMB-TH", + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -408,6 +413,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x8551, .card = CX23885_BOARD_HAUPPAUGE_HVR1290, + }, { + .subvendor = 0x14f1, + .subdevice = 0x8578, + .card = CX23885_BOARD_MYGICA_X8558PRO, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -830,6 +839,15 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2); mdelay(100); break; + case CX23885_BOARD_MYGICA_X8558PRO: + /* GPIO-0 reset first ATBM8830 */ + /* GPIO-1 reset second ATBM8830 */ + cx23885_gpio_enable(dev, GPIO_0 | GPIO_1, 1); + cx23885_gpio_clear(dev, GPIO_0 | GPIO_1); + mdelay(100); + cx23885_gpio_set(dev, GPIO_0 | GPIO_1); + mdelay(100); + break; case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: /* GPIO-0 656_CLK */ @@ -1005,6 +1023,14 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; + case CX23885_BOARD_MYGICA_X8558PRO: + ts1->gen_ctrl_val = 0x5; /* Parallel */ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ + ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 133e80290711..bf24e86293c6 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -38,6 +38,7 @@ #include "tda18271.h" #include "lgdt330x.h" #include "xc5000.h" +#include "max2165.h" #include "tda10048.h" #include "tuner-xc2028.h" #include "tuner-simple.h" @@ -54,6 +55,7 @@ #include "netup-eeprom.h" #include "netup-init.h" #include "lgdt3305.h" +#include "atbm8830.h" static unsigned int debug; @@ -543,6 +545,38 @@ static struct xc5000_config magicpro_prohdtve2_xc5000_config = { .if_khz = 6500, }; +static struct atbm8830_config mygica_x8558pro_atbm8830_cfg1 = { + .prod = ATBM8830_PROD_8830, + .demod_address = 0x44, + .serial_ts = 0, + .ts_sampling_edge = 1, + .ts_clk_gated = 0, + .osc_clk_freq = 30400, /* in kHz */ + .if_freq = 0, /* zero IF */ + .zif_swap_iq = 1, +}; + +static struct max2165_config mygic_x8558pro_max2165_cfg1 = { + .i2c_address = 0x60, + .osc_clk = 20 +}; + +static struct atbm8830_config mygica_x8558pro_atbm8830_cfg2 = { + .prod = ATBM8830_PROD_8830, + .demod_address = 0x44, + .serial_ts = 1, + .ts_sampling_edge = 1, + .ts_clk_gated = 0, + .osc_clk_freq = 30400, /* in kHz */ + .if_freq = 0, /* zero IF */ + .zif_swap_iq = 1, +}; + +static struct max2165_config mygic_x8558pro_max2165_cfg2 = { + .i2c_address = 0x60, + .osc_clk = 20 +}; + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -908,6 +942,36 @@ static int dvb_register(struct cx23885_tsport *port) 0x60, &dev->i2c_bus[0].i2c_adap, &hauppauge_tda18271_config); break; + case CX23885_BOARD_MYGICA_X8558PRO: + switch (port->nr) { + /* port B */ + case 1: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(atbm8830_attach, + &mygica_x8558pro_atbm8830_cfg1, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(max2165_attach, + fe0->dvb.frontend, + &i2c_bus->i2c_adap, + &mygic_x8558pro_max2165_cfg1); + } + break; + /* port C */ + case 2: + i2c_bus = &dev->i2c_bus[1]; + fe0->dvb.frontend = dvb_attach(atbm8830_attach, + &mygica_x8558pro_atbm8830_cfg2, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(max2165_attach, + fe0->dvb.frontend, + &i2c_bus->i2c_adap, + &mygic_x8558pro_max2165_cfg2); + } + break; + } + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 12d1a344a8ab..338320025529 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -80,6 +80,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1850 24 #define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 +#define CX23885_BOARD_MYGICA_X8558PRO 27 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 From b18bd1d8806c0982c7835dcb58a27c4e9005e4fb Mon Sep 17 00:00:00 2001 From: David Wong Date: Mon, 26 Oct 2009 09:41:22 -0300 Subject: [PATCH 226/345] V4L/DVB (13376): cx-usb: add Mygica D689 DMB-TH USB support X-Patchwork-Id: 55873 Add support for cxusb card Mygica D689 DBM-TH USB Signed-off-by: David T. L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 118 ++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 119 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 2a53dd096eef..542de171874a 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -36,9 +36,11 @@ #include "tuner-xc2028.h" #include "tuner-simple.h" #include "mxl5005s.h" +#include "max2165.h" #include "dib7000p.h" #include "dib0070.h" #include "lgs8gxx.h" +#include "atbm8830.h" /* debug */ static int dvb_usb_cxusb_debug; @@ -714,6 +716,11 @@ static struct mxl5005s_config d680_dmb_tuner = { .AgcMasterByte = 0x00, }; +static struct max2165_config mygica_d689_max2165_cfg = { + .i2c_address = 0x60, + .osc_clk = 20 +}; + /* Callbacks for DVB USB */ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) { @@ -813,6 +820,14 @@ static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap) return (fe == NULL) ? -EIO : 0; } +static int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_frontend *fe; + fe = dvb_attach(max2165_attach, adap->fe, + &adap->dev->i2c_adap, &mygica_d689_max2165_cfg); + return (fe == NULL) ? -EIO : 0; +} + static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) { u8 b; @@ -1160,6 +1175,56 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) return 0; } +static struct atbm8830_config mygica_d689_atbm8830_cfg = { + .prod = ATBM8830_PROD_8830, + .demod_address = 0x40, + .serial_ts = 0, + .ts_sampling_edge = 1, + .ts_clk_gated = 0, + .osc_clk_freq = 30400, /* in kHz */ + .if_freq = 0, /* zero IF */ + .zif_swap_iq = 1, +}; + +static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap->dev; + int n; + + /* Select required USB configuration */ + if (usb_set_interface(d->udev, 0, 0) < 0) + err("set interface failed"); + + /* Unblock all USB pipes */ + usb_clear_halt(d->udev, + usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); + usb_clear_halt(d->udev, + usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); + usb_clear_halt(d->udev, + usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint)); + + + /* Reset the tuner */ + if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) { + err("clear tuner gpio failed"); + return -EIO; + } + msleep(100); + if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) { + err("set tuner gpio failed"); + return -EIO; + } + msleep(100); + + /* Attach frontend */ + adap->fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg, + &d->i2c_adap); + if (adap->fe == NULL) + return -EIO; + + return 0; +} + /* * DViCO has shipped two devices with the same USB ID, but only one of them * needs a firmware download. Check the device class details to see if they @@ -1240,6 +1305,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; static struct dvb_usb_device_properties cxusb_aver_a868r_properties; static struct dvb_usb_device_properties cxusb_d680_dmb_properties; +static struct dvb_usb_device_properties cxusb_mygica_d689_properties; static int cxusb_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1268,6 +1334,8 @@ static int cxusb_probe(struct usb_interface *intf, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, + THIS_MODULE, NULL, adapter_nr) || 0) return 0; @@ -1294,6 +1362,7 @@ static struct usb_device_id cxusb_table [] = { { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, + { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, cxusb_table); @@ -1837,6 +1906,55 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = { } }; +static struct dvb_usb_device_properties cxusb_mygica_d689_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = CYPRESS_FX2, + + .size_of_priv = sizeof(struct cxusb_state), + + .num_adapters = 1, + .adapter = { + { + .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl, + .frontend_attach = cxusb_mygica_d689_frontend_attach, + .tuner_attach = cxusb_mygica_d689_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, + }, + }, + + .power_ctrl = cxusb_d680_dmb_power_ctrl, + + .i2c_algo = &cxusb_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + + .rc_interval = 100, + .rc_key_map = d680_dmb_rc_keys, + .rc_key_map_size = ARRAY_SIZE(d680_dmb_rc_keys), + .rc_query = cxusb_d680_dmb_rc_query, + + .num_device_descs = 1, + .devices = { + { + "Mygica D689 DMB-TH", + { NULL }, + { &cxusb_table[19], NULL }, + }, + } +}; + static struct usb_driver cxusb_driver = { .name = "dvb_usb_cxusb", .probe = cxusb_probe, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index dc57fe1b6f0f..f1602d4ace6d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -279,6 +279,7 @@ #define USB_PID_TELESTAR_STARSTICK_2 0x8000 #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 #define USB_PID_SONY_PLAYTV 0x0003 +#define USB_PID_MYGICA_D689 0xd811 #define USB_PID_ELGATO_EYETV_DTT 0x0021 #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 From 38a54f35a0a90c0b62b111dd4de24248b22616b9 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Tue, 17 Nov 2009 19:43:41 -0300 Subject: [PATCH 227/345] V4L/DVB (13377): make struct videobuf_queue_ops constant The videobuf_queue_ops function vector is not declared constant, but there's no need for the videobuf layer to ever change it. Make it const so that videobuf users can make their operations const without warnings. Signed-off-by: Jonathan Corbet Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 2 +- drivers/media/video/videobuf-dma-contig.c | 2 +- drivers/media/video/videobuf-dma-sg.c | 2 +- drivers/media/video/videobuf-vmalloc.c | 2 +- include/media/videobuf-core.h | 4 ++-- include/media/videobuf-dma-contig.h | 2 +- include/media/videobuf-dma-sg.h | 2 +- include/media/videobuf-vmalloc.h | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index a96b08d3df5a..136bc3496c87 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -110,7 +110,7 @@ EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc); void videobuf_queue_core_init(struct videobuf_queue *q, - struct videobuf_queue_ops *ops, + const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index c3065c4bcba9..d25f28461da1 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -429,7 +429,7 @@ static struct videobuf_qtype_ops qops = { }; void videobuf_queue_dma_contig_init(struct videobuf_queue *q, - struct videobuf_queue_ops *ops, + const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index a583d394696e..fa78555b118b 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -702,7 +702,7 @@ void *videobuf_sg_alloc(size_t size) } void videobuf_queue_sg_init(struct videobuf_queue* q, - struct videobuf_queue_ops *ops, + const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 35f3900c5633..99d646ed0248 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -391,7 +391,7 @@ static struct videobuf_qtype_ops qops = { }; void videobuf_queue_vmalloc_init(struct videobuf_queue* q, - struct videobuf_queue_ops *ops, + const struct videobuf_queue_ops *ops, void *dev, spinlock_t *irqlock, enum v4l2_buf_type type, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 1c5946c44758..316fdccdcaa0 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -166,7 +166,7 @@ struct videobuf_queue { enum v4l2_field field; enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; - struct videobuf_queue_ops *ops; + const struct videobuf_queue_ops *ops; struct videobuf_qtype_ops *int_ops; unsigned int streaming:1; @@ -195,7 +195,7 @@ void *videobuf_queue_to_vmalloc (struct videobuf_queue* q, struct videobuf_buffer *buf); void videobuf_queue_core_init(struct videobuf_queue *q, - struct videobuf_queue_ops *ops, + const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, diff --git a/include/media/videobuf-dma-contig.h b/include/media/videobuf-dma-contig.h index 549386681aab..ebaa9bc1ee8d 100644 --- a/include/media/videobuf-dma-contig.h +++ b/include/media/videobuf-dma-contig.h @@ -17,7 +17,7 @@ #include void videobuf_queue_dma_contig_init(struct videobuf_queue *q, - struct videobuf_queue_ops *ops, + const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index dda47f0082e9..53e72f787175 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -103,7 +103,7 @@ struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf); void *videobuf_sg_alloc(size_t size); void videobuf_queue_sg_init(struct videobuf_queue* q, - struct videobuf_queue_ops *ops, + const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h index e87222c6a125..1ffdb6624436 100644 --- a/include/media/videobuf-vmalloc.h +++ b/include/media/videobuf-vmalloc.h @@ -30,7 +30,7 @@ struct videobuf_vmalloc_memory }; void videobuf_queue_vmalloc_init(struct videobuf_queue* q, - struct videobuf_queue_ops *ops, + const struct videobuf_queue_ops *ops, void *dev, spinlock_t *irqlock, enum v4l2_buf_type type, From caac970f91f39f67b5e48680840605e24896ff99 Mon Sep 17 00:00:00 2001 From: Alexander Strakh Date: Tue, 17 Nov 2009 19:43:37 -0300 Subject: [PATCH 228/345] V4L/DVB (13378): konicawc.c: possible buffer overflow while use strncat In driver ./drivers/media/video/usbvideo/konicawc.c in line 227: 227 usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); After this line we use strncat: 228 strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); where sizeof(cam->input_physname) returns length of cam->input_phisname without length for null-symbol. But this parameter must be - "maximum numbers of bytes to copy", i.e.: sizeof(cam->input_physname)-strlen(cam->input_physname)-1. In this case, after call to usb_make_path the similar drivers use strlcat. Like in drivers/hid/usbhid/hid-core.c: 1152 usb_make_path(dev, hid->phys, sizeof(hid->phys)); 1153 strlcat(hid->phys, "/input", sizeof(hid->phys)); Found by Linux Driver Verification Project. Use strlcat instead of strncat. Signed-off-by: Alexander Strakh Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvideo/konicawc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 31d57f2d09e1..a0addcb04295 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -225,7 +225,7 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev int error; usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); - strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); + strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname)); cam->input = input_dev = input_allocate_device(); if (!input_dev) { From 2b588db82d2c210e84da129a223bb403d3131abe Mon Sep 17 00:00:00 2001 From: Alexander Strakh Date: Tue, 17 Nov 2009 19:43:38 -0300 Subject: [PATCH 229/345] V4L/DVB (13379): quickcam_messenger: possible buffer overflow while use strncat In driver ./drivers/media/video/usbvideo/quickcam_messenger.c in line 91: 91 usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); After this line we use strncat: 92 strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); where sizeof(cam->input_physname) returns length of cam->input_phisname without length for null-symbol. But this parameter must be - "maximum numbers of bytes to copy", i.e.: sizeof(cam->input_physname)-strlen(cam->input_physname)-1. In this case, after call to usb_make_path the similar drivers use strlcat. Like in: drivers/hid/usbhid/hid-core.c: 1152 usb_make_path(dev, hid->phys, sizeof(hid->phys)); 1153 strlcat(hid->phys, "/input", sizeof(hid->phys)); Found by Linux Driver Verification Project. Use strlcat instead of strncat. Signed-off-by: Alexander Strakh Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvideo/quickcam_messenger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 803d3e4e29a2..c4d1b96b5cee 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -89,7 +89,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) int error; usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); - strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); + strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname)); cam->input = input_dev = input_allocate_device(); if (!input_dev) { From 3a054627cc949c3b7bb8387543919e7d4022753a Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 17 Nov 2009 19:43:40 -0300 Subject: [PATCH 230/345] V4L/DVB (13380): sms-cards: make id unsigned in sms_get_board() Make id signed so we can't get an invalid pointer when we pass a negative id. Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/sms-cards.c | 2 +- drivers/media/dvb/siano/sms-cards.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index e21638969cd3..1067b22eb0c6 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c @@ -97,7 +97,7 @@ static struct sms_board sms_boards[] = { }, }; -struct sms_board *sms_get_board(int id) +struct sms_board *sms_get_board(unsigned id) { BUG_ON(id >= ARRAY_SIZE(sms_boards)); diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h index 38f062f6ad68..8f19fc000b46 100644 --- a/drivers/media/dvb/siano/sms-cards.h +++ b/drivers/media/dvb/siano/sms-cards.h @@ -81,7 +81,7 @@ struct sms_board { int led_power, led_hi, led_lo, lna_ctrl, rf_switch; }; -struct sms_board *sms_get_board(int id); +struct sms_board *sms_get_board(unsigned id); extern struct smscore_device_t *coredev; From 67c98f72e132e191ff4db0ac7bd81ea94fa5c667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=83=C2=A1rton=20N=C3=83=C2=A9meth?= Date: Sat, 7 Nov 2009 05:45:33 -0300 Subject: [PATCH 231/345] V4L/DVB (13382): gspca - pac7302: Remove redundant stream off command. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stream off command is sent to the device twice, one is enough. Signed-off-by: Márton Németh Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7302.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 09d3d191d949..ae1d90a85c5c 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -606,9 +606,9 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { + /* stop stream */ reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x78, 0x00); - reg_w(gspca_dev, 0x78, 0x00); } /* called on streamoff with alt 0 and on disconnect for pac7302 */ From b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=83=C2=A1rton=20N=C3=83=C2=A9meth?= Date: Sat, 7 Nov 2009 05:52:02 -0300 Subject: [PATCH 232/345] V4L/DVB (13383): gspca - pac7311/pac7302: Propagate error to higher level software. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The usb_control_msg() can fail any time. Only continue writing sequence if there was no error with the previous write. If there was any problem stop sending URBs and propagate the error to the gspca_main. Signed-off-by: Márton Németh Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7302.c | 155 +++++++++++++++++--------- drivers/media/video/gspca/pac7311.c | 161 ++++++++++++++++++---------- 2 files changed, 207 insertions(+), 109 deletions(-) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index ae1d90a85c5c..ec2930871d1f 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -331,7 +331,7 @@ static const __u8 page3_7302[] = { 0x00 }; -static void reg_w_buf(struct gspca_dev *gspca_dev, +static int reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, const char *buffer, int len) { @@ -349,10 +349,11 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, PDEBUG(D_ERR, "reg_w_buf(): " "Failed to write registers to index 0x%x, error %i", index, ret); + return ret; } -static void reg_w(struct gspca_dev *gspca_dev, +static int reg_w(struct gspca_dev *gspca_dev, __u8 index, __u8 value) { @@ -369,23 +370,27 @@ static void reg_w(struct gspca_dev *gspca_dev, PDEBUG(D_ERR, "reg_w(): " "Failed to write register to index 0x%x, value 0x%x, error %i", index, value, ret); + return ret; } -static void reg_w_seq(struct gspca_dev *gspca_dev, +static int reg_w_seq(struct gspca_dev *gspca_dev, const __u8 *seq, int len) { + int ret = 0; while (--len >= 0) { - reg_w(gspca_dev, seq[0], seq[1]); + if (0 <= ret) + ret = reg_w(gspca_dev, seq[0], seq[1]); seq += 2; } + return ret; } /* load the beginning of a page */ -static void reg_w_page(struct gspca_dev *gspca_dev, +static int reg_w_page(struct gspca_dev *gspca_dev, const __u8 *page, int len) { int index; - int ret; + int ret = 0; for (index = 0; index < len; index++) { if (page[index] == SKIP) /* skip this index */ @@ -397,52 +402,61 @@ static void reg_w_page(struct gspca_dev *gspca_dev, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, gspca_dev->usb_buf, 1, 500); - if (ret < 0) + if (ret < 0) { PDEBUG(D_ERR, "reg_w_page(): " "Failed to write register to index 0x%x, " "value 0x%x, error %i", index, page[index], ret); + break; + } } + return ret; } /* output a variable sequence */ -static void reg_w_var(struct gspca_dev *gspca_dev, +static int reg_w_var(struct gspca_dev *gspca_dev, const __u8 *seq, const __u8 *page3, unsigned int page3_len, const __u8 *page4, unsigned int page4_len) { int index, len; + int ret = 0; for (;;) { index = *seq++; len = *seq++; switch (len) { case END_OF_SEQUENCE: - return; + return ret; case LOAD_PAGE4: - reg_w_page(gspca_dev, page4, page4_len); + ret = reg_w_page(gspca_dev, page4, page4_len); break; case LOAD_PAGE3: - reg_w_page(gspca_dev, page3, page3_len); + ret = reg_w_page(gspca_dev, page3, page3_len); break; default: if (len > USB_BUF_SZ) { PDEBUG(D_ERR|D_STREAM, "Incorrect variable sequence"); - return; + return -EINVAL; } while (len > 0) { if (len < 8) { - reg_w_buf(gspca_dev, index, seq, len); + ret = reg_w_buf(gspca_dev, + index, seq, len); + if (ret < 0) + return ret; seq += len; break; } - reg_w_buf(gspca_dev, index, seq, 8); + ret = reg_w_buf(gspca_dev, index, seq, 8); seq += 8; index += 8; len -= 8; } } + if (ret < 0) + return ret; } /* not reached */ } @@ -472,10 +486,11 @@ static int sd_config(struct gspca_dev *gspca_dev, } /* This function is used by pac7302 only */ -static void setbrightcont(struct gspca_dev *gspca_dev) +static int setbrightcont(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i, v; + int ret; static const __u8 max[10] = {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, 0xd4, 0xec}; @@ -483,7 +498,7 @@ static void setbrightcont(struct gspca_dev *gspca_dev) {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, 0x11, 0x0b}; - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ for (i = 0; i < 10; i++) { v = max[i]; v += (sd->brightness - BRIGHTNESS_MAX) @@ -493,47 +508,62 @@ static void setbrightcont(struct gspca_dev *gspca_dev) v = 0; else if (v > 0xff) v = 0xff; - reg_w(gspca_dev, 0xa2 + i, v); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xa2 + i, v); } - reg_w(gspca_dev, 0xdc, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xdc, 0x01); + return ret; } /* This function is used by pac7302 only */ -static void setcolors(struct gspca_dev *gspca_dev) +static int setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i, v; + int ret; static const int a[9] = {217, -212, 0, -101, 170, -67, -38, -315, 355}; static const int b[9] = {19, 106, 0, 19, 106, 1, 19, 106, 1}; - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x11, 0x01); - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0x11, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ for (i = 0; i < 9; i++) { v = a[i] * sd->colors / COLOR_MAX + b[i]; - reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); - reg_w(gspca_dev, 0x0f + 2 * i + 1, v); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v); } - reg_w(gspca_dev, 0xdc, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xdc, 0x01); PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); + return ret; } -static void setgain(struct gspca_dev *gspca_dev) +static int setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int ret; - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x10, sd->gain >> 3); + ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0x10, sd->gain >> 3); /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x11, 0x01); + return ret; } -static void setexposure(struct gspca_dev *gspca_dev) +static int setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int ret; __u8 reg; /* register 2 of frame 3/4 contains the clock divider configuring the @@ -549,47 +579,58 @@ static void setexposure(struct gspca_dev *gspca_dev) the nearest multiple of 3, except when between 6 and 12? */ if (reg < 6 || reg > 12) reg = ((reg + 1) / 3) * 3; - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x02, reg); + ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0x02, reg); /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x11, 0x01); + return ret; } -static void sethvflip(struct gspca_dev *gspca_dev) +static int sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int ret; __u8 data; - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00); - reg_w(gspca_dev, 0x21, data); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x21, data); /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x11, 0x01); + return ret; } /* this function is called at probe and resume time for pac7302 */ static int sd_init(struct gspca_dev *gspca_dev) { - reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); - - return 0; + return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); } static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int ret = 0; sd->sof_read = 0; - reg_w_var(gspca_dev, start_7302, + ret = reg_w_var(gspca_dev, start_7302, page3_7302, sizeof(page3_7302), NULL, 0); - setbrightcont(gspca_dev); - setcolors(gspca_dev); - setgain(gspca_dev); - setexposure(gspca_dev); - sethvflip(gspca_dev); + if (0 <= ret) + ret = setbrightcont(gspca_dev); + if (0 <= ret) + ret = setcolors(gspca_dev); + if (0 <= ret) + setgain(gspca_dev); + if (0 <= ret) + setexposure(gspca_dev); + if (0 <= ret) + sethvflip(gspca_dev); /* only resolution 640x480 is supported for pac7302 */ @@ -598,26 +639,34 @@ static int sd_start(struct gspca_dev *gspca_dev) atomic_set(&sd->avg_lum, -1); /* start stream */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x78, 0x01); - return 0; + return ret; } static void sd_stopN(struct gspca_dev *gspca_dev) { + int ret; + /* stop stream */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x00); + ret = reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x78, 0x00); } /* called on streamoff with alt 0 and on disconnect for pac7302 */ static void sd_stop0(struct gspca_dev *gspca_dev) { + int ret; + if (!gspca_dev->present) return; - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x40); + ret = reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x78, 0x40); } /* Include pac common sof detection functions */ diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index b1127d948974..c3e1f80351ad 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -259,7 +259,7 @@ static const __u8 page4_7311[] = { 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 }; -static void reg_w_buf(struct gspca_dev *gspca_dev, +static int reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, const char *buffer, int len) { @@ -277,10 +277,11 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, PDEBUG(D_ERR, "reg_w_buf(): " "Failed to write registers to index 0x%x, error %i", index, ret); + return ret; } -static void reg_w(struct gspca_dev *gspca_dev, +static int reg_w(struct gspca_dev *gspca_dev, __u8 index, __u8 value) { @@ -297,23 +298,27 @@ static void reg_w(struct gspca_dev *gspca_dev, PDEBUG(D_ERR, "reg_w(): " "Failed to write register to index 0x%x, value 0x%x, error %i", index, value, ret); + return ret; } -static void reg_w_seq(struct gspca_dev *gspca_dev, +static int reg_w_seq(struct gspca_dev *gspca_dev, const __u8 *seq, int len) { + int ret = 0; while (--len >= 0) { - reg_w(gspca_dev, seq[0], seq[1]); + if (0 <= ret) + ret = reg_w(gspca_dev, seq[0], seq[1]); seq += 2; } + return ret; } /* load the beginning of a page */ -static void reg_w_page(struct gspca_dev *gspca_dev, +static int reg_w_page(struct gspca_dev *gspca_dev, const __u8 *page, int len) { int index; - int ret; + int ret = 0; for (index = 0; index < len; index++) { if (page[index] == SKIP) /* skip this index */ @@ -325,52 +330,61 @@ static void reg_w_page(struct gspca_dev *gspca_dev, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, gspca_dev->usb_buf, 1, 500); - if (ret < 0) + if (ret < 0) { PDEBUG(D_ERR, "reg_w_page(): " "Failed to write register to index 0x%x, " "value 0x%x, error %i", index, page[index], ret); + break; + } } + return ret; } /* output a variable sequence */ -static void reg_w_var(struct gspca_dev *gspca_dev, +static int reg_w_var(struct gspca_dev *gspca_dev, const __u8 *seq, const __u8 *page3, unsigned int page3_len, const __u8 *page4, unsigned int page4_len) { int index, len; + int ret = 0; for (;;) { index = *seq++; len = *seq++; switch (len) { case END_OF_SEQUENCE: - return; + return ret; case LOAD_PAGE4: - reg_w_page(gspca_dev, page4, page4_len); + ret = reg_w_page(gspca_dev, page4, page4_len); break; case LOAD_PAGE3: - reg_w_page(gspca_dev, page3, page3_len); + ret = reg_w_page(gspca_dev, page3, page3_len); break; default: if (len > USB_BUF_SZ) { PDEBUG(D_ERR|D_STREAM, "Incorrect variable sequence"); - return; + return -EINVAL; } while (len > 0) { if (len < 8) { - reg_w_buf(gspca_dev, index, seq, len); + ret = reg_w_buf(gspca_dev, + index, seq, len); + if (ret < 0) + return ret; seq += len; break; } - reg_w_buf(gspca_dev, index, seq, 8); + ret = reg_w_buf(gspca_dev, index, seq, 8); seq += 8; index += 8; len -= 8; } } + if (ret < 0) + return ret; } /* not reached */ } @@ -398,36 +412,46 @@ static int sd_config(struct gspca_dev *gspca_dev, } /* This function is used by pac7311 only */ -static void setcontrast(struct gspca_dev *gspca_dev) +static int setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int ret; - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x10, sd->contrast >> 4); + ret = reg_w(gspca_dev, 0xff, 0x04); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4); /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x11, 0x01); + return ret; } -static void setgain(struct gspca_dev *gspca_dev) +static int setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int gain = GAIN_MAX - sd->gain; + int ret; if (gain < 1) gain = 1; else if (gain > 245) gain = 245; - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ - reg_w(gspca_dev, 0x0e, 0x00); - reg_w(gspca_dev, 0x0f, gain); + ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0x0e, 0x00); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x0f, gain); /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x11, 0x01); + return ret; } -static void setexposure(struct gspca_dev *gspca_dev) +static int setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int ret; __u8 reg; /* register 2 of frame 3/4 contains the clock divider configuring the @@ -439,71 +463,94 @@ static void setexposure(struct gspca_dev *gspca_dev) else if (reg > 63) reg = 63; - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ - reg_w(gspca_dev, 0x02, reg); + ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0x02, reg); /* Page 1 register 8 must always be 0x08 except when not in 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ - reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xff, 0x01); if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && - reg <= 3) - reg_w(gspca_dev, 0x08, 0x09); - else - reg_w(gspca_dev, 0x08, 0x08); + reg <= 3) { + if (0 <= ret) + ret = reg_w(gspca_dev, 0x08, 0x09); + } else { + if (0 <= ret) + ret = reg_w(gspca_dev, 0x08, 0x08); + } /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x11, 0x01); + return ret; } -static void sethvflip(struct gspca_dev *gspca_dev) +static int sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int ret; __u8 data; - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ + ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); - reg_w(gspca_dev, 0x21, data); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x21, data); /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x11, 0x01); + return ret; } /* this function is called at probe and resume time for pac7311 */ static int sd_init(struct gspca_dev *gspca_dev) { - reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); - - return 0; + return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); } static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int ret; sd->sof_read = 0; - reg_w_var(gspca_dev, start_7311, + ret = reg_w_var(gspca_dev, start_7311, NULL, 0, page4_7311, sizeof(page4_7311)); - setcontrast(gspca_dev); - setgain(gspca_dev); - setexposure(gspca_dev); - sethvflip(gspca_dev); + if (0 <= ret) + ret = setcontrast(gspca_dev); + if (0 <= ret) + ret = setgain(gspca_dev); + if (0 <= ret) + ret = setexposure(gspca_dev); + if (0 <= ret) + ret = sethvflip(gspca_dev); /* set correct resolution */ switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { case 2: /* 160x120 pac7311 */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x17, 0x20); - reg_w(gspca_dev, 0x87, 0x10); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x17, 0x20); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x87, 0x10); break; case 1: /* 320x240 pac7311 */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x17, 0x30); - reg_w(gspca_dev, 0x87, 0x11); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x17, 0x30); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x87, 0x11); break; case 0: /* 640x480 */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x17, 0x00); - reg_w(gspca_dev, 0x87, 0x12); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x17, 0x00); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x87, 0x12); break; } @@ -512,10 +559,12 @@ static int sd_start(struct gspca_dev *gspca_dev) atomic_set(&sd->avg_lum, -1); /* start stream */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x05); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x78, 0x05); - return 0; + return ret; } static void sd_stopN(struct gspca_dev *gspca_dev) From d5aa3856fd09ad0ea04619d6cba31192dac08e84 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 7 Nov 2009 06:10:08 -0300 Subject: [PATCH 233/345] V4L/DVB (13384): gspca - sonixj: Optimize code and add some comments. - the i2c base address is now taken from the sn9c1xx register table Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 161 +++++++++++++++-------------- 1 file changed, 82 insertions(+), 79 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index a9643a0f78d5..5f82efb93d9b 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1,5 +1,6 @@ /* * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver + * * Copyright (C) 2009 Jean-Francois Moine * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr * @@ -72,7 +73,7 @@ struct sd { #define SENSOR_OV7648 6 #define SENSOR_OV7660 7 #define SENSOR_SP80708 8 - u8 i2c_base; + u8 i2c_addr; u8 *jpeg_hdr; }; @@ -597,10 +598,11 @@ static const u8 om6802_sensor_init[][8] = { {0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10}, /* factory mode */ {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10}, + /* output raw RGB */ {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10}, /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */ {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10}, - /* white balance & auto-exposure */ + /* auto-exposure speed (0) / white balance mode (auto RGB) */ /* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10}, * set color mode */ /* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10}, @@ -614,7 +616,7 @@ static const u8 om6802_sensor_init[][8] = { /* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10}, * preset gamma */ {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10}, - /* luminance mode (0x4f = AE) */ + /* luminance mode (0x4f -> AutoExpo on) */ {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10}, /* preset shutter */ /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10}, @@ -999,7 +1001,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) gspca_dev->usb_buf[0] = 0x81 | (2 << 4); break; } - gspca_dev->usb_buf[1] = sd->i2c_base; + gspca_dev->usb_buf[1] = sd->i2c_addr; gspca_dev->usb_buf[2] = reg; gspca_dev->usb_buf[3] = val; gspca_dev->usb_buf[4] = 0; @@ -1045,7 +1047,7 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) mode[0] = 0x81 | 0x10; break; } - mode[1] = sd->i2c_base; + mode[1] = sd->i2c_addr; mode[2] = reg; mode[3] = 0; mode[4] = 0; @@ -1132,7 +1134,6 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) case 0x823a: PDEBUG(D_PROBE, "Sensor mt9v111"); sd->sensor = SENSOR_MT9V111; - sd->i2c_base = 0x5c; break; case 0x8243: PDEBUG(D_PROBE, "Sensor mi0360"); @@ -1160,7 +1161,7 @@ static void bridge_init(struct gspca_dev *gspca_dev, /* configure gpio */ reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2); reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); - reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */ + reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); switch (sd->sensor) { case SENSOR_OV7660: case SENSOR_SP80708: @@ -1172,7 +1173,7 @@ static void bridge_init(struct gspca_dev *gspca_dev, } reg_w(gspca_dev, 0x9a, reg9a, 6); - reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/ + reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); @@ -1222,14 +1223,15 @@ static void bridge_init(struct gspca_dev *gspca_dev, msleep(100); reg_w1(gspca_dev, 0x02, 0x62); break; + default: /* case SENSOR_HV7131R: */ /* case SENSOR_MI0360: */ /* case SENSOR_MO4000: */ - default: reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0x61); reg_w1(gspca_dev, 0x01, 0x42); - if (sd->sensor == SENSOR_HV7131R) + if (sd->sensor == SENSOR_HV7131R + && sd->bridge == BRIDGE_SN9C102P) hv7131r_probe(gspca_dev); break; } @@ -1248,8 +1250,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->npkt = 24; /* 24 packets per ISOC message */ sd->bridge = id->driver_info >> 16; - sd->sensor = id->driver_info >> 8; - sd->i2c_base = id->driver_info; + sd->sensor = id->driver_info; sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; @@ -1273,6 +1274,7 @@ 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; @@ -1315,6 +1317,10 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0xf1, 0x01); + /* set the i2c address */ + sn9c1xx = sn_tb[sd->sensor]; + sd->i2c_addr = sn9c1xx[9]; + return 0; } @@ -1326,7 +1332,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, switch (sd->sensor) { case SENSOR_HV7131R: { u8 Expodoit[] = - { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 }; + { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 }; Expodoit[3] = expo >> 16; Expodoit[4] = expo >> 8; @@ -1336,7 +1342,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, } case SENSOR_MI0360: { u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ - { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 }; + { 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 }; static const u8 doit[] = /* update sensor */ { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; static const u8 sensorgo[] = /* sensor on */ @@ -1355,9 +1361,9 @@ static u32 setexposure(struct gspca_dev *gspca_dev, } case SENSOR_MO4000: { u8 expoMof[] = - { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 }; + { 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 }; u8 expoMo10[] = - { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 }; + { 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 }; static const u8 gainMo[] = { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d }; @@ -1393,6 +1399,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, case SENSOR_OM6802: { u8 gainOm[] = { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; + /* preset AGC - works when AutoExpo = off */ if (expo > 0x03ff) expo = 0x03ff; @@ -1400,7 +1407,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, expo = 0x0001; gainOm[3] = expo >> 2; i2c_w8(gspca_dev, gainOm); - reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f); + reg_w1(gspca_dev, 0x96, expo >> 5); PDEBUG(D_FRAM, "set exposure %d", gainOm[3]); break; } @@ -1432,7 +1439,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) case SENSOR_MT9V111: expo = sd->brightness >> 8; sd->exposure = setexposure(gspca_dev, expo); - break; + return; /* don't set the Y offset */ case SENSOR_OM6802: expo = sd->brightness >> 6; sd->exposure = setexposure(gspca_dev, expo); @@ -1440,8 +1447,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) break; } - if (sd->sensor != SENSOR_MT9V111) - reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ + reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ } static void setcontrast(struct gspca_dev *gspca_dev) @@ -1469,6 +1475,7 @@ static void setcolors(struct gspca_dev *gspca_dev) -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; reg8a[i * 2] = v; @@ -1692,6 +1699,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* initialize the bridge */ sn9c1xx = sn_tb[sd->sensor]; bridge_init(gspca_dev, sn9c1xx); + /* initialize the sensor */ i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); @@ -1779,7 +1787,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ init = NULL; - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; if (mode) reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */ else @@ -1913,12 +1921,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev) case SENSOR_OV7630: data = 0x29; break; - default: -/* case SENSOR_MO4000: */ -/* case SENSOR_OV7660: */ - break; } - sn9c1xx = sn_tb[(int) sd->sensor]; + sn9c1xx = sn_tb[sd->sensor]; reg_w1(gspca_dev, 0x01, sn9c1xx[1]); reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); reg_w1(gspca_dev, 0x01, sn9c1xx[1]); @@ -2277,70 +2281,69 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -#define BSI(bridge, sensor, i2c_addr) \ +#define BS(bridge, sensor) \ .driver_info = (BRIDGE_ ## bridge << 16) \ - | (SENSOR_ ## sensor << 8) \ - | (i2c_addr) + | SENSOR_ ## sensor static const __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)}, - {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)}, + {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)}, + {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)}, #endif - {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, - {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, - {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, - {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(0x06f8, 0x3008), BSI(SN9C105, OV7660, 0x21)}, -/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x21)}, */ - {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)}, -/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x21)}, */ -/* {USB_DEVICE(0x0c45, 0x607b), BSI(SN9C102P, OV7660, 0x21)}, */ - {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, -/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x21)}, */ - {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, -/* {USB_DEVICE(0x0c45, 0x60c2), BSI(SN9C105, P1030xC, 0x??)}, */ -/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x34)}, */ -/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ - {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, -/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ -/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x21)}, */ - {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, + {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)}, + {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)}, + {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)}, + {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)}, + {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, + {USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)}, + {USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)}, +/* {USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */ + {USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)}, +/* {USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */ +/* {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */ + {USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)}, +/* {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */ + {USB_DEVICE(0x0c45, 0x60c0), BS(SN9C105, MI0360)}, +/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */ +/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */ +/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */ + {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)}, +/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */ +/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */ + {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, - {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, + {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)}, + {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)}, #endif - {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ -/* {USB_DEVICE(0x0c45, 0x6102), BSI(SN9C120, P1030xC, ??)}, */ -/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6802, 0x34)}, */ - {USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/ - {USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/ - {USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/ - {USB_DEVICE(0x0c45, 0x610e), BSI(SN9C120, OV7630, 0x21)}, /*sn9c128*/ -/* {USB_DEVICE(0x0c45, 0x610f), BSI(SN9C120, S5K53BEB, 0x??)}, */ -/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ -/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ - {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C120, OM6802, 0x34)}, /*sn9c325?*/ + {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/ +/* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, P1030xC)}, */ +/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */ + {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/ + {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/ + {USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)}, /*sn9c128*/ + {USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)}, /*sn9c128*/ +/* {USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */ +/* {USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */ +/* {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */ + {USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)}, /*sn9c325?*/ /*bw600.inf:*/ - {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/ - {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)}, - {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)}, -/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */ + {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)}, /*sn9c110?*/ + {USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)}, + {USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)}, +/* {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */ #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)}, + {USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)}, #endif -/* {USB_DEVICE(0x0c45, 0x6132), BSI(SN9C120, OV7670, 0x21)}, */ - {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)}, - {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)}, +/* {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */ + {USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)}, + {USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)}, + {USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)}, #endif - {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, - {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)}, -/* {USB_DEVICE(0x0c45, 0x6142), BSI(SN9C120, PO2030N, ??)}, *sn9c120b*/ - {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, /*sn9c120b*/ - {USB_DEVICE(0x0c45, 0x6148), BSI(SN9C120, OM6802, 0x34)}, /*sn9c120b*/ + {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, + {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, +/* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/ + {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ + {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ {} }; MODULE_DEVICE_TABLE(usb, device_table); From 265a8098e75e156985abfaac250ee4f2b407f863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=83=C2=A1rton=20N=C3=83=C2=A9meth?= Date: Sat, 7 Nov 2009 15:15:56 -0300 Subject: [PATCH 234/345] V4L/DVB (13385): gspca - pac7302: Add red and blue balance control. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The valid values for these controls are 0..3 (lower two bits) which was identified by trial and error on Labtec Webcam 2200 (USB ID 093a:2626). The upper 6 bits are ignored on page 0, registers 0xc5 and 0xc7 by the camera. Signed-off-by: Márton Németh Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7302.c | 126 ++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index ec2930871d1f..e7a4ced86e9b 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -49,6 +49,20 @@ -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to completely disable the analog amplification block. Set to 0x68 for max gain, 0x14 for minimal gain. + + The registers are accessed in the following functions: + + Page | Register | Function + -----+------------+--------------------------------------------------- + 0 | 0x0f..0x20 | setcolors() + 0 | 0xa2..0xab | setbrightcont() + 0 | 0xc5 | setredbalance() + 0 | 0xc7 | setbluebalance() + 0 | 0xdc | setbrightcont(), setcolors() + 3 | 0x02 | setexposure() + 3 | 0x10 | setgain() + 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip() + 3 | 0x21 | sethvflip() */ #define MODULE_NAME "pac7302" @@ -66,6 +80,8 @@ struct sd { unsigned char brightness; unsigned char contrast; unsigned char colors; + unsigned char red_balance; + unsigned char blue_balance; unsigned char gain; unsigned char exposure; unsigned char autogain; @@ -85,6 +101,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_setredbalance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getbluebalance(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_sethflip(struct gspca_dev *gspca_dev, __s32 val); @@ -145,6 +165,34 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, + { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red", + .minimum = 0, + .maximum = 3, + .step = 1, +#define REDBALANCE_DEF 1 + .default_value = REDBALANCE_DEF, + }, + .set = sd_setredbalance, + .get = sd_getredbalance, + }, + { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue", + .minimum = 0, + .maximum = 3, + .step = 1, +#define BLUEBALANCE_DEF 1 + .default_value = BLUEBALANCE_DEF, + }, + .set = sd_setbluebalance, + .get = sd_getbluebalance, + }, /* All controls below are for both the 7302 and the 7311 */ { { @@ -477,6 +525,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->red_balance = REDBALANCE_DEF; + sd->blue_balance = BLUEBALANCE_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; sd->autogain = AUTOGAIN_DEF; @@ -545,6 +595,36 @@ static int setcolors(struct gspca_dev *gspca_dev) return ret; } +static int setredbalance(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int ret; + + ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0xc5, sd->red_balance); + + if (0 <= ret) + ret = reg_w(gspca_dev, 0xdc, 0x01); + PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); + return ret; +} + +static int setbluebalance(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int ret; + + ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0xc7, sd->blue_balance); + + if (0 <= ret) + ret = reg_w(gspca_dev, 0xdc, 0x01); + PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); + return ret; +} + static int setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -625,6 +705,10 @@ static int sd_start(struct gspca_dev *gspca_dev) ret = setbrightcont(gspca_dev); if (0 <= ret) ret = setcolors(gspca_dev); + if (0 <= ret) + ret = setredbalance(gspca_dev); + if (0 <= ret) + ret = setbluebalance(gspca_dev); if (0 <= ret) setgain(gspca_dev); if (0 <= ret) @@ -857,6 +941,48 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + int ret = 0; + + sd->red_balance = val; + if (gspca_dev->streaming) + ret = setredbalance(gspca_dev); + if (0 <= ret) + ret = 0; + return ret; +} + +static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->red_balance; + return 0; +} + +static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + int ret = 0; + + sd->blue_balance = val; + if (gspca_dev->streaming) + ret = setbluebalance(gspca_dev); + if (0 <= ret) + ret = 0; + return ret; +} + +static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->blue_balance; + return 0; +} + static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; From 77ee33184fb4a37926c460d337c8d181f7c4c680 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 7 Nov 2009 15:30:50 -0300 Subject: [PATCH 235/345] V4L/DVB (13386): gspca - main: Change version to 2.8.0. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index eb166048540d..ecf449be189e 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -47,7 +47,7 @@ MODULE_AUTHOR("Jean-Francois Moine "); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 7, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 8, 0) #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; @@ -74,7 +74,7 @@ static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h) #define PDEBUG_MODE(txt, pixfmt, w, h) #endif -/* specific memory types - !! should different from V4L2_MEMORY_xxx */ +/* specific memory types - !! should be different from V4L2_MEMORY_xxx */ #define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */ #define GSPCA_MEMORY_READ 7 From b760812ed78c93249ac7957fedb87ba9c3ca3906 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 7 Nov 2009 16:38:55 -0300 Subject: [PATCH 236/345] V4L/DVB (13387): gspca - main: Fix a compilation warning. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ecf449be189e..afd99beab30d 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1619,7 +1619,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) size -= PAGE_SIZE; } - vma->vm_ops = &gspca_vm_ops; + vma->vm_ops = (struct vm_operations_struct *) &gspca_vm_ops; vma->vm_private_data = frame; gspca_vm_open(vma); ret = 0; From 23fbee6f88d59b4edca0855242d55e5b7cfc2401 Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Sun, 8 Nov 2009 04:35:12 -0300 Subject: [PATCH 237/345] V4L/DVB (13388): gspca - pac7302: Add white balance control. Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7302.c | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index e7a4ced86e9b..f8bf6a63f042 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -57,6 +57,7 @@ 0 | 0x0f..0x20 | setcolors() 0 | 0xa2..0xab | setbrightcont() 0 | 0xc5 | setredbalance() + 0 | 0xc6 | setwhitebalance() 0 | 0xc7 | setbluebalance() 0 | 0xdc | setbrightcont(), setcolors() 3 | 0x02 | setexposure() @@ -80,6 +81,7 @@ struct sd { unsigned char brightness; unsigned char contrast; unsigned char colors; + unsigned char white_balance; unsigned char red_balance; unsigned char blue_balance; unsigned char gain; @@ -101,6 +103,8 @@ 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_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val); static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); @@ -165,6 +169,20 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, + { + { + .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "White Balance", + .minimum = 0, + .maximum = 255, + .step = 1, +#define WHITEBALANCE_DEF 4 + .default_value = WHITEBALANCE_DEF, + }, + .set = sd_setwhitebalance, + .get = sd_getwhitebalance, + }, { { .id = V4L2_CID_RED_BALANCE, @@ -525,6 +543,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->white_balance = WHITEBALANCE_DEF; sd->red_balance = REDBALANCE_DEF; sd->blue_balance = BLUEBALANCE_DEF; sd->gain = GAIN_DEF; @@ -595,6 +614,21 @@ static int setcolors(struct gspca_dev *gspca_dev) return ret; } +static int setwhitebalance(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int ret; + + ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0xc6, sd->white_balance); + + if (0 <= ret) + ret = reg_w(gspca_dev, 0xdc, 0x01); + PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); + return ret; +} + static int setredbalance(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -705,6 +739,8 @@ static int sd_start(struct gspca_dev *gspca_dev) ret = setbrightcont(gspca_dev); if (0 <= ret) ret = setcolors(gspca_dev); + if (0 <= ret) + ret = setwhitebalance(gspca_dev); if (0 <= ret) ret = setredbalance(gspca_dev); if (0 <= ret) @@ -941,6 +977,27 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + int ret = 0; + + sd->white_balance = val; + if (gspca_dev->streaming) + ret = setwhitebalance(gspca_dev); + if (0 <= ret) + ret = 0; + return ret; +} + +static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->white_balance; + return 0; +} + static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; From 012880be6e1c8503e2901f8de90cc1e711334989 Mon Sep 17 00:00:00 2001 From: Marton Nemeth Date: Sun, 8 Nov 2009 04:41:28 -0300 Subject: [PATCH 238/345] V4L/DVB (13389): gspca - pac7302: Handle return values in sd_start(). Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7302.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index f8bf6a63f042..5cd02571bbf9 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -746,11 +746,11 @@ static int sd_start(struct gspca_dev *gspca_dev) if (0 <= ret) ret = setbluebalance(gspca_dev); if (0 <= ret) - setgain(gspca_dev); + ret = setgain(gspca_dev); if (0 <= ret) - setexposure(gspca_dev); + ret = setexposure(gspca_dev); if (0 <= ret) - sethvflip(gspca_dev); + ret = sethvflip(gspca_dev); /* only resolution 640x480 is supported for pac7302 */ From c4c1e295d2721470141843e31a69c4b1c131e0f7 Mon Sep 17 00:00:00 2001 From: "hiranotaka@zng.jp" Date: Sun, 8 Nov 2009 05:42:28 -0300 Subject: [PATCH 239/345] V4L/DVB (13394): pt1: Support FE_READ_SNR Signed-off-by: HIRANO Takahito Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/pt1/va1j5jf8007s.c | 55 ++++++++++++++++++++++++++++ drivers/media/dvb/pt1/va1j5jf8007t.c | 47 ++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.c b/drivers/media/dvb/pt1/va1j5jf8007s.c index 2db940f8635f..a20927e10d70 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007s.c +++ b/drivers/media/dvb/pt1/va1j5jf8007s.c @@ -48,6 +48,60 @@ struct va1j5jf8007s_state { enum va1j5jf8007s_tune_state tune_state; }; +static int va1j5jf8007s_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct va1j5jf8007s_state *state; + u8 addr; + int i; + u8 write_buf[1], read_buf[1]; + struct i2c_msg msgs[2]; + s32 word, x1, x2, x3, x4, x5, y; + + state = fe->demodulator_priv; + addr = state->config->demod_address; + + word = 0; + for (i = 0; i < 2; i++) { + write_buf[0] = 0xbc + i; + + msgs[0].addr = addr; + msgs[0].flags = 0; + msgs[0].len = sizeof(write_buf); + msgs[0].buf = write_buf; + + msgs[1].addr = addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = sizeof(read_buf); + msgs[1].buf = read_buf; + + if (i2c_transfer(state->adap, msgs, 2) != 2) + return -EREMOTEIO; + + word <<= 8; + word |= read_buf[0]; + } + + word -= 3000; + if (word < 0) + word = 0; + + x1 = int_sqrt(word << 16) * ((15625ll << 21) / 1000000); + x2 = (s64)x1 * x1 >> 31; + x3 = (s64)x2 * x1 >> 31; + x4 = (s64)x2 * x2 >> 31; + x5 = (s64)x4 * x1 >> 31; + + y = (58857ll << 23) / 1000; + y -= (s64)x1 * ((89565ll << 24) / 1000) >> 30; + y += (s64)x2 * ((88977ll << 24) / 1000) >> 28; + y -= (s64)x3 * ((50259ll << 25) / 1000) >> 27; + y += (s64)x4 * ((14341ll << 27) / 1000) >> 27; + y -= (s64)x5 * ((16346ll << 30) / 10000) >> 28; + + *snr = y < 0 ? 0 : y >> 15; + return 0; +} + static int va1j5jf8007s_get_frontend_algo(struct dvb_frontend *fe) { return DVBFE_ALGO_HW; @@ -536,6 +590,7 @@ static struct dvb_frontend_ops va1j5jf8007s_ops = { FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, }, + .read_snr = va1j5jf8007s_read_snr, .get_frontend_algo = va1j5jf8007s_get_frontend_algo, .read_status = va1j5jf8007s_read_status, .tune = va1j5jf8007s_tune, diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.c b/drivers/media/dvb/pt1/va1j5jf8007t.c index 71117f4ca7e6..fe897343f4f8 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007t.c +++ b/drivers/media/dvb/pt1/va1j5jf8007t.c @@ -46,6 +46,52 @@ struct va1j5jf8007t_state { enum va1j5jf8007t_tune_state tune_state; }; +static int va1j5jf8007t_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct va1j5jf8007t_state *state; + u8 addr; + int i; + u8 write_buf[1], read_buf[1]; + struct i2c_msg msgs[2]; + s32 word, x, y; + + state = fe->demodulator_priv; + addr = state->config->demod_address; + + word = 0; + for (i = 0; i < 3; i++) { + write_buf[0] = 0x8b + i; + + msgs[0].addr = addr; + msgs[0].flags = 0; + msgs[0].len = sizeof(write_buf); + msgs[0].buf = write_buf; + + msgs[1].addr = addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = sizeof(read_buf); + msgs[1].buf = read_buf; + + if (i2c_transfer(state->adap, msgs, 2) != 2) + return -EREMOTEIO; + + word <<= 8; + word |= read_buf[0]; + } + + if (!word) + return -EIO; + + x = 10 * (intlog10(0x540000 * 100 / word) - (2 << 24)); + y = (24ll << 46) / 1000000; + y = ((s64)y * x >> 30) - (16ll << 40) / 10000; + y = ((s64)y * x >> 29) + (398ll << 35) / 10000; + y = ((s64)y * x >> 30) + (5491ll << 29) / 10000; + y = ((s64)y * x >> 30) + (30965ll << 23) / 10000; + *snr = y >> 15; + return 0; +} + static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe) { return DVBFE_ALGO_HW; @@ -393,6 +439,7 @@ static struct dvb_frontend_ops va1j5jf8007t_ops = { FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, }, + .read_snr = va1j5jf8007t_read_snr, .get_frontend_algo = va1j5jf8007t_get_frontend_algo, .read_status = va1j5jf8007t_read_status, .tune = va1j5jf8007t_tune, From b921d929f4a012be3e809fbb1ff1e8e6c0751c06 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 8 Nov 2009 14:49:05 -0300 Subject: [PATCH 240/345] V4L/DVB (13396): correct initialization of audio_mode This initialization of the value of audio_mode is the one used if nothing matches in the subsequent switch. The variable audio_mode is subsequently assigned to constants such as TUNER_AUDIO_MONO and TUNER_AUDIO_STEREO. TUNER_AUDIO_STEREO has the same value as V4L2_TUNER_MODE_STEREO, so it would seem better to use that value here. Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa717x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index ad6cd37311fa..6818df571168 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c @@ -1312,7 +1312,7 @@ static int saa717x_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) "MONO", "STEREO", "LANG1", "LANG2/SAP" }; - audio_mode = V4L2_TUNER_MODE_STEREO; + audio_mode = TUNER_AUDIO_STEREO; switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: From 56411f49f69140b97e259256b99dc276f2b2b427 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 8 Nov 2009 18:28:45 -0300 Subject: [PATCH 241/345] V4L/DVB (13397): firedtv: move remote control workqueue handling into rc source file Preparation for the port of firedtv to the firewire-core kernel API: Canceling of the remote control workqueue job is factored into firedtv-rc.c. Plus trivial whitespace change. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-1394.c | 5 +++-- drivers/media/dvb/firewire/firedtv-rc.c | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c index 2b6eeeab5b25..a2e3841f8ee9 100644 --- a/drivers/media/dvb/firewire/firedtv-1394.c +++ b/drivers/media/dvb/firewire/firedtv-1394.c @@ -212,6 +212,7 @@ static int node_probe(struct device *dev) goto fail; avc_register_remote_control(fdtv); + return 0; fail: spin_lock_irq(&node_list_lock); @@ -220,6 +221,7 @@ static int node_probe(struct device *dev) fdtv_unregister_rc(fdtv); fail_free: kfree(fdtv); + return err; } @@ -233,10 +235,9 @@ static int node_remove(struct device *dev) list_del(&fdtv->list); spin_unlock_irq(&node_list_lock); - cancel_work_sync(&fdtv->remote_ctrl_work); fdtv_unregister_rc(fdtv); - kfree(fdtv); + return 0; } diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c index 27bca2e283df..599d66e5843d 100644 --- a/drivers/media/dvb/firewire/firedtv-rc.c +++ b/drivers/media/dvb/firewire/firedtv-rc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "firedtv.h" @@ -163,6 +164,7 @@ int fdtv_register_rc(struct firedtv *fdtv, struct device *dev) void fdtv_unregister_rc(struct firedtv *fdtv) { + cancel_work_sync(&fdtv->remote_ctrl_work); kfree(fdtv->remote_ctrl_dev->keycode); input_unregister_device(fdtv->remote_ctrl_dev); } From 054286b12c7ba7d37a945326d38716a00434002b Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 8 Nov 2009 18:29:08 -0300 Subject: [PATCH 242/345] V4L/DVB (13398): firedtv: reform lock transaction backend call Preparation for the port of firedtv to the firewire-core kernel API: The fdtv->backend->lock() hook and thus the CMP code is slightly changed to better fit with the new API. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-1394.c | 11 +++-- drivers/media/dvb/firewire/firedtv-avc.c | 50 +++++++++++++---------- drivers/media/dvb/firewire/firedtv.h | 2 +- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c index a2e3841f8ee9..22ea4c90f5c9 100644 --- a/drivers/media/dvb/firewire/firedtv-1394.c +++ b/drivers/media/dvb/firewire/firedtv-1394.c @@ -87,10 +87,15 @@ static inline struct node_entry *node_of(struct firedtv *fdtv) return container_of(fdtv->device, struct unit_directory, device)->ne; } -static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg) +static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) { - return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data, - (__force quadlet_t)arg); + int ret; + + ret = hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, + (__force quadlet_t *)&data[1], (__force quadlet_t)data[0]); + data[0] = data[1]; + + return ret; } static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len) diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 485d061319ab..5516c33b1453 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -1251,14 +1251,14 @@ static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len) return ret; } -static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg) +static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) { int ret; if (mutex_lock_interruptible(&fdtv->avc_mutex)) return -EINTR; - ret = fdtv->backend->lock(fdtv, addr, data, arg); + ret = fdtv->backend->lock(fdtv, addr, data); if (ret < 0) dev_err(fdtv->device, "CMP: lock I/O error\n"); @@ -1288,25 +1288,25 @@ static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift) int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel) { - __be32 old_opcr, opcr; + __be32 old_opcr, opcr[2]; u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); int attempts = 0; int ret; - ret = cmp_read(fdtv, &opcr, opcr_address, 4); + ret = cmp_read(fdtv, opcr, opcr_address, 4); if (ret < 0) return ret; repeat: - if (!get_opcr_online(opcr)) { + if (!get_opcr_online(*opcr)) { dev_err(fdtv->device, "CMP: output offline\n"); return -EBUSY; } - old_opcr = opcr; + old_opcr = *opcr; - if (get_opcr_p2p_connections(opcr)) { - if (get_opcr_channel(opcr) != channel) { + if (get_opcr_p2p_connections(*opcr)) { + if (get_opcr_channel(*opcr) != channel) { dev_err(fdtv->device, "CMP: cannot change channel\n"); return -EBUSY; } @@ -1314,11 +1314,11 @@ int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel) /* We don't allocate isochronous resources. */ } else { - set_opcr_channel(&opcr, channel); - set_opcr_data_rate(&opcr, 2); /* S400 */ + set_opcr_channel(opcr, channel); + set_opcr_data_rate(opcr, 2); /* S400 */ /* FIXME: this is for the worst case - optimize */ - set_opcr_overhead_id(&opcr, 0); + set_opcr_overhead_id(opcr, 0); /* * FIXME: allocate isochronous channel and bandwidth at IRM @@ -1326,13 +1326,16 @@ int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel) */ } - set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1); + set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) + 1); - ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr); + opcr[1] = *opcr; + opcr[0] = old_opcr; + + ret = cmp_lock(fdtv, opcr_address, opcr); if (ret < 0) return ret; - if (old_opcr != opcr) { + if (old_opcr != *opcr) { /* * FIXME: if old_opcr.P2P_Connections > 0, * deallocate isochronous channel and bandwidth at IRM @@ -1350,27 +1353,30 @@ int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel) void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel) { - __be32 old_opcr, opcr; + __be32 old_opcr, opcr[2]; u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); int attempts = 0; - if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0) + if (cmp_read(fdtv, opcr, opcr_address, 4) < 0) return; repeat: - if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) || - get_opcr_channel(opcr) != channel) { + if (!get_opcr_online(*opcr) || !get_opcr_p2p_connections(*opcr) || + get_opcr_channel(*opcr) != channel) { dev_err(fdtv->device, "CMP: no connection to break\n"); return; } - old_opcr = opcr; - set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1); + old_opcr = *opcr; + set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) - 1); - if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr) < 0) + opcr[1] = *opcr; + opcr[0] = old_opcr; + + if (cmp_lock(fdtv, opcr_address, opcr) < 0) return; - if (old_opcr != opcr) { + if (old_opcr != *opcr) { /* * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last * owner, deallocate isochronous channel and bandwidth at IRM diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h index d48530b81e61..1b99660a8397 100644 --- a/drivers/media/dvb/firewire/firedtv.h +++ b/drivers/media/dvb/firewire/firedtv.h @@ -72,7 +72,7 @@ struct input_dev; struct firedtv; struct firedtv_backend { - int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg); + int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]); int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len); int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len); int (*start_iso)(struct firedtv *fdtv); From 6e25abb522e055beeaf887f50a49cb370acc62b6 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 8 Nov 2009 18:29:41 -0300 Subject: [PATCH 243/345] V4L/DVB (13399): firedtv: add missing include, rename a constant Add #include for dvb_dmx_swfilter_packets(). This was already indirectly included via firedtv.h, but don't rely on it. The 4 bytes which were referred to as FIREWIRE_HEADER_SIZE are actually the source packet header from IEC 61883-4 (MPEG2-TS data transmission over 1394), not e.g. the IEEE 1394 isochronous packet header. So choose a more precise name. Also, express the payload size as a preprocessor constant too. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-1394.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c index 22ea4c90f5c9..82b576a4774d 100644 --- a/drivers/media/dvb/firewire/firedtv-1394.c +++ b/drivers/media/dvb/firewire/firedtv-1394.c @@ -26,13 +26,16 @@ #include #include +#include + #include "firedtv.h" static LIST_HEAD(node_list); static DEFINE_SPINLOCK(node_list_lock); -#define FIREWIRE_HEADER_SIZE 4 -#define CIP_HEADER_SIZE 8 +#define CIP_HEADER_SIZE 8 +#define MPEG2_TS_HEADER_SIZE 4 +#define MPEG2_TS_SOURCE_PACKET_SIZE (4 + 188) static void rawiso_activity_cb(struct hpsb_iso *iso) { @@ -62,20 +65,20 @@ static void rawiso_activity_cb(struct hpsb_iso *iso) buf = dma_region_i(&iso->data_buf, unsigned char, iso->infos[packet].offset + CIP_HEADER_SIZE); count = (iso->infos[packet].len - CIP_HEADER_SIZE) / - (188 + FIREWIRE_HEADER_SIZE); + MPEG2_TS_SOURCE_PACKET_SIZE; /* ignore empty packet */ if (iso->infos[packet].len <= CIP_HEADER_SIZE) continue; while (count--) { - if (buf[FIREWIRE_HEADER_SIZE] == 0x47) + if (buf[MPEG2_TS_HEADER_SIZE] == 0x47) dvb_dmx_swfilter_packets(&fdtv->demux, - &buf[FIREWIRE_HEADER_SIZE], 1); + &buf[MPEG2_TS_HEADER_SIZE], 1); else dev_err(fdtv->device, "skipping invalid packet\n"); - buf += 188 + FIREWIRE_HEADER_SIZE; + buf += MPEG2_TS_SOURCE_PACKET_SIZE; } } out: From 87918334792a4d8a73b0511466b77bd6aa055db3 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 8 Nov 2009 18:30:54 -0300 Subject: [PATCH 244/345] V4L/DVB (13400): firedtv: port to new firewire core The firedtv DVB driver will now work not only on top of the old ieee1394 driver stack but also on the new firewire driver stack. Alongside to the firedtv-1394.c backend for driver binding and I/O, the firedtv-fw.c backend is added. Depending on which of the two 1394 stacks is configured, one or the other or both backends will be built into the firedtv driver. This has been tested with a DVB-T and a DVB-C box on x86-64 and x86-32 together with a few different controllers (Agere FW323, a NEC chip, TI TSB82AA2, TSB43AB22/A, VIA VT6306). Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/Kconfig | 7 +- drivers/media/dvb/firewire/Makefile | 1 + drivers/media/dvb/firewire/firedtv-1394.c | 6 +- drivers/media/dvb/firewire/firedtv-dvb.c | 15 +- drivers/media/dvb/firewire/firedtv-fw.c | 385 ++++++++++++++++++++++ drivers/media/dvb/firewire/firedtv.h | 15 +- 6 files changed, 420 insertions(+), 9 deletions(-) create mode 100644 drivers/media/dvb/firewire/firedtv-fw.c diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/dvb/firewire/Kconfig index 69028253e984..4afa29256df1 100644 --- a/drivers/media/dvb/firewire/Kconfig +++ b/drivers/media/dvb/firewire/Kconfig @@ -1,6 +1,6 @@ config DVB_FIREDTV tristate "FireDTV and FloppyDTV" - depends on DVB_CORE && IEEE1394 + depends on DVB_CORE && (FIREWIRE || IEEE1394) help Support for DVB receivers from Digital Everywhere which are connected via IEEE 1394 (FireWire). @@ -13,8 +13,11 @@ config DVB_FIREDTV if DVB_FIREDTV +config DVB_FIREDTV_FIREWIRE + def_bool FIREWIRE = y || (FIREWIRE = m && DVB_FIREDTV = m) + config DVB_FIREDTV_IEEE1394 - def_bool IEEE1394 + def_bool IEEE1394 = y || (IEEE1394 = m && DVB_FIREDTV = m) config DVB_FIREDTV_INPUT def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m) diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile index 2034695ba194..da84203d51c6 100644 --- a/drivers/media/dvb/firewire/Makefile +++ b/drivers/media/dvb/firewire/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_DVB_FIREDTV) += firedtv.o firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o +firedtv-$(CONFIG_DVB_FIREDTV_FIREWIRE) += firedtv-fw.o firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c index 82b576a4774d..ed98fdb650c5 100644 --- a/drivers/media/dvb/firewire/firedtv-1394.c +++ b/drivers/media/dvb/firewire/firedtv-1394.c @@ -1,5 +1,5 @@ /* - * FireDTV driver (formerly known as FireSAT) + * FireDTV driver -- ieee1394 I/O backend * * Copyright (C) 2004 Andreas Monitzer * Copyright (C) 2007-2008 Ben Backx @@ -261,6 +261,7 @@ static int node_update(struct unit_directory *ud) static struct hpsb_protocol_driver fdtv_driver = { .name = "firedtv", + .id_table = fdtv_id_table, .update = node_update, .driver = { .probe = node_probe, @@ -273,12 +274,11 @@ static struct hpsb_highlevel fdtv_highlevel = { .fcp_request = fcp_request, }; -int __init fdtv_1394_init(struct ieee1394_device_id id_table[]) +int __init fdtv_1394_init(void) { int ret; hpsb_register_highlevel(&fdtv_highlevel); - fdtv_driver.id_table = id_table; ret = hpsb_register_protocol(&fdtv_driver); if (ret) { printk(KERN_ERR "firedtv: failed to register protocol\n"); diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c index 5742fde79d99..fc9996c13e13 100644 --- a/drivers/media/dvb/firewire/firedtv-dvb.c +++ b/drivers/media/dvb/firewire/firedtv-dvb.c @@ -297,7 +297,7 @@ struct firedtv *fdtv_alloc(struct device *dev, #define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d #define AVC_SW_VERSION_ENTRY 0x010001 -static struct ieee1394_device_id fdtv_id_table[] = { +const struct ieee1394_device_id fdtv_id_table[] = { { /* FloppyDTV S/CI and FloppyDTV S2 */ .match_flags = MATCH_FLAGS, @@ -346,12 +346,23 @@ MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table); static int __init fdtv_init(void) { - return fdtv_1394_init(fdtv_id_table); + int ret; + + ret = fdtv_fw_init(); + if (ret < 0) + return ret; + + ret = fdtv_1394_init(); + if (ret < 0) + fdtv_fw_exit(); + + return ret; } static void __exit fdtv_exit(void) { fdtv_1394_exit(); + fdtv_fw_exit(); } module_init(fdtv_init); diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c new file mode 100644 index 000000000000..208e5b59e830 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -0,0 +1,385 @@ +/* + * FireDTV driver -- firewire I/O backend + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "firedtv.h" + +static LIST_HEAD(node_list); +static DEFINE_SPINLOCK(node_list_lock); + +static inline struct fw_device *device_of(struct firedtv *fdtv) +{ + return fw_device(fdtv->device->parent); +} + +static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len, + int tcode) +{ + struct fw_device *device = device_of(fdtv); + int rcode, generation = device->generation; + + smp_rmb(); /* node_id vs. generation */ + + rcode = fw_run_transaction(device->card, tcode, device->node_id, + generation, device->max_speed, addr, data, len); + + return rcode != RCODE_COMPLETE ? -EIO : 0; +} + +static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) +{ + return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP); +} + +static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len) +{ + return node_req(fdtv, addr, data, len, len == 4 ? + TCODE_READ_QUADLET_REQUEST : TCODE_READ_BLOCK_REQUEST); +} + +static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len) +{ + return node_req(fdtv, addr, data, len, TCODE_WRITE_BLOCK_REQUEST); +} + +#define ISO_HEADER_SIZE 4 +#define CIP_HEADER_SIZE 8 +#define MPEG2_TS_HEADER_SIZE 4 +#define MPEG2_TS_SOURCE_PACKET_SIZE (4 + 188) + +#define MAX_PACKET_SIZE 1024 /* 776, rounded up to 2^n */ +#define PACKETS_PER_PAGE (PAGE_SIZE / MAX_PACKET_SIZE) +#define N_PACKETS 64 /* buffer size */ +#define N_PAGES DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE) +#define IRQ_INTERVAL 16 + +struct firedtv_receive_context { + struct fw_iso_context *context; + struct fw_iso_buffer buffer; + int interrupt_packet; + int current_packet; + char *packets[N_PACKETS]; +}; + +static int queue_iso(struct firedtv_receive_context *ctx, int index) +{ + struct fw_iso_packet p; + int err; + + p.payload_length = MAX_PACKET_SIZE; + p.interrupt = !(ctx->interrupt_packet & (IRQ_INTERVAL - 1)); + p.skip = 0; + p.header_length = ISO_HEADER_SIZE; + + err = fw_iso_context_queue(ctx->context, &p, &ctx->buffer, + index * MAX_PACKET_SIZE); + if (!err) + ctx->interrupt_packet++; + + return err; +} + +static void handle_iso(struct fw_iso_context *context, u32 cycle, + size_t header_length, void *header, void *data) +{ + struct firedtv *fdtv = data; + struct firedtv_receive_context *ctx = fdtv->backend_data; + __be32 *h, *h_end; + int i = ctx->current_packet, length, err; + char *p, *p_end; + + for (h = header, h_end = h + header_length / 4; h < h_end; h++) { + length = be32_to_cpup(h) >> 16; + if (unlikely(length > MAX_PACKET_SIZE)) { + dev_err(fdtv->device, "length = %d\n", length); + length = MAX_PACKET_SIZE; + } + + p = ctx->packets[i]; + p_end = p + length; + + for (p += CIP_HEADER_SIZE + MPEG2_TS_HEADER_SIZE; p < p_end; + p += MPEG2_TS_SOURCE_PACKET_SIZE) + dvb_dmx_swfilter_packets(&fdtv->demux, p, 1); + + err = queue_iso(ctx, i); + if (unlikely(err)) + dev_err(fdtv->device, "requeue failed\n"); + + i = (i + 1) & (N_PACKETS - 1); + } + ctx->current_packet = i; +} + +static int start_iso(struct firedtv *fdtv) +{ + struct firedtv_receive_context *ctx; + struct fw_device *device = device_of(fdtv); + char *p; + int i, j, k, err; + + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->context = fw_iso_context_create(device->card, + FW_ISO_CONTEXT_RECEIVE, fdtv->isochannel, + device->max_speed, ISO_HEADER_SIZE, handle_iso, fdtv); + if (IS_ERR(ctx->context)) { + err = PTR_ERR(ctx->context); + goto fail_free; + } + + err = fw_iso_buffer_init(&ctx->buffer, device->card, + N_PAGES, DMA_FROM_DEVICE); + if (err) + goto fail_context_destroy; + + ctx->interrupt_packet = 1; + ctx->current_packet = 0; + + for (i = 0, k = 0; k < N_PAGES; k++) { + p = kmap(ctx->buffer.pages[k]); + for (j = 0; j < PACKETS_PER_PAGE && i < N_PACKETS; j++, i++) + ctx->packets[i] = p + j * MAX_PACKET_SIZE; + } + + for (i = 0; i < N_PACKETS; i++) { + err = queue_iso(ctx, i); + if (err) + goto fail; + } + + err = fw_iso_context_start(ctx->context, -1, 0, + FW_ISO_CONTEXT_MATCH_ALL_TAGS); + if (err) + goto fail; + + fdtv->backend_data = ctx; + + return 0; +fail: + fw_iso_buffer_destroy(&ctx->buffer, device->card); +fail_context_destroy: + fw_iso_context_destroy(ctx->context); +fail_free: + kfree(ctx); + + return err; +} + +static void stop_iso(struct firedtv *fdtv) +{ + struct firedtv_receive_context *ctx = fdtv->backend_data; + + fw_iso_context_stop(ctx->context); + fw_iso_buffer_destroy(&ctx->buffer, device_of(fdtv)->card); + fw_iso_context_destroy(ctx->context); + kfree(ctx); +} + +static const struct firedtv_backend backend = { + .lock = node_lock, + .read = node_read, + .write = node_write, + .start_iso = start_iso, + .stop_iso = stop_iso, +}; + +static void handle_fcp(struct fw_card *card, struct fw_request *request, + int tcode, int destination, int source, int generation, + int speed, unsigned long long offset, + void *payload, size_t length, void *callback_data) +{ + struct firedtv *f, *fdtv = NULL; + struct fw_device *device; + unsigned long flags; + int su; + + if ((tcode != TCODE_WRITE_QUADLET_REQUEST && + tcode != TCODE_WRITE_BLOCK_REQUEST) || + offset != CSR_REGISTER_BASE + CSR_FCP_RESPONSE || + length == 0 || + (((u8 *)payload)[0] & 0xf0) != 0) { + fw_send_response(card, request, RCODE_TYPE_ERROR); + return; + } + + su = ((u8 *)payload)[1] & 0x7; + + spin_lock_irqsave(&node_list_lock, flags); + list_for_each_entry(f, &node_list, list) { + device = device_of(f); + if (device->generation != generation) + continue; + + smp_rmb(); /* node_id vs. generation */ + + if (device->card == card && + device->node_id == source && + (f->subunit == su || (f->subunit == 0 && su == 0x7))) { + fdtv = f; + break; + } + } + spin_unlock_irqrestore(&node_list_lock, flags); + + if (fdtv) { + avc_recv(fdtv, payload, length); + fw_send_response(card, request, RCODE_COMPLETE); + } +} + +static struct fw_address_handler fcp_handler = { + .length = CSR_FCP_END - CSR_FCP_RESPONSE, + .address_callback = handle_fcp, +}; + +static const struct fw_address_region fcp_region = { + .start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE, + .end = CSR_REGISTER_BASE + CSR_FCP_END, +}; + +/* Adjust the template string if models with longer names appear. */ +#define MAX_MODEL_NAME_LEN ((int)DIV_ROUND_UP(sizeof("FireDTV ????"), 4)) + +static size_t model_name(u32 *directory, __be32 *buffer) +{ + struct fw_csr_iterator ci; + int i, length, key, value, last_key = 0; + u32 *block = NULL; + + fw_csr_iterator_init(&ci, directory); + while (fw_csr_iterator_next(&ci, &key, &value)) { + if (last_key == CSR_MODEL && + key == (CSR_DESCRIPTOR | CSR_LEAF)) + block = ci.p - 1 + value; + last_key = key; + } + + if (block == NULL) + return 0; + + length = min((int)(block[0] >> 16) - 2, MAX_MODEL_NAME_LEN); + if (length <= 0) + return 0; + + /* fast-forward to text string */ + block += 3; + + for (i = 0; i < length; i++) + buffer[i] = cpu_to_be32(block[i]); + + return length * 4; +} + +static int node_probe(struct device *dev) +{ + struct firedtv *fdtv; + __be32 name[MAX_MODEL_NAME_LEN]; + int name_len, err; + + name_len = model_name(fw_unit(dev)->directory, name); + + fdtv = fdtv_alloc(dev, &backend, (char *)name, name_len); + if (!fdtv) + return -ENOMEM; + + err = fdtv_register_rc(fdtv, dev); + if (err) + goto fail_free; + + spin_lock_irq(&node_list_lock); + list_add_tail(&fdtv->list, &node_list); + spin_unlock_irq(&node_list_lock); + + err = avc_identify_subunit(fdtv); + if (err) + goto fail; + + err = fdtv_dvb_register(fdtv); + if (err) + goto fail; + + avc_register_remote_control(fdtv); + + return 0; +fail: + spin_lock_irq(&node_list_lock); + list_del(&fdtv->list); + spin_unlock_irq(&node_list_lock); + fdtv_unregister_rc(fdtv); +fail_free: + kfree(fdtv); + + return err; +} + +static int node_remove(struct device *dev) +{ + struct firedtv *fdtv = dev_get_drvdata(dev); + + fdtv_dvb_unregister(fdtv); + + spin_lock_irq(&node_list_lock); + list_del(&fdtv->list); + spin_unlock_irq(&node_list_lock); + + fdtv_unregister_rc(fdtv); + + kfree(fdtv); + return 0; +} + +static void node_update(struct fw_unit *unit) +{ + struct firedtv *fdtv = dev_get_drvdata(&unit->device); + + if (fdtv->isochannel >= 0) + cmp_establish_pp_connection(fdtv, fdtv->subunit, + fdtv->isochannel); +} + +static struct fw_driver fdtv_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "firedtv", + .bus = &fw_bus_type, + .probe = node_probe, + .remove = node_remove, + }, + .update = node_update, + .id_table = fdtv_id_table, +}; + +int __init fdtv_fw_init(void) +{ + int ret; + + ret = fw_core_add_address_handler(&fcp_handler, &fcp_region); + if (ret < 0) + return ret; + + return driver_register(&fdtv_driver.driver); +} + +void fdtv_fw_exit(void) +{ + driver_unregister(&fdtv_driver.driver); + fw_core_remove_address_handler(&fcp_handler); +} diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h index 1b99660a8397..f7b5c030bedf 100644 --- a/drivers/media/dvb/firewire/firedtv.h +++ b/drivers/media/dvb/firewire/firedtv.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -119,10 +120,10 @@ struct firedtv { /* firedtv-1394.c */ #ifdef CONFIG_DVB_FIREDTV_IEEE1394 -int fdtv_1394_init(struct ieee1394_device_id id_table[]); +int fdtv_1394_init(void); void fdtv_1394_exit(void); #else -static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; } +static inline int fdtv_1394_init(void) { return 0; } static inline void fdtv_1394_exit(void) {} #endif @@ -163,10 +164,20 @@ struct firedtv *fdtv_alloc(struct device *dev, const struct firedtv_backend *backend, const char *name, size_t name_len); extern const char *fdtv_model_names[]; +extern const struct ieee1394_device_id fdtv_id_table[]; /* firedtv-fe.c */ void fdtv_frontend_init(struct firedtv *fdtv); +/* firedtv-fw.c */ +#ifdef CONFIG_DVB_FIREDTV_FIREWIRE +int fdtv_fw_init(void); +void fdtv_fw_exit(void); +#else +static inline int fdtv_fw_init(void) { return 0; } +static inline void fdtv_fw_exit(void) {} +#endif + /* firedtv-rc.c */ #ifdef CONFIG_DVB_FIREDTV_INPUT int fdtv_register_rc(struct firedtv *fdtv, struct device *dev); From d89ce0d9ec9f980d59eae8d5a0ead98988e3b545 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 9 Nov 2009 19:09:49 -0300 Subject: [PATCH 245/345] V4L/DVB (13402): radio-mr800 - autosuspend for radio-mr800 driver Patch adds autosuspend support for mr800 radio driver. Signed-off-by: Oliver Neukum Acked-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 4064109c4205..44efa68d9f8e 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -132,6 +132,7 @@ static int usb_amradio_resume(struct usb_interface *intf); struct amradio_device { /* reference to USB and video device */ struct usb_device *usbdev; + struct usb_interface *intf; struct video_device videodev; struct v4l2_device v4l2_dev; @@ -163,7 +164,7 @@ static struct usb_driver usb_amradio_driver = { .resume = usb_amradio_resume, .reset_resume = usb_amradio_resume, .id_table = usb_amradio_device_table, - .supports_autosuspend = 0, + .supports_autosuspend = 1, }; /* switch on/off the radio. Send 8 bytes to device */ @@ -506,9 +507,15 @@ static int usb_amradio_open(struct file *file) } file->private_data = radio; + retval = usb_autopm_get_interface(radio->intf); + if (retval) + goto unlock; - if (unlikely(!radio->initialized)) + if (unlikely(!radio->initialized)) { retval = usb_amradio_init(radio); + if (retval) + usb_autopm_put_interface(radio->intf); + } unlock: mutex_unlock(&radio->lock); @@ -525,6 +532,8 @@ static int usb_amradio_close(struct file *file) if (!radio->usbdev) retval = -EIO; + else + usb_autopm_put_interface(radio->intf); mutex_unlock(&radio->lock); return retval; @@ -666,6 +675,7 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->videodev.release = usb_amradio_video_device_release; radio->usbdev = interface_to_usbdev(intf); + radio->intf = intf; radio->curfreq = 95.16 * FREQ_MUL; mutex_init(&radio->lock); From fa26ae3e8260530121e6e0e57427468a9f0038d7 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Thu, 12 Nov 2009 10:16:09 -0300 Subject: [PATCH 246/345] V4L/DVB: pt1: remove duplicated #include Remove duplicated #include('s) in drivers/media/dvb/pt1/pt1.c Signed-off-by: Huang Weiyi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/pt1/pt1.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c index 1fd8306371e2..81e623a90f09 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/dvb/pt1/pt1.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "dvbdev.h" #include "dvb_demux.h" From b699c2712b1ddcc3ef4491adde00a47a880fde97 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 16 Nov 2009 22:22:32 -0300 Subject: [PATCH 247/345] V4L/DVB (13407): Add Prof 7301 PCI DVB-S2 card Add Prof 7301 PCI DVB-S2 card The card based on stv0903 demod, stb6100 tuner. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/dvb/frontends/stb6100_proc.h | 138 +++++++++++++++++++++ drivers/media/dvb/frontends/stv0900.h | 2 + drivers/media/dvb/frontends/stv0900_core.c | 3 + drivers/media/video/cx88/Kconfig | 2 + drivers/media/video/cx88/cx88-cards.c | 17 +++ drivers/media/video/cx88/cx88-dvb.c | 54 ++++++++ drivers/media/video/cx88/cx88-input.c | 2 + drivers/media/video/cx88/cx88.h | 1 + 9 files changed, 220 insertions(+) create mode 100644 drivers/media/dvb/frontends/stb6100_proc.h diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 3385f8b094a5..7ec3c4e4b60f 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -81,3 +81,4 @@ 80 -> Hauppauge WinTV-IR Only [0070:9290] 81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654] 82 -> WinFast DTV2000 H rev. J [107d:6f2b] + 83 -> Prof 7301 DVB-S/S2 [b034:3034] diff --git a/drivers/media/dvb/frontends/stb6100_proc.h b/drivers/media/dvb/frontends/stb6100_proc.h new file mode 100644 index 000000000000..112163a48622 --- /dev/null +++ b/drivers/media/dvb/frontends/stb6100_proc.h @@ -0,0 +1,138 @@ +/* + STB6100 Silicon Tuner wrapper + Copyright (C)2009 Igor M. Liplianin (liplianin@me.by) + + 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. +*/ + +static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency) +{ + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + struct tuner_state state; + int err = 0; + + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->get_state) { + if (frontend_ops->i2c_gate_ctrl) + frontend_ops->i2c_gate_ctrl(fe, 1); + + err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &state); + if (err < 0) { + printk(KERN_ERR "%s: Invalid parameter\n", __func__); + return err; + } + + if (frontend_ops->i2c_gate_ctrl) + frontend_ops->i2c_gate_ctrl(fe, 0); + + *frequency = state.frequency; + } + + return 0; +} + +static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency) +{ + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + struct tuner_state state; + int err = 0; + + state.frequency = frequency; + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->set_state) { + if (frontend_ops->i2c_gate_ctrl) + frontend_ops->i2c_gate_ctrl(fe, 1); + + err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &state); + if (err < 0) { + printk(KERN_ERR "%s: Invalid parameter\n", __func__); + return err; + } + + if (frontend_ops->i2c_gate_ctrl) + frontend_ops->i2c_gate_ctrl(fe, 0); + + } + + return 0; +} + +static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + struct tuner_state state; + int err = 0; + + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->get_state) { + if (frontend_ops->i2c_gate_ctrl) + frontend_ops->i2c_gate_ctrl(fe, 1); + + err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &state); + if (err < 0) { + printk(KERN_ERR "%s: Invalid parameter\n", __func__); + return err; + } + + if (frontend_ops->i2c_gate_ctrl) + frontend_ops->i2c_gate_ctrl(fe, 0); + + *bandwidth = state.bandwidth; + } + + return 0; +} + +static int stb6100_set_bandw(struct dvb_frontend *fe, u32 bandwidth) +{ + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + struct tuner_state state; + int err = 0; + + state.bandwidth = bandwidth; + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->set_state) { + if (frontend_ops->i2c_gate_ctrl) + frontend_ops->i2c_gate_ctrl(fe, 1); + + err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &state); + if (err < 0) { + printk(KERN_ERR "%s: Invalid parameter\n", __func__); + return err; + } + + if (frontend_ops->i2c_gate_ctrl) + frontend_ops->i2c_gate_ctrl(fe, 0); + + } + + return 0; +} diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h index 446bdfc8ad10..29c3fa85c227 100644 --- a/drivers/media/dvb/frontends/stv0900.h +++ b/drivers/media/dvb/frontends/stv0900.h @@ -49,6 +49,8 @@ struct stv0900_config { u8 tun2_maddress; u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */ u8 tun2_adc; + /* Set device param to start dma */ + int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); }; #if defined(CONFIG_DVB_STV0900) || (defined(CONFIG_DVB_STV0900_MODULE) \ diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index e2062048f433..df49ea0983bc 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -1494,6 +1494,9 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, if (!(INRANGE(100000, c->symbol_rate, 70000000))) return DVBFE_ALGO_SEARCH_FAILED; + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); + p_result.locked = FALSE; p_search.path = demod; p_search.frequency = c->frequency; diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 49952980dab3..c7e5851d3486 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -61,6 +61,8 @@ config VIDEO_CX88_DVB select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0288 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE + select DVB_STV0900 if !DVB_FE_CUSTOMISE + select DVB_STB6100 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE ---help--- This adds support for DVB/ATSC cards based on the diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 7330a2d70439..d844f2aaa01d 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2075,6 +2075,18 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_PROF_7301] = { + .name = "Prof 7301 DVB-S/S2", + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = { { + .type = CX88_VMUX_DVB, + .vmux = 0, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2535,6 +2547,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x107d, .subdevice = 0x6618, .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, + }, { + .subvendor = 0xb034, + .subdevice = 0x3034, + .card = CX88_BOARD_PROF_7301, }, }; @@ -3211,6 +3227,7 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_TBS_8920: case CX88_BOARD_PROF_6200: case CX88_BOARD_PROF_7300: + case CX88_BOARD_PROF_7301: case CX88_BOARD_SATTRADE_ST4200: cx_write(MO_GP0_IO, 0x8000); msleep(100); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 9df71d0244a8..b14296923250 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -53,6 +53,9 @@ #include "stv0288.h" #include "stb6000.h" #include "cx24116.h" +#include "stv0900.h" +#include "stb6100.h" +#include "stb6100_proc.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -573,6 +576,15 @@ static int cx24116_set_ts_param(struct dvb_frontend *fe, return 0; } +static int stv0900_set_ts_param(struct dvb_frontend *fe, + int is_punctured) +{ + struct cx8802_dev *dev = fe->dvb->priv; + dev->ts_gen_cntrl = 0; + + return 0; +} + static int cx24116_reset_device(struct dvb_frontend *fe) { struct cx8802_dev *dev = fe->dvb->priv; @@ -601,6 +613,23 @@ static struct cx24116_config tevii_s460_config = { .reset_device = cx24116_reset_device, }; +static struct stv0900_config prof_7301_stv0900_config = { + .demod_address = 0x6a, +/* demod_mode = 0,*/ + .xtal = 27000000, + .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ + .diseqc_mode = 2,/* 2/3 PWM */ + .tun1_maddress = 0,/* 0x60 */ + .tun1_adc = 0,/* 2 Vpp */ + .path1_mode = 3, + .set_ts_params = stv0900_set_ts_param, +}; + +static struct stb6100_config prof_7301_stb6100_config = { + .tuner_address = 0x60, + .refclock = 27000000, +}; + static struct stv0299_config tevii_tuner_sharp_config = { .demod_address = 0x68, .inittab = sharp_z0194a_inittab, @@ -1149,6 +1178,31 @@ static int dvb_register(struct cx8802_dev *dev) goto frontend_detach; } break; + case CX88_BOARD_PROF_7301:{ + struct dvb_tuner_ops *tuner_ops = NULL; + + fe0->dvb.frontend = dvb_attach(stv0900_attach, + &prof_7301_stv0900_config, + &core->i2c_adap, 0); + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(stb6100_attach, fe0->dvb.frontend, + &prof_7301_stb6100_config, + &core->i2c_adap)) + goto frontend_detach; + + tuner_ops = &fe0->dvb.frontend->ops.tuner_ops; + tuner_ops->set_frequency = stb6100_set_freq; + tuner_ops->get_frequency = stb6100_get_freq; + tuner_ops->set_bandwidth = stb6100_set_bandw; + tuner_ops->get_bandwidth = stb6100_get_bandw; + + core->prev_set_voltage = + fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = + tevii_dvbs_set_voltage; + } + break; + } default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index c0047c1960cc..47c03019357d 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -308,6 +308,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_TBS_8920: case CX88_BOARD_TBS_8910: case CX88_BOARD_PROF_7300: + case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: ir_codes = &ir_codes_tbs_nec_table; ir_type = IR_TYPE_PD; @@ -457,6 +458,7 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_TBS_8920: case CX88_BOARD_TBS_8910: case CX88_BOARD_PROF_7300: + case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index d5cea41f4207..e1c521710103 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -238,6 +238,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_HAUPPAUGE_IRONLY 80 #define CX88_BOARD_WINFAST_DTV1800H 81 #define CX88_BOARD_WINFAST_DTV2000H_J 82 +#define CX88_BOARD_PROF_7301 83 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, From a8aeb7836edac3e0cce1286eefbca793c54cbad0 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 18 Nov 2009 16:00:55 -0300 Subject: [PATCH 248/345] V4L/DVB (13408): firedtv: shrink buffer pointer table Cache only addresses of whole pages, not of each buffer chunk. Besides, page addresses can be obtained by page_address() instead of kmap() since they were allocated in lowmem. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-fw.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index 208e5b59e830..6954848b5803 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -6,9 +6,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -73,7 +73,7 @@ struct firedtv_receive_context { struct fw_iso_buffer buffer; int interrupt_packet; int current_packet; - char *packets[N_PACKETS]; + char *pages[N_PAGES]; }; static int queue_iso(struct firedtv_receive_context *ctx, int index) @@ -100,7 +100,7 @@ static void handle_iso(struct fw_iso_context *context, u32 cycle, struct firedtv *fdtv = data; struct firedtv_receive_context *ctx = fdtv->backend_data; __be32 *h, *h_end; - int i = ctx->current_packet, length, err; + int length, err, i = ctx->current_packet; char *p, *p_end; for (h = header, h_end = h + header_length / 4; h < h_end; h++) { @@ -110,7 +110,8 @@ static void handle_iso(struct fw_iso_context *context, u32 cycle, length = MAX_PACKET_SIZE; } - p = ctx->packets[i]; + p = ctx->pages[i / PACKETS_PER_PAGE] + + (i % PACKETS_PER_PAGE) * MAX_PACKET_SIZE; p_end = p + length; for (p += CIP_HEADER_SIZE + MPEG2_TS_HEADER_SIZE; p < p_end; @@ -130,8 +131,7 @@ static int start_iso(struct firedtv *fdtv) { struct firedtv_receive_context *ctx; struct fw_device *device = device_of(fdtv); - char *p; - int i, j, k, err; + int i, err; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -153,11 +153,8 @@ static int start_iso(struct firedtv *fdtv) ctx->interrupt_packet = 1; ctx->current_packet = 0; - for (i = 0, k = 0; k < N_PAGES; k++) { - p = kmap(ctx->buffer.pages[k]); - for (j = 0; j < PACKETS_PER_PAGE && i < N_PACKETS; j++, i++) - ctx->packets[i] = p + j * MAX_PACKET_SIZE; - } + for (i = 0; i < N_PAGES; i++) + ctx->pages[i] = page_address(ctx->buffer.pages[i]); for (i = 0; i < N_PACKETS; i++) { err = queue_iso(ctx, i); From b1d33f4b0ae319ca79b6bafd6e815cbe0dcd7c14 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 18 Nov 2009 16:01:14 -0300 Subject: [PATCH 249/345] V4L/DVB (13409): firedtv: packet requeuing is likely to succeed Packet DMA buffers are queued either initially all at once (then, a queueing failure will cause firedtv to release the DMA context as a whole) or subsequently one by one as they recycled after use (then a failure is extremely unlikely). Therefore we can be a little less cautious when counting at which packet buffer to set the interrupt flag. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-fw.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index 6954848b5803..d8408cea335f 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -79,19 +79,14 @@ struct firedtv_receive_context { static int queue_iso(struct firedtv_receive_context *ctx, int index) { struct fw_iso_packet p; - int err; p.payload_length = MAX_PACKET_SIZE; - p.interrupt = !(ctx->interrupt_packet & (IRQ_INTERVAL - 1)); + p.interrupt = !(++ctx->interrupt_packet & (IRQ_INTERVAL - 1)); p.skip = 0; p.header_length = ISO_HEADER_SIZE; - err = fw_iso_context_queue(ctx->context, &p, &ctx->buffer, - index * MAX_PACKET_SIZE); - if (!err) - ctx->interrupt_packet++; - - return err; + return fw_iso_context_queue(ctx->context, &p, &ctx->buffer, + index * MAX_PACKET_SIZE); } static void handle_iso(struct fw_iso_context *context, u32 cycle, @@ -150,7 +145,7 @@ static int start_iso(struct firedtv *fdtv) if (err) goto fail_context_destroy; - ctx->interrupt_packet = 1; + ctx->interrupt_packet = 0; ctx->current_packet = 0; for (i = 0; i < N_PAGES; i++) From 5375659a3df319700d97d911e44926fb43354839 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 18 Nov 2009 16:01:34 -0300 Subject: [PATCH 250/345] V4L/DVB (13410): firedtv: remove an unnecessary function argument All read transactions initiated by firedtv are only quadlet-sized, hence the backend->read call can be simplified a little. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-1394.c | 4 ++-- drivers/media/dvb/firewire/firedtv-avc.c | 8 ++++---- drivers/media/dvb/firewire/firedtv-fw.c | 5 ++--- drivers/media/dvb/firewire/firedtv.h | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c index ed98fdb650c5..7c5459c27b75 100644 --- a/drivers/media/dvb/firewire/firedtv-1394.c +++ b/drivers/media/dvb/firewire/firedtv-1394.c @@ -101,9 +101,9 @@ static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) return ret; } -static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len) +static int node_read(struct firedtv *fdtv, u64 addr, void *data) { - return hpsb_node_read(node_of(fdtv), addr, data, len); + return hpsb_node_read(node_of(fdtv), addr, data, 4); } static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len) diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 5516c33b1453..50c42a4b972b 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -1236,14 +1236,14 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL -static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len) +static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data) { int ret; if (mutex_lock_interruptible(&fdtv->avc_mutex)) return -EINTR; - ret = fdtv->backend->read(fdtv, addr, buf, len); + ret = fdtv->backend->read(fdtv, addr, data); if (ret < 0) dev_err(fdtv->device, "CMP: read I/O error\n"); @@ -1293,7 +1293,7 @@ int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel) int attempts = 0; int ret; - ret = cmp_read(fdtv, opcr, opcr_address, 4); + ret = cmp_read(fdtv, opcr_address, opcr); if (ret < 0) return ret; @@ -1357,7 +1357,7 @@ void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel) u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); int attempts = 0; - if (cmp_read(fdtv, opcr, opcr_address, 4) < 0) + if (cmp_read(fdtv, opcr_address, opcr) < 0) return; repeat: diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index d8408cea335f..fe44789ab037 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -46,10 +46,9 @@ static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP); } -static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len) +static int node_read(struct firedtv *fdtv, u64 addr, void *data) { - return node_req(fdtv, addr, data, len, len == 4 ? - TCODE_READ_QUADLET_REQUEST : TCODE_READ_BLOCK_REQUEST); + return node_req(fdtv, addr, data, 4, TCODE_READ_QUADLET_REQUEST); } static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len) diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h index f7b5c030bedf..35080dbb3c66 100644 --- a/drivers/media/dvb/firewire/firedtv.h +++ b/drivers/media/dvb/firewire/firedtv.h @@ -74,7 +74,7 @@ struct firedtv; struct firedtv_backend { int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]); - int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len); + int (*read)(struct firedtv *fdtv, u64 addr, void *data); int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len); int (*start_iso)(struct firedtv *fdtv); void (*stop_iso)(struct firedtv *fdtv); From c95a419a5604ec8a23cd73f61e9bb151e8cbe89b Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 20 Nov 2009 15:34:13 -0300 Subject: [PATCH 251/345] V4L/DVB: Fix test in copy_reg_bits() The reg_pair2[j].reg was tested twice. Cc: Signed-off-by: Roel Kluin Acked-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5007t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c index 2d02698d4f4f..7eb1bf75cd07 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/common/tuners/mxl5007t.c @@ -196,7 +196,7 @@ static void copy_reg_bits(struct reg_pair_t *reg_pair1, i = j = 0; while (reg_pair1[i].reg || reg_pair1[i].val) { - while (reg_pair2[j].reg || reg_pair2[j].reg) { + while (reg_pair2[j].reg || reg_pair2[j].val) { if (reg_pair1[i].reg != reg_pair2[j].reg) { j++; continue; From cd0e280f1bbecebcd20ed0ddd4dd8fb03a506b3c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 Nov 2009 08:49:41 -0300 Subject: [PATCH 252/345] V4L/DVB (13413): introduce missing kfree Error handling code following a kzalloc should free the allocated data. Similarly for usb-alloc urb. 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; expression E; identifier f,f1,l; position p1,p2; expression *ptr != NULL; @@ x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S <... when != x when != if (...) { <+...x...+> } ( x->f1 = E | (x->f1 == NULL || ...) | f(...,x->f1,...) ) ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-video.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 2eb9dc2ebe59..b5439cabb381 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -139,7 +139,7 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n"); - goto exit; + goto exit_urb; } buf->urb = urb; @@ -148,7 +148,7 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) if (!mem) { v4l2_err(&dev->v4l2_dev, "cannot allocate usb transfer buffer\n"); - goto exit; + goto exit_urb_buffer; } usb_fill_bulk_urb(buf->urb, dev->udev, @@ -161,6 +161,10 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) list_add_tail(&buf->buff_list, &dev->free_buff_list); } return 0; +exit_urb_buffer: + usb_free_urb(urb); +exit_urb: + kfree(buf); exit: hdpvr_free_buffers(dev); return retval; From b1858190fc0180df70e9e7bab24a679129643f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sat, 21 Nov 2009 13:46:12 -0300 Subject: [PATCH 253/345] V4L/DVB (13414): ttusb-dec: do not overwrite the first part of phys string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use strlcat() to append a string to the previously created first part. The semantic match that finds this kind of problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression dev; expression phys; expression str; expression size; @@ usb_make_path(dev, phys, size); - strlcpy(phys, str, size); + strlcat(phys, str, size); // Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index d91e0638448f..53baccbab17f 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1198,7 +1198,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec) int err; usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys)); - strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); + strlcat(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); input_dev = input_allocate_device(); if (!input_dev) From 296372e3b04a41853df1be6623a5bd634051458c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sun, 22 Nov 2009 18:03:05 -0300 Subject: [PATCH 254/345] V4L/DVB (13415): videobuf-core: explicitly cast page count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicitly cast page count in the debug message. Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 136bc3496c87..bb0a1c8de414 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -430,8 +430,9 @@ int videobuf_reqbufs(struct videobuf_queue *q, count = VIDEO_MAX_FRAME; size = 0; q->ops->buf_setup(q, &count, &size); - dprintk(1, "reqbufs: bufs=%d, size=0x%x [%d pages total]\n", - count, size, (count*PAGE_ALIGN(size))>>PAGE_SHIFT); + dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n", + count, size, + (unsigned int)((count*PAGE_ALIGN(size))>>PAGE_SHIFT) ); retval = __videobuf_mmap_setup(q, count, size, req->memory); if (retval < 0) { From f58d7856695b6a3a03a56250c6c591022ac9918f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sun, 22 Nov 2009 18:52:31 -0300 Subject: [PATCH 255/345] V4L/DVB (13416): smssdio: initialize return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return value may be used uninitialized when the size parameter happens to be 0. Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smssdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c index d1d652e7f890..24206cbda264 100644 --- a/drivers/media/dvb/siano/smssdio.c +++ b/drivers/media/dvb/siano/smssdio.c @@ -78,7 +78,7 @@ struct smssdio_device { static int smssdio_sendrequest(void *context, void *buffer, size_t size) { - int ret; + int ret = 0; struct smssdio_device *smsdev; smsdev = context; From f8b0bca1a7ea8479490bcc06835ccbf590ba2c4e Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 23 Nov 2009 14:29:35 -0300 Subject: [PATCH 256/345] V4L/DVB (13417): Fix videobuf_queue_vmalloc_init() prototype For whatever reason, the device structure pointer to videobuf_queue_vmalloc_init is typed "void *", even though it's passed right through to videobuf_queue_core_init(), which expects a struct device pointer. The other videobuf implementations use struct device *; I think vmalloc should too. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-vmalloc.c | 2 +- include/media/videobuf-vmalloc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 99d646ed0248..d6e6a28fb6b8 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -392,7 +392,7 @@ static struct videobuf_qtype_ops qops = { void videobuf_queue_vmalloc_init(struct videobuf_queue* q, const struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h index 1ffdb6624436..4b419a257a7d 100644 --- a/include/media/videobuf-vmalloc.h +++ b/include/media/videobuf-vmalloc.h @@ -31,7 +31,7 @@ struct videobuf_vmalloc_memory void videobuf_queue_vmalloc_init(struct videobuf_queue* q, const struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, From 4d0fc03a76d96fff0cf6c815702ae04896b74cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=83=C2=A1rton=20N=C3=83=C2=A9meth?= Date: Mon, 9 Nov 2009 07:08:04 -0300 Subject: [PATCH 257/345] V4L/DVB (13418): gspca - pac7311: Stop sending URBs on first error. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Márton Németh Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7311.c | 31 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index c3e1f80351ad..1a27da00ccc1 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -569,16 +569,27 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x27, 0x80); - reg_w(gspca_dev, 0x28, 0xca); - reg_w(gspca_dev, 0x29, 0x53); - reg_w(gspca_dev, 0x2a, 0x0e); - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x3e, 0x20); - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ + int ret; + + ret = reg_w(gspca_dev, 0xff, 0x04); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x27, 0x80); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x28, 0xca); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x29, 0x53); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x2a, 0x0e); + if (0 <= ret) + ret = reg_w(gspca_dev, 0xff, 0x01); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x3e, 0x20); + if (0 <= ret) + ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ + if (0 <= ret) + ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ } /* called on streamoff with alt 0 and on disconnect for 7311 */ From 6763cc0e54e95eea356e15f9cd9a2f7b5ebeb7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=83=C2=A1rton=20N=C3=83=C2=A9meth?= Date: Mon, 9 Nov 2009 07:10:46 -0300 Subject: [PATCH 258/345] V4L/DVB (13419): gspca - pac7302: Add debug register write interface. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add debug register write interface to pac7302 to be able to set for example the edge detect mode (bit 2 register 0x55) or the test pattern (bit 0..3, register 0x72) and test overlay (bit 4, register 0x72) from the user space. Only write of register page 0 is supported by this patch. Signed-off-by: Márton Németh Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac7302.c | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 5cd02571bbf9..e0fd767984b3 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -68,6 +68,7 @@ #define MODULE_NAME "pac7302" +#include #include "gspca.h" MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); @@ -1143,6 +1144,55 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int sd_dbg_s_register(struct gspca_dev *gspca_dev, + struct v4l2_dbg_register *reg) +{ + int ret = -EINVAL; + __u8 index; + __u8 value; + + /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit + long on the USB bus) + */ + if (reg->match.type == V4L2_CHIP_MATCH_HOST && + reg->match.addr == 0 && + (reg->reg < 0x000000ff) && + (reg->val <= 0x000000ff) + ) { + /* Currently writing to page 0 is only supported. */ + /* reg_w() only supports 8bit index */ + index = reg->reg & 0x000000ff; + value = reg->val & 0x000000ff; + + /* Note that there shall be no access to other page + by any other function between the page swith and + the actual register write */ + ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + if (0 <= ret) + ret = reg_w(gspca_dev, index, value); + + if (0 <= ret) + ret = reg_w(gspca_dev, 0xdc, 0x01); + } + return ret; +} + +static int sd_chip_ident(struct gspca_dev *gspca_dev, + struct v4l2_dbg_chip_ident *chip) +{ + int ret = -EINVAL; + + if (chip->match.type == V4L2_CHIP_MATCH_HOST && + chip->match.addr == 0) { + chip->revision = 0; + chip->ident = V4L2_IDENT_UNKNOWN; + ret = 0; + } + return ret; +} +#endif + /* sub-driver description for pac7302 */ static struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -1155,6 +1205,10 @@ static struct sd_desc sd_desc = { .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .set_register = sd_dbg_s_register, + .get_chip_ident = sd_chip_ident, +#endif }; /* -- module initialisation -- */ From 89b3d78d153a049924eb0da92caf55dc1e0f5d75 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 10 Nov 2009 06:46:59 -0300 Subject: [PATCH 259/345] V4L/DVB (13420): gspca - doc: Change the name of some webcams. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index a87a8ceb6246..546667024f54 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -7,6 +7,7 @@ The modules are: xxxx vend:prod ---- spca501 0000:0000 MystFromOri Unknow Camera +spca508 0130:0130 Clone Digital Webcam 11043 m5602 0402:5602 ALi Video Camera Controller spca501 040a:0002 Kodak DVC-325 spca500 040a:0300 Kodak EZ200 @@ -69,12 +70,12 @@ zc3xx 046d:08a3 Logitech QC Chat zc3xx 046d:08a6 Logitech QCim zc3xx 046d:08a7 Logitech QuickCam Image zc3xx 046d:08a9 Logitech Notebook Deluxe -zc3xx 046d:08aa Labtec Webcam Notebook +zc3xx 046d:08aa Labtec Webcam Notebook zc3xx 046d:08ac Logitech QuickCam Cool zc3xx 046d:08ad Logitech QCCommunicate STX zc3xx 046d:08ae Logitech QuickCam for Notebooks zc3xx 046d:08af Logitech QuickCam Cool -zc3xx 046d:08b9 Logitech QC IM ??? +zc3xx 046d:08b9 Logitech QuickCam Express zc3xx 046d:08d7 Logitech QCam STX zc3xx 046d:08d9 Logitech QuickCam IM/Connect zc3xx 046d:08d8 Logitech Notebook Deluxe @@ -83,7 +84,7 @@ zc3xx 046d:08dd Logitech QuickCam for Notebooks spca500 046d:0900 Logitech Inc. ClickSmart 310 spca500 046d:0901 Logitech Inc. ClickSmart 510 sunplus 046d:0905 Logitech ClickSmart 820 -tv8532 046d:0920 QC Express +tv8532 046d:0920 Logitech QuickCam Express tv8532 046d:0921 Labtec Webcam spca561 046d:0928 Logitech QC Express Etch2 spca561 046d:0929 Labtec Webcam Elch2 @@ -92,7 +93,7 @@ spca561 046d:092b Labtec Webcam Plus spca561 046d:092c Logitech QC chat Elch2 spca561 046d:092d Logitech QC Elch2 spca561 046d:092e Logitech QC Elch2 -spca561 046d:092f Logitech QuickCam Express Plus +spca561 046d:092f Logitech QuickCam Express Plus sunplus 046d:0960 Logitech ClickSmart 420 sunplus 0471:0322 Philips DMVC1300K zc3xx 0471:0325 Philips SPC 200 NC @@ -188,7 +189,6 @@ sonixj 06f8:3004 Hercules Classic Silver sonixj 06f8:3008 Hercules Deluxe Optical Glass pac7311 06f8:3009 Hercules Classic Link spca508 0733:0110 ViewQuest VQ110 -spca508 0130:0130 Clone Digital Webcam 11043 spca501 0733:0401 Intel Create and Share spca501 0733:0402 ViewQuest M318B spca505 0733:0430 Intel PC Camera Pro @@ -224,7 +224,7 @@ 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 +pac207 093a:2468 Webcam WB-1400T pac207 093a:2470 Genius GF112 pac207 093a:2471 Genius VideoCam ge111 pac207 093a:2472 Genius VideoCam ge110 @@ -232,7 +232,7 @@ pac207 093a:2474 Genius iLook 111 pac207 093a:2476 Genius e-Messenger 112 pac7311 093a:2600 PAC7311 Typhoon pac7311 093a:2601 Philips SPC 610 NC -pac7311 093a:2603 PAC7312 +pac7311 093a:2603 Philips SPC 500 NC pac7311 093a:2608 Trust WB-3300p pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 pac7311 093a:260f SnakeCam @@ -253,7 +253,7 @@ vc032x 0ac8:0328 A4Tech PK-130MG zc3xx 0ac8:301b Z-Star zc301b zc3xx 0ac8:303b Vimicro 0x303b zc3xx 0ac8:305b Z-star Vimicro zc0305b -zc3xx 0ac8:307b Ldlc VC302+Ov7620 +zc3xx 0ac8:307b PC Camera (ZS0211) vc032x 0ac8:c001 Sony embedded vimicro vc032x 0ac8:c002 Sony embedded vimicro vc032x 0ac8:c301 Samsung Q1 Ultra Premium From 4bdf4a8342ca01ff794f5de8f9766cf15947a2ef Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 10 Nov 2009 14:49:43 -0300 Subject: [PATCH 260/345] V4L/DVB (13421): gspca - main: Clearer message when bandwidth too small. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index afd99beab30d..6915db2d36db 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -657,15 +657,19 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) } if (ret >= 0) break; - PDEBUG(D_ERR|D_STREAM, - "usb_submit_urb alt %d err %d", gspca_dev->alt, ret); gspca_dev->streaming = 0; destroy_urbs(gspca_dev); - if (ret != -ENOSPC) + if (ret != -ENOSPC) { + PDEBUG(D_ERR|D_STREAM, + "usb_submit_urb alt %d err %d", + gspca_dev->alt, ret); goto out; + } /* the bandwidth is not wide enough * negociate or try a lower alternate setting */ + PDEBUG(D_ERR|D_STREAM, + "bandwidth not wide enough - trying again"); msleep(20); /* wait for kill complete */ if (gspca_dev->sd_desc->isoc_nego) { ret = gspca_dev->sd_desc->isoc_nego(gspca_dev); From 189d92af707ead6aa4a3e14511662462e8e956e2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 11 Nov 2009 07:46:28 -0300 Subject: [PATCH 261/345] V4L/DVB (13422): gspca - ov534: ov772x changes from Richard Kaswy. - 320x240 resolution added - controls added - different sd_desc tables Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 684 ++++++++++++++++++++++++++---- 1 file changed, 595 insertions(+), 89 deletions(-) diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4b528b372911..fa28316c06ed 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1,5 +1,6 @@ /* * ov534 gspca driver + * * Copyright (C) 2008 Antonio Ospite * Copyright (C) 2008 Jim Paris * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr @@ -8,6 +9,8 @@ * USB protocol reverse engineered by Jim Paris * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ * + * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr + * * 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 @@ -50,6 +53,14 @@ struct sd { __u32 last_pts; u16 last_fid; u8 frame_rate; + u8 gain; + u8 exposure; + u8 redblc; + u8 blueblc; + u8 autogain; + u8 sharpness; + u8 hflip; + u8 vflip; u8 sensor; #define SENSOR_OV772X 0 @@ -57,10 +68,146 @@ struct sd { }; /* V4L2 controls supported by the driver */ -static struct ctrl sd_ctrls[] = { +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getblueblc(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_setsharpness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getsharpness(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 struct ctrl sd_ctrls_ov772x[] = { + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Main Gain", + .minimum = 0, + .maximum = 63, + .step = 1, +#define GAIN_DEF 20 + .default_value = GAIN_DEF, + }, + .set = sd_setgain, + .get = sd_getgain, + }, + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 255, + .step = 1, +#define EXPO_DEF 255 + .default_value = EXPO_DEF, + }, + .set = sd_setexposure, + .get = sd_getexposure, + }, + { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = 0, + .maximum = 255, + .step = 1, +#define RED_BALANCE_DEF 128 + .default_value = RED_BALANCE_DEF, + }, + .set = sd_setredblc, + .get = sd_getredblc, + }, + { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = 0, + .maximum = 255, + .step = 1, +#define BLUE_BALANCE_DEF 128 + .default_value = BLUE_BALANCE_DEF, + }, + .set = sd_setblueblc, + .get = sd_getblueblc, + }, + { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Autogain", + .minimum = 0, + .maximum = 1, + .step = 1, +#define AUTOGAIN_DEF 1 + .default_value = AUTOGAIN_DEF, + }, + .set = sd_setautogain, + .get = sd_getautogain, + }, + { + { + .id = V4L2_CID_SHARPNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Sharpness", + .minimum = 0, + .maximum = 63, + .step = 1, +#define SHARPNESS_DEF 4 + .default_value = SHARPNESS_DEF, + }, + .set = sd_setsharpness, + .get = sd_getsharpness, + }, + { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "HFlip", + .minimum = 0, + .maximum = 1, + .step = 1, +#define HFLIP_DEF 0 + .default_value = HFLIP_DEF, + }, + .set = sd_sethflip, + .get = sd_gethflip, + }, + { + { + .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, + }, +}; +static struct ctrl sd_ctrls_ov965x[] = { }; static const struct v4l2_pix_format vga_yuyv_mode[] = { + {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, + .bytesperline = 320 * 2, + .sizeimage = 320 * 240 * 2, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 640 * 2, .sizeimage = 640 * 480 * 2, @@ -80,8 +227,7 @@ static const struct v4l2_pix_format vga_jpeg_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; - -static const u8 bridge_init_ov722x[][2] = { +static const u8 bridge_init_ov772x[][2] = { { 0xc2, 0x0c }, { 0x88, 0xf8 }, { 0xc3, 0x69 }, @@ -122,6 +268,7 @@ static const u8 bridge_init_ov722x[][2] = { { 0x1d, 0x40 }, { 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 */ @@ -138,10 +285,20 @@ static const u8 bridge_init_ov722x[][2] = { { 0xc1, 0x3c }, { 0xc2, 0x0c }, }; - -static const u8 sensor_init_ov722x[][2] = { +static const u8 sensor_init_ov772x[][2] = { { 0x12, 0x80 }, { 0x11, 0x01 }, +/*fixme: better have a delay?*/ + { 0x11, 0x01 }, + { 0x11, 0x01 }, + { 0x11, 0x01 }, + { 0x11, 0x01 }, + { 0x11, 0x01 }, + { 0x11, 0x01 }, + { 0x11, 0x01 }, + { 0x11, 0x01 }, + { 0x11, 0x01 }, + { 0x11, 0x01 }, { 0x3d, 0x03 }, { 0x17, 0x26 }, @@ -154,7 +311,7 @@ static const u8 sensor_init_ov722x[][2] = { { 0x65, 0x20 }, { 0x11, 0x01 }, { 0x42, 0x7f }, - { 0x63, 0xe0 }, + { 0x63, 0xaa }, /* was e0 */ { 0x64, 0xff }, { 0x66, 0x00 }, { 0x13, 0xf0 }, @@ -221,6 +378,46 @@ static const u8 sensor_init_ov722x[][2] = { { 0x8e, 0x00 }, { 0x0c, 0xd0 } }; +static const u8 bridge_start_ov772x_vga[][2] = { + {0x1c, 0x00}, + {0x1d, 0x40}, + {0x1d, 0x02}, + {0x1d, 0x00}, + {0x1d, 0x02}, + {0x1d, 0x58}, + {0x1d, 0x00}, + {0xc0, 0x50}, + {0xc1, 0x3c}, +}; +static const u8 sensor_start_ov772x_vga[][2] = { + {0x12, 0x00}, + {0x17, 0x26}, + {0x18, 0xa0}, + {0x19, 0x07}, + {0x1a, 0xf0}, + {0x29, 0xa0}, + {0x2c, 0xf0}, +}; +static const u8 bridge_start_ov772x_qvga[][2] = { + {0x1c, 0x00}, + {0x1d, 0x40}, + {0x1d, 0x02}, + {0x1d, 0x00}, + {0x1d, 0x01}, + {0x1d, 0x4b}, + {0x1d, 0x00}, + {0xc0, 0x28}, + {0xc1, 0x1e}, +}; +static const u8 sensor_start_ov772x_qvga[][2] = { + {0x12, 0x40}, + {0x17, 0x3f}, + {0x18, 0x50}, + {0x19, 0x03}, + {0x1a, 0x78}, + {0x29, 0x50}, + {0x2c, 0x78}, +}; static const u8 bridge_init_ov965x[][2] = { {0x88, 0xf8}, @@ -757,35 +954,150 @@ static void sccb_w_array(struct gspca_dev *gspca_dev, static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int fr = sd->frame_rate; + int i; + struct rate_s { + u8 fps; + u8 r11; + u8 r0d; + u8 re5; + }; + const struct rate_s *r; + static const struct rate_s rate_0[] = { /* 640x480 */ + {60, 0x01, 0xc1, 0x04}, + {50, 0x01, 0x41, 0x02}, + {40, 0x02, 0xc1, 0x04}, + {30, 0x04, 0x81, 0x02}, + {15, 0x03, 0x41, 0x04}, + }; + static const struct rate_s rate_1[] = { /* 320x240 */ + {125, 0x02, 0x81, 0x02}, + {100, 0x02, 0xc1, 0x04}, + {75, 0x03, 0xc1, 0x04}, + {60, 0x04, 0xc1, 0x04}, + {50, 0x02, 0x41, 0x04}, + {40, 0x03, 0x41, 0x04}, + {30, 0x04, 0x41, 0x04}, + }; - switch (fr) { - case 50: - 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, 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, 0x11, 0x04); - sccb_reg_write(gspca_dev, 0x0d, 0x81); - ov534_reg_write(gspca_dev, 0xe5, 0x02); - break; - case 15: - sccb_reg_write(gspca_dev, 0x11, 0x03); - sccb_reg_write(gspca_dev, 0x0d, 0x41); - ov534_reg_write(gspca_dev, 0xe5, 0x04); - break; + if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) { + r = rate_0; + i = ARRAY_SIZE(rate_0); + } else { + r = rate_1; + i = ARRAY_SIZE(rate_1); + } + while (--i > 0) { + if (sd->frame_rate >= r->fps) + break; + r++; } - sd->frame_rate = fr; - PDEBUG(D_PROBE, "frame_rate: %d", fr); + sccb_reg_write(gspca_dev, 0x11, r->r11); + sccb_reg_write(gspca_dev, 0x0d, r->r0d); + ov534_reg_write(gspca_dev, 0xe5, r->re5); + + PDEBUG(D_PROBE, "frame_rate: %d", r->fps); +} + +/* ov772x controls */ +static void setgain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + + val = sd->gain; + switch (val & 0x30) { + case 0x00: + val &= 0x0f; + break; + case 0x10: + val &= 0x0f; + val |= 0x30; + break; + case 0x20: + val &= 0x0f; + val |= 0x70; + break; + default: +/* case 0x30: */ + val &= 0x0f; + val |= 0xf0; + break; + } + sccb_reg_write(gspca_dev, 0x00, val); +} + +static void setexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + + val = sd->exposure; + sccb_reg_write(gspca_dev, 0x08, val >> 7); + sccb_reg_write(gspca_dev, 0x10, val << 1); +} + +static void setredblc(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sccb_reg_write(gspca_dev, 0x43, sd->redblc); +} + +static void setblueblc(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sccb_reg_write(gspca_dev, 0x42, sd->blueblc); +} + +static void setautogain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->autogain) { + sccb_reg_write(gspca_dev, 0x13, 0xf7); /* AGC,AEC,AWB ON */ + sccb_reg_write(gspca_dev, 0x64, + sccb_reg_read(gspca_dev, 0x64) | 0x03); + } else { + sccb_reg_write(gspca_dev, 0x13, 0xf0); /* AGC,AEC,AWB OFF */ + sccb_reg_write(gspca_dev, 0x64, + sccb_reg_read(gspca_dev, 0x64) & 0xfc); + } +} + +static void setsharpness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + + val = sd->sharpness; + sccb_reg_write(gspca_dev, 0x91, val); /* vga noise */ + sccb_reg_write(gspca_dev, 0x8e, val); /* qvga noise */ +} + +static void sethflip(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->hflip == 0) + sccb_reg_write(gspca_dev, 0x0c, + sccb_reg_read(gspca_dev, 0x0c) | 0x40); + else + sccb_reg_write(gspca_dev, 0x0c, + sccb_reg_read(gspca_dev, 0x0c) & 0xbf); +} + +static void setvflip(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->vflip == 0) + sccb_reg_write(gspca_dev, 0x0c, + sccb_reg_read(gspca_dev, 0x0c) | 0x80); + else + sccb_reg_write(gspca_dev, 0x0c, + sccb_reg_read(gspca_dev, 0x0c) & 0x7f); } /* this function is called at probe time */ @@ -811,6 +1123,19 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = ARRAY_SIZE(vga_jpeg_mode); } + sd->frame_rate = 30; + sd->gain = GAIN_DEF; + sd->exposure = EXPO_DEF; + sd->redblc = RED_BALANCE_DEF; + sd->blueblc = BLUE_BALANCE_DEF; + sd->autogain = AUTOGAIN_DEF; + sd->sharpness = SHARPNESS_DEF; +#if HFLIP_DEF != 0 + sd->hflip = HFLIP_DEF; +#endif +#if VFLIP_DEF != 0 + sd->vflip = VFLIP_DEF; +#endif return 0; } @@ -847,11 +1172,11 @@ static int sd_init(struct gspca_dev *gspca_dev) /* initialize */ switch (sd->sensor) { case SENSOR_OV772X: - reg_w_array(gspca_dev, bridge_init_ov722x, - ARRAY_SIZE(bridge_init_ov722x)); + reg_w_array(gspca_dev, bridge_init_ov772x, + ARRAY_SIZE(bridge_init_ov772x)); ov534_set_led(gspca_dev, 1); - sccb_w_array(gspca_dev, sensor_init_ov722x, - ARRAY_SIZE(sensor_init_ov722x)); + sccb_w_array(gspca_dev, sensor_init_ov772x, + ARRAY_SIZE(sensor_init_ov772x)); ov534_reg_write(gspca_dev, 0xe0, 0x09); ov534_set_led(gspca_dev, 0); ov534_set_frame_rate(gspca_dev); @@ -875,60 +1200,78 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static int sd_start(struct gspca_dev *gspca_dev) +static int sd_start_ov772x(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; int mode; - switch (sd->sensor) { - case SENSOR_OV772X: - ov534_set_led(gspca_dev, 1); - ov534_reg_write(gspca_dev, 0xe0, 0x00); - break; - default: -/* case SENSOR_OV965X: */ - - sccb_w_array(gspca_dev, sensor_start_ov965x, - ARRAY_SIZE(sensor_start_ov965x)); - reg_w_array(gspca_dev, bridge_start_ov965x, - ARRAY_SIZE(bridge_start_ov965x)); - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - if (mode != 0) { /* 320x240 */ - reg_w_array(gspca_dev, bridge_start_ov965x_cif, - ARRAY_SIZE(bridge_start_ov965x_cif)); - sccb_w_array(gspca_dev, sensor_start_ov965x_cif, - ARRAY_SIZE(sensor_start_ov965x_cif)); - } else { /* 640x480 */ - reg_w_array(gspca_dev, bridge_start_ov965x_vga, - ARRAY_SIZE(bridge_start_ov965x_vga)); - sccb_w_array(gspca_dev, sensor_start_ov965x_vga, - ARRAY_SIZE(sensor_start_ov965x_vga)); - } - sccb_w_array(gspca_dev, sensor_start_ov965x_2, - ARRAY_SIZE(sensor_start_ov965x_2)); - ov534_reg_write(gspca_dev, 0xe0, 0x00); - ov534_reg_write(gspca_dev, 0xe0, 0x00); - ov534_set_led(gspca_dev, 1); + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; + if (mode != 0) { /* 320x240 */ + reg_w_array(gspca_dev, bridge_start_ov772x_qvga, + ARRAY_SIZE(bridge_start_ov772x_qvga)); + sccb_w_array(gspca_dev, sensor_start_ov772x_qvga, + ARRAY_SIZE(sensor_start_ov772x_qvga)); + } else { /* 640x480 */ + reg_w_array(gspca_dev, bridge_start_ov772x_vga, + ARRAY_SIZE(bridge_start_ov772x_vga)); + sccb_w_array(gspca_dev, sensor_start_ov772x_vga, + ARRAY_SIZE(sensor_start_ov772x_vga)); } + ov534_set_frame_rate(gspca_dev); + + setautogain(gspca_dev); + setgain(gspca_dev); + setredblc(gspca_dev); + setblueblc(gspca_dev); + setexposure(gspca_dev); + setsharpness(gspca_dev); + setvflip(gspca_dev); + sethflip(gspca_dev); + + ov534_set_led(gspca_dev, 1); + ov534_reg_write(gspca_dev, 0xe0, 0x00); return 0; } -static void sd_stopN(struct gspca_dev *gspca_dev) +static int sd_start_ov965x(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; + int mode; - switch (sd->sensor) { - case SENSOR_OV772X: - ov534_reg_write(gspca_dev, 0xe0, 0x09); - ov534_set_led(gspca_dev, 0); - break; - default: -/* case SENSOR_OV965X: */ - ov534_reg_write(gspca_dev, 0xe0, 0x01); - ov534_set_led(gspca_dev, 0); - ov534_reg_write(gspca_dev, 0xe0, 0x00); - break; + sccb_w_array(gspca_dev, sensor_start_ov965x, + ARRAY_SIZE(sensor_start_ov965x)); + reg_w_array(gspca_dev, bridge_start_ov965x, + ARRAY_SIZE(bridge_start_ov965x)); + + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; + if (mode != 0) { /* 320x240 */ + reg_w_array(gspca_dev, bridge_start_ov965x_cif, + ARRAY_SIZE(bridge_start_ov965x_cif)); + sccb_w_array(gspca_dev, sensor_start_ov965x_cif, + ARRAY_SIZE(sensor_start_ov965x_cif)); + } else { /* 640x480 */ + reg_w_array(gspca_dev, bridge_start_ov965x_vga, + ARRAY_SIZE(bridge_start_ov965x_vga)); + sccb_w_array(gspca_dev, sensor_start_ov965x_vga, + ARRAY_SIZE(sensor_start_ov965x_vga)); } + sccb_w_array(gspca_dev, sensor_start_ov965x_2, + ARRAY_SIZE(sensor_start_ov965x_2)); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + ov534_set_led(gspca_dev, 1); + return 0; +} + +static void sd_stopN_ov772x(struct gspca_dev *gspca_dev) +{ + ov534_reg_write(gspca_dev, 0xe0, 0x09); + ov534_set_led(gspca_dev, 0); +} + +static void sd_stopN_ov965x(struct gspca_dev *gspca_dev) +{ + ov534_reg_write(gspca_dev, 0xe0, 0x01); + ov534_set_led(gspca_dev, 0); + ov534_reg_write(gspca_dev, 0xe0, 0x00); } /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ @@ -1002,7 +1345,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, data + 12, len - 12); } - /* Done this payload */ goto scan_next; @@ -1016,6 +1358,151 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, } while (remaining_len > 0); } +/* ov772x controls */ +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gain = val; + if (gspca_dev->streaming) + setgain(gspca_dev); + return 0; +} + +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->gain; + return 0; +} + +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->exposure = val; + if (gspca_dev->streaming) + setexposure(gspca_dev); + return 0; +} + +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->exposure; + return 0; +} + +static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->redblc = val; + if (gspca_dev->streaming) + setredblc(gspca_dev); + return 0; +} + +static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->redblc; + return 0; +} + +static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->blueblc = val; + if (gspca_dev->streaming) + setblueblc(gspca_dev); + return 0; +} + +static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->blueblc; + return 0; +} + +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_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_sethflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->hflip = val; + if (gspca_dev->streaming) + sethflip(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) + setvflip(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; +} + /* get stream parameters (framerate) */ static int sd_get_streamparm(struct gspca_dev *gspca_dev, struct v4l2_streamparm *parm) @@ -1047,7 +1534,8 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, /* Set requested framerate */ sd->frame_rate = tpf->denominator / tpf->numerator; - ov534_set_frame_rate(gspca_dev); + if (gspca_dev->streaming) + ov534_set_frame_rate(gspca_dev); /* Return the actual framerate */ tpf->numerator = 1; @@ -1057,14 +1545,27 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, } /* sub-driver description */ -static const struct sd_desc sd_desc = { +static const struct sd_desc sd_desc_ov772x = { .name = MODULE_NAME, - .ctrls = sd_ctrls, - .nctrls = ARRAY_SIZE(sd_ctrls), + .ctrls = sd_ctrls_ov772x, + .nctrls = ARRAY_SIZE(sd_ctrls_ov772x), .config = sd_config, .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, + .start = sd_start_ov772x, + .stopN = sd_stopN_ov772x, + .pkt_scan = sd_pkt_scan, + .get_streamparm = sd_get_streamparm, + .set_streamparm = sd_set_streamparm, +}; + +static const struct sd_desc sd_desc_ov965x = { + .name = MODULE_NAME, + .ctrls = sd_ctrls_ov965x, + .nctrls = ARRAY_SIZE(sd_ctrls_ov965x), + .config = sd_config, + .init = sd_init, + .start = sd_start_ov965x, + .stopN = sd_stopN_ov965x, .pkt_scan = sd_pkt_scan, .get_streamparm = sd_get_streamparm, .set_streamparm = sd_set_streamparm, @@ -1082,8 +1583,12 @@ MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); + return gspca_dev_probe(intf, id, + id->driver_info == SENSOR_OV772X + ? &sd_desc_ov772x + : &sd_desc_ov965x, + sizeof(struct sd), + THIS_MODULE); } static struct usb_driver sd_driver = { @@ -1101,6 +1606,7 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { int ret; + ret = usb_register(&sd_driver); if (ret < 0) return ret; From b014f94b28713e169a438131a5ce2752068068ad Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 11 Nov 2009 14:28:53 -0300 Subject: [PATCH 262/345] V4L/DVB (13423): gspca - ov534: More ov772x changes from Max Thrun. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 205 ++++++++++++++++++++++++++++-- 1 file changed, 197 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index fa28316c06ed..b665c84ca864 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -10,6 +10,8 @@ * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ * * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr + * PS3 Eye camera, brightness, contrast, hue, AWB control added + * by Max Thrun * * 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 @@ -53,11 +55,16 @@ struct sd { __u32 last_pts; u16 last_fid; u8 frame_rate; + + u8 brightness; + u8 contrast; u8 gain; u8 exposure; u8 redblc; u8 blueblc; + u8 hue; u8 autogain; + u8 awb; u8 sharpness; u8 hflip; u8 vflip; @@ -84,8 +91,44 @@ 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_sethue(struct gspca_dev *gspca_dev, __s32 val); +static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls_ov772x[] = { + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, +#define BRIGHTNESS_DEF 20 + .default_value = BRIGHTNESS_DEF, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, + { + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 1, +#define CONTRAST_DEF 37 + .default_value = CONTRAST_DEF, + }, + .set = sd_setcontrast, + .get = sd_getcontrast, + }, { { .id = V4L2_CID_GAIN, @@ -108,7 +151,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .minimum = 0, .maximum = 255, .step = 1, -#define EXPO_DEF 255 +#define EXPO_DEF 120 .default_value = EXPO_DEF, }, .set = sd_setexposure, @@ -142,6 +185,20 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setblueblc, .get = sd_getblueblc, }, + { + { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = 0, + .maximum = 255, + .step = 1, +#define HUE_DEF 143 + .default_value = HUE_DEF, + }, + .set = sd_sethue, + .get = sd_gethue, + }, { { .id = V4L2_CID_AUTOGAIN, @@ -150,12 +207,26 @@ static struct ctrl sd_ctrls_ov772x[] = { .minimum = 0, .maximum = 1, .step = 1, -#define AUTOGAIN_DEF 1 +#define AUTOGAIN_DEF 0 .default_value = AUTOGAIN_DEF, }, .set = sd_setautogain, .get = sd_getautogain, }, + { + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto White Balance", + .minimum = 0, + .maximum = 1, + .step = 1, +#define AWB_DEF 0 + .default_value = AWB_DEF, + }, + .set = sd_setawb, + .get = sd_getawb, + }, { { .id = V4L2_CID_SHARPNESS, @@ -164,7 +235,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .minimum = 0, .maximum = 63, .step = 1, -#define SHARPNESS_DEF 4 +#define SHARPNESS_DEF 0 .default_value = SHARPNESS_DEF, }, .set = sd_setsharpness, @@ -206,7 +277,7 @@ static const struct v4l2_pix_format vga_yuyv_mode[] = { {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 320 * 2, .sizeimage = 320 * 240 * 2, - .colorspace = V4L2_COLORSPACE_JPEG, + .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 640 * 2, @@ -311,10 +382,10 @@ static const u8 sensor_init_ov772x[][2] = { { 0x65, 0x20 }, { 0x11, 0x01 }, { 0x42, 0x7f }, - { 0x63, 0xaa }, /* was e0 */ + { 0x63, 0xaa }, /* AWB - was e0 */ { 0x64, 0xff }, { 0x66, 0x00 }, - { 0x13, 0xf0 }, + { 0x13, 0xf0 }, /* com8 */ { 0x0d, 0x41 }, { 0x0f, 0xc5 }, { 0x14, 0x11 }, @@ -327,7 +398,7 @@ static const u8 sensor_init_ov772x[][2] = { { 0x2a, 0x00 }, { 0x2b, 0x00 }, { 0x6b, 0xaa }, - { 0x13, 0xff }, + { 0x13, 0xff }, /* AWB */ { 0x90, 0x05 }, { 0x91, 0x01 }, @@ -375,7 +446,7 @@ static const u8 sensor_init_ov772x[][2] = { { 0x14, 0x41 }, { 0x0e, 0xcd }, { 0xac, 0xbf }, - { 0x8e, 0x00 }, + { 0x8e, 0x00 }, /* De-noise threshold */ { 0x0c, 0xd0 } }; static const u8 bridge_start_ov772x_vga[][2] = { @@ -397,6 +468,7 @@ static const u8 sensor_start_ov772x_vga[][2] = { {0x1a, 0xf0}, {0x29, 0xa0}, {0x2c, 0xf0}, + {0x65, 0x20}, }; static const u8 bridge_start_ov772x_qvga[][2] = { {0x1c, 0x00}, @@ -417,6 +489,7 @@ static const u8 sensor_start_ov772x_qvga[][2] = { {0x1a, 0x78}, {0x29, 0x50}, {0x2c, 0x78}, + {0x65, 0x2f}, }; static const u8 bridge_init_ov965x[][2] = { @@ -1000,6 +1073,20 @@ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) } /* ov772x controls */ +static void setbrightness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sccb_reg_write(gspca_dev, 0x9B, sd->brightness); +} + +static void setcontrast(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sccb_reg_write(gspca_dev, 0x9C, sd->contrast); +} + static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1051,6 +1138,13 @@ static void setblueblc(struct gspca_dev *gspca_dev) sccb_reg_write(gspca_dev, 0x42, sd->blueblc); } +static void sethue(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sccb_reg_write(gspca_dev, 0x01, sd->hue); +} + static void setautogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1066,6 +1160,16 @@ static void setautogain(struct gspca_dev *gspca_dev) } } +static void setawb(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->awb) + sccb_reg_write(gspca_dev, 0x63, 0xe0); /* AWB on */ + else + sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ +} + static void setsharpness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1124,11 +1228,20 @@ static int sd_config(struct gspca_dev *gspca_dev, } sd->frame_rate = 30; + + sd->brightness = BRIGHTNESS_DEF; + sd->contrast = CONTRAST_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPO_DEF; sd->redblc = RED_BALANCE_DEF; sd->blueblc = BLUE_BALANCE_DEF; + sd->hue = HUE_DEF; +#if AUTOGAIN_DEF != 0 sd->autogain = AUTOGAIN_DEF; +#endif +#if AWB_DEF != 0 + sd->awb = AWB_DEF +#endif sd->sharpness = SHARPNESS_DEF; #if HFLIP_DEF != 0 sd->hflip = HFLIP_DEF; @@ -1219,10 +1332,14 @@ static int sd_start_ov772x(struct gspca_dev *gspca_dev) ov534_set_frame_rate(gspca_dev); setautogain(gspca_dev); + setawb(gspca_dev); setgain(gspca_dev); setredblc(gspca_dev); setblueblc(gspca_dev); + sethue(gspca_dev); setexposure(gspca_dev); + setbrightness(gspca_dev); + setcontrast(gspca_dev); setsharpness(gspca_dev); setvflip(gspca_dev); sethflip(gspca_dev); @@ -1395,6 +1512,42 @@ static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +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) + setcontrast(gspca_dev); + return 0; +} + +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->brightness; + return 0; +} + +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) + setcontrast(gspca_dev); + return 0; +} + +static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->contrast; + return 0; +} + static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1431,6 +1584,24 @@ static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->hue = val; + if (gspca_dev->streaming) + sethue(gspca_dev); + return 0; +} + +static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->hue; + return 0; +} + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1449,6 +1620,24 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->awb = val; + if (gspca_dev->streaming) + setawb(gspca_dev); + return 0; +} + +static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->awb; + return 0; +} + static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; From 69f1fe28f08000a123b3d71fac88564109da09fd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 12 Nov 2009 06:10:36 -0300 Subject: [PATCH 263/345] V4L/DVB (13424): gspca - ov534: Fix ov772x brightness and ov965x frame rate. - the ov772x brightness was not setteble (fixed by M. Thrun) - the set_frame_rate function does not work for ov965x Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index b665c84ca864..548f9e7edd8c 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1023,8 +1023,8 @@ static void sccb_w_array(struct gspca_dev *gspca_dev, } } -/* set framerate */ -static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) +/* ov772x specific controls */ +static void set_frame_rate(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; @@ -1072,7 +1072,6 @@ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "frame_rate: %d", r->fps); } -/* ov772x controls */ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1292,7 +1291,7 @@ static int sd_init(struct gspca_dev *gspca_dev) ARRAY_SIZE(sensor_init_ov772x)); ov534_reg_write(gspca_dev, 0xe0, 0x09); ov534_set_led(gspca_dev, 0); - ov534_set_frame_rate(gspca_dev); + set_frame_rate(gspca_dev); break; default: /* case SENSOR_OV965X: */ @@ -1329,7 +1328,7 @@ static int sd_start_ov772x(struct gspca_dev *gspca_dev) sccb_w_array(gspca_dev, sensor_start_ov772x_vga, ARRAY_SIZE(sensor_start_ov772x_vga)); } - ov534_set_frame_rate(gspca_dev); + set_frame_rate(gspca_dev); setautogain(gspca_dev); setawb(gspca_dev); @@ -1518,7 +1517,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) sd->brightness = val; if (gspca_dev->streaming) - setcontrast(gspca_dev); + setbrightness(gspca_dev); return 0; } @@ -1723,8 +1722,8 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, /* Set requested framerate */ sd->frame_rate = tpf->denominator / tpf->numerator; - if (gspca_dev->streaming) - ov534_set_frame_rate(gspca_dev); + if (gspca_dev->streaming && sd->sensor == SENSOR_OV772X) + set_frame_rate(gspca_dev); /* Return the actual framerate */ tpf->numerator = 1; From c76e6f11662f49dd31a49a07f4c06ee9bea6572b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 12 Nov 2009 06:13:41 -0300 Subject: [PATCH 264/345] V4L/DVB (13425): gspca - ov534: Bad name of the ov965x 320x240 resolution. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 548f9e7edd8c..f2f844af54c0 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -828,7 +828,7 @@ static const u8 bridge_start_ov965x_vga[][2] = { {} }; -static const u8 bridge_start_ov965x_cif[][2] = { +static const u8 bridge_start_ov965x_qvga[][2] = { {0xc2, 0x4c}, {0xc3, 0xf9}, {0xda, 0x00}, @@ -865,7 +865,7 @@ static const u8 sensor_start_ov965x_vga[][2] = { {} }; -static const u8 sensor_start_ov965x_cif[][2] = { +static const u8 sensor_start_ov965x_qvga[][2] = { {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ {0x1e, 0x04}, /* mvfp */ {0x13, 0xe0}, /* com8 */ @@ -1359,10 +1359,10 @@ static int sd_start_ov965x(struct gspca_dev *gspca_dev) mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; if (mode != 0) { /* 320x240 */ - reg_w_array(gspca_dev, bridge_start_ov965x_cif, - ARRAY_SIZE(bridge_start_ov965x_cif)); - sccb_w_array(gspca_dev, sensor_start_ov965x_cif, - ARRAY_SIZE(sensor_start_ov965x_cif)); + reg_w_array(gspca_dev, bridge_start_ov965x_qvga, + ARRAY_SIZE(bridge_start_ov965x_qvga)); + sccb_w_array(gspca_dev, sensor_start_ov965x_qvga, + ARRAY_SIZE(sensor_start_ov965x_qvga)); } else { /* 640x480 */ reg_w_array(gspca_dev, bridge_start_ov965x_vga, ARRAY_SIZE(bridge_start_ov965x_vga)); From f0076e60b5a61072b671b597ed2cc210f1b3cbf1 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 4 Nov 2009 22:33:33 -0300 Subject: [PATCH 265/345] V4L/DVB (13426): cx18: Rename struct cx18_mdl to struct cx18_mdl_ent Rename type in anticipation of implementing a struct cx18_mdl type that actually keeps track of a memory descriptor list. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-queue.c | 2 +- drivers/media/video/cx18/cx18-scb.h | 4 ++-- drivers/media/video/cx18/cx23418.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index fa1ed7897d97..9061ff3eac6f 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -201,7 +201,7 @@ int cx18_stream_alloc(struct cx18_stream *s) CX18_ERR("Too many buffers, cannot fit in SCB area\n"); CX18_ERR("Max buffers = %zd\n", - bufsz / sizeof(struct cx18_mdl)); + bufsz / sizeof(struct cx18_mdl_ent)); return -ENOMEM; } diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h index 1dc1c431f5a1..368f23d08709 100644 --- a/drivers/media/video/cx18/cx18-scb.h +++ b/drivers/media/video/cx18/cx18-scb.h @@ -81,7 +81,7 @@ /* This structure is used by EPU to provide memory descriptors in its memory */ -struct cx18_mdl { +struct cx18_mdl_ent { u32 paddr; /* Physical address of a buffer segment */ u32 length; /* Length of the buffer segment */ }; @@ -272,7 +272,7 @@ struct cx18_scb { struct cx18_mailbox ppu2epu_mb; struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS]; - struct cx18_mdl cpu_mdl[1]; + struct cx18_mdl_ent cpu_mdl[1]; }; void cx18_init_scb(struct cx18 *cx); diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index 9956abf576c5..868806effdcf 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h @@ -363,7 +363,7 @@ /* Description: This command provides the offset to a Memory Descriptor List IN[0] - Task handle. Handle of the task to start IN[1] - Offset of the MDL from the beginning of the local DDR. - IN[2] - Number of cx18_mdl structures in the array pointed to by IN[1] + IN[2] - Number of cx18_mdl_ent structures in the array pointed to by IN[1] IN[3] - Buffer ID IN[4] - Total buffer length ReturnCode - One of the ERR_DE_... */ From c37b11bf17b66b960b217c35283aa9c55eacb292 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 4 Nov 2009 23:13:58 -0300 Subject: [PATCH 266/345] V4L/DVB (13427): cx18: Rename struct cx18_queue.buffers to struct cx18_queue.depth Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 2 +- drivers/media/video/cx18/cx18-fileops.c | 4 ++-- drivers/media/video/cx18/cx18-ioctl.c | 2 +- drivers/media/video/cx18/cx18-queue.c | 16 ++++++++-------- drivers/media/video/cx18/cx18-streams.c | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index c6a1e907f63a..0b182fa2ad0b 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -285,7 +285,7 @@ struct cx18_buffer { struct cx18_queue { struct list_head list; - atomic_t buffers; + atomic_t depth; u32 bytesused; spinlock_t lock; }; diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 04d9c2508b86..e4a3faebff46 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -229,7 +229,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); /* New buffers might have become available before we were added to the waitqueue */ - if (!atomic_read(&s->q_full.buffers)) + if (!atomic_read(&s->q_full.depth)) schedule(); finish_wait(&s->waitq, &wait); if (signal_pending(current)) { @@ -543,7 +543,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)) + if (atomic_read(&s->q_full.depth)) return POLLIN | POLLRDNORM; if (eof) return POLLHUP; diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index fc76e4d6ffa7..6539b031b4eb 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -910,7 +910,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, - atomic_read(&s->q_full.buffers) * 100 / s->buffers, + atomic_read(&s->q_full.depth) * 100 / s->buffers, (s->buffers * s->buf_size) / 1024, s->buffers); } CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 9061ff3eac6f..bc4c5e4a6c03 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -38,7 +38,7 @@ void cx18_buf_swap(struct cx18_buffer *buf) void cx18_queue_init(struct cx18_queue *q) { INIT_LIST_HEAD(&q->list); - atomic_set(&q->buffers, 0); + atomic_set(&q->depth, 0); q->bytesused = 0; } @@ -55,7 +55,7 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, /* 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) + atomic_read(&q->depth) >= CX18_MAX_FW_MDLS_PER_STREAM) q = &s->q_free; spin_lock(&q->lock); @@ -65,7 +65,7 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, else list_add_tail(&buf->list, &q->list); /* FIFO */ q->bytesused += buf->bytesused - buf->readpos; - atomic_inc(&q->buffers); + atomic_inc(&q->depth); spin_unlock(&q->lock); return q; @@ -81,7 +81,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) list_del_init(&buf->list); q->bytesused -= buf->bytesused - buf->readpos; buf->skipped = 0; - atomic_dec(&q->buffers); + atomic_dec(&q->depth); } spin_unlock(&q->lock); return buf; @@ -113,7 +113,7 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, */ if (buf->id != id) { buf->skipped++; - if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { + if (buf->skipped >= atomic_read(&s->q_busy.depth)-1) { /* buffer must have fallen out of rotation */ CX18_WARN("Skipped %s, buffer %d, %d " "times - it must have dropped out of " @@ -121,7 +121,7 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, buf->skipped); /* Sweep it up to put it back into rotation */ list_move_tail(&buf->list, &sweep_up); - atomic_dec(&s->q_busy.buffers); + atomic_dec(&s->q_busy.depth); } continue; } @@ -130,7 +130,7 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, * will have to put it back on a queue later. */ list_del_init(&buf->list); - atomic_dec(&s->q_busy.buffers); + atomic_dec(&s->q_busy.depth); ret = buf; break; } @@ -170,7 +170,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) 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); + atomic_inc(&s->q_free.depth); } cx18_queue_init(q); spin_unlock(&q->lock); diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 7df513a2dba8..10228c5ca5a0 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -470,8 +470,8 @@ void _cx18_stream_load_fw_queue(struct cx18_stream *s) struct cx18_queue *q; struct cx18_buffer *buf; - if (atomic_read(&s->q_free.buffers) == 0 || - atomic_read(&s->q_busy.buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) + if (atomic_read(&s->q_free.depth) == 0 || + atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM) return; /* Move from q_free to q_busy notifying the firmware, until the limit */ @@ -480,7 +480,7 @@ 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) < CX18_MAX_FW_MDLS_PER_STREAM + } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM && q == &s->q_busy); } From fa655dda5ce6e5ac4a9b94fd451358edca2ddab8 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 5 Nov 2009 21:51:24 -0300 Subject: [PATCH 267/345] V4L/DVB (13428): cx18: Rename mdl_offset to mdl_base_idx or free_mdl_idx as appropriate Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 4 ++-- drivers/media/video/cx18/cx18-mailbox.c | 4 ++-- drivers/media/video/cx18/cx18-queue.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 0b182fa2ad0b..1a899e0773d7 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -337,7 +337,7 @@ struct cx18_stream { const char *name; /* name of the stream */ int type; /* stream type */ u32 handle; /* task handle */ - unsigned mdl_offset; + unsigned int mdl_base_idx; u32 id; unsigned long s_flags; /* status flags, see above */ @@ -514,7 +514,7 @@ struct cx18 { u16 buffer_id; /* buffer ID counter */ u32 v4l2_cap; /* V4L2 capabilities of card */ u32 hw_flags; /* Hardware description of the board */ - unsigned mdl_offset; + unsigned int free_mdl_idx; struct cx18_scb __iomem *scb; /* pointer to SCB */ struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/ struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/ diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index afe46c3d4057..4a1249a7d46a 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -178,8 +178,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) * 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 && - id < (s->mdl_offset + s->buffers))) { + !(id >= s->mdl_base_idx && + id < (s->mdl_base_idx + s->buffers))) { CX18_WARN("Fell behind! Ignoring stale mailbox with " " inconsistent data. Lost buffer for mailbox " "seq no %d\n", mb->request); diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index bc4c5e4a6c03..b9bd4ff5535e 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -194,7 +194,7 @@ int cx18_stream_alloc(struct cx18_stream *s) s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); - if (((char __iomem *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] - + if (((char __iomem *)&cx->scb->cpu_mdl[cx->free_mdl_idx + s->buffers] - (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) { unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE - ((char __iomem *)cx->scb->cpu_mdl)); @@ -205,7 +205,7 @@ int cx18_stream_alloc(struct cx18_stream *s) return -ENOMEM; } - s->mdl_offset = cx->mdl_offset; + s->mdl_base_idx = cx->free_mdl_idx; /* allocate stream buffers. Initially all buffers are in q_free. */ for (i = 0; i < s->buffers; i++) { @@ -227,7 +227,7 @@ int cx18_stream_alloc(struct cx18_stream *s) cx18_enqueue(s, buf, &s->q_free); } if (i == s->buffers) { - cx->mdl_offset += s->buffers; + cx->free_mdl_idx += s->buffers; return 0; } CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name); From 52fcb3ecc6707f52dfe4297f96b7609d4ba517fb Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 8 Nov 2009 23:45:24 -0300 Subject: [PATCH 268/345] V4L/DVB (13429): cx18: Add Memory Descriptor List (MDL) layer to buffer handling Add a Memory Descriptor List (MDL) layer to buffer handling to implement scatter-gather I/O. Currently there is still only 1 buffer per MDL. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 6 + drivers/media/video/cx18/cx18-driver.h | 45 ++-- drivers/media/video/cx18/cx18-fileops.c | 128 +++++++--- drivers/media/video/cx18/cx18-ioctl.c | 3 +- drivers/media/video/cx18/cx18-mailbox.c | 58 +++-- drivers/media/video/cx18/cx18-mailbox.h | 6 +- drivers/media/video/cx18/cx18-queue.c | 316 +++++++++++++++++++----- drivers/media/video/cx18/cx18-queue.h | 54 +++- drivers/media/video/cx18/cx18-streams.c | 50 ++-- drivers/media/video/cx18/cx18-streams.h | 10 +- drivers/media/video/cx18/cx18-vbi.c | 35 ++- drivers/media/video/cx18/cx18-vbi.h | 2 +- 12 files changed, 540 insertions(+), 173 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index e12082b8a08d..ba4c3ceffbb3 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -669,6 +669,12 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; + /* IVTV style VBI insertion into MPEG streams */ + INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_buf.list); + INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.list); + INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.buf_list); + list_add(&cx->vbi.sliced_mpeg_buf.list, + &cx->vbi.sliced_mpeg_mdl.buf_list); return 0; } diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 1a899e0773d7..bed8bcc65411 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -246,8 +246,8 @@ struct cx18_options { int radio; /* enable/disable radio */ }; -/* per-buffer bit flags */ -#define CX18_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */ +/* per-mdl bit flags */ +#define CX18_F_M_NEED_SWAP 0 /* mdl buffer data must be endianess swapped */ /* per-stream, s_flags */ #define CX18_F_S_CLAIMED 3 /* this stream is claimed */ @@ -274,15 +274,26 @@ struct cx18_options { struct cx18_buffer { struct list_head list; dma_addr_t dma_handle; - u32 id; - unsigned long b_flags; - unsigned skipped; char *buf; u32 bytesused; u32 readpos; }; +struct cx18_mdl { + struct list_head list; + u32 id; /* index into cx->scb->cpu_mdl[] of 1st cx18_mdl_ent */ + + unsigned int skipped; + unsigned long m_flags; + + struct list_head buf_list; + struct cx18_buffer *curr_buf; /* current buffer in list for reading */ + + u32 bytesused; + u32 readpos; +}; + struct cx18_queue { struct list_head list; atomic_t depth; @@ -346,14 +357,20 @@ struct cx18_stream { PCI_DMA_NONE */ wait_queue_head_t waitq; - /* Buffer Stats */ - u32 buffers; - u32 buf_size; + /* Buffers */ + struct list_head buf_pool; /* buffers not attached to an MDL */ + u32 buffers; /* total buffers owned by this stream */ + u32 buf_size; /* size in bytes of a single buffer */ - /* Buffer Queues */ - struct cx18_queue q_free; /* free buffers */ - struct cx18_queue q_busy; /* busy buffers - in use by firmware */ - struct cx18_queue q_full; /* full buffers - data for user apps */ + /* MDL sizes - all stream MDLs are the same size */ + u32 bufs_per_mdl; + u32 mdl_size; /* total bytes in all buffers in a mdl */ + + /* MDL Queues */ + struct cx18_queue q_free; /* free - in rotation, not committed */ + struct cx18_queue q_busy; /* busy - in use by firmware */ + struct cx18_queue q_full; /* full - data for user apps */ + struct cx18_queue q_idle; /* idle - not in rotation */ struct work_struct out_work_order; @@ -481,10 +498,11 @@ struct vbi_info { u32 inserted_frame; /* - * A dummy driver stream transfer buffer with a copy of the next + * A dummy driver stream transfer mdl & buffer with a copy of the next * sliced_mpeg_data[] buffer for output to userland apps. * Only used in cx18-fileops.c, but its state needs to persist at times. */ + struct cx18_mdl sliced_mpeg_mdl; struct cx18_buffer sliced_mpeg_buf; }; @@ -511,7 +529,6 @@ struct cx18 { u8 is_60hz; u8 nof_inputs; /* number of video inputs */ u8 nof_audio_inputs; /* number of audio inputs */ - u16 buffer_id; /* buffer ID counter */ u32 v4l2_cap; /* V4L2 capabilities of card */ u32 hw_flags; /* Hardware description of the board */ unsigned int free_mdl_idx; diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index e4a3faebff46..4e278db31cc9 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -166,11 +166,12 @@ static void cx18_dualwatch(struct cx18 *cx) } -static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, int *err) +static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block, + int *err) { struct cx18 *cx = s->cx; struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; - struct cx18_buffer *buf; + struct cx18_mdl *mdl; DEFINE_WAIT(wait); *err = 0; @@ -185,32 +186,33 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, } if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { - while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { + while ((mdl = cx18_dequeue(s_vbi, + &s_vbi->q_full))) { /* byteswap and process VBI data */ - cx18_process_vbi_data(cx, buf, + cx18_process_vbi_data(cx, mdl, s_vbi->type); - cx18_stream_put_buf_fw(s_vbi, buf); + cx18_stream_put_mdl_fw(s_vbi, mdl); } } - buf = &cx->vbi.sliced_mpeg_buf; - if (buf->readpos != buf->bytesused) - return buf; + mdl = &cx->vbi.sliced_mpeg_mdl; + if (mdl->readpos != mdl->bytesused) + return mdl; } /* do we have new data? */ - buf = cx18_dequeue(s, &s->q_full); - if (buf) { - if (!test_and_clear_bit(CX18_F_B_NEED_BUF_SWAP, - &buf->b_flags)) - return buf; + mdl = cx18_dequeue(s, &s->q_full); + if (mdl) { + if (!test_and_clear_bit(CX18_F_M_NEED_SWAP, + &mdl->m_flags)) + return mdl; if (s->type == CX18_ENC_STREAM_TYPE_MPG) /* byteswap MPG data */ - cx18_buf_swap(buf); + cx18_mdl_swap(mdl); else { /* byteswap and process VBI data */ - cx18_process_vbi_data(cx, buf, s->type); + cx18_process_vbi_data(cx, mdl, s->type); } - return buf; + return mdl; } /* return if end of stream */ @@ -241,21 +243,28 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, } } -static void cx18_setup_sliced_vbi_buf(struct cx18 *cx) +static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx) { + struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl; + struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf; int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; - cx->vbi.sliced_mpeg_buf.buf = cx->vbi.sliced_mpeg_data[idx]; - cx->vbi.sliced_mpeg_buf.bytesused = cx->vbi.sliced_mpeg_size[idx]; - cx->vbi.sliced_mpeg_buf.readpos = 0; + buf->buf = cx->vbi.sliced_mpeg_data[idx]; + buf->bytesused = cx->vbi.sliced_mpeg_size[idx]; + buf->readpos = 0; + + mdl->curr_buf = NULL; + mdl->bytesused = cx->vbi.sliced_mpeg_size[idx]; + mdl->readpos = 0; } static size_t cx18_copy_buf_to_user(struct cx18_stream *s, - struct cx18_buffer *buf, char __user *ubuf, size_t ucount) + struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop) { struct cx18 *cx = s->cx; size_t len = buf->bytesused - buf->readpos; + *stop = false; if (len > ucount) len = ucount; if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && @@ -335,7 +344,8 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, /* We declare we actually found a Program Pack*/ cx->search_pack_header = 0; /* expect vid PES */ len = (char *)q - start; - cx18_setup_sliced_vbi_buf(cx); + cx18_setup_sliced_vbi_mdl(cx); + *stop = true; break; } } @@ -352,6 +362,60 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, return len; } +/** + * list_entry_is_past_end - check if a previous loop cursor is off list end + * @pos: the type * previously used as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Check if the entry's list_head is the head of the list, thus it's not a + * real entry but was the loop cursor that walked past the end + */ +#define list_entry_is_past_end(pos, head, member) \ + (&pos->member == (head)) + +static size_t cx18_copy_mdl_to_user(struct cx18_stream *s, + struct cx18_mdl *mdl, char __user *ubuf, size_t ucount) +{ + size_t tot_written = 0; + int rc; + bool stop = false; + + if (mdl->curr_buf == NULL) + mdl->curr_buf = list_first_entry(&mdl->buf_list, + struct cx18_buffer, list); + + if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) { + /* + * For some reason we've exhausted the buffers, but the MDL + * object still said some data was unread. + * Fix that and bail out. + */ + mdl->readpos = mdl->bytesused; + return 0; + } + + list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) { + + if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused) + continue; + + rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written, + ucount - tot_written, &stop); + if (rc < 0) + return rc; + mdl->readpos += rc; + tot_written += rc; + + if (stop || /* Forced stopping point for VBI insertion */ + tot_written >= ucount || /* Reader request statisfied */ + mdl->curr_buf->readpos < mdl->curr_buf->bytesused || + mdl->readpos >= mdl->bytesused) /* MDL buffers drained */ + break; + } + return tot_written; +} + static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, size_t tot_count, int non_block) { @@ -373,12 +437,12 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, single_frame = 1; for (;;) { - struct cx18_buffer *buf; + struct cx18_mdl *mdl; int rc; - buf = cx18_get_buffer(s, non_block, &rc); + mdl = cx18_get_mdl(s, non_block, &rc); /* if there is no data available... */ - if (buf == NULL) { + if (mdl == NULL) { /* if we got data, then return that regardless */ if (tot_written) break; @@ -392,20 +456,20 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, return rc; } - rc = cx18_copy_buf_to_user(s, buf, ubuf + tot_written, + rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written, tot_count - tot_written); - if (buf != &cx->vbi.sliced_mpeg_buf) { - if (buf->readpos == buf->bytesused) - cx18_stream_put_buf_fw(s, buf); + if (mdl != &cx->vbi.sliced_mpeg_mdl) { + if (mdl->readpos == mdl->bytesused) + cx18_stream_put_mdl_fw(s, mdl); else - cx18_push(s, buf, &s->q_full); - } else if (buf->readpos == buf->bytesused) { + cx18_push(s, mdl, &s->q_full); + } else if (mdl->readpos == mdl->bytesused) { int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; cx->vbi.sliced_mpeg_size[idx] = 0; cx->vbi.inserted_frame++; - cx->vbi_data_inserted += buf->bytesused; + cx->vbi_data_inserted += mdl->bytesused; } if (rc < 0) return rc; diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 6539b031b4eb..3e4fc192fdec 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -910,7 +910,8 @@ 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, - atomic_read(&s->q_full.depth) * 100 / s->buffers, + atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100 + / s->buffers, (s->buffers * s->buf_size) / 1024, s->buffers); } CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 4a1249a7d46a..f231dd09c720 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -131,13 +131,39 @@ static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name) * Functions that run in a work_queue work handling context */ +static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) +{ + struct cx18_buffer *buf; + + if (!s->dvb.enabled || mdl->bytesused == 0) + return; + + /* We ignore mdl and buf readpos accounting here - it doesn't matter */ + + /* The likely case */ + if (list_is_singular(&mdl->buf_list)) { + buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, + list); + if (buf->bytesused) + dvb_dmx_swfilter(&s->dvb.demux, + buf->buf, buf->bytesused); + return; + } + + list_for_each_entry(buf, &mdl->buf_list, list) { + if (buf->bytesused == 0) + break; + dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused); + } +} + static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) { u32 handle, mdl_ack_count, id; struct cx18_mailbox *mb; struct cx18_mdl_ack *mdl_ack; struct cx18_stream *s; - struct cx18_buffer *buf; + struct cx18_mdl *mdl; int i; mb = &order->mb; @@ -158,7 +184,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) id = mdl_ack->id; /* * Simple integrity check for processing a stale (and possibly - * inconsistent mailbox): make sure the buffer id is in the + * inconsistent mailbox): make sure the MDL id is in the * valid range for the stream. * * We go through the trouble of dealing with stale mailboxes @@ -169,44 +195,42 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) * There are occasions when we get a half changed mailbox, * which this check catches for a handle & id mismatch. If the * handle and id do correspond, the worst case is that we - * completely lost the old buffer, but pick up the new buffer + * completely lost the old MDL, but pick up the new MDL * early (but the new mdl_ack is guaranteed to be good in this * case as the firmware wouldn't point us to a new mdl_ack until * it's filled in). * - * cx18_queue_get buf() will detect the lost buffers + * cx18_queue_get_mdl() will detect the lost MDLs * and send them back to q_free for fw rotation eventually. */ if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) && !(id >= s->mdl_base_idx && id < (s->mdl_base_idx + s->buffers))) { CX18_WARN("Fell behind! Ignoring stale mailbox with " - " inconsistent data. Lost buffer for mailbox " + " inconsistent data. Lost MDL for mailbox " "seq no %d\n", mb->request); break; } - buf = cx18_queue_get_buf(s, id, mdl_ack->data_used); + mdl = cx18_queue_get_mdl(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", + CX18_DEBUG_HI_DMA("DMA DONE for %s (MDL %d)\n", s->name, id); + if (mdl == NULL) { + CX18_WARN("Could not find MDL %d for stream %s\n", id, s->name); continue; } CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", - s->name, buf->bytesused); + s->name, mdl->bytesused); if (s->type != CX18_ENC_STREAM_TYPE_TS) - cx18_enqueue(s, buf, &s->q_full); + cx18_enqueue(s, mdl, &s->q_full); else { - if (s->dvb.enabled) - dvb_dmx_swfilter(&s->dvb.demux, buf->buf, - buf->bytesused); - cx18_enqueue(s, buf, &s->q_free); + cx18_mdl_send_to_dvb(s, mdl); + cx18_enqueue(s, mdl, &s->q_free); } } - /* Put as many buffers as possible back into fw use */ + /* Put as many MDLs as possible back into fw use */ cx18_stream_load_fw_queue(s); wake_up(&cx->dma_waitq); @@ -616,7 +640,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) /* * Wait for XPU to perform extra actions for the caller in some cases. - * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all buffers + * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all MDLs * back in a burst shortly thereafter */ if (info->flags & API_SLOW) diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h index e23aaac5b280..5ea07359904c 100644 --- a/drivers/media/video/cx18/cx18-mailbox.h +++ b/drivers/media/video/cx18/cx18-mailbox.h @@ -39,14 +39,14 @@ struct cx18; /* - * This structure is used by CPU to provide completed buffers information - * Its structure is dictrated by the layout of the SCB, required by the + * This structure is used by CPU to provide completed MDL & buffers information. + * Its structure is dictated by the layout of the SCB, required by the * firmware, but its defintion needs to be here, instead of in cx18-scb.h, * for mailbox work order scheduling */ struct cx18_mdl_ack { u32 id; /* ID of a completed MDL */ - u32 data_used; /* Total data filled in the MDL for buffer 'id' */ + u32 data_used; /* Total data filled in the MDL with 'id' */ }; /* The cx18_mailbox struct is the mailbox structure which is used for passing diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index b9bd4ff5535e..c1a49ecf9d98 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -26,6 +26,7 @@ #include "cx18-queue.h" #include "cx18-streams.h" #include "cx18-scb.h" +#include "cx18-io.h" void cx18_buf_swap(struct cx18_buffer *buf) { @@ -35,6 +36,17 @@ void cx18_buf_swap(struct cx18_buffer *buf) swab32s((u32 *)(buf->buf + i)); } +void _cx18_mdl_swap(struct cx18_mdl *mdl) +{ + struct cx18_buffer *buf; + + list_for_each_entry(buf, &mdl->buf_list, list) { + if (buf->bytesused == 0) + break; + cx18_buf_swap(buf); + } +} + void cx18_queue_init(struct cx18_queue *q) { INIT_LIST_HEAD(&q->list); @@ -42,15 +54,16 @@ void cx18_queue_init(struct cx18_queue *q) q->bytesused = 0; } -struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, +struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl, struct cx18_queue *q, int to_front) { - /* clear the buffer if it is not to be enqueued to the full queue */ + /* clear the mdl 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; + mdl->bytesused = 0; + mdl->readpos = 0; + mdl->m_flags = 0; + mdl->skipped = 0; + mdl->curr_buf = NULL; } /* q_busy is restricted to a max buffer count imposed by firmware */ @@ -61,125 +74,270 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, spin_lock(&q->lock); if (to_front) - list_add(&buf->list, &q->list); /* LIFO */ + list_add(&mdl->list, &q->list); /* LIFO */ else - list_add_tail(&buf->list, &q->list); /* FIFO */ - q->bytesused += buf->bytesused - buf->readpos; + list_add_tail(&mdl->list, &q->list); /* FIFO */ + q->bytesused += mdl->bytesused - mdl->readpos; atomic_inc(&q->depth); spin_unlock(&q->lock); return q; } -struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) +struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) { - struct cx18_buffer *buf = NULL; + struct cx18_mdl *mdl = NULL; spin_lock(&q->lock); if (!list_empty(&q->list)) { - buf = list_first_entry(&q->list, struct cx18_buffer, list); - list_del_init(&buf->list); - q->bytesused -= buf->bytesused - buf->readpos; - buf->skipped = 0; + mdl = list_first_entry(&q->list, struct cx18_mdl, list); + list_del_init(&mdl->list); + q->bytesused -= mdl->bytesused - mdl->readpos; + mdl->skipped = 0; atomic_dec(&q->depth); } spin_unlock(&q->lock); - return buf; + return mdl; } -struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, +static void _cx18_mdl_set_buf_bytesused(struct cx18_stream *s, + struct cx18_mdl *mdl) +{ + struct cx18_buffer *buf; + u32 buf_size = s->buf_size; + u32 bytesused = mdl->bytesused; + + list_for_each_entry(buf, &mdl->buf_list, list) { + buf->readpos = 0; + if (bytesused >= buf_size) { + buf->bytesused = buf_size; + bytesused -= buf_size; + } else { + buf->bytesused = bytesused; + bytesused = 0; + } + } +} + +static inline void cx18_mdl_set_buf_bytesused(struct cx18_stream *s, + struct cx18_mdl *mdl) +{ + struct cx18_buffer *buf; + + if (list_is_singular(&mdl->buf_list)) { + buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, + list); + buf->bytesused = mdl->bytesused; + buf->readpos = 0; + } else { + _cx18_mdl_set_buf_bytesused(s, mdl); + } +} + +struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id, u32 bytesused) { struct cx18 *cx = s->cx; - struct cx18_buffer *buf; - struct cx18_buffer *tmp; - struct cx18_buffer *ret = NULL; + struct cx18_mdl *mdl; + struct cx18_mdl *tmp; + struct cx18_mdl *ret = NULL; LIST_HEAD(sweep_up); /* * We don't have to acquire multiple q locks here, because we are * serialized by the single threaded work handler. - * Buffers from the firmware will thus remain in order as + * MDLs from the firmware will thus remain in order as * they are moved from q_busy to q_full or to the dvb ring buffer. */ spin_lock(&s->q_busy.lock); - list_for_each_entry_safe(buf, tmp, &s->q_busy.list, list) { + list_for_each_entry_safe(mdl, tmp, &s->q_busy.list, list) { /* * We should find what the firmware told us is done, * right at the front of the queue. If we don't, we likely have - * missed a buffer done message from the firmware. - * Once we skip a buffer repeatedly, relative to the size of + * missed an mdl done message from the firmware. + * Once we skip an mdl repeatedly, relative to the size of * q_busy, we have high confidence we've missed it. */ - if (buf->id != id) { - buf->skipped++; - if (buf->skipped >= atomic_read(&s->q_busy.depth)-1) { - /* buffer must have fallen out of rotation */ - CX18_WARN("Skipped %s, buffer %d, %d " + if (mdl->id != id) { + mdl->skipped++; + if (mdl->skipped >= atomic_read(&s->q_busy.depth)-1) { + /* mdl must have fallen out of rotation */ + CX18_WARN("Skipped %s, MDL %d, %d " "times - it must have dropped out of " - "rotation\n", s->name, buf->id, - buf->skipped); + "rotation\n", s->name, mdl->id, + mdl->skipped); /* Sweep it up to put it back into rotation */ - list_move_tail(&buf->list, &sweep_up); + list_move_tail(&mdl->list, &sweep_up); atomic_dec(&s->q_busy.depth); } continue; } /* - * We pull the desired buffer off of the queue here. Something + * We pull the desired mdl off of the queue here. Something * will have to put it back on a queue later. */ - list_del_init(&buf->list); + list_del_init(&mdl->list); atomic_dec(&s->q_busy.depth); - ret = buf; + ret = mdl; break; } spin_unlock(&s->q_busy.lock); /* - * We found the buffer for which we were looking. Get it ready for + * We found the mdl for which we were looking. Get it ready for * the caller to put on q_full or in the dvb ring buffer. */ if (ret != NULL) { ret->bytesused = bytesused; ret->skipped = 0; - /* readpos and b_flags were 0'ed when the buf went on q_busy */ - cx18_buf_sync_for_cpu(s, ret); + /* 0'ed readpos, m_flags & curr_buf when mdl went on q_busy */ + cx18_mdl_set_buf_bytesused(s, ret); + cx18_mdl_sync_for_cpu(s, ret); if (s->type != CX18_ENC_STREAM_TYPE_TS) - set_bit(CX18_F_B_NEED_BUF_SWAP, &ret->b_flags); + set_bit(CX18_F_M_NEED_SWAP, &ret->m_flags); } - /* Put any buffers the firmware is ignoring back into normal rotation */ - list_for_each_entry_safe(buf, tmp, &sweep_up, list) { - list_del_init(&buf->list); - cx18_enqueue(s, buf, &s->q_free); + /* Put any mdls the firmware is ignoring back into normal rotation */ + list_for_each_entry_safe(mdl, tmp, &sweep_up, list) { + list_del_init(&mdl->list); + cx18_enqueue(s, mdl, &s->q_free); } return ret; } -/* Move all buffers of a queue to q_free, while flushing the buffers */ -static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) +/* Move all mdls of a queue, while flushing the mdl */ +static void cx18_queue_flush(struct cx18_stream *s, + struct cx18_queue *q_src, struct cx18_queue *q_dst) { - struct cx18_buffer *buf; + struct cx18_mdl *mdl; - if (q == &s->q_free) + /* It only makes sense to flush to q_free or q_idle */ + if (q_src == q_dst || q_dst == &s->q_full || q_dst == &s->q_busy) return; - spin_lock(&q->lock); - while (!list_empty(&q->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.depth); + spin_lock(&q_src->lock); + spin_lock(&q_dst->lock); + while (!list_empty(&q_src->list)) { + mdl = list_first_entry(&q_src->list, struct cx18_mdl, list); + list_move_tail(&mdl->list, &q_dst->list); + mdl->bytesused = 0; + mdl->readpos = 0; + mdl->m_flags = 0; + mdl->skipped = 0; + mdl->curr_buf = NULL; + atomic_inc(&q_dst->depth); } - cx18_queue_init(q); - spin_unlock(&q->lock); + cx18_queue_init(q_src); + spin_unlock(&q_src->lock); + spin_unlock(&q_dst->lock); } void cx18_flush_queues(struct cx18_stream *s) { - cx18_queue_flush(s, &s->q_busy); - cx18_queue_flush(s, &s->q_full); + cx18_queue_flush(s, &s->q_busy, &s->q_free); + cx18_queue_flush(s, &s->q_full, &s->q_free); +} + +/* + * Note, s->buf_pool is not protected by a lock, + * the stream better not have *anything* going on when calling this + */ +void cx18_unload_queues(struct cx18_stream *s) +{ + struct cx18_queue *q_idle = &s->q_idle; + struct cx18_mdl *mdl; + struct cx18_buffer *buf; + + /* Move all MDLS to q_idle */ + cx18_queue_flush(s, &s->q_busy, q_idle); + cx18_queue_flush(s, &s->q_full, q_idle); + cx18_queue_flush(s, &s->q_free, q_idle); + + /* Reset MDL id's and move all buffers back to the stream's buf_pool */ + spin_lock(&q_idle->lock); + list_for_each_entry(mdl, &q_idle->list, list) { + while (!list_empty(&mdl->buf_list)) { + buf = list_first_entry(&mdl->buf_list, + struct cx18_buffer, list); + list_move_tail(&buf->list, &s->buf_pool); + buf->bytesused = 0; + buf->readpos = 0; + } + mdl->id = s->mdl_base_idx; /* reset id to a "safe" value */ + /* all other mdl fields were cleared by cx18_queue_flush() */ + } + spin_unlock(&q_idle->lock); +} + +/* + * Note, s->buf_pool is not protected by a lock, + * the stream better not have *anything* going on when calling this + */ +void cx18_load_queues(struct cx18_stream *s) +{ + struct cx18 *cx = s->cx; + struct cx18_mdl *mdl; + struct cx18_buffer *buf; + int mdl_id; + int i; + + /* + * Attach buffers to MDLs, give the MDLs ids, and add MDLs to q_free + * Excess MDLs are left on q_idle + * Excess buffers are left in buf_pool and/or on an MDL in q_idle + */ + mdl_id = s->mdl_base_idx; + for (mdl = cx18_dequeue(s, &s->q_idle), i = s->bufs_per_mdl; + mdl != NULL && i == s->bufs_per_mdl; + mdl = cx18_dequeue(s, &s->q_idle)) { + + mdl->id = mdl_id; + + for (i = 0; i < s->bufs_per_mdl; i++) { + if (list_empty(&s->buf_pool)) + break; + + buf = list_first_entry(&s->buf_pool, struct cx18_buffer, + list); + list_move_tail(&buf->list, &mdl->buf_list); + + /* update the firmware's MDL array with this buffer */ + cx18_writel(cx, buf->dma_handle, + &cx->scb->cpu_mdl[mdl_id + i].paddr); + cx18_writel(cx, s->buf_size, + &cx->scb->cpu_mdl[mdl_id + i].length); + } + + if (i == s->bufs_per_mdl) + cx18_enqueue(s, mdl, &s->q_free); + else + cx18_push(s, mdl, &s->q_idle); /* not enough buffers */ + mdl_id += i; + } +} + +void _cx18_mdl_sync_for_cpu(struct cx18_stream *s, struct cx18_mdl *mdl) +{ + int dma = s->dma; + u32 buf_size = s->buf_size; + struct pci_dev *pci_dev = s->cx->pci_dev; + struct cx18_buffer *buf; + + list_for_each_entry(buf, &mdl->buf_list, list) + pci_dma_sync_single_for_cpu(pci_dev, buf->dma_handle, + buf_size, dma); +} + +void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl) +{ + int dma = s->dma; + u32 buf_size = s->buf_size; + struct pci_dev *pci_dev = s->cx->pci_dev; + struct cx18_buffer *buf; + + list_for_each_entry(buf, &mdl->buf_list, list) + pci_dma_sync_single_for_device(pci_dev, buf->dma_handle, + buf_size, dma); } int cx18_stream_alloc(struct cx18_stream *s) @@ -207,24 +365,40 @@ int cx18_stream_alloc(struct cx18_stream *s) s->mdl_base_idx = cx->free_mdl_idx; - /* allocate stream buffers. Initially all buffers are in q_free. */ + /* allocate stream buffers and MDLs */ for (i = 0; i < s->buffers; i++) { - struct cx18_buffer *buf = kzalloc(sizeof(struct cx18_buffer), - GFP_KERNEL|__GFP_NOWARN); + struct cx18_mdl *mdl; + struct cx18_buffer *buf; - if (buf == NULL) + /* 1 MDL per buffer to handle the worst & also default case */ + mdl = kzalloc(sizeof(struct cx18_mdl), GFP_KERNEL|__GFP_NOWARN); + if (mdl == NULL) break; + + buf = kzalloc(sizeof(struct cx18_buffer), + GFP_KERNEL|__GFP_NOWARN); + if (buf == NULL) { + kfree(mdl); + break; + } + buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN); if (buf->buf == NULL) { + kfree(mdl); kfree(buf); break; } - buf->id = cx->buffer_id++; + + INIT_LIST_HEAD(&mdl->list); + INIT_LIST_HEAD(&mdl->buf_list); + mdl->id = s->mdl_base_idx; /* a somewhat safe value */ + cx18_enqueue(s, mdl, &s->q_idle); + INIT_LIST_HEAD(&buf->list); buf->dma_handle = pci_map_single(s->cx->pci_dev, buf->buf, s->buf_size, s->dma); cx18_buf_sync_for_cpu(s, buf); - cx18_enqueue(s, buf, &s->q_free); + list_add_tail(&buf->list, &s->buf_pool); } if (i == s->buffers) { cx->free_mdl_idx += s->buffers; @@ -237,13 +411,21 @@ int cx18_stream_alloc(struct cx18_stream *s) void cx18_stream_free(struct cx18_stream *s) { + struct cx18_mdl *mdl; struct cx18_buffer *buf; - /* move all buffers to q_free */ - cx18_flush_queues(s); + /* move all buffers to buf_pool and all MDLs to q_idle */ + cx18_unload_queues(s); + + /* empty q_idle */ + while ((mdl = cx18_dequeue(s, &s->q_idle))) + kfree(mdl); + + /* empty buf_pool */ + while (!list_empty(&s->buf_pool)) { + buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list); + list_del_init(&buf->list); - /* empty q_free */ - while ((buf = cx18_dequeue(s, &s->q_free))) { pci_unmap_single(s->cx->pci_dev, buf->dma_handle, s->buf_size, s->dma); kfree(buf->buf); diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index 4de06269d88f..96747e5e7c3c 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h @@ -33,6 +33,19 @@ static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s, s->buf_size, s->dma); } +void _cx18_mdl_sync_for_cpu(struct cx18_stream *s, struct cx18_mdl *mdl); + +static inline void cx18_mdl_sync_for_cpu(struct cx18_stream *s, + struct cx18_mdl *mdl) +{ + if (list_is_singular(&mdl->buf_list)) + cx18_buf_sync_for_cpu(s, list_first_entry(&mdl->buf_list, + struct cx18_buffer, + list)); + else + _cx18_mdl_sync_for_cpu(s, mdl); +} + static inline void cx18_buf_sync_for_device(struct cx18_stream *s, struct cx18_buffer *buf) { @@ -40,32 +53,59 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s, s->buf_size, s->dma); } +void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl); + +static inline void cx18_mdl_sync_for_device(struct cx18_stream *s, + struct cx18_mdl *mdl) +{ + if (list_is_singular(&mdl->buf_list)) + cx18_buf_sync_for_device(s, list_first_entry(&mdl->buf_list, + struct cx18_buffer, + list)); + else + _cx18_mdl_sync_for_device(s, mdl); +} + void cx18_buf_swap(struct cx18_buffer *buf); +void _cx18_mdl_swap(struct cx18_mdl *mdl); + +static inline void cx18_mdl_swap(struct cx18_mdl *mdl) +{ + if (list_is_singular(&mdl->buf_list)) + cx18_buf_swap(list_first_entry(&mdl->buf_list, + struct cx18_buffer, list)); + else + _cx18_mdl_swap(mdl); +} /* cx18_queue utility functions */ -struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, +struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl, struct cx18_queue *q, int to_front); static inline -struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, +struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl, struct cx18_queue *q) { - return _cx18_enqueue(s, buf, q, 0); /* FIFO */ + return _cx18_enqueue(s, mdl, q, 0); /* FIFO */ } static inline -struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_buffer *buf, +struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_mdl *mdl, struct cx18_queue *q) { - return _cx18_enqueue(s, buf, q, 1); /* LIFO */ + return _cx18_enqueue(s, mdl, 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, +struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); +struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id, u32 bytesused); void cx18_flush_queues(struct cx18_stream *s); +/* queue MDL reconfiguration helpers */ +void cx18_unload_queues(struct cx18_stream *s); +void cx18_load_queues(struct cx18_stream *s); + /* cx18_stream utility functions */ int cx18_stream_alloc(struct cx18_stream *s); void cx18_stream_free(struct cx18_stream *s); diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 10228c5ca5a0..9f8adda6f261 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -115,6 +115,9 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->dma = cx18_stream_info[type].dma; s->buffers = cx->stream_buffers[type]; s->buf_size = cx->stream_buf_size[type]; + INIT_LIST_HEAD(&s->buf_pool); + s->bufs_per_mdl = 1; + s->mdl_size = s->buf_size * s->bufs_per_mdl; init_waitqueue_head(&s->waitq); s->id = -1; @@ -124,6 +127,8 @@ static void cx18_stream_init(struct cx18 *cx, int type) cx18_queue_init(&s->q_busy); spin_lock_init(&s->q_full.lock); cx18_queue_init(&s->q_full); + spin_lock_init(&s->q_idle.lock); + cx18_queue_init(&s->q_idle); INIT_WORK(&s->out_work_order, cx18_out_work_handler); } @@ -441,8 +446,8 @@ static void cx18_vbi_setup(struct cx18_stream *s) } static -struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, - struct cx18_buffer *buf) +struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, + struct cx18_mdl *mdl) { struct cx18 *cx = s->cx; struct cx18_queue *q; @@ -451,16 +456,16 @@ struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, if (s->handle == CX18_INVALID_TASK_HANDLE || test_bit(CX18_F_S_STOPPING, &s->s_flags) || !test_bit(CX18_F_S_STREAMING, &s->s_flags)) - return cx18_enqueue(s, buf, &s->q_free); + return cx18_enqueue(s, mdl, &s->q_free); - q = cx18_enqueue(s, buf, &s->q_busy); + q = cx18_enqueue(s, mdl, &s->q_busy); if (q != &s->q_busy) - return q; /* The firmware has the max buffers it can handle */ + return q; /* The firmware has the max MDLs it can handle */ - cx18_buf_sync_for_device(s, buf); + cx18_mdl_sync_for_device(s, mdl); 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); + (void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem, + s->bufs_per_mdl, mdl->id, s->mdl_size); return q; } @@ -468,7 +473,7 @@ static void _cx18_stream_load_fw_queue(struct cx18_stream *s) { struct cx18_queue *q; - struct cx18_buffer *buf; + struct cx18_mdl *mdl; if (atomic_read(&s->q_free.depth) == 0 || atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM) @@ -476,10 +481,10 @@ void _cx18_stream_load_fw_queue(struct cx18_stream *s) /* Move from q_free to q_busy notifying the firmware, until the limit */ do { - buf = cx18_dequeue(s, &s->q_free); - if (buf == NULL) + mdl = cx18_dequeue(s, &s->q_free); + if (mdl == NULL) break; - q = _cx18_stream_put_buf_fw(s, buf); + q = _cx18_stream_put_mdl_fw(s, mdl); } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM && q == &s->q_busy); } @@ -492,11 +497,21 @@ void cx18_out_work_handler(struct work_struct *work) _cx18_stream_load_fw_queue(s); } +static void cx18_stream_configure_mdls(struct cx18_stream *s) +{ + cx18_unload_queues(s); + + /* For now */ + s->bufs_per_mdl = 1; + s->mdl_size = s->buf_size * s->bufs_per_mdl; + + cx18_load_queues(s); +} + int cx18_start_v4l2_encode_stream(struct cx18_stream *s) { u32 data[MAX_MB_ARGUMENTS]; struct cx18 *cx = s->cx; - struct cx18_buffer *buf; int captype = 0; struct cx18_api_func_private priv; @@ -619,14 +634,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) (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); - spin_lock(&s->q_free.lock); - 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); - } - spin_unlock(&s->q_free.lock); + cx18_stream_configure_mdls(s); _cx18_stream_load_fw_queue(s); /* begin_capture */ diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 1afc3fd9d822..4a01db5e5a35 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h @@ -28,18 +28,18 @@ int cx18_streams_setup(struct cx18 *cx); int cx18_streams_register(struct cx18 *cx); void cx18_streams_cleanup(struct cx18 *cx, int unregister); -/* Related to submission of buffers to firmware */ +/* Related to submission of mdls to firmware */ static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) { struct cx18 *cx = s->cx; queue_work(cx->out_work_queue, &s->out_work_order); } -static inline void cx18_stream_put_buf_fw(struct cx18_stream *s, - struct cx18_buffer *buf) +static inline void cx18_stream_put_mdl_fw(struct cx18_stream *s, + struct cx18_mdl *mdl) { - /* Put buf on q_free; the out work handler will move buf(s) to q_busy */ - cx18_enqueue(s, buf, &s->q_free); + /* Put mdl on q_free; the out work handler will move mdl(s) to q_busy */ + cx18_enqueue(s, mdl, &s->q_free); cx18_stream_load_fw_queue(s); } diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index c2aef4add31d..574c1c6974f8 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -105,6 +105,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) /* Compress raw VBI format, removes leading SAV codes and surplus space after the frame. Returns new compressed size. */ +/* FIXME - this function ignores the input size. */ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size) { u32 line_size = vbi_active_samples; @@ -185,8 +186,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, return line; } -void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, - int streamtype) +static void _cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf) { /* * The CX23418 provides a 12 byte header in its raw VBI buffers to us: @@ -203,9 +203,6 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, u32 pts; int lines; - if (streamtype != CX18_ENC_STREAM_TYPE_VBI) - return; - /* * The CX23418 sends us data that is 32 bit little-endian swapped, * but we want the raw VBI bytes in the order they were in the raster @@ -250,3 +247,31 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, copy_vbi_data(cx, lines, pts); cx->vbi.frame++; } + +void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl, + int streamtype) +{ + struct cx18_buffer *buf; + u32 orig_used; + + if (streamtype != CX18_ENC_STREAM_TYPE_VBI) + return; + + /* + * Big assumption here: + * Every buffer hooked to the MDL's buf_list is a complete VBI frame + * that ends at the end of the buffer. + * + * To assume anything else would make the code in this file + * more complex, or require extra memcpy()'s to make the + * buffers satisfy the above assumption. It's just simpler to set + * up the encoder buffer transfers to make the assumption true. + */ + list_for_each_entry(buf, &mdl->buf_list, list) { + orig_used = buf->bytesused; + if (orig_used == 0) + break; + _cx18_process_vbi_data(cx, buf); + mdl->bytesused -= (orig_used - buf->bytesused); + } +} diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/video/cx18/cx18-vbi.h index e7e1ae427f34..b365cf4b4668 100644 --- a/drivers/media/video/cx18/cx18-vbi.h +++ b/drivers/media/video/cx18/cx18-vbi.h @@ -21,6 +21,6 @@ * 02111-1307 USA */ -void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, +void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl, int streamtype); int cx18_used_line(struct cx18 *cx, int line, int field); From 22dce188ef3e1e058ceabe3b3072640d7568f764 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 9 Nov 2009 23:55:30 -0300 Subject: [PATCH 269/345] V4L/DVB (13430): cx18: Fix YUV capture so that encoder passes a single frame per transfer Fix YUV capture such that the encoder will pass one frame per transfer. This will allow the application to maintain frame alignment when a transfer from the encoder is missed due to high system latency in service the CX23418 IRQ. Also force YUV buffer sizes to be specified in multiples of 33.75 kB, the smalled amount of buffer sizes need to store a complete set of HM12 4:2:0 macroblocks specifying 32 lines of the frame. A full 60Hz/525 line screen requires 15 * 33.75 kB per frame and a full 50Hz/625 line screen requires 18 * 33.75 kB per frame so the default buffer size is 3 * 33.75 kB, requiring exactly 5 or 6 buffers per MDL respectively. The bytes needed per frame and hence MDL need not be the bytes in an integer number of buffers. However, if frame artifacts are seen with scaled screen sizes, the YUV buffer size can be set 34 kB (33.75 kB) to get rid of the artifacts at the cost of more copies between the kernel and userspace. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 49 +++++++++++++++++++------ drivers/media/video/cx18/cx18-driver.h | 7 +++- drivers/media/video/cx18/cx18-dvb.c | 5 ++- drivers/media/video/cx18/cx18-queue.c | 6 ++- drivers/media/video/cx18/cx18-streams.c | 26 ++++++++++--- 5 files changed, 71 insertions(+), 22 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index ba4c3ceffbb3..87a735f1ee9e 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -211,7 +211,9 @@ MODULE_PARM_DESC(enc_yuv_buffers, "\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)); + "\t\t\tAllowed values are multiples of 33.75 kB rounded up\n" + "\t\t\t(multiples of size required for 32 screen lines)\n" + "\t\t\tDefault: 102"); MODULE_PARM_DESC(enc_yuv_bufs, "Number of encoder YUV buffers\n" "\t\t\tDefault is computed from other enc_yuv_* parameters"); @@ -499,10 +501,27 @@ static void cx18_process_options(struct cx18 *cx) continue; } /* + * YUV is a special case where the stream_buf_size needs to be + * an integral multiple of 33.75 kB (storage for 32 screens + * lines to maintain alignment in case of lost buffers + */ + if (i == CX18_ENC_STREAM_TYPE_YUV) { + cx->stream_buf_size[i] *= 1024; + cx->stream_buf_size[i] -= + (cx->stream_buf_size[i] % CX18_UNIT_ENC_YUV_BUFSIZE); + + if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE) + cx->stream_buf_size[i] = + CX18_UNIT_ENC_YUV_BUFSIZE; + } + /* + * YUV is a special case where the stream_buf_size is + * now in bytes. * VBI is a special case where the stream_buf_size is fixed * and already in bytes */ - if (i == CX18_ENC_STREAM_TYPE_VBI) { + if (i == CX18_ENC_STREAM_TYPE_VBI || + i == CX18_ENC_STREAM_TYPE_YUV) { if (cx->stream_buffers[i] < 0) { cx->stream_buffers[i] = cx->options.megabytes[i] * 1024 * 1024 @@ -513,18 +532,24 @@ static void cx18_process_options(struct cx18 *cx) cx->stream_buffers[i] * cx->stream_buf_size[i]/(1024 * 1024); } - continue; - } - /* All other streams have stream_buf_size in kB at this point */ - 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; + /* All other streams have stream_buf_size in kB here */ + 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; + } + /* convert from kB to bytes */ + cx->stream_buf_size[i] *= 1024; } - cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */ + CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, " + "%d bytes\n", i, cx->options.megabytes[i], + cx->stream_buffers[i], cx->stream_buf_size[i]); } cx->options.cardtype = cardtype[cx->instance]; diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index bed8bcc65411..5c78b014dbc0 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -120,11 +120,16 @@ /* Maximum firmware DMA buffers per stream */ #define CX18_MAX_FW_MDLS_PER_STREAM 63 +/* YUV buffer sizes in bytes to ensure integer # of frames per buffer */ +#define CX18_UNIT_ENC_YUV_BUFSIZE (720 * 32 * 3 / 2) /* bytes */ +#define CX18_625_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32) +#define CX18_525_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32) + /* 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 +#define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1) /* Default VBI bufsize based on standards supported by card tuner for now */ #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 54a6fd3f7af5..71ad2d1b4c2c 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -362,9 +362,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", + CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n", stream->dvb.dvb_adapter.num, stream->name, - stream->buffers, stream->buf_size/1024); + stream->buffers, stream->buf_size/1024, + (stream->buf_size * 100 / 1024) % 100); mutex_init(&dvb->feedlock); dvb->enabled = 1; diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index c1a49ecf9d98..98cbf001f8da 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -348,9 +348,11 @@ int cx18_stream_alloc(struct cx18_stream *s) if (s->buffers == 0) return 0; - CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers (%dkB total)\n", + CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers " + "(%d.%02d kB total)\n", s->name, s->buffers, s->buf_size, - s->buffers * s->buf_size / 1024); + s->buffers * s->buf_size / 1024, + (s->buffers * s->buf_size * 100 / 1024) % 100); if (((char __iomem *)&cx->scb->cpu_mdl[cx->free_mdl_idx + s->buffers] - (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) { diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 9f8adda6f261..7755937fc521 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -262,9 +262,11 @@ 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 x %d kB)\n", + CX18_INFO("Registered device video%d for %s " + "(%d x %d.%02d kB)\n", num, s->name, cx->stream_buffers[type], - cx->stream_buf_size[type]/1024); + cx->stream_buf_size[type] / 1024, + (cx->stream_buf_size[type] * 100 / 1024) % 100); break; case VFL_TYPE_RADIO: @@ -501,9 +503,23 @@ static void cx18_stream_configure_mdls(struct cx18_stream *s) { cx18_unload_queues(s); - /* For now */ - s->bufs_per_mdl = 1; - s->mdl_size = s->buf_size * s->bufs_per_mdl; + switch (s->type) { + case CX18_ENC_STREAM_TYPE_YUV: + /* + * Height should be a multiple of 32 lines. + * Set the MDL size to the exact size needed for one frame. + * Use enough buffers per MDL to cover the MDL size + */ + s->mdl_size = 720 * s->cx->params.height * 3 / 2; + s->bufs_per_mdl = s->mdl_size / s->buf_size; + if (s->mdl_size % s->buf_size) + s->bufs_per_mdl++; + break; + default: + s->bufs_per_mdl = 1; + s->mdl_size = s->buf_size * s->bufs_per_mdl; + break; + } cx18_load_queues(s); } From 1047a83844a4d894a068d94aca2d3efe54ac7a9c Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 10 Nov 2009 23:28:30 -0300 Subject: [PATCH 270/345] V4L/DVB (13431): cx18: Adjust an MDL's final buffer size to force encoder transfer size The encoder was not honoring the MDL size sent in DE_SET_MDL mailbox commands. This change adjusts the size of the last buffer in an MDL, as reported to the firmware, so that the encoder will send the exact amount of bytes we specify per MDL transfer. This eliminates tearing in YUV playback when using non-default YUV buffer sizes. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-queue.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 98cbf001f8da..f2d539f6bdf9 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -280,6 +280,7 @@ void cx18_load_queues(struct cx18_stream *s) struct cx18_buffer *buf; int mdl_id; int i; + u32 partial_buf_size; /* * Attach buffers to MDLs, give the MDLs ids, and add MDLs to q_free @@ -308,10 +309,24 @@ void cx18_load_queues(struct cx18_stream *s) &cx->scb->cpu_mdl[mdl_id + i].length); } - if (i == s->bufs_per_mdl) + if (i == s->bufs_per_mdl) { + /* + * The encoder doesn't honor s->mdl_size. So in the + * case of a non-integral number of buffers to meet + * mdl_size, we lie about the size of the last buffer + * in the MDL to get the encoder to really only send + * us mdl_size bytes per MDL transfer. + */ + partial_buf_size = s->mdl_size % s->buf_size; + if (partial_buf_size) { + cx18_writel(cx, partial_buf_size, + &cx->scb->cpu_mdl[mdl_id + i - 1].length); + } cx18_enqueue(s, mdl, &s->q_free); - else - cx18_push(s, mdl, &s->q_idle); /* not enough buffers */ + } else { + /* Not enough buffers for this MDL; we won't use it */ + cx18_push(s, mdl, &s->q_idle); + } mdl_id += i; } } From 127ce5f0adcca71eeeed2386ed4742ea6363a063 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 11 Nov 2009 00:22:57 -0300 Subject: [PATCH 271/345] V4L/DVB (13432): cx18: Adjust encoder VBI MDL size to be exactly frame's worth of VBI data Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 4 +--- drivers/media/video/cx18/cx18-driver.h | 1 - drivers/media/video/cx18/cx18-streams.c | 16 ++++++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 87a735f1ee9e..1a67ad5daad3 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -87,7 +87,6 @@ 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; @@ -128,7 +127,6 @@ 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); @@ -222,7 +220,7 @@ MODULE_PARM_DESC(enc_vbi_buffers, "\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"); + "\t\t\tDefault is computed from enc_vbi_buffers"); MODULE_PARM_DESC(enc_pcm_buffers, "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n" "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 5c78b014dbc0..fe767b82c9a8 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -130,7 +130,6 @@ #define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 #define CX18_DEFAULT_ENC_IDX_BUFSIZE 32 #define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1) -/* Default VBI bufsize based on standards supported by card tuner for now */ #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 /* i2c stuff */ diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 7755937fc521..c398651dd74c 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -515,6 +515,22 @@ static void cx18_stream_configure_mdls(struct cx18_stream *s) if (s->mdl_size % s->buf_size) s->bufs_per_mdl++; break; + case CX18_ENC_STREAM_TYPE_VBI: + s->bufs_per_mdl = 1; + if (cx18_raw_vbi(s->cx)) { + s->mdl_size = (s->cx->is_60hz ? 12 : 18) + * 2 * vbi_active_samples; + } else { + /* + * See comment in cx18_vbi_setup() below about the + * extra lines we capture in sliced VBI mode due to + * the lines on which EAV RP codes toggle. + */ + s->mdl_size = s->cx->is_60hz + ? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz + : (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz; + } + break; default: s->bufs_per_mdl = 1; s->mdl_size = s->buf_size * s->bufs_per_mdl; From ad689d54f979233c024c25a2221f4fd6f56543fe Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 11 Nov 2009 00:57:16 -0300 Subject: [PATCH 272/345] V4L/DVB (13433): cx18: Remove duplicate list traversal when processing incoming MDLs Update the incoming MDL's buffers' bytesused and sync the buffers for the cpu in one pass instead of two. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-queue.c | 27 ++++++++------------------- drivers/media/video/cx18/cx18-queue.h | 13 ------------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index f2d539f6bdf9..63304823cef5 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -100,8 +100,8 @@ struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) return mdl; } -static void _cx18_mdl_set_buf_bytesused(struct cx18_stream *s, - struct cx18_mdl *mdl) +static void _cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s, + struct cx18_mdl *mdl) { struct cx18_buffer *buf; u32 buf_size = s->buf_size; @@ -116,11 +116,12 @@ static void _cx18_mdl_set_buf_bytesused(struct cx18_stream *s, buf->bytesused = bytesused; bytesused = 0; } + cx18_buf_sync_for_cpu(s, buf); } } -static inline void cx18_mdl_set_buf_bytesused(struct cx18_stream *s, - struct cx18_mdl *mdl) +static inline void cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s, + struct cx18_mdl *mdl) { struct cx18_buffer *buf; @@ -129,8 +130,9 @@ static inline void cx18_mdl_set_buf_bytesused(struct cx18_stream *s, list); buf->bytesused = mdl->bytesused; buf->readpos = 0; + cx18_buf_sync_for_cpu(s, buf); } else { - _cx18_mdl_set_buf_bytesused(s, mdl); + _cx18_mdl_update_bufs_for_cpu(s, mdl); } } @@ -191,8 +193,7 @@ struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id, ret->bytesused = bytesused; ret->skipped = 0; /* 0'ed readpos, m_flags & curr_buf when mdl went on q_busy */ - cx18_mdl_set_buf_bytesused(s, ret); - cx18_mdl_sync_for_cpu(s, ret); + cx18_mdl_update_bufs_for_cpu(s, ret); if (s->type != CX18_ENC_STREAM_TYPE_TS) set_bit(CX18_F_M_NEED_SWAP, &ret->m_flags); } @@ -331,18 +332,6 @@ void cx18_load_queues(struct cx18_stream *s) } } -void _cx18_mdl_sync_for_cpu(struct cx18_stream *s, struct cx18_mdl *mdl) -{ - int dma = s->dma; - u32 buf_size = s->buf_size; - struct pci_dev *pci_dev = s->cx->pci_dev; - struct cx18_buffer *buf; - - list_for_each_entry(buf, &mdl->buf_list, list) - pci_dma_sync_single_for_cpu(pci_dev, buf->dma_handle, - buf_size, dma); -} - void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl) { int dma = s->dma; diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index 96747e5e7c3c..88a6d34ad3bb 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h @@ -33,19 +33,6 @@ static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s, s->buf_size, s->dma); } -void _cx18_mdl_sync_for_cpu(struct cx18_stream *s, struct cx18_mdl *mdl); - -static inline void cx18_mdl_sync_for_cpu(struct cx18_stream *s, - struct cx18_mdl *mdl) -{ - if (list_is_singular(&mdl->buf_list)) - cx18_buf_sync_for_cpu(s, list_first_entry(&mdl->buf_list, - struct cx18_buffer, - list)); - else - _cx18_mdl_sync_for_cpu(s, mdl); -} - static inline void cx18_buf_sync_for_device(struct cx18_stream *s, struct cx18_buffer *buf) { From 543ae45a7fc88c773358da326bc9e965b69aad06 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 11 Nov 2009 01:18:41 -0300 Subject: [PATCH 273/345] V4L/DVB (13434): cx18: Bump version number due to significant buffer handling changes. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index 45494b094e7f..9c0b5bb1b019 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h @@ -24,7 +24,7 @@ #define CX18_DRIVER_NAME "cx18" #define CX18_DRIVER_VERSION_MAJOR 1 -#define CX18_DRIVER_VERSION_MINOR 2 +#define CX18_DRIVER_VERSION_MINOR 3 #define CX18_DRIVER_VERSION_PATCHLEVEL 0 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) From 9018f6c3a22ef2d7413da17813312d781163d950 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Thu, 19 Nov 2009 22:35:38 -0300 Subject: [PATCH 274/345] V4L/DVB (13438): zr364xx: add support for Trust Powerc@m 910Z Tested-by: Enrique Dominguez Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/zr364xx.txt | 1 + drivers/media/video/zr364xx.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/video4linux/zr364xx.txt b/Documentation/video4linux/zr364xx.txt index 7f3d1955d214..d98e4d302977 100644 --- a/Documentation/video4linux/zr364xx.txt +++ b/Documentation/video4linux/zr364xx.txt @@ -66,3 +66,4 @@ Vendor Product Distributor Model 0x0a17 0x004e Pentax Optio 50 0x041e 0x405d Creative DiVi CAM 516 0x08ca 0x2102 Aiptek DV T300 +0x06d6 0x003d Trust Powerc@m 910Z diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 9aae011d92ab..2ef110b5221b 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -115,6 +115,7 @@ static struct usb_device_id device_table[] = { {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 }, + {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 }, {} /* Terminating entry */ }; From 23bff27aaf81f58a042ee2c9c58c1881635703c3 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Nov 2009 00:08:09 -0300 Subject: [PATCH 275/345] V4L/DVB (13440): ivtv: Update the cards definitions to add another AVerMedia M113 variant Add an AVerMedia M113 variant that was... Reported-by: Hiemanshu Sharma Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-cards.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index 4873b6ca5801..ec7883723d18 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -1025,13 +1025,15 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = { /* AVerMedia UltraTV 1500 MCE (newer non-cx88 version, M113 variant) card */ static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, + { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, /* NTSC */ + { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc01b }, /* PAL/SECAM */ { 0, 0, 0 } }; static const struct ivtv_card ivtv_card_aver_ultra1500mce = { .type = IVTV_CARD_AVER_ULTRA1500MCE, .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner", + .comment = "For non-NTSC tuners, use the pal= or secam= module options", .v4l2_capabilities = IVTV_CAP_ENCODER, .hw_video = IVTV_HW_CX25840, .hw_audio = IVTV_HW_CX25840, @@ -1058,6 +1060,7 @@ static const struct ivtv_card ivtv_card_aver_ultra1500mce = { .tuners = { /* The UltraTV 1500 MCE has a Philips FM1236 MK5 TV/FM tuner */ { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 }, + { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216MK5 }, }, .pci_list = ivtv_pci_aver_ultra1500mce, .i2c = &ivtv_i2c_std, From e45e8f5cee75b0559ce1ca7007b4963b91910fa8 Mon Sep 17 00:00:00 2001 From: "Aleksandr V. Piskunov" Date: Sat, 21 Nov 2009 00:47:25 -0300 Subject: [PATCH 276/345] V4L/DVB (13441): ivtv: Added FM radio support to Avermedia AVerTV MCE 116 Plus card Signed-off-by: Aleksandr V. Piskunov Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index ec7883723d18..e15c153b3012 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -965,6 +965,7 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = { { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, }, + .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, /* enable line-in */ .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, .xceive_pin = 10, From f412d36a8c9f8e40e057b71e80d534ac388e903e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Nov 2009 01:47:45 -0300 Subject: [PATCH 277/345] V4L/DVB (13442): ivtv: Add module parameter to adjust I2C SCL clock period per board Add a module parameter to adjust I2C SCL clock period per board. This allows some experimental fine tuning by end users to overcome quirky I2C device problems. Reported-by: "Aleksandr V. Piskunov" Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 19 +++++++++++++++++++ drivers/media/video/ivtv/ivtv-driver.h | 4 ++++ drivers/media/video/ivtv/ivtv-i2c.c | 7 +++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 7cdbc1a8f218..8330fb5c7eb3 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -91,10 +91,15 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }; static unsigned int cardtype_c = 1; static unsigned int tuner_c = 1; static unsigned int radio_c = 1; +static unsigned int i2c_clock_period_c = 1; static char pal[] = "---"; static char secam[] = "--"; static char ntsc[] = "-"; @@ -151,6 +156,7 @@ module_param(dec_vbi_buffers, int, 0644); module_param(tunertype, int, 0644); module_param(newi2c, int, 0644); +module_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644); MODULE_PARM_DESC(tuner, "Tuner type selection,\n" "\t\t\tsee tuner.h for values"); @@ -245,6 +251,10 @@ MODULE_PARM_DESC(newi2c, "Use new I2C implementation\n" "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" "\t\t\tDefault is autodetect"); +MODULE_PARM_DESC(i2c_clock_period, + "Period of SCL for the I2C bus controlled by the CX23415/6\n" + "\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n" + "\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD)); MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); @@ -600,6 +610,15 @@ static void ivtv_process_options(struct ivtv *itv) itv->options.cardtype = cardtype[itv->instance]; itv->options.tuner = tuner[itv->instance]; itv->options.radio = radio[itv->instance]; + + itv->options.i2c_clock_period = i2c_clock_period[itv->instance]; + if (itv->options.i2c_clock_period == -1) + itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD; + else if (itv->options.i2c_clock_period < 10) + itv->options.i2c_clock_period = 10; + else if (itv->options.i2c_clock_period > 4500) + itv->options.i2c_clock_period = 4500; + itv->options.newi2c = newi2c; if (tunertype < -1 || tunertype > 1) { IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 440f7328a7ed..2b3db90afb74 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -176,12 +176,16 @@ extern int ivtv_debug; #define IVTV_MAX_PGM_INDEX (400) +/* Default I2C SCL period in microseconds */ +#define IVTV_DEFAULT_I2C_CLOCK_PERIOD 20 + struct ivtv_options { int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */ int cardtype; /* force card type on load */ int tuner; /* set tuner on load */ int radio; /* enable/disable radio */ int newi2c; /* new I2C algorithm */ + int i2c_clock_period; /* period of SCL for I2C bus */ }; /* ivtv-specific mailbox template */ diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index b9c71e61f7d6..d4cc3365038e 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -564,13 +564,15 @@ static struct i2c_adapter ivtv_i2c_adap_template = { .owner = THIS_MODULE, }; +#define IVTV_ALGO_BIT_TIMEOUT (2) /* seconds */ + static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { .setsda = ivtv_setsda_old, .setscl = ivtv_setscl_old, .getsda = ivtv_getsda_old, .getscl = ivtv_getscl_old, - .udelay = 10, - .timeout = 200, + .udelay = IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2, /* microseconds */ + .timeout = IVTV_ALGO_BIT_TIMEOUT * HZ, /* jiffies */ }; static struct i2c_client ivtv_i2c_client_template = { @@ -602,6 +604,7 @@ int init_ivtv_i2c(struct ivtv *itv) memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template, sizeof(struct i2c_algo_bit_data)); } + itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2; itv->i2c_algo.data = itv; itv->i2c_adap.algo_data = &itv->i2c_algo; From bfbde8ee56d4a19e2d36a5a24b6dbfd298298bf1 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Nov 2009 11:41:33 -0300 Subject: [PATCH 278/345] V4L/DVB (13443): ivtv: Defer legacy I2C IR probing until after setup of known I2C devices This avoids collisions of legacy IR controller probing with known I2C devices in the card definitions in ivtv-cards.c. I2C driver modules for device listed explicitly in a card definition should always take precedence over a probe guessing where and IR controller may be. Reviewed-by: Jean Delvare Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 3 ++ drivers/media/video/ivtv/ivtv-i2c.c | 58 ++++++++++++++------------ drivers/media/video/ivtv/ivtv-i2c.h | 1 + 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 8330fb5c7eb3..d14f94e254bb 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -884,6 +884,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) itv->hw_flags |= device; } + /* probe for legacy IR controllers that aren't in card definitions */ + ivtv_i2c_new_ir_legacy(itv); + 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) diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index d4cc3365038e..71a8aa60b3fe 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -149,6 +149,36 @@ static const char * const hw_devicenames[] = { "gpio", }; +/* Instantiate the IR receiver device using probing -- undesirable */ +struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) +{ + struct i2c_board_info info; + /* + * The external IR receiver is at i2c address 0x34. + * The internal IR receiver is at i2c address 0x30. + * + * In theory, both can be fitted, and Hauppauge suggests an external + * overrides an internal. That's why we probe 0x1a (~0x34) first. CB + * + * Some of these addresses we probe may collide with other i2c address + * allocations, so this function must be called after all other i2c + * devices we care about are registered. + */ + const unsigned short addr_list[] = { + 0x1a, /* Hauppauge IR external - collides with WM8739 */ + 0x18, /* Hauppauge IR internal */ + 0x71, /* Hauppauge IR (PVR150) */ + 0x64, /* Pixelview IR */ + 0x30, /* KNC ONE IR */ + 0x6b, /* Adaptec IR */ + I2C_CLIENT_END + }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); +} + int ivtv_i2c_register(struct ivtv *itv, unsigned idx) { struct v4l2_subdev *sd; @@ -579,7 +609,7 @@ static struct i2c_client ivtv_i2c_client_template = { .name = "ivtv internal", }; -/* init + register i2c adapter + instantiate IR receiver */ +/* init + register i2c adapter */ int init_ivtv_i2c(struct ivtv *itv) { int retval; @@ -626,32 +656,6 @@ int init_ivtv_i2c(struct ivtv *itv) else retval = i2c_bit_add_bus(&itv->i2c_adap); - /* Instantiate the IR receiver device, if present */ - if (retval == 0) { - struct i2c_board_info info; - /* The external IR receiver is at i2c address 0x34 (0x35 for - reads). Future Hauppauge cards will have an internal - receiver at 0x30 (0x31 for reads). In theory, both can be - fitted, and Hauppauge suggest an external overrides an - internal. - - That's why we probe 0x1a (~0x34) first. CB - */ - const unsigned short addr_list[] = { - 0x1a, /* Hauppauge IR external */ - 0x18, /* Hauppauge IR internal */ - 0x71, /* Hauppauge IR (PVR150) */ - 0x64, /* Pixelview IR */ - 0x30, /* KNC ONE IR */ - 0x6b, /* Adaptec IR */ - I2C_CLIENT_END - }; - - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); - } - return retval; } diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h index 396928a06a54..9332920ca4ff 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ b/drivers/media/video/ivtv/ivtv-i2c.h @@ -21,6 +21,7 @@ #ifndef IVTV_I2C_H #define IVTV_I2C_H +struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv); int ivtv_i2c_register(struct ivtv *itv, unsigned idx); struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw); From ad2fe2d48812029b0b674594f297d0723f7c6e8f Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Nov 2009 12:52:34 -0300 Subject: [PATCH 279/345] V4L/DVB (13444): ivtv: Add explicit IR controller initialization for the AVerTV M116 Add explicit support for the AVerTV M116 for use with the ir-kbd-i2c module. This also eases future support for other AVerMedia ivtv boards with the same microcontroller program at I2C address 0x40. This is a reworked version of an earlier patch that was... Reviewed-by: Jean Delvare Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-cards.c | 3 +- drivers/media/video/ivtv/ivtv-cards.h | 36 +++++++++++---------- drivers/media/video/ivtv/ivtv-driver.h | 2 ++ drivers/media/video/ivtv/ivtv-i2c.c | 45 +++++++++++++++++++++++--- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index e15c153b3012..e98ecadfde29 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -955,7 +955,8 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = { .hw_video = IVTV_HW_CX25840, .hw_audio = IVTV_HW_CX25840, .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739, + .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739 | + IVTV_HW_I2C_IR_RX_AVER, .video_inputs = { { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index e99a0a255578..1ac09ebaa2f0 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h @@ -87,25 +87,27 @@ #define IVTV_PCI_ID_GOTVIEW1 0xffac #define IVTV_PCI_ID_GOTVIEW2 0xffad -/* hardware flags, no gaps allowed, IVTV_HW_GPIO must always be last */ -#define IVTV_HW_CX25840 (1 << 0) -#define IVTV_HW_SAA7115 (1 << 1) -#define IVTV_HW_SAA7127 (1 << 2) -#define IVTV_HW_MSP34XX (1 << 3) -#define IVTV_HW_TUNER (1 << 4) -#define IVTV_HW_WM8775 (1 << 5) -#define IVTV_HW_CS53L32A (1 << 6) -#define IVTV_HW_TVEEPROM (1 << 7) -#define IVTV_HW_SAA7114 (1 << 8) -#define IVTV_HW_UPD64031A (1 << 9) -#define IVTV_HW_UPD6408X (1 << 10) -#define IVTV_HW_SAA717X (1 << 11) -#define IVTV_HW_WM8739 (1 << 12) -#define IVTV_HW_VP27SMPX (1 << 13) -#define IVTV_HW_M52790 (1 << 14) -#define IVTV_HW_GPIO (1 << 15) +/* hardware flags, no gaps allowed */ +#define IVTV_HW_CX25840 (1 << 0) +#define IVTV_HW_SAA7115 (1 << 1) +#define IVTV_HW_SAA7127 (1 << 2) +#define IVTV_HW_MSP34XX (1 << 3) +#define IVTV_HW_TUNER (1 << 4) +#define IVTV_HW_WM8775 (1 << 5) +#define IVTV_HW_CS53L32A (1 << 6) +#define IVTV_HW_TVEEPROM (1 << 7) +#define IVTV_HW_SAA7114 (1 << 8) +#define IVTV_HW_UPD64031A (1 << 9) +#define IVTV_HW_UPD6408X (1 << 10) +#define IVTV_HW_SAA717X (1 << 11) +#define IVTV_HW_WM8739 (1 << 12) +#define IVTV_HW_VP27SMPX (1 << 13) +#define IVTV_HW_M52790 (1 << 14) +#define IVTV_HW_GPIO (1 << 15) +#define IVTV_HW_I2C_IR_RX_AVER (1 << 16) #define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) +#define IVTV_HW_IR_ANY (IVTV_HW_I2C_IR_RX_AVER) /* video inputs */ #define IVTV_CARD_INPUT_VID_TUNER 1 diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 2b3db90afb74..e4816da6482b 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -64,6 +64,7 @@ #include #include #include +#include #include @@ -681,6 +682,7 @@ struct ivtv { int i2c_state; /* i2c bit state */ struct mutex i2c_bus_lock; /* lock i2c bus */ + struct IR_i2c_init_data ir_i2c_init_data; /* Program Index information */ u32 pgm_info_offset; /* start of pgm info in encoder memory */ diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 71a8aa60b3fe..6838683cdaae 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -88,6 +88,7 @@ #define IVTV_UPD64083_I2C_ADDR 0x5c #define IVTV_VP27SMPX_I2C_ADDR 0x5b #define IVTV_M52790_I2C_ADDR 0x48 +#define IVTV_AVERMEDIA_IR_RX_I2C_ADDR 0x40 /* This array should match the IVTV_HW_ defines */ static const u8 hw_addrs[] = { @@ -106,7 +107,8 @@ static const u8 hw_addrs[] = { IVTV_WM8739_I2C_ADDR, IVTV_VP27SMPX_I2C_ADDR, IVTV_M52790_I2C_ADDR, - 0 /* IVTV_HW_GPIO dummy driver ID */ + 0, /* IVTV_HW_GPIO dummy driver ID */ + IVTV_AVERMEDIA_IR_RX_I2C_ADDR /* IVTV_HW_I2C_IR_RX_AVER */ }; /* This array should match the IVTV_HW_ defines */ @@ -126,7 +128,8 @@ static const char *hw_modules[] = { "wm8739", "vp27smpx", "m52790", - NULL + NULL, + NULL /* IVTV_HW_I2C_IR_RX_AVER */ }; /* This array should match the IVTV_HW_ defines */ @@ -147,8 +150,34 @@ static const char * const hw_devicenames[] = { "vp27smpx", "m52790", "gpio", + "ir_video", /* IVTV_HW_I2C_IR_RX_AVER */ }; +static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) +{ + struct i2c_board_info info; + struct i2c_adapter *adap = &itv->i2c_adap; + struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data; + unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; + + /* Our default information for ir-kbd-i2c.c to use */ + switch (hw) { + case IVTV_HW_I2C_IR_RX_AVER: + init_data->ir_codes = &ir_codes_avermedia_cardbus_table; + init_data->internal_get_key_func = + IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; + init_data->type = IR_TYPE_OTHER; + init_data->name = "AVerMedia AVerTV card"; + break; + } + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.platform_data = init_data; + strlcpy(info.type, type, I2C_NAME_SIZE); + + return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0; +} + /* Instantiate the IR receiver device using probing -- undesirable */ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) { @@ -208,8 +237,15 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) sd->grp_id = 1 << idx; return sd ? 0 : -1; } + + if (hw & IVTV_HW_IR_ANY) + return ivtv_i2c_new_ir(itv, hw, type, hw_addrs[idx]); + + /* Is it not an I2C device or one we do not wish to register? */ if (!hw_addrs[idx]) return -1; + + /* It's an I2C device other than an analog tuner or IR chip */ if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, mod, type, 0, I2C_ADDRS(hw_addrs[idx])); @@ -617,11 +653,10 @@ int init_ivtv_i2c(struct ivtv *itv) IVTV_DEBUG_I2C("i2c init\n"); /* Sanity checks for the I2C hardware arrays. They must be the - * same size and GPIO must be the last entry. + * same size. */ 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))) { + ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_modules)) { IVTV_ERR("Mismatched I2C hardware arrays\n"); return -ENODEV; } From 8352619043a04785b8d20e438629b14e556fffce Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Nov 2009 13:39:28 -0300 Subject: [PATCH 280/345] V4L/DVB (13445): cx18: Use per cx18 instance init data for ir-kbd-i2c instead of const data This change creates per cx18 instances of IR_i2c_init_data for handing over initialization data to ir-kbd-i2c, since that module wants non-const data even though it never modifies the data. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-cards.h | 3 +++ drivers/media/video/cx18/cx18-driver.h | 3 +++ drivers/media/video/cx18/cx18-i2c.c | 25 ++++++++++--------------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index 444e3c7c563e..af3d71607dc9 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h @@ -34,6 +34,9 @@ #define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \ CX18_HW_Z8F0811_IR_TX_HAUP) +#define CX18_HW_IR_ANY (CX18_HW_Z8F0811_IR_RX_HAUP | \ + CX18_HW_Z8F0811_IR_TX_HAUP) + /* video inputs */ #define CX18_CARD_INPUT_VID_TUNER 1 #define CX18_CARD_INPUT_SVIDEO1 2 diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index fe767b82c9a8..e3f7911a7385 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -50,6 +50,7 @@ #include #include #include +#include #include "cx18-mailbox.h" #include "cx18-av-core.h" #include "cx23418.h" @@ -606,6 +607,8 @@ struct cx18 { struct i2c_algo_bit_data i2c_algo[2]; struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2]; + struct IR_i2c_init_data ir_i2c_init_data; + /* gpio */ u32 gpio_dir; u32 gpio_val; diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 2477461e84d7..eecf29af916c 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -28,7 +28,6 @@ #include "cx18-gpio.h" #include "cx18-i2c.h" #include "cx18-irq.h" -#include #define CX18_REG_I2C_1_WR 0xf15000 #define CX18_REG_I2C_1_RD 0xf15008 @@ -97,17 +96,11 @@ static const char * const hw_devicenames[] = { "ir_rx_z8f0811_haup", }; -static const struct IR_i2c_init_data z8f0811_ir_init_data = { - .ir_codes = &ir_codes_hauppauge_new_table, - .internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR, - .type = IR_TYPE_RC5, - .name = "CX23418 Z8F0811 Hauppauge", -}; - -static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, - u8 addr) +static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, + const char *type, u8 addr) { struct i2c_board_info info; + struct IR_i2c_init_data *init_data = &cx->ir_i2c_init_data; unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; memset(&info, 0, sizeof(struct i2c_board_info)); @@ -116,9 +109,11 @@ static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { case CX18_HW_Z8F0811_IR_RX_HAUP: - info.platform_data = (void *) &z8f0811_ir_init_data; - break; - default: + init_data->ir_codes = &ir_codes_hauppauge_new_table; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = IR_TYPE_RC5; + init_data->name = cx->card_name; + info.platform_data = init_data; break; } @@ -154,8 +149,8 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) return sd != NULL ? 0 : -1; } - if (hw & CX18_HW_Z8F0811_IR_HAUP) - return cx18_i2c_new_ir(adap, hw, type, hw_addrs[idx]); + if (hw & CX18_HW_IR_ANY) + return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]); /* Is it not an I2C device or one we do not wish to register? */ if (!hw_addrs[idx]) From 7ce5c41db3672c8b4419b16d9b3ac1ccf11a1445 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Nov 2009 16:19:27 -0300 Subject: [PATCH 281/345] V4L/DVB (13446): ivtv: Add more explicit detection of known IR devices for Hauppauge cards Avoid legacy IR I2C probing for PVR-150, PVR-500, and PVR-350 cards. This still probes, but restricts the possbile addresses probed per card. Also removed legacy probe addresses for the KNC and PixelView cards which are not supported by ivtv as far as I know. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-cards.c | 7 +++- drivers/media/video/ivtv/ivtv-cards.h | 51 ++++++++++++++++--------- drivers/media/video/ivtv/ivtv-driver.c | 3 +- drivers/media/video/ivtv/ivtv-i2c.c | 53 +++++++++++++++++++++++--- 4 files changed, 88 insertions(+), 26 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index e98ecadfde29..79d0fe4990d6 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -136,7 +136,8 @@ static const struct ivtv_card ivtv_card_pvr350 = { .hw_audio = IVTV_HW_MSP34XX, .hw_audio_ctrl = IVTV_HW_MSP34XX, .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | - IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER, + IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER | + IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT, .video_inputs = { { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, @@ -199,7 +200,9 @@ static const struct ivtv_card ivtv_card_pvr150 = { .hw_audio_ctrl = IVTV_HW_CX25840, .hw_muxer = IVTV_HW_WM8775, .hw_all = IVTV_HW_WM8775 | IVTV_HW_CX25840 | - IVTV_HW_TVEEPROM | IVTV_HW_TUNER, + IVTV_HW_TVEEPROM | IVTV_HW_TUNER | + IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT | + IVTV_HW_Z8F0811_IR_HAUP, .video_inputs = { { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE7 }, { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO1 }, diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 1ac09ebaa2f0..6148827ec885 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h @@ -88,26 +88,41 @@ #define IVTV_PCI_ID_GOTVIEW2 0xffad /* hardware flags, no gaps allowed */ -#define IVTV_HW_CX25840 (1 << 0) -#define IVTV_HW_SAA7115 (1 << 1) -#define IVTV_HW_SAA7127 (1 << 2) -#define IVTV_HW_MSP34XX (1 << 3) -#define IVTV_HW_TUNER (1 << 4) -#define IVTV_HW_WM8775 (1 << 5) -#define IVTV_HW_CS53L32A (1 << 6) -#define IVTV_HW_TVEEPROM (1 << 7) -#define IVTV_HW_SAA7114 (1 << 8) -#define IVTV_HW_UPD64031A (1 << 9) -#define IVTV_HW_UPD6408X (1 << 10) -#define IVTV_HW_SAA717X (1 << 11) -#define IVTV_HW_WM8739 (1 << 12) -#define IVTV_HW_VP27SMPX (1 << 13) -#define IVTV_HW_M52790 (1 << 14) -#define IVTV_HW_GPIO (1 << 15) -#define IVTV_HW_I2C_IR_RX_AVER (1 << 16) +#define IVTV_HW_CX25840 (1 << 0) +#define IVTV_HW_SAA7115 (1 << 1) +#define IVTV_HW_SAA7127 (1 << 2) +#define IVTV_HW_MSP34XX (1 << 3) +#define IVTV_HW_TUNER (1 << 4) +#define IVTV_HW_WM8775 (1 << 5) +#define IVTV_HW_CS53L32A (1 << 6) +#define IVTV_HW_TVEEPROM (1 << 7) +#define IVTV_HW_SAA7114 (1 << 8) +#define IVTV_HW_UPD64031A (1 << 9) +#define IVTV_HW_UPD6408X (1 << 10) +#define IVTV_HW_SAA717X (1 << 11) +#define IVTV_HW_WM8739 (1 << 12) +#define IVTV_HW_VP27SMPX (1 << 13) +#define IVTV_HW_M52790 (1 << 14) +#define IVTV_HW_GPIO (1 << 15) +#define IVTV_HW_I2C_IR_RX_AVER (1 << 16) +#define IVTV_HW_I2C_IR_RX_HAUP_EXT (1 << 17) /* External before internal */ +#define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18) +#define IVTV_HW_Z8F0811_IR_TX_HAUP (1 << 19) +#define IVTV_HW_Z8F0811_IR_RX_HAUP (1 << 20) + +#define IVTV_HW_Z8F0811_IR_HAUP (IVTV_HW_Z8F0811_IR_RX_HAUP | \ + IVTV_HW_Z8F0811_IR_TX_HAUP) #define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) -#define IVTV_HW_IR_ANY (IVTV_HW_I2C_IR_RX_AVER) + +#define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \ + IVTV_HW_I2C_IR_RX_HAUP_EXT | \ + IVTV_HW_I2C_IR_RX_HAUP_INT | \ + IVTV_HW_Z8F0811_IR_RX_HAUP) + +#define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP) + +#define IVTV_HW_IR_ANY (IVTV_HW_IR_RX_ANY | IVTV_HW_IR_TX_ANY) /* video inputs */ #define IVTV_CARD_INPUT_VID_TUNER 1 diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index d14f94e254bb..347c3344f56d 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -885,7 +885,8 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) } /* probe for legacy IR controllers that aren't in card definitions */ - ivtv_i2c_new_ir_legacy(itv); + if ((itv->hw_flags & IVTV_HW_IR_ANY) == 0) + ivtv_i2c_new_ir_legacy(itv); if (itv->card->hw_all & IVTV_HW_CX25840) itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840); diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 6838683cdaae..2ee03c2a1b58 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -89,6 +89,10 @@ #define IVTV_VP27SMPX_I2C_ADDR 0x5b #define IVTV_M52790_I2C_ADDR 0x48 #define IVTV_AVERMEDIA_IR_RX_I2C_ADDR 0x40 +#define IVTV_HAUP_EXT_IR_RX_I2C_ADDR 0x1a +#define IVTV_HAUP_INT_IR_RX_I2C_ADDR 0x18 +#define IVTV_Z8F0811_IR_TX_I2C_ADDR 0x70 +#define IVTV_Z8F0811_IR_RX_I2C_ADDR 0x71 /* This array should match the IVTV_HW_ defines */ static const u8 hw_addrs[] = { @@ -108,7 +112,11 @@ static const u8 hw_addrs[] = { IVTV_VP27SMPX_I2C_ADDR, IVTV_M52790_I2C_ADDR, 0, /* IVTV_HW_GPIO dummy driver ID */ - IVTV_AVERMEDIA_IR_RX_I2C_ADDR /* IVTV_HW_I2C_IR_RX_AVER */ + IVTV_AVERMEDIA_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_AVER */ + IVTV_HAUP_EXT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ + IVTV_HAUP_INT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ + IVTV_Z8F0811_IR_TX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ + IVTV_Z8F0811_IR_RX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ }; /* This array should match the IVTV_HW_ defines */ @@ -129,7 +137,11 @@ static const char *hw_modules[] = { "vp27smpx", "m52790", NULL, - NULL /* IVTV_HW_I2C_IR_RX_AVER */ + NULL, /* IVTV_HW_I2C_IR_RX_AVER */ + NULL, /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ + NULL, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ + NULL, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ + NULL, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ }; /* This array should match the IVTV_HW_ defines */ @@ -150,7 +162,11 @@ static const char * const hw_devicenames[] = { "vp27smpx", "m52790", "gpio", - "ir_video", /* IVTV_HW_I2C_IR_RX_AVER */ + "ir_video", /* IVTV_HW_I2C_IR_RX_AVER */ + "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ + "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_INT */ + "ir_tx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_TX_HAUP */ + "ir_rx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_RX_HAUP */ }; static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) @@ -160,6 +176,20 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data; unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; + /* Only allow one IR transmitter to be registered per board */ + if (hw & IVTV_HW_IR_TX_ANY) { + if (itv->hw_flags & IVTV_HW_IR_TX_ANY) + return -1; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, type, I2C_NAME_SIZE); + return i2c_new_probed_device(adap, &info, addr_list) == NULL + ? -1 : 0; + } + + /* Only allow one IR receiver to be registered per board */ + if (itv->hw_flags & IVTV_HW_IR_RX_ANY) + return -1; + /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { case IVTV_HW_I2C_IR_RX_AVER: @@ -169,6 +199,21 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) init_data->type = IR_TYPE_OTHER; init_data->name = "AVerMedia AVerTV card"; break; + case IVTV_HW_I2C_IR_RX_HAUP_EXT: + case IVTV_HW_I2C_IR_RX_HAUP_INT: + /* Default to old black remote */ + init_data->ir_codes = &ir_codes_rc5_tv_table; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; + init_data->type = IR_TYPE_RC5; + init_data->name = itv->card_name; + break; + case IVTV_HW_Z8F0811_IR_RX_HAUP: + /* Default to grey remote */ + init_data->ir_codes = &ir_codes_hauppauge_new_table; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = IR_TYPE_RC5; + init_data->name = itv->card_name; + break; } memset(&info, 0, sizeof(struct i2c_board_info)); @@ -197,8 +242,6 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) 0x1a, /* Hauppauge IR external - collides with WM8739 */ 0x18, /* Hauppauge IR internal */ 0x71, /* Hauppauge IR (PVR150) */ - 0x64, /* Pixelview IR */ - 0x30, /* KNC ONE IR */ 0x6b, /* Adaptec IR */ I2C_CLIENT_END }; From 4af85668588e249d98957a41030c3a2d2acc87e5 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 12 Nov 2009 15:59:27 -0300 Subject: [PATCH 282/345] V4L/DVB (13448): gspca - main: Add a gspca flag for inactive controls. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 3 +++ drivers/media/video/gspca/gspca.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 6915db2d36db..369eddd352c3 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1158,10 +1158,13 @@ static int vidioc_queryctrl(struct file *file, void *priv, } } else { ctrls = get_ctrl(gspca_dev, id); + i = ctrls - gspca_dev->sd_desc->ctrls; } if (ctrls == NULL) return -EINVAL; memcpy(q_ctrl, ctrls, sizeof *q_ctrl); + if (gspca_dev->ctrl_inac & (1 << i)) + q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; return 0; } diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 1d761d7cefc6..d59a684056ca 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -143,6 +143,7 @@ struct gspca_dev { struct cam cam; /* device information */ const struct sd_desc *sd_desc; /* subdriver description */ unsigned ctrl_dis; /* disabled controls (bit map) */ + unsigned ctrl_inac; /* inactive controls (bit map) */ #define USB_BUF_SZ 64 __u8 *usb_buf; /* buffer for USB exchanges */ From 2d19a2c1186d86e38b51ef59e4b9678f8ad7acf4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 12 Nov 2009 16:15:44 -0300 Subject: [PATCH 283/345] V4L/DVB (13449): gspca - ov534: The AWB control works only when autogain is set. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 34 ++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index f2f844af54c0..26d98b1312e0 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -101,7 +101,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls_ov772x[] = { - { + { /* 0 */ { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -115,7 +115,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setbrightness, .get = sd_getbrightness, }, - { + { /* 1 */ { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -129,7 +129,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setcontrast, .get = sd_getcontrast, }, - { + { /* 2 */ { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -143,7 +143,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setgain, .get = sd_getgain, }, - { + { /* 3 */ { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -157,7 +157,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setexposure, .get = sd_getexposure, }, - { + { /* 4 */ { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -171,7 +171,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setredblc, .get = sd_getredblc, }, - { + { /* 5 */ { .id = V4L2_CID_BLUE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -185,7 +185,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setblueblc, .get = sd_getblueblc, }, - { + { /* 6 */ { .id = V4L2_CID_HUE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -199,7 +199,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_sethue, .get = sd_gethue, }, - { + { /* 7 */ { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -213,7 +213,8 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setautogain, .get = sd_getautogain, }, - { +#define AWB_IDX 8 + { /* 8 */ { .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -227,7 +228,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setawb, .get = sd_getawb, }, - { + { /* 9 */ { .id = V4L2_CID_SHARPNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -241,7 +242,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_setsharpness, .get = sd_getsharpness, }, - { + { /* 10 */ { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -255,7 +256,7 @@ static struct ctrl sd_ctrls_ov772x[] = { .set = sd_sethflip, .get = sd_gethflip, }, - { + { /* 11 */ { .id = V4L2_CID_VFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -1237,6 +1238,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->hue = HUE_DEF; #if AUTOGAIN_DEF != 0 sd->autogain = AUTOGAIN_DEF; +#else + gspca_dev->ctrl_inac |= (1 << AWB_IDX); #endif #if AWB_DEF != 0 sd->awb = AWB_DEF @@ -1606,6 +1609,13 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->autogain = val; + + /* the auto white balance control works only when auto gain is set */ + if (val) + gspca_dev->ctrl_inac &= ~(1 << AWB_IDX); + else + gspca_dev->ctrl_inac |= (1 << AWB_IDX); + if (gspca_dev->streaming) setautogain(gspca_dev); return 0; From 8157852f73f961b28d495bfa8374263d293b106d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 13 Nov 2009 07:15:08 -0300 Subject: [PATCH 284/345] V4L/DVB (13450): gspca - main: Clear the urb status before resubmit. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 369eddd352c3..08433f77245a 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -139,6 +139,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, return; #endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); + urb->status = 0; goto resubmit; } pkt_scan = gspca_dev->sd_desc->pkt_scan; @@ -214,15 +215,13 @@ static void bulk_irq(struct urb *urb) break; case -ESHUTDOWN: return; /* disconnection */ - case -ECONNRESET: - urb->status = 0; - break; default: #ifdef CONFIG_PM if (gspca_dev->frozen) return; #endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); + urb->status = 0; goto resubmit; } From 3ec342f25004c87c0d94de1bc1b5399685d58ad8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 13 Nov 2009 07:38:16 -0300 Subject: [PATCH 285/345] V4L/DVB (13451): gspca - main: Memorize the current frame buffer. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 21 +++++++++++---------- drivers/media/video/gspca/gspca.h | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 08433f77245a..31ec5aa44910 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -126,7 +126,6 @@ EXPORT_SYMBOL(gspca_get_i_frame); static void fill_frame(struct gspca_dev *gspca_dev, struct urb *urb) { - struct gspca_frame *frame; u8 *data; /* address of data in the iso message */ int i, len, st; cam_pkt_op pkt_scan; @@ -146,8 +145,8 @@ static void fill_frame(struct gspca_dev *gspca_dev, for (i = 0; i < urb->number_of_packets; i++) { /* check the availability of the frame buffer */ - frame = gspca_get_i_frame(gspca_dev); - if (!frame) { + if ((gspca_dev->cur_frame->v4l2_buf.flags & BUF_ALL_FLAGS) + != V4L2_BUF_FLAG_QUEUED) { gspca_dev->last_packet_type = DISCARD_PACKET; break; } @@ -173,7 +172,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, i, urb->iso_frame_desc[i].offset, len); data = (u8 *) urb->transfer_buffer + urb->iso_frame_desc[i].offset; - pkt_scan(gspca_dev, frame, data, len); + pkt_scan(gspca_dev, gspca_dev->cur_frame, data, len); } resubmit: @@ -204,7 +203,6 @@ static void isoc_irq(struct urb *urb) static void bulk_irq(struct urb *urb) { struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; - struct gspca_frame *frame; int st; PDEBUG(D_PACK, "bulk irq"); @@ -226,13 +224,13 @@ static void bulk_irq(struct urb *urb) } /* check the availability of the frame buffer */ - frame = gspca_get_i_frame(gspca_dev); - if (!frame) { + if ((gspca_dev->cur_frame->v4l2_buf.flags & BUF_ALL_FLAGS) + != V4L2_BUF_FLAG_QUEUED) { gspca_dev->last_packet_type = DISCARD_PACKET; } else { PDEBUG(D_PACK, "packet l:%d", urb->actual_length); gspca_dev->sd_desc->pkt_scan(gspca_dev, - frame, + gspca_dev->frame, urb->transfer_buffer, urb->actual_length); } @@ -260,13 +258,15 @@ static void bulk_irq(struct urb *urb) */ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, enum gspca_packet_type packet_type, - struct gspca_frame *frame, + struct gspca_frame *dummy, const __u8 *data, int len) { + struct gspca_frame *frame; int i, j; PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len); + frame = gspca_dev->cur_frame; /* when start of a new frame, if the current frame buffer * is not queued, discard the whole frame */ @@ -315,7 +315,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, i, gspca_dev->fr_o); j = gspca_dev->fr_queue[i]; - frame = &gspca_dev->frame[j]; + gspca_dev->cur_frame = frame = &gspca_dev->frame[j]; } return frame; } @@ -398,6 +398,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev, frame->v4l2_buf.m.offset = i * frsz; } gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; + gspca_dev->cur_frame = &gspca_dev->frame[0]; gspca_dev->last_packet_type = DISCARD_PACKET; gspca_dev->sequence = 0; return 0; diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index d59a684056ca..59078bbf472c 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -151,6 +151,7 @@ struct gspca_dev { __u8 *frbuf; /* buffer for nframes */ struct gspca_frame frame[GSPCA_MAX_FRAMES]; + struct gspca_frame *cur_frame; /* frame beeing filled */ __u32 frsz; /* frame size */ char nframes; /* number of frames */ char fr_i; /* frame being filled */ From d131c3c9e136cb5a817094c3dc4b7261b495cd6e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 13 Nov 2009 08:16:02 -0300 Subject: [PATCH 286/345] V4L/DVB (13452): gspca - main: Let the driver scan URB packets when no frame buffer. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 35 +++++++++++-------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 31ec5aa44910..68ba535300f7 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -144,13 +144,6 @@ static void fill_frame(struct gspca_dev *gspca_dev, pkt_scan = gspca_dev->sd_desc->pkt_scan; for (i = 0; i < urb->number_of_packets; i++) { - /* check the availability of the frame buffer */ - if ((gspca_dev->cur_frame->v4l2_buf.flags & BUF_ALL_FLAGS) - != V4L2_BUF_FLAG_QUEUED) { - gspca_dev->last_packet_type = DISCARD_PACKET; - break; - } - /* check the packet status and length */ len = urb->iso_frame_desc[i].actual_length; if (len == 0) { @@ -223,17 +216,11 @@ static void bulk_irq(struct urb *urb) goto resubmit; } - /* check the availability of the frame buffer */ - if ((gspca_dev->cur_frame->v4l2_buf.flags & BUF_ALL_FLAGS) - != V4L2_BUF_FLAG_QUEUED) { - gspca_dev->last_packet_type = DISCARD_PACKET; - } else { - PDEBUG(D_PACK, "packet l:%d", urb->actual_length); - gspca_dev->sd_desc->pkt_scan(gspca_dev, - gspca_dev->frame, - urb->transfer_buffer, - urb->actual_length); - } + PDEBUG(D_PACK, "packet l:%d", urb->actual_length); + gspca_dev->sd_desc->pkt_scan(gspca_dev, + gspca_dev->frame, + urb->transfer_buffer, + urb->actual_length); resubmit: /* resubmit the URB */ @@ -266,16 +253,18 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, int i, j; PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len); + + /* check the availability of the frame buffer */ frame = gspca_dev->cur_frame; + if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) + != V4L2_BUF_FLAG_QUEUED) { + gspca_dev->last_packet_type = DISCARD_PACKET; + return frame; + } /* when start of a new frame, if the current frame buffer * is not queued, discard the whole frame */ if (packet_type == FIRST_PACKET) { - if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) - != V4L2_BUF_FLAG_QUEUED) { - gspca_dev->last_packet_type = DISCARD_PACKET; - return frame; - } frame->data_end = frame->data; jiffies_to_timeval(get_jiffies_64(), &frame->v4l2_buf.timestamp); From 76dd272b56cd1c7fa013ef5d7eb28c4d319e322b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 13 Nov 2009 09:21:03 -0300 Subject: [PATCH 287/345] V4L/DVB (13453): gspca - all subdrivers: Remove the unused frame ptr from pkt_scan(). Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/conex.c | 12 ++--- drivers/media/video/gspca/etoms.c | 10 ++-- drivers/media/video/gspca/finepix.c | 23 +++------ drivers/media/video/gspca/gl860/gl860.c | 10 ++-- drivers/media/video/gspca/gspca.c | 20 ++++---- drivers/media/video/gspca/gspca.h | 12 ++--- drivers/media/video/gspca/jeilinj.c | 21 +++----- drivers/media/video/gspca/m5602/m5602_core.c | 25 +++++---- drivers/media/video/gspca/mars.c | 11 ++-- drivers/media/video/gspca/mr97310a.c | 11 ++-- drivers/media/video/gspca/ov519.c | 54 +++++++++----------- drivers/media/video/gspca/ov534.c | 21 ++++---- drivers/media/video/gspca/pac207.c | 11 ++-- drivers/media/video/gspca/pac7302.c | 22 +++++--- drivers/media/video/gspca/pac7311.c | 22 +++++--- drivers/media/video/gspca/sn9c20x.c | 11 ++-- drivers/media/video/gspca/sonixb.c | 21 +++++--- drivers/media/video/gspca/sonixj.c | 7 ++- drivers/media/video/gspca/spca500.c | 11 ++-- drivers/media/video/gspca/spca501.c | 14 ++--- drivers/media/video/gspca/spca505.c | 10 ++-- drivers/media/video/gspca/spca506.c | 12 ++--- drivers/media/video/gspca/spca508.c | 10 ++-- drivers/media/video/gspca/spca561.c | 14 ++--- drivers/media/video/gspca/sq905.c | 21 +++----- drivers/media/video/gspca/sq905c.c | 12 ++--- drivers/media/video/gspca/stk014.c | 11 ++-- drivers/media/video/gspca/stv0680.c | 7 ++- drivers/media/video/gspca/stv06xx/stv06xx.c | 11 ++-- drivers/media/video/gspca/sunplus.c | 11 ++-- drivers/media/video/gspca/t613.c | 7 ++- drivers/media/video/gspca/tv8532.c | 7 ++- drivers/media/video/gspca/vc032x.c | 21 ++++---- drivers/media/video/gspca/w996Xcf.c | 13 +++-- drivers/media/video/gspca/zc3xx.c | 11 ++-- 35 files changed, 240 insertions(+), 287 deletions(-) diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index eca003566ae3..2f0b8d621e00 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -888,8 +888,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -897,16 +896,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - sd->jpeg_hdr, JPEG_HDR_SZ); + gspca_frame_add(gspca_dev, FIRST_PACKET, + sd->jpeg_hdr, JPEG_HDR_SZ); data += 2; len -= 2; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static void setbrightness(struct gspca_dev*gspca_dev) diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index c1461e63647f..9de86419ae1e 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -752,8 +752,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) #undef LIMIT static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { int seqframe; @@ -767,14 +766,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data[2], data[3], data[4], data[5]); data += 30; /* don't change datalength as the chips provided it */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); return; } if (len) { data += 8; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } else { /* Drop Packet */ gspca_dev->last_packet_type = DISCARD_PACKET; } diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index 480ec5c87d0e..5d90e7448579 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -82,7 +82,6 @@ static void dostream(struct work_struct *work) struct gspca_dev *gspca_dev = &dev->gspca_dev; struct urb *urb = gspca_dev->urb[0]; u8 *data = urb->transfer_buffer; - struct gspca_frame *frame; int ret = 0; int len; @@ -118,10 +117,6 @@ static void dostream(struct work_struct *work) } if (!gspca_dev->present || !gspca_dev->streaming) goto out; - frame = gspca_get_i_frame(&dev->gspca_dev); - if (frame == NULL) - gspca_dev->last_packet_type = DISCARD_PACKET; - if (len < FPIX_MAX_TRANSFER || (data[len - 2] == 0xff && data[len - 1] == 0xd9)) { @@ -132,21 +127,17 @@ static void dostream(struct work_struct *work) * but there's nothing we can do. We also end * here if the the jpeg ends right at the end * of the frame. */ - if (frame) - frame = gspca_frame_add(gspca_dev, - LAST_PACKET, - frame, - data, len); + gspca_frame_add(gspca_dev, LAST_PACKET, + data, len); break; } /* got a partial image */ - if (frame) - gspca_frame_add(gspca_dev, - gspca_dev->last_packet_type - == LAST_PACKET - ? FIRST_PACKET : INTER_PACKET, - frame, data, len); + gspca_frame_add(gspca_dev, + gspca_dev->last_packet_type + == LAST_PACKET + ? FIRST_PACKET : INTER_PACKET, + data, len); } /* We must wait before trying reading the next diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index a2108dd71053..a695e0ae13c2 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c @@ -36,7 +36,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev); static int sd_start(struct gspca_dev *gspca_dev); static void sd_stop0(struct gspca_dev *gspca_dev); static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, u8 *data, s32 len); + u8 *data, int len); static void sd_callback(struct gspca_dev *gspca_dev); static int gl860_guess_sensor(struct gspca_dev *gspca_dev, @@ -433,7 +433,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) /* This function is called when an image is being received */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, u8 *data, s32 len) + u8 *data, int len) { struct sd *sd = (struct sd *) gspca_dev; static s32 nSkipped; @@ -445,11 +445,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* Test only against 0202h, so endianess does not matter */ switch (*(s16 *) data) { case 0x0202: /* End of frame, start a new one */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); nSkipped = 0; if (sd->nbIm >= 0 && sd->nbIm < 10) sd->nbIm++; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); + gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); break; default: @@ -464,7 +464,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, nSkipped = nToSkip + 1; } gspca_frame_add(gspca_dev, - INTER_PACKET, frame, data, len); + INTER_PACKET, data, len); } break; } diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 68ba535300f7..4076f8e5a6fc 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -165,7 +165,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, i, urb->iso_frame_desc[i].offset, len); data = (u8 *) urb->transfer_buffer + urb->iso_frame_desc[i].offset; - pkt_scan(gspca_dev, gspca_dev->cur_frame, data, len); + pkt_scan(gspca_dev, data, len); } resubmit: @@ -218,7 +218,6 @@ static void bulk_irq(struct urb *urb) PDEBUG(D_PACK, "packet l:%d", urb->actual_length); gspca_dev->sd_desc->pkt_scan(gspca_dev, - gspca_dev->frame, urb->transfer_buffer, urb->actual_length); @@ -243,11 +242,10 @@ static void bulk_irq(struct urb *urb) * DISCARD_PACKET invalidates the whole frame. * On LAST_PACKET, a new frame is returned. */ -struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, - enum gspca_packet_type packet_type, - struct gspca_frame *dummy, - const __u8 *data, - int len) +void gspca_frame_add(struct gspca_dev *gspca_dev, + enum gspca_packet_type packet_type, + const u8 *data, + int len) { struct gspca_frame *frame; int i, j; @@ -259,7 +257,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) != V4L2_BUF_FLAG_QUEUED) { gspca_dev->last_packet_type = DISCARD_PACKET; - return frame; + return; } /* when start of a new frame, if the current frame buffer @@ -272,7 +270,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { if (packet_type == LAST_PACKET) gspca_dev->last_packet_type = packet_type; - return frame; + return; } /* append the packet to the frame buffer */ @@ -304,9 +302,9 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, i, gspca_dev->fr_o); j = gspca_dev->fr_queue[i]; - gspca_dev->cur_frame = frame = &gspca_dev->frame[j]; + gspca_dev->cur_frame = &gspca_dev->frame[j]; } - return frame; + return; } EXPORT_SYMBOL(gspca_frame_add); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 59078bbf472c..181617355ec3 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -79,8 +79,7 @@ typedef int (*cam_streamparm_op) (struct gspca_dev *, typedef int (*cam_qmnu_op) (struct gspca_dev *, struct v4l2_querymenu *); typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, - struct gspca_frame *frame, - __u8 *data, + u8 *data, int len); struct ctrl { @@ -192,11 +191,10 @@ int gspca_dev_probe(struct usb_interface *intf, int dev_size, struct module *module); void gspca_disconnect(struct usb_interface *intf); -struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, - enum gspca_packet_type packet_type, - struct gspca_frame *frame, - const __u8 *data, - int len); +void gspca_frame_add(struct gspca_dev *gspca_dev, + enum gspca_packet_type packet_type, + const u8 *data, + int len); struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev); #ifdef CONFIG_PM int gspca_suspend(struct usb_interface *intf, pm_message_t message); diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c index d679970d5b3e..2019b04f9235 100644 --- a/drivers/media/video/gspca/jeilinj.c +++ b/drivers/media/video/gspca/jeilinj.c @@ -181,7 +181,6 @@ static void jlj_dostream(struct work_struct *work) { struct sd *dev = container_of(work, struct sd, work_struct); struct gspca_dev *gspca_dev = &dev->gspca_dev; - struct gspca_frame *frame; int blocks_left; /* 0x200-sized blocks remaining in current frame. */ int size_in_blocks; int act_len; @@ -214,15 +213,13 @@ static void jlj_dostream(struct work_struct *work) PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left); /* Start a new frame, and add the JPEG header, first thing */ - frame = gspca_get_i_frame(gspca_dev); - if (frame) { - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - dev->jpeg_hdr, JPEG_HDR_SZ); - /* Toss line 0 of data block 0, keep the rest. */ - gspca_frame_add(gspca_dev, INTER_PACKET, - frame, buffer + FRAME_HEADER_LEN, + gspca_frame_add(gspca_dev, FIRST_PACKET, + dev->jpeg_hdr, JPEG_HDR_SZ); + /* Toss line 0 of data block 0, keep the rest. */ + gspca_frame_add(gspca_dev, INTER_PACKET, + buffer + FRAME_HEADER_LEN, JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); - } + while (blocks_left > 0) { if (!gspca_dev->present) goto quit_stream; @@ -239,10 +236,8 @@ static void jlj_dostream(struct work_struct *work) packet_type = LAST_PACKET; else packet_type = INTER_PACKET; - if (frame) - gspca_frame_add(gspca_dev, packet_type, - frame, buffer, - JEILINJ_MAX_TRANSFER); + gspca_frame_add(gspca_dev, packet_type, + buffer, JEILINJ_MAX_TRANSFER); } } quit_stream: diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 7f1e5415850b..844fc1d886d1 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -274,8 +274,7 @@ static int m5602_start_transfer(struct gspca_dev *gspca_dev) } static void m5602_urb_complete(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, - __u8 *data, int len) + u8 *data, int len) { struct sd *sd = (struct sd *) gspca_dev; @@ -295,19 +294,27 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, len -= 6; /* Complete the last frame (if any) */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, + NULL, 0); sd->frame_count++; /* Create a new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); PDEBUG(D_FRAM, "Starting new frame %d", sd->frame_count); } else { - int cur_frame_len = frame->data_end - frame->data; + struct gspca_frame *frame; + int cur_frame_len; + frame = gspca_get_i_frame(gspca_dev); + if (frame == NULL) { + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } + + cur_frame_len = frame->data_end - frame->data; /* Remove urb header */ data += 4; len -= 4; @@ -316,12 +323,12 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes", sd->frame_count, len); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } else if (frame->v4l2_buf.length - cur_frame_len > 0) { /* Add the remaining data up to frame size */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, - frame->v4l2_buf.length - cur_frame_len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, + frame->v4l2_buf.length - cur_frame_len); } } } diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index de769caf013d..9cf8d68c71bf 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -325,8 +325,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -348,11 +347,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, || data[5 + p] == 0x67) { PDEBUG(D_PACK, "sof offset: %d len: %d", p, len); - frame = gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, p); + gspca_frame_add(gspca_dev, LAST_PACKET, + data, p); /* put the JPEG header */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); data += p + 16; len -= p + 16; @@ -360,7 +359,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } } } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index ffb5e6d62c0b..126d968dd9e0 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -1030,9 +1030,8 @@ static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val) #include "pac_common.h" static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ - int len) /* iso packet length */ + u8 *data, /* isoc packet */ + int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; unsigned char *sof; @@ -1047,15 +1046,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, n -= sizeof pac_sof_marker; else n = 0; - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + gspca_frame_add(gspca_dev, LAST_PACKET, data, n); /* Start next frame. */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, pac_sof_marker, sizeof pac_sof_marker); len -= sof - data; data = sof; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } /* sub-driver description */ diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index f88a526e216f..ad9ec339981d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3920,9 +3920,8 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void ov511_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *in, /* isoc packet */ - int len) /* iso packet length */ + u8 *in, /* isoc packet */ + int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -3953,11 +3952,11 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev, return; } /* Add 11 byte footer to frame, might be usefull */ - gspca_frame_add(gspca_dev, LAST_PACKET, frame, in, 11); + gspca_frame_add(gspca_dev, LAST_PACKET, in, 11); return; } else { /* Frame start */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, in, 0); + gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0); sd->packet_nr = 0; } } @@ -3966,12 +3965,11 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev, len--; /* intermediate packet */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, in, len); + gspca_frame_add(gspca_dev, INTER_PACKET, in, len); } static void ov518_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -3979,8 +3977,8 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev, /* A false positive here is likely, until OVT gives me * the definitive SOF/EOF format */ if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); + gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); sd->packet_nr = 0; } @@ -4004,12 +4002,11 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev, } /* intermediate packet */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static void ov519_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { /* Header of ov519 is 16 bytes: @@ -4032,7 +4029,7 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, len -= HDRSZ; #undef HDRSZ if (data[0] == 0xff || data[1] == 0xd8) - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); else gspca_dev->last_packet_type = DISCARD_PACKET; @@ -4040,34 +4037,31 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, case 0x51: /* end of frame */ if (data[9] != 0) gspca_dev->last_packet_type = DISCARD_PACKET; - gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, + NULL, 0); return; } } /* intermediate packet */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { /* A short read signals EOF */ if (len < OVFX2_BULK_SIZE) { - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, len); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); return; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -4075,20 +4069,20 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ov511_pkt_scan(gspca_dev, frame, data, len); + ov511_pkt_scan(gspca_dev, data, len); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - ov518_pkt_scan(gspca_dev, frame, data, len); + ov518_pkt_scan(gspca_dev, data, len); break; case BRIDGE_OV519: - ov519_pkt_scan(gspca_dev, frame, data, len); + ov519_pkt_scan(gspca_dev, data, len); break; case BRIDGE_OVFX2: - ovfx2_pkt_scan(gspca_dev, frame, data, len); + ovfx2_pkt_scan(gspca_dev, data, len); break; case BRIDGE_W9968CF: - w9968cf_pkt_scan(gspca_dev, frame, data, len); + w9968cf_pkt_scan(gspca_dev, data, len); break; } } diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 26d98b1312e0..193129a59ab7 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1403,8 +1403,8 @@ static void sd_stopN_ov965x(struct gspca_dev *gspca_dev) #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) +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, int len) { struct sd *sd = (struct sd *) gspca_dev; __u32 this_pts; @@ -1445,23 +1445,22 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* If PTS or FID has changed, start a new frame. */ if (this_pts != sd->last_pts || this_fid != sd->last_fid) { if (gspca_dev->last_packet_type == INTER_PACKET) - frame = gspca_frame_add(gspca_dev, - LAST_PACKET, frame, - NULL, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, + NULL, 0); sd->last_pts = this_pts; sd->last_fid = this_fid; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, data + 12, len - 12); /* If this packet is marked as EOF, end the frame */ } else if (data[1] & UVC_STREAM_EOF) { sd->last_pts = 0; - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data + 12, len - 12); + gspca_frame_add(gspca_dev, LAST_PACKET, + data + 12, len - 12); } else { /* Add the data from this payload */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data + 12, len - 12); + gspca_frame_add(gspca_dev, INTER_PACKET, + data + 12, len - 12); } /* Done this payload */ @@ -1469,7 +1468,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, discard: /* Discard data until a new frame starts. */ - gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); + gspca_dev->last_packet_type = DISCARD_PACKET; scan_next: remaining_len -= len; diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 57e13e2d550c..4706a823add0 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -337,8 +337,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, - __u8 *data, + u8 *data, int len) { struct sd *sd = (struct sd *) gspca_dev; @@ -354,10 +353,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, n -= sizeof pac_sof_marker; else n = 0; - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, n); + gspca_frame_add(gspca_dev, LAST_PACKET, + data, n); sd->header_read = 0; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); len -= sof - data; data = sof; } @@ -381,7 +380,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, sd->header_read = 11; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static void setbrightness(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index e0fd767984b3..74acceea8094 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -855,7 +855,7 @@ static void pac_start_frame(struct gspca_dev *gspca_dev, { unsigned char tmpbuf[4]; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, pac_jpeg_header1, sizeof(pac_jpeg_header1)); tmpbuf[0] = lines >> 8; @@ -863,25 +863,31 @@ static void pac_start_frame(struct gspca_dev *gspca_dev, tmpbuf[2] = samples_per_line >> 8; tmpbuf[3] = samples_per_line & 0xff; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, tmpbuf, sizeof(tmpbuf)); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, pac_jpeg_header2, sizeof(pac_jpeg_header2)); } /* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; + struct gspca_frame *frame; unsigned char *sof; sof = pac_find_sof(&sd->sof_read, data, len); if (sof) { int n, lum_offset, footer_length; + frame = gspca_get_i_frame(gspca_dev); + if (frame == NULL) { + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } + /* 6 bytes after the FF D9 EOF marker a number of lumination bytes are send corresponding to different parts of the image, the 14th and 15th byte after the EOF seem to @@ -895,12 +901,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame->data_end += n; n = 0; } - frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, data, n); if (gspca_dev->last_packet_type != DISCARD_PACKET && frame->data_end[-2] == 0xff && frame->data_end[-1] == 0xd9) - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); n = sof - data; @@ -920,7 +926,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, pac_start_frame(gspca_dev, frame, gspca_dev->width, gspca_dev->height); } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 1a27da00ccc1..e5697a6345e8 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -653,7 +653,7 @@ static void pac_start_frame(struct gspca_dev *gspca_dev, { unsigned char tmpbuf[4]; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, pac_jpeg_header1, sizeof(pac_jpeg_header1)); tmpbuf[0] = lines >> 8; @@ -661,25 +661,31 @@ static void pac_start_frame(struct gspca_dev *gspca_dev, tmpbuf[2] = samples_per_line >> 8; tmpbuf[3] = samples_per_line & 0xff; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, tmpbuf, sizeof(tmpbuf)); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, pac_jpeg_header2, sizeof(pac_jpeg_header2)); } /* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; unsigned char *sof; + struct gspca_frame *frame; sof = pac_find_sof(&sd->sof_read, data, len); if (sof) { int n, lum_offset, footer_length; + frame = gspca_get_i_frame(gspca_dev); + if (frame == NULL) { + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } + /* 6 bytes after the FF D9 EOF marker a number of lumination bytes are send corresponding to different parts of the image, the 14th and 15th byte after the EOF seem to @@ -693,12 +699,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame->data_end += n; n = 0; } - frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, data, n); if (gspca_dev->last_packet_type != DISCARD_PACKET && frame->data_end[-2] == 0xff && frame->data_end[-1] == 0xd9) - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); n = sof - data; @@ -717,7 +723,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, pac_start_frame(gspca_dev, frame, gspca_dev->height, gspca_dev->width); } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index cdad3db33367..b1944a7cbb0f 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -2342,7 +2342,6 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ u8 *data, /* isoc packet */ int len) /* iso packet length */ { @@ -2378,22 +2377,22 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, avg_lum >>= 9; atomic_set(&sd->avg_lum, avg_lum); gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, len); + data, len); return; } if (gspca_dev->last_packet_type == LAST_PACKET) { if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & MODE_JPEG) { - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } else { - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); } } else { - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } } diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index cf3af8de6e97..a9f061063b49 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -995,8 +995,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - unsigned char *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { int i; @@ -1054,12 +1053,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, pkt_type = DISCARD_PACKET; } - frame = gspca_frame_add(gspca_dev, pkt_type, - frame, data, 0); + gspca_frame_add(gspca_dev, pkt_type, + NULL, 0); data += i + fr_h_sz; len -= i + fr_h_sz; gspca_frame_add(gspca_dev, FIRST_PACKET, - frame, data, len); + data, len); return; } } @@ -1068,15 +1067,21 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { /* In raw mode we sometimes get some garbage after the frame ignore this */ - int used = frame->data_end - frame->data; + struct gspca_frame *frame; + int used; int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; + frame = gspca_get_i_frame(gspca_dev); + if (frame == NULL) { + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } + used = frame->data_end - frame->data; if (used + len > size) len = size - used; } - gspca_frame_add(gspca_dev, INTER_PACKET, - frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 5f82efb93d9b..282c707e5e81 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1993,7 +1993,6 @@ static void do_autogain(struct gspca_dev *gspca_dev) /* scan the URB packets */ /* This function is run at interrupt level. */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ u8 *data, /* isoc packet */ int len) /* iso packet length */ { @@ -2005,7 +2004,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* end of frame */ gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, sof + 2); + data, sof + 2); if (sd->ag_cnt < 0) return; /* w1 w2 w3 */ @@ -2028,10 +2027,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (gspca_dev->last_packet_type == LAST_PACKET) { /* put the JPEG 422 header */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index fab7ef85a6c1..8bd844d319ea 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -899,8 +899,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -913,11 +912,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* gspca_dev->last_packet_type = DISCARD_PACKET; */ return; } - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + gspca_frame_add(gspca_dev, LAST_PACKET, ffd9, 2); /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); data += SPCA500_OFFSET_DATA; @@ -931,7 +930,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, i = 0; do { if (data[i] == 0xff) { - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, data, i + 1); len -= i; data += i; @@ -940,7 +939,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } i++; } while (i < len); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static void setbrightness(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index b74a34218da0..d251f145a751 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -2032,20 +2032,15 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { switch (data[0]) { case 0: /* start of frame */ - frame = gspca_frame_add(gspca_dev, - LAST_PACKET, - frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); data += SPCA501_OFFSET_DATA; len -= SPCA501_OFFSET_DATA; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); return; case 0xff: /* drop */ /* gspca_dev->last_packet_type = DISCARD_PACKET; */ @@ -2053,8 +2048,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } data++; len--; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index ea8c9fe2e961..0f9232ff1281 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -739,26 +739,22 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ u8 *data, /* isoc packet */ int len) /* iso packet length */ { switch (data[0]) { case 0: /* start of frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); data += SPCA50X_OFFSET_DATA; len -= SPCA50X_OFFSET_DATA; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); break; case 0xff: /* drop */ break; default: data += 1; len -= 1; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); break; } } diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index a199298a6419..ab28cc23e415 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -543,18 +543,15 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { switch (data[0]) { case 0: /* start of frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); data += SPCA50X_OFFSET_DATA; len -= SPCA50X_OFFSET_DATA; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); break; case 0xff: /* drop */ /* gspca_dev->last_packet_type = DISCARD_PACKET; */ @@ -562,8 +559,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, default: data += 1; len -= 1; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); break; } } diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 9696c4caf5c9..4d8e6cf75d55 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1447,26 +1447,22 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ u8 *data, /* isoc packet */ int len) /* iso packet length */ { switch (data[0]) { case 0: /* start of frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); data += SPCA508_OFFSET_DATA; len -= SPCA508_OFFSET_DATA; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); break; case 0xff: /* drop */ break; default: data += 1; len -= 1; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); break; } } diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 27e82b35f3e7..58c2f0039af1 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -779,8 +779,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -788,12 +787,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, len--; switch (*data++) { /* sequence number */ case 0: /* start of frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); if (data[1] & 0x10) { /* compressed bayer */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - frame, data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); } else { /* raw bayer (with a header, which we skip) */ if (sd->chip_revision == Rev012A) { @@ -803,14 +800,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data += 16; len -= 16; } - gspca_frame_add(gspca_dev, FIRST_PACKET, - frame, data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); } return; case 0xff: /* drop (empty mpackets) */ return; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } /* rev 72a only */ diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c index 547d1fd5191d..1fcaca6a87f7 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/video/gspca/sq905.c @@ -214,7 +214,6 @@ static void sq905_dostream(struct work_struct *work) { struct sd *dev = container_of(work, struct sd, work_struct); struct gspca_dev *gspca_dev = &dev->gspca_dev; - struct gspca_frame *frame; int bytes_left; /* bytes remaining in current frame. */ int data_len; /* size to use for the next read. */ int header_read; /* true if we have already read the frame header. */ @@ -266,18 +265,14 @@ static void sq905_dostream(struct work_struct *work) } else { packet_type = INTER_PACKET; } - frame = gspca_get_i_frame(gspca_dev); - if (frame) { - frame = gspca_frame_add(gspca_dev, packet_type, - frame, data, data_len); - /* If entire frame fits in one packet we still - need to add a LAST_PACKET */ - if (packet_type == FIRST_PACKET && - bytes_left == 0) - frame = gspca_frame_add(gspca_dev, - LAST_PACKET, - frame, data, 0); - } + gspca_frame_add(gspca_dev, packet_type, + data, data_len); + /* If entire frame fits in one packet we still + need to add a LAST_PACKET */ + if (packet_type == FIRST_PACKET && + bytes_left == 0) + gspca_frame_add(gspca_dev, LAST_PACKET, + NULL, 0); } if (gspca_dev->present) { /* acknowledge the frame */ diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index 81020f6f739e..d70b156872d6 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c @@ -115,7 +115,6 @@ static void sq905c_dostream(struct work_struct *work) { struct sd *dev = container_of(work, struct sd, work_struct); struct gspca_dev *gspca_dev = &dev->gspca_dev; - struct gspca_frame *frame; int bytes_left; /* bytes remaining in current frame. */ int data_len; /* size to use for the next read. */ int act_len; @@ -146,10 +145,8 @@ static void sq905c_dostream(struct work_struct *work) PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left); /* We keep the header. It has other information, too. */ packet_type = FIRST_PACKET; - frame = gspca_get_i_frame(gspca_dev); - if (frame) - gspca_frame_add(gspca_dev, packet_type, - frame, buffer, FRAME_HEADER_LEN); + gspca_frame_add(gspca_dev, packet_type, + buffer, FRAME_HEADER_LEN); while (bytes_left > 0 && gspca_dev->present) { data_len = bytes_left > SQ905C_MAX_TRANSFER ? SQ905C_MAX_TRANSFER : bytes_left; @@ -167,9 +164,8 @@ static void sq905c_dostream(struct work_struct *work) packet_type = LAST_PACKET; else packet_type = INTER_PACKET; - if (frame) - gspca_frame_add(gspca_dev, packet_type, - frame, buffer, data_len); + gspca_frame_add(gspca_dev, packet_type, + buffer, data_len); } } quit_stream: diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 47628964801e..8e23320d7ab7 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -418,8 +418,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -435,11 +434,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, * (without ending - ff d9) */ if (data[0] == 0xff && data[1] == 0xfe) { - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - ffd9, 2); + gspca_frame_add(gspca_dev, LAST_PACKET, + ffd9, 2); /* put the JPEG 411 header */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); /* beginning of the frame */ @@ -447,7 +446,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data += STKHDRSZ; len -= STKHDRSZ; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c index 0981ce14235d..2a69d7ccb50d 100644 --- a/drivers/media/video/gspca/stv0680.c +++ b/drivers/media/video/gspca/stv0680.c @@ -281,8 +281,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, - __u8 *data, + u8 *data, int len) { struct sd *sd = (struct sd *) gspca_dev; @@ -299,10 +298,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* Finish the previous frame, we do this upon reception of the next packet, even though it is already complete so that the strange 16 byte packets send after a corrupt frame can discard it. */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, NULL, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); /* Store the just received frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); } /* sub-driver description */ diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index bfae63f5584c..5d0241bb1611 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -312,8 +312,7 @@ static void stv06xx_stopN(struct gspca_dev *gspca_dev) * 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 */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -366,7 +365,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, sd->to_skip -= skip; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, data, chunk_len); break; @@ -378,7 +377,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, /* Create a new frame, chunk length should be zero */ gspca_frame_add(gspca_dev, FIRST_PACKET, - frame, data, 0); + NULL, 0); if (sd->bridge == BRIDGE_ST6422) sd->to_skip = gspca_dev->width * 4; @@ -394,8 +393,8 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, PDEBUG(D_PACK, "End of frame detected"); /* Complete the last frame (if any) */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, + NULL, 0); if (chunk_len) PDEBUG(D_ERR, "Chunk length is " diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index aa8f995ce04e..682652cb7fe1 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -1116,7 +1116,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ u8 *data, /* isoc packet */ int len) /* iso packet length */ { @@ -1186,11 +1185,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, break; } if (sof) { /* start of frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - ffd9, 2); + gspca_frame_add(gspca_dev, LAST_PACKET, + ffd9, 2); /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); } @@ -1198,7 +1197,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, i = 0; do { if (data[i] == 0xff) { - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, INTER_PACKET, data, i + 1); len -= i; data += i; @@ -1207,7 +1206,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } i++; } while (i < len); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 1d321c30d22f..55ef6a744427 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -938,7 +938,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ u8 *data, /* isoc packet */ int len) /* iso packet length */ { @@ -956,9 +955,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* extra bytes....., could be processed too but would be * a waste of time, right now leave the application and * libjpeg do it for ourserlves.. */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + gspca_frame_add(gspca_dev, LAST_PACKET, ffd9, 2); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); return; } @@ -967,7 +966,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, * other's do not include it... */ len -= 2; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 4b44dde9f8b8..b74a3b6489c7 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -398,8 +398,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -424,9 +423,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, * - 4 bytes */ gspca_frame_add(gspca_dev, packet_type0, - frame, data + 2, gspca_dev->width); + data + 2, gspca_dev->width); gspca_frame_add(gspca_dev, packet_type1, - frame, data + gspca_dev->width + 5, gspca_dev->width); + data + gspca_dev->width + 5, gspca_dev->width); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 589042f6adbe..26675236fbd2 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -2987,7 +2987,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ u8 *data, /* isoc packet */ int len) /* iso pkt length */ { @@ -2996,21 +2995,25 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (data[0] == 0xff && data[1] == 0xd8) { PDEBUG(D_PACK, "vc032x header packet found len %d", len); - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); data += sd->image_offset; len -= sd->image_offset; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - data, len); + gspca_frame_add(gspca_dev, FIRST_PACKET, 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); + if (sd->bridge == BRIDGE_VC0321) { + struct gspca_frame *frame; + int l; + + frame = gspca_get_i_frame(gspca_dev); + l = frame->data_end - frame->data; + if (len > frame->v4l2_buf.length - l) + len = frame->v4l2_buf.length - l; + } + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 4f9add79ce13..2fffe203bed8 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -576,8 +576,7 @@ static void w9968cf_stop0(struct sd *sd) to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS, V-data, EOI. */ static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -587,9 +586,9 @@ static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, if (len >= 2 && data[0] == 0xff && data[1] == 0xd8) { - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); /* Strip the ff d8, our own header (which adds huffman and quantization tables) already has this */ @@ -599,12 +598,12 @@ static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, } else { /* In UYVY mode an empty packet signals EOF */ if (gspca_dev->empty_packet) { - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); gspca_dev->empty_packet = 0; } } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 113050792246..864974b61145 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6974,17 +6974,16 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } static void sd_pkt_scan(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, - __u8 *data, + u8 *data, int len) { struct sd *sd = (struct sd *) gspca_dev; if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, 0); + gspca_frame_add(gspca_dev, LAST_PACKET, + NULL, 0); /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, sd->jpeg_hdr, JPEG_HDR_SZ); /* remove the webcam's header: @@ -6996,7 +6995,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data += 18; len -= 18; } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) From 0b398f4f124e2b4b03f9acf726370c8459610c5c Mon Sep 17 00:00:00 2001 From: Pete Eberlein Date: Mon, 16 Nov 2009 15:07:42 -0300 Subject: [PATCH 288/345] V4L/DVB (13455): go7007: Add struct v4l2_device. This adds a struct v4l2_device to the go7007 device struct and registers it during v4l2 initialization. The v4l2_device registration overwrites the go->dev device_data, which is a struct usb_interface with intfdata set to the struct go7007. This changes intfdata to point to the struct v4l2_device inside struct go7007, which is what v4l2_device_register will also set it to (and warn about non-null drvdata on register.) Since usb disconnect can happen any time, this intfdata should always be present. Signed-off-by: Pete Eberlein Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/go7007/go7007-driver.c | 10 +++++----- drivers/staging/go7007/go7007-priv.h | 8 ++++++++ drivers/staging/go7007/go7007-usb.c | 4 ++-- drivers/staging/go7007/go7007-v4l2.c | 9 ++++++++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c index 472f4bb08fdc..869430ec0319 100644 --- a/drivers/staging/go7007/go7007-driver.c +++ b/drivers/staging/go7007/go7007-driver.c @@ -49,7 +49,7 @@ int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data) go->hpi_ops->read_interrupt(go); if (wait_event_timeout(go->interrupt_waitq, go->interrupt_available, 5*HZ) < 0) { - v4l2_err(go->video_dev, "timeout waiting for read interrupt\n"); + v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n"); return -1; } if (!go->interrupt_available) @@ -315,7 +315,7 @@ int go7007_start_encoder(struct go7007 *go) if (go7007_send_firmware(go, fw, fw_len) < 0 || go7007_read_interrupt(go, &intr_val, &intr_data) < 0) { - v4l2_err(go->video_dev, "error transferring firmware\n"); + v4l2_err(&go->v4l2_dev, "error transferring firmware\n"); rv = -1; goto start_error; } @@ -324,7 +324,7 @@ int go7007_start_encoder(struct go7007 *go) go->parse_length = 0; go->seen_frame = 0; if (go7007_stream_start(go) < 0) { - v4l2_err(go->video_dev, "error starting stream transfer\n"); + v4l2_err(&go->v4l2_dev, "error starting stream transfer\n"); rv = -1; goto start_error; } @@ -420,7 +420,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) for (i = 0; i < length; ++i) { if (go->active_buf != NULL && go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) { - v4l2_info(go->video_dev, "dropping oversized frame\n"); + v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); go->active_buf->offset -= go->active_buf->bytesused; go->active_buf->bytesused = 0; go->active_buf->modet_active = 0; @@ -668,7 +668,7 @@ void go7007_remove(struct go7007 *go) if (i2c_del_adapter(&go->i2c_adapter) == 0) go->i2c_adapter_online = 0; else - v4l2_err(go->video_dev, + v4l2_err(&go->v4l2_dev, "error removing I2C adapter!\n"); } diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h index ce9307e3e186..b58c394c6555 100644 --- a/drivers/staging/go7007/go7007-priv.h +++ b/drivers/staging/go7007/go7007-priv.h @@ -21,6 +21,8 @@ * user-space applications. */ +#include + struct go7007; /* IDs to activate board-specific support code */ @@ -167,6 +169,7 @@ struct go7007 { int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */ char name[64]; struct video_device *video_dev; + struct v4l2_device v4l2_dev; int ref_count; enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; spinlock_t spinlock; @@ -240,6 +243,11 @@ struct go7007 { unsigned short interrupt_data; }; +static inline struct go7007 *to_go7007(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct go7007, v4l2_dev); +} + /* All of these must be called with the hpi_lock mutex held! */ #define go7007_interface_reset(go) \ ((go)->hpi_ops->interface_reset(go)) diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c index ecaa3c989cf4..f17e7b337a15 100644 --- a/drivers/staging/go7007/go7007-usb.c +++ b/drivers/staging/go7007/go7007-usb.c @@ -1057,7 +1057,7 @@ static int go7007_usb_probe(struct usb_interface *intf, usb_rcvintpipe(usb->usbdev, 4), usb->intr_urb->transfer_buffer, 2*sizeof(u16), go7007_usb_readinterrupt_complete, go, 8); - usb_set_intfdata(intf, go); + usb_set_intfdata(intf, &go->v4l2_dev); /* Boot the GO7007 */ if (go7007_boot_encoder(go, go->board_info->flags & @@ -1233,7 +1233,7 @@ static int go7007_usb_probe(struct usb_interface *intf, static void go7007_usb_disconnect(struct usb_interface *intf) { - struct go7007 *go = usb_get_intfdata(intf); + struct go7007 *go = to_go7007(usb_get_intfdata(intf)); struct go7007_usb *usb = go->hpi_context; struct urb *vurb, *aurb; int i; diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c index 4bd353afa596..faa749dd0356 100644 --- a/drivers/staging/go7007/go7007-v4l2.c +++ b/drivers/staging/go7007/go7007-v4l2.c @@ -1827,7 +1827,7 @@ int go7007_v4l2_init(struct go7007 *go) go->video_dev = video_device_alloc(); if (go->video_dev == NULL) return -ENOMEM; - memcpy(go->video_dev, &go7007_template, sizeof(go7007_template)); + *go->video_dev = go7007_template; go->video_dev->parent = go->dev; rv = video_register_device(go->video_dev, VFL_TYPE_GRABBER, -1); if (rv < 0) { @@ -1835,6 +1835,12 @@ int go7007_v4l2_init(struct go7007 *go) go->video_dev = NULL; return rv; } + rv = v4l2_device_register(go->dev, &go->v4l2_dev); + if (rv < 0) { + video_device_release(go->video_dev); + go->video_dev = NULL; + return rv; + } video_set_drvdata(go->video_dev, go); ++go->ref_count; printk(KERN_INFO "%s: registered device video%d [v4l2]\n", @@ -1858,4 +1864,5 @@ void go7007_v4l2_remove(struct go7007 *go) mutex_unlock(&go->hw_lock); if (go->video_dev) video_unregister_device(go->video_dev); + v4l2_device_unregister(&go->v4l2_dev); } From 47a50307982b4a3de2d7270c28527c3a360269bf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 23 Nov 2009 14:14:26 -0300 Subject: [PATCH 289/345] V4L/DVB (13460): v4l2-spec: add missing V4L2-PIX-FMT-STV0680 description. [mchehab@redhat.com: fix the wrong videodev2.h.xml file] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/pixfmt.xml | 5 + Documentation/DocBook/v4l/videodev2.h.xml | 1097 +++++++++++---------- 2 files changed, 554 insertions(+), 548 deletions(-) diff --git a/Documentation/DocBook/v4l/pixfmt.xml b/Documentation/DocBook/v4l/pixfmt.xml index 7d396a3785f5..885968d6a2fc 100644 --- a/Documentation/DocBook/v4l/pixfmt.xml +++ b/Documentation/DocBook/v4l/pixfmt.xml @@ -770,6 +770,11 @@ kernel sources in the file Documentation/video4linux/cx2341x/README.hm 'S920' YUV 4:2:0 format of the gspca sn9c20x driver. + + V4L2_PIX_FMT_STV0680 + 'S680' + Bayer format of the gspca stv0680 driver. + V4L2_PIX_FMT_WNVA 'WNVA' diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index 97002060ac4f..bb6b07f9ea14 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml @@ -99,148 +99,148 @@ /* Four-character-code (FOURCC) */ #define v4l2_fourcc(a, b, c, d)\ - ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24)) + ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24)) /* * E N U M S */ enum v4l2_field { - V4L2_FIELD_ANY = 0, /* driver can choose from none, - top, bottom, interlaced - depending on whatever it thinks - is approximate ... */ - V4L2_FIELD_NONE = 1, /* this device has no fields ... */ - V4L2_FIELD_TOP = 2, /* top field only */ - V4L2_FIELD_BOTTOM = 3, /* bottom field only */ - V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ - V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one - buffer, top-bottom order */ - V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ - V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into - separate buffers */ - V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field - first and the top field is - transmitted first */ - V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field - first and the bottom field is - transmitted first */ + V4L2_FIELD_ANY = 0, /* driver can choose from none, + top, bottom, interlaced + depending on whatever it thinks + is approximate ... */ + V4L2_FIELD_NONE = 1, /* this device has no fields ... */ + V4L2_FIELD_TOP = 2, /* top field only */ + V4L2_FIELD_BOTTOM = 3, /* bottom field only */ + V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ + V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one + buffer, top-bottom order */ + V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ + V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into + separate buffers */ + V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field + first and the top field is + transmitted first */ + V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field + first and the bottom field is + transmitted first */ }; #define V4L2_FIELD_HAS_TOP(field) \ - ((field) == V4L2_FIELD_TOP ||\ - (field) == V4L2_FIELD_INTERLACED ||\ - (field) == V4L2_FIELD_INTERLACED_TB ||\ - (field) == V4L2_FIELD_INTERLACED_BT ||\ - (field) == V4L2_FIELD_SEQ_TB ||\ - (field) == V4L2_FIELD_SEQ_BT) + ((field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) #define V4L2_FIELD_HAS_BOTTOM(field) \ - ((field) == V4L2_FIELD_BOTTOM ||\ - (field) == V4L2_FIELD_INTERLACED ||\ - (field) == V4L2_FIELD_INTERLACED_TB ||\ - (field) == V4L2_FIELD_INTERLACED_BT ||\ - (field) == V4L2_FIELD_SEQ_TB ||\ - (field) == V4L2_FIELD_SEQ_BT) + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) #define V4L2_FIELD_HAS_BOTH(field) \ - ((field) == V4L2_FIELD_INTERLACED ||\ - (field) == V4L2_FIELD_INTERLACED_TB ||\ - (field) == V4L2_FIELD_INTERLACED_BT ||\ - (field) == V4L2_FIELD_SEQ_TB ||\ - (field) == V4L2_FIELD_SEQ_BT) + ((field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) enum v4l2_buf_type { - V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, - V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, - V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, - V4L2_BUF_TYPE_VBI_CAPTURE = 4, - V4L2_BUF_TYPE_VBI_OUTPUT = 5, - V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, - V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, + V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, + V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, + V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, + V4L2_BUF_TYPE_VBI_CAPTURE = 4, + V4L2_BUF_TYPE_VBI_OUTPUT = 5, + V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, + V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, #if 1 /*KEEP*/ - /* Experimental */ - V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, + /* Experimental */ + V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, #endif - V4L2_BUF_TYPE_PRIVATE = 0x80, + V4L2_BUF_TYPE_PRIVATE = 0x80, }; enum v4l2_ctrl_type { - V4L2_CTRL_TYPE_INTEGER = 1, - V4L2_CTRL_TYPE_BOOLEAN = 2, - V4L2_CTRL_TYPE_MENU = 3, - V4L2_CTRL_TYPE_BUTTON = 4, - V4L2_CTRL_TYPE_INTEGER64 = 5, - V4L2_CTRL_TYPE_CTRL_CLASS = 6, - V4L2_CTRL_TYPE_STRING = 7, + V4L2_CTRL_TYPE_INTEGER = 1, + V4L2_CTRL_TYPE_BOOLEAN = 2, + V4L2_CTRL_TYPE_MENU = 3, + V4L2_CTRL_TYPE_BUTTON = 4, + V4L2_CTRL_TYPE_INTEGER64 = 5, + V4L2_CTRL_TYPE_CTRL_CLASS = 6, + V4L2_CTRL_TYPE_STRING = 7, }; enum v4l2_tuner_type { - V4L2_TUNER_RADIO = 1, - V4L2_TUNER_ANALOG_TV = 2, - V4L2_TUNER_DIGITAL_TV = 3, + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, + V4L2_TUNER_DIGITAL_TV = 3, }; enum v4l2_memory { - V4L2_MEMORY_MMAP = 1, - V4L2_MEMORY_USERPTR = 2, - V4L2_MEMORY_OVERLAY = 3, + V4L2_MEMORY_MMAP = 1, + V4L2_MEMORY_USERPTR = 2, + V4L2_MEMORY_OVERLAY = 3, }; /* see also http://vektor.theorem.ca/graphics/ycbcr/ */ enum v4l2_colorspace { - /* ITU-R 601 -- broadcast NTSC/PAL */ - V4L2_COLORSPACE_SMPTE170M = 1, + /* ITU-R 601 -- broadcast NTSC/PAL */ + V4L2_COLORSPACE_SMPTE170M = 1, - /* 1125-Line (US) HDTV */ - V4L2_COLORSPACE_SMPTE240M = 2, + /* 1125-Line (US) HDTV */ + V4L2_COLORSPACE_SMPTE240M = 2, - /* HD and modern captures. */ - V4L2_COLORSPACE_REC709 = 3, + /* HD and modern captures. */ + V4L2_COLORSPACE_REC709 = 3, - /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ - V4L2_COLORSPACE_BT878 = 4, + /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ + V4L2_COLORSPACE_BT878 = 4, - /* These should be useful. Assume 601 extents. */ - V4L2_COLORSPACE_470_SYSTEM_M = 5, - V4L2_COLORSPACE_470_SYSTEM_BG = 6, + /* These should be useful. Assume 601 extents. */ + V4L2_COLORSPACE_470_SYSTEM_M = 5, + V4L2_COLORSPACE_470_SYSTEM_BG = 6, - /* I know there will be cameras that send this. So, this is - * unspecified chromaticities and full 0-255 on each of the - * Y'CbCr components - */ - V4L2_COLORSPACE_JPEG = 7, + /* I know there will be cameras that send this. So, this is + * unspecified chromaticities and full 0-255 on each of the + * Y'CbCr components + */ + V4L2_COLORSPACE_JPEG = 7, - /* For RGB colourspaces, this is probably a good start. */ - V4L2_COLORSPACE_SRGB = 8, + /* For RGB colourspaces, this is probably a good start. */ + V4L2_COLORSPACE_SRGB = 8, }; enum v4l2_priority { - V4L2_PRIORITY_UNSET = 0, /* not initialized */ - V4L2_PRIORITY_BACKGROUND = 1, - V4L2_PRIORITY_INTERACTIVE = 2, - V4L2_PRIORITY_RECORD = 3, - V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, + V4L2_PRIORITY_UNSET = 0, /* not initialized */ + V4L2_PRIORITY_BACKGROUND = 1, + V4L2_PRIORITY_INTERACTIVE = 2, + V4L2_PRIORITY_RECORD = 3, + V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, }; struct v4l2_rect { - __s32 left; - __s32 top; - __s32 width; - __s32 height; + __s32 left; + __s32 top; + __s32 width; + __s32 height; }; struct v4l2_fract { - __u32 numerator; - __u32 denominator; + __u32 numerator; + __u32 denominator; }; /* * D R I V E R C A P A B I L I T I E S */ struct v4l2_capability { - __u8 driver[16]; /* i.e.ie; "bttv" */ - __u8 card[32]; /* i.e.ie; "Hauppauge WinTV" */ - __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ - __u32 version; /* should use KERNEL_VERSION() */ - __u32 capabilities; /* Device capabilities */ - __u32 reserved[4]; + __u8 driver[16]; /* i.e.ie; "bttv" */ + __u8 card[32]; /* i.e.ie; "Hauppauge WinTV" */ + __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ + __u32 version; /* should use KERNEL_VERSION() */ + __u32 capabilities; /* Device capabilities */ + __u32 reserved[4]; }; /* Values for 'capabilities' field */ @@ -269,14 +269,14 @@ struct v4l2_capability { * V I D E O I M A G E F O R M A T */ struct v4l2_pix_format { - __u32 width; - __u32 height; - __u32 pixelformat; - enum v4l2_field field; - __u32 bytesperline; /* for padding, zero if unused */ - __u32 sizeimage; - enum v4l2_colorspace colorspace; - __u32 priv; /* private data, depends on pixelformat */ + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; + enum v4l2_colorspace colorspace; + __u32 priv; /* private data, depends on pixelformat */ }; /* Pixel format FOURCC depth Description */ @@ -331,12 +331,12 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ #define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ #define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10bit raw bayer */ - /* 10bit raw bayer DPCM compressed to 8 bits */ + /* 10bit raw bayer DPCM compressed to 8 bits */ #define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0') - /* - * 10bit raw bayer, expanded to 16 bits - * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... - */ + /* + * 10bit raw bayer, expanded to 16 bits + * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... + */ #define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16 BGBG.. GRGR.. */ /* compressed formats */ @@ -363,88 +363,89 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */ #define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ #define V4L2_PIX_FMT_TM6000 v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */ +#define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */ /* * F O R M A T E N U M E R A T I O N */ struct v4l2_fmtdesc { - __u32 index; /* Format number */ - enum v4l2_buf_type type; /* buffer type */ - __u32 flags; - __u8 description[32]; /* Description string */ - __u32 pixelformat; /* Format fourcc */ - __u32 reserved[4]; + __u32 index; /* Format number */ + enum v4l2_buf_type type; /* buffer type */ + __u32 flags; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; }; #define V4L2_FMT_FLAG_COMPRESSED 0x0001 #define V4L2_FMT_FLAG_EMULATED 0x0002 #if 1 /*KEEP*/ - /* Experimental Frame Size and frame rate enumeration */ + /* Experimental Frame Size and frame rate enumeration */ /* * F R A M E S I Z E E N U M E R A T I O N */ enum v4l2_frmsizetypes { - V4L2_FRMSIZE_TYPE_DISCRETE = 1, - V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, - V4L2_FRMSIZE_TYPE_STEPWISE = 3, + V4L2_FRMSIZE_TYPE_DISCRETE = 1, + V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, + V4L2_FRMSIZE_TYPE_STEPWISE = 3, }; struct v4l2_frmsize_discrete { - __u32 width; /* Frame width [pixel] */ - __u32 height; /* Frame height [pixel] */ + __u32 width; /* Frame width [pixel] */ + __u32 height; /* Frame height [pixel] */ }; struct v4l2_frmsize_stepwise { - __u32 min_width; /* Minimum frame width [pixel] */ - __u32 max_width; /* Maximum frame width [pixel] */ - __u32 step_width; /* Frame width step size [pixel] */ - __u32 min_height; /* Minimum frame height [pixel] */ - __u32 max_height; /* Maximum frame height [pixel] */ - __u32 step_height; /* Frame height step size [pixel] */ + __u32 min_width; /* Minimum frame width [pixel] */ + __u32 max_width; /* Maximum frame width [pixel] */ + __u32 step_width; /* Frame width step size [pixel] */ + __u32 min_height; /* Minimum frame height [pixel] */ + __u32 max_height; /* Maximum frame height [pixel] */ + __u32 step_height; /* Frame height step size [pixel] */ }; struct v4l2_frmsizeenum { - __u32 index; /* Frame size number */ - __u32 pixel_format; /* Pixel format */ - __u32 type; /* Frame size type the device supports. */ + __u32 index; /* Frame size number */ + __u32 pixel_format; /* Pixel format */ + __u32 type; /* Frame size type the device supports. */ - union { /* Frame size */ - struct v4l2_frmsize_discrete discrete; - struct v4l2_frmsize_stepwise stepwise; - }; + union { /* Frame size */ + struct v4l2_frmsize_discrete discrete; + struct v4l2_frmsize_stepwise stepwise; + }; - __u32 reserved[2]; /* Reserved space for future use */ + __u32 reserved[2]; /* Reserved space for future use */ }; /* * F R A M E R A T E E N U M E R A T I O N */ enum v4l2_frmivaltypes { - V4L2_FRMIVAL_TYPE_DISCRETE = 1, - V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, - V4L2_FRMIVAL_TYPE_STEPWISE = 3, + V4L2_FRMIVAL_TYPE_DISCRETE = 1, + V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, + V4L2_FRMIVAL_TYPE_STEPWISE = 3, }; struct v4l2_frmival_stepwise { - struct v4l2_fract min; /* Minimum frame interval [s] */ - struct v4l2_fract max; /* Maximum frame interval [s] */ - struct v4l2_fract step; /* Frame interval step size [s] */ + struct v4l2_fract min; /* Minimum frame interval [s] */ + struct v4l2_fract max; /* Maximum frame interval [s] */ + struct v4l2_fract step; /* Frame interval step size [s] */ }; struct v4l2_frmivalenum { - __u32 index; /* Frame format index */ - __u32 pixel_format; /* Pixel format */ - __u32 width; /* Frame width */ - __u32 height; /* Frame height */ - __u32 type; /* Frame interval type the device supports. */ + __u32 index; /* Frame format index */ + __u32 pixel_format; /* Pixel format */ + __u32 width; /* Frame width */ + __u32 height; /* Frame height */ + __u32 type; /* Frame interval type the device supports. */ - union { /* Frame interval */ - struct v4l2_fract discrete; - struct v4l2_frmival_stepwise stepwise; - }; + union { /* Frame interval */ + struct v4l2_fract discrete; + struct v4l2_frmival_stepwise stepwise; + }; - __u32 reserved[2]; /* Reserved space for future use */ + __u32 reserved[2]; /* Reserved space for future use */ }; #endif @@ -452,13 +453,13 @@ struct v4l2_frmivalenum { * T I M E C O D E */ struct v4l2_timecode { - __u32 type; - __u32 flags; - __u8 frames; - __u8 seconds; - __u8 minutes; - __u8 hours; - __u8 userbits[4]; + __u32 type; + __u32 flags; + __u8 frames; + __u8 seconds; + __u8 minutes; + __u8 hours; + __u8 userbits[4]; }; /* Type */ @@ -477,63 +478,63 @@ struct v4l2_timecode { /* The above is based on SMPTE timecodes */ struct v4l2_jpegcompression { - int quality; + int quality; - int APPn; /* Number of APP segment to be written, - * must be 0..15 */ - int APP_len; /* Length of data in JPEG APPn segment */ - char APP_data[60]; /* Data in the JPEG APPn segment. */ + int APPn; /* Number of APP segment to be written, + * must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ - int COM_len; /* Length of data in JPEG COM segment */ - char COM_data[60]; /* Data in JPEG COM segment */ + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ - __u32 jpeg_markers; /* Which markers should go into the JPEG - * output. Unless you exactly know what - * you do, leave them untouched. - * Inluding less markers will make the - * resulting code smaller, but there will - * be fewer aplications which can read it. - * The presence of the APP and COM marker - * is influenced by APP_len and COM_len - * ONLY, not by this property! */ + __u32 jpeg_markers; /* Which markers should go into the JPEG + * output. Unless you exactly know what + * you do, leave them untouched. + * Inluding less markers will make the + * resulting code smaller, but there will + * be fewer aplications which can read it. + * The presence of the APP and COM marker + * is influenced by APP_len and COM_len + * ONLY, not by this property! */ #define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ #define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * allways use APP0 */ }; /* * M E M O R Y - M A P P I N G B U F F E R S */ struct v4l2_requestbuffers { - __u32 count; - enum v4l2_buf_type type; - enum v4l2_memory memory; - __u32 reserved[2]; + __u32 count; + enum v4l2_buf_type type; + enum v4l2_memory memory; + __u32 reserved[2]; }; struct v4l2_buffer { - __u32 index; - enum v4l2_buf_type type; - __u32 bytesused; - __u32 flags; - enum v4l2_field field; - struct timeval timestamp; - struct v4l2_timecode timecode; - __u32 sequence; + __u32 index; + enum v4l2_buf_type type; + __u32 bytesused; + __u32 flags; + enum v4l2_field field; + struct timeval timestamp; + struct v4l2_timecode timecode; + __u32 sequence; - /* memory location */ - enum v4l2_memory memory; - union { - __u32 offset; - unsigned long userptr; - } m; - __u32 length; - __u32 input; - __u32 reserved; + /* memory location */ + enum v4l2_memory memory; + union { + __u32 offset; + unsigned long userptr; + } m; + __u32 length; + __u32 input; + __u32 reserved; }; /* Flags for 'flags' field */ @@ -550,12 +551,12 @@ struct v4l2_buffer { * O V E R L A Y P R E V I E W */ struct v4l2_framebuffer { - __u32 capability; - __u32 flags; + __u32 capability; + __u32 flags; /* FIXME: in theory we should pass something like PCI device + memory * region + offset instead of some physical address */ - void *base; - struct v4l2_pix_format fmt; + void *base; + struct v4l2_pix_format fmt; }; /* Flags for the 'capability' field. Read only */ #define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 @@ -574,30 +575,30 @@ struct v4l2_framebuffer { #define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020 struct v4l2_clip { - struct v4l2_rect c; - struct v4l2_clip __user *next; + struct v4l2_rect c; + struct v4l2_clip __user *next; }; struct v4l2_window { - struct v4l2_rect w; - enum v4l2_field field; - __u32 chromakey; - struct v4l2_clip __user *clips; - __u32 clipcount; - void __user *bitmap; - __u8 global_alpha; + struct v4l2_rect w; + enum v4l2_field field; + __u32 chromakey; + struct v4l2_clip __user *clips; + __u32 clipcount; + void __user *bitmap; + __u8 global_alpha; }; /* * C A P T U R E P A R A M E T E R S */ struct v4l2_captureparm { - __u32 capability; /* Supported modes */ - __u32 capturemode; /* Current mode */ - struct v4l2_fract timeperframe; /* Time per frame in .1us units */ - __u32 extendedmode; /* Driver-specific extensions */ - __u32 readbuffers; /* # of buffers for read */ - __u32 reserved[4]; + __u32 capability; /* Supported modes */ + __u32 capturemode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in .1us units */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 readbuffers; /* # of buffers for read */ + __u32 reserved[4]; }; /* Flags for 'capability' and 'capturemode' fields */ @@ -605,27 +606,27 @@ struct v4l2_captureparm { #define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ struct v4l2_outputparm { - __u32 capability; /* Supported modes */ - __u32 outputmode; /* Current mode */ - struct v4l2_fract timeperframe; /* Time per frame in seconds */ - __u32 extendedmode; /* Driver-specific extensions */ - __u32 writebuffers; /* # of buffers for write */ - __u32 reserved[4]; + __u32 capability; /* Supported modes */ + __u32 outputmode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in seconds */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 writebuffers; /* # of buffers for write */ + __u32 reserved[4]; }; /* * I N P U T I M A G E C R O P P I N G */ struct v4l2_cropcap { - enum v4l2_buf_type type; - struct v4l2_rect bounds; - struct v4l2_rect defrect; - struct v4l2_fract pixelaspect; + enum v4l2_buf_type type; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; }; struct v4l2_crop { - enum v4l2_buf_type type; - struct v4l2_rect c; + enum v4l2_buf_type type; + struct v4l2_rect c; }; /* @@ -684,64 +685,64 @@ typedef __u64 v4l2_std_id; /* some common needed stuff */ #define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\ - V4L2_STD_PAL_B1 |\ - V4L2_STD_PAL_G) + V4L2_STD_PAL_B1 |\ + V4L2_STD_PAL_G) #define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\ - V4L2_STD_PAL_D1 |\ - V4L2_STD_PAL_K) + V4L2_STD_PAL_D1 |\ + V4L2_STD_PAL_K) #define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ - V4L2_STD_PAL_DK |\ - V4L2_STD_PAL_H |\ - V4L2_STD_PAL_I) + V4L2_STD_PAL_DK |\ + V4L2_STD_PAL_H |\ + V4L2_STD_PAL_I) #define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ - V4L2_STD_NTSC_M_JP |\ - V4L2_STD_NTSC_M_KR) + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) #define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ - V4L2_STD_SECAM_K |\ - V4L2_STD_SECAM_K1) + V4L2_STD_SECAM_K |\ + V4L2_STD_SECAM_K1) #define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ - V4L2_STD_SECAM_G |\ - V4L2_STD_SECAM_H |\ - V4L2_STD_SECAM_DK |\ - V4L2_STD_SECAM_L |\ - V4L2_STD_SECAM_LC) + V4L2_STD_SECAM_G |\ + V4L2_STD_SECAM_H |\ + V4L2_STD_SECAM_DK |\ + V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) #define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ - V4L2_STD_PAL_60 |\ - V4L2_STD_NTSC |\ - V4L2_STD_NTSC_443) + V4L2_STD_PAL_60 |\ + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) #define V4L2_STD_625_50 (V4L2_STD_PAL |\ - V4L2_STD_PAL_N |\ - V4L2_STD_PAL_Nc |\ - V4L2_STD_SECAM) + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_SECAM) #define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ - V4L2_STD_ATSC_16_VSB) + V4L2_STD_ATSC_16_VSB) #define V4L2_STD_UNKNOWN 0 #define V4L2_STD_ALL (V4L2_STD_525_60 |\ - V4L2_STD_625_50) + V4L2_STD_625_50) struct v4l2_standard { - __u32 index; - v4l2_std_id id; - __u8 name[24]; - struct v4l2_fract frameperiod; /* Frames, not fields */ - __u32 framelines; - __u32 reserved[4]; + __u32 index; + v4l2_std_id id; + __u8 name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + __u32 framelines; + __u32 reserved[4]; }; /* * V I D E O I N P U T S */ struct v4l2_input { - __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]; + __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]; }; /* Values for the 'type' field */ @@ -776,13 +777,13 @@ struct v4l2_input { * V I D E O O U T P U T S */ struct v4l2_output { - __u32 index; /* Which output */ - __u8 name[32]; /* Label */ - __u32 type; /* Type of output */ - __u32 audioset; /* Associated audios (bitfield) */ - __u32 modulator; /* Associated modulator */ - v4l2_std_id std; - __u32 reserved[4]; + __u32 index; /* Which output */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of output */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 modulator; /* Associated modulator */ + v4l2_std_id std; + __u32 reserved[4]; }; /* Values for the 'type' field */ #define V4L2_OUTPUT_TYPE_MODULATOR 1 @@ -793,27 +794,27 @@ struct v4l2_output { * C O N T R O L S */ struct v4l2_control { - __u32 id; - __s32 value; + __u32 id; + __s32 value; }; struct v4l2_ext_control { - __u32 id; - __u32 size; - __u32 reserved2[1]; - union { - __s32 value; - __s64 value64; - char *string; - }; + __u32 id; + __u32 size; + __u32 reserved2[1]; + union { + __s32 value; + __s64 value64; + char *string; + }; } __attribute__ ((packed)); struct v4l2_ext_controls { - __u32 ctrl_class; - __u32 count; - __u32 error_idx; - __u32 reserved[2]; - struct v4l2_ext_control *controls; + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + struct v4l2_ext_control *controls; }; /* Values for ctrl_class field */ @@ -828,23 +829,23 @@ struct v4l2_ext_controls { /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ struct v4l2_queryctrl { - __u32 id; - enum v4l2_ctrl_type type; - __u8 name[32]; /* Whatever */ - __s32 minimum; /* Note signedness */ - __s32 maximum; - __s32 step; - __s32 default_value; - __u32 flags; - __u32 reserved[2]; + __u32 id; + enum v4l2_ctrl_type type; + __u8 name[32]; /* Whatever */ + __s32 minimum; /* Note signedness */ + __s32 maximum; + __s32 step; + __s32 default_value; + __u32 flags; + __u32 reserved[2]; }; /* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ struct v4l2_querymenu { - __u32 id; - __u32 index; - __u8 name[32]; /* Whatever */ - __u32 reserved; + __u32 id; + __u32 index; + __u8 name[32]; /* Whatever */ + __u32 reserved; }; /* Control flags */ @@ -895,9 +896,9 @@ struct v4l2_querymenu { #define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) enum v4l2_power_line_frequency { - V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, - V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, }; #define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) #define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) @@ -907,9 +908,9 @@ enum v4l2_power_line_frequency #define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30) #define V4L2_CID_COLORFX (V4L2_CID_BASE+31) enum v4l2_colorfx { - V4L2_COLORFX_NONE = 0, - V4L2_COLORFX_BW = 1, - V4L2_COLORFX_SEPIA = 2, + V4L2_COLORFX_NONE = 0, + V4L2_COLORFX_BW = 1, + V4L2_COLORFX_SEPIA = 2, }; #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) @@ -924,12 +925,12 @@ enum v4l2_colorfx { /* MPEG streams */ #define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE+0) enum v4l2_mpeg_stream_type { - V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ - V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ - V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ - V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible stream */ - V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ - V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ }; #define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_MPEG_BASE+1) #define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_MPEG_BASE+2) @@ -939,139 +940,139 @@ enum v4l2_mpeg_stream_type { #define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) #define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) enum v4l2_mpeg_stream_vbi_fmt { - V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ - V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ + V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ + V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ }; /* MPEG audio */ #define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) enum v4l2_mpeg_audio_sampling_freq { - V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, }; #define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_MPEG_BASE+101) enum v4l2_mpeg_audio_encoding { - V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, - V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, - V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, - V4L2_MPEG_AUDIO_ENCODING_AAC = 3, - V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, + V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, + V4L2_MPEG_AUDIO_ENCODING_AAC = 3, + V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, }; #define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) enum v4l2_mpeg_audio_l1_bitrate { - V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, - V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, - V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, - V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, - V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, - V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, - V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, - V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, - V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, - V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, - V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, - V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, - V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, - V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, + V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, + V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, + V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, + V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, + V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, + V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, + V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, + V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, + V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, + V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, + V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, + V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, + V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, }; #define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_MPEG_BASE+103) enum v4l2_mpeg_audio_l2_bitrate { - V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, - V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, - V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, - V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, - V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, - V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, - V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, - V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, - V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, - V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, - V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, - V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, - V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, - V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, + V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, + V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, + V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, + V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, + V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, + V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, + V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, + V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, + V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, + V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, + V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, + V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, + V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, }; #define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_MPEG_BASE+104) enum v4l2_mpeg_audio_l3_bitrate { - V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, - V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, - V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, - V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, - V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, - V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, - V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, - V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, - V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, - V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, - V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, - V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, - V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, - V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, + V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, }; #define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_MPEG_BASE+105) enum v4l2_mpeg_audio_mode { - V4L2_MPEG_AUDIO_MODE_STEREO = 0, - V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, - V4L2_MPEG_AUDIO_MODE_DUAL = 2, - V4L2_MPEG_AUDIO_MODE_MONO = 3, + V4L2_MPEG_AUDIO_MODE_STEREO = 0, + V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, + V4L2_MPEG_AUDIO_MODE_DUAL = 2, + V4L2_MPEG_AUDIO_MODE_MONO = 3, }; #define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_MPEG_BASE+106) enum v4l2_mpeg_audio_mode_extension { - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, }; #define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_MPEG_BASE+107) enum v4l2_mpeg_audio_emphasis { - V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, - V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, - V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, + V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, + V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, }; #define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_MPEG_BASE+108) enum v4l2_mpeg_audio_crc { - V4L2_MPEG_AUDIO_CRC_NONE = 0, - V4L2_MPEG_AUDIO_CRC_CRC16 = 1, + V4L2_MPEG_AUDIO_CRC_NONE = 0, + V4L2_MPEG_AUDIO_CRC_CRC16 = 1, }; #define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) #define V4L2_CID_MPEG_AUDIO_AAC_BITRATE (V4L2_CID_MPEG_BASE+110) #define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_MPEG_BASE+111) enum v4l2_mpeg_audio_ac3_bitrate { - V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, - V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, - V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, - V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, - V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, - V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, - V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, - V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, - V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, - V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, - V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, - V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, - V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, - V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, - V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, - V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, - V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, - V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, - V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, + V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, + V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, + V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, + V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, }; /* MPEG video */ #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) enum v4l2_mpeg_video_encoding { - V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, }; #define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) enum v4l2_mpeg_video_aspect { - V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, - V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, - V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, - V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, + V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, + V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, + V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, + V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, }; #define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_MPEG_BASE+202) #define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_MPEG_BASE+203) @@ -1079,8 +1080,8 @@ enum v4l2_mpeg_video_aspect { #define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_MPEG_BASE+205) #define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_MPEG_BASE+206) enum v4l2_mpeg_video_bitrate_mode { - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, }; #define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE+207) #define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE+208) @@ -1092,36 +1093,36 @@ enum v4l2_mpeg_video_bitrate_modev4l2_mpeg_cx2341x_video_spatial_filter_mode { - V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, - V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+1) #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+2) enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+3) enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type { - V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, - V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+4) enum v4l2_mpeg_cx2341x_video_temporal_filter_mode { - V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, - V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+5) #define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+6) enum v4l2_mpeg_cx2341x_video_median_filter_type { - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+7) #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+8) @@ -1135,10 +1136,10 @@ enum v4l2_mpeg_cx2341 #define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) enum v4l2_exposure_auto_type { - V4L2_EXPOSURE_AUTO = 0, - V4L2_EXPOSURE_MANUAL = 1, - V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, - V4L2_EXPOSURE_APERTURE_PRIORITY = 3 + V4L2_EXPOSURE_AUTO = 0, + V4L2_EXPOSURE_MANUAL = 1, + V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, + V4L2_EXPOSURE_APERTURE_PRIORITY = 3 }; #define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) #define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) @@ -1187,9 +1188,9 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_TUNE_PREEMPHASIS (V4L2_CID_FM_TX_CLASS_BASE + 112) enum v4l2_preemphasis { - V4L2_PREEMPHASIS_DISABLED = 0, - V4L2_PREEMPHASIS_50_uS = 1, - V4L2_PREEMPHASIS_75_uS = 2, + V4L2_PREEMPHASIS_DISABLED = 0, + V4L2_PREEMPHASIS_50_uS = 1, + V4L2_PREEMPHASIS_75_uS = 2, }; #define V4L2_CID_TUNE_POWER_LEVEL (V4L2_CID_FM_TX_CLASS_BASE + 113) #define V4L2_CID_TUNE_ANTENNA_CAPACITOR (V4L2_CID_FM_TX_CLASS_BASE + 114) @@ -1198,27 +1199,27 @@ enum v4l2_preemphasis { * T U N I N G */ struct v4l2_tuner { - __u32 index; - __u8 name[32]; - enum v4l2_tuner_type type; - __u32 capability; - __u32 rangelow; - __u32 rangehigh; - __u32 rxsubchans; - __u32 audmode; - __s32 signal; - __s32 afc; - __u32 reserved[4]; + __u32 index; + __u8 name[32]; + enum v4l2_tuner_type type; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 rxsubchans; + __u32 audmode; + __s32 signal; + __s32 afc; + __u32 reserved[4]; }; struct v4l2_modulator { - __u32 index; - __u8 name[32]; - __u32 capability; - __u32 rangelow; - __u32 rangehigh; - __u32 txsubchans; - __u32 reserved[4]; + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 txsubchans; + __u32 reserved[4]; }; /* Flags for the 'capability' field */ @@ -1247,18 +1248,18 @@ struct v4l2_modulator { #define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 struct v4l2_frequency { - __u32 tuner; - enum v4l2_tuner_type type; - __u32 frequency; - __u32 reserved[8]; + __u32 tuner; + enum v4l2_tuner_type type; + __u32 frequency; + __u32 reserved[8]; }; struct v4l2_hw_freq_seek { - __u32 tuner; - enum v4l2_tuner_type type; - __u32 seek_upward; - __u32 wrap_around; - __u32 reserved[8]; + __u32 tuner; + enum v4l2_tuner_type type; + __u32 seek_upward; + __u32 wrap_around; + __u32 reserved[8]; }; /* @@ -1266,9 +1267,9 @@ struct v4l2_hw_freq_seek { */ struct v4l2_rds_data { - __u8 lsb; - __u8 msb; - __u8 block; + __u8 lsb; + __u8 msb; + __u8 block; } __attribute__ ((packed)); #define V4L2_RDS_BLOCK_MSK 0x7 @@ -1286,11 +1287,11 @@ struct v4l2_rds_data { * A U D I O */ struct v4l2_audio { - __u32 index; - __u8 name[32]; - __u32 capability; - __u32 mode; - __u32 reserved[2]; + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; }; /* Flags for the 'capability' field */ @@ -1301,11 +1302,11 @@ struct v4l2_audio { #define V4L2_AUDMODE_AVL 0x00001 struct v4l2_audioout { - __u32 index; - __u8 name[32]; - __u32 capability; - __u32 mode; - __u32 reserved[2]; + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; }; /* @@ -1320,19 +1321,19 @@ struct v4l2_audioout { #define V4L2_ENC_IDX_FRAME_MASK (0xf) struct v4l2_enc_idx_entry { - __u64 offset; - __u64 pts; - __u32 length; - __u32 flags; - __u32 reserved[2]; + __u64 offset; + __u64 pts; + __u32 length; + __u32 flags; + __u32 reserved[2]; }; #define V4L2_ENC_IDX_ENTRIES (64) struct v4l2_enc_idx { - __u32 entries; - __u32 entries_cap; - __u32 reserved[4]; - struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; + __u32 entries; + __u32 entries_cap; + __u32 reserved[4]; + struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; }; @@ -1345,13 +1346,13 @@ struct v4l2_enc_idx { #define V4L2_ENC_CMD_STOP_AT_GOP_END (1 << 0) struct v4l2_encoder_cmd { - __u32 cmd; - __u32 flags; - union { - struct { - __u32 data[8]; - } raw; - }; + __u32 cmd; + __u32 flags; + union { + struct { + __u32 data[8]; + } raw; + }; }; #endif @@ -1365,14 +1366,14 @@ struct v4l2_encoder_cmd { /* Raw VBI */ struct v4l2_vbi_format { - __u32 sampling_rate; /* in 1 Hz */ - __u32 offset; - __u32 samples_per_line; - __u32 sample_format; /* V4L2_PIX_FMT_* */ - __s32 start[2]; - __u32 count[2]; - __u32 flags; /* V4L2_VBI_* */ - __u32 reserved[2]; /* must be zero */ + __u32 sampling_rate; /* in 1 Hz */ + __u32 offset; + __u32 samples_per_line; + __u32 sample_format; /* V4L2_PIX_FMT_* */ + __s32 start[2]; + __u32 count[2]; + __u32 flags; /* V4L2_VBI_* */ + __u32 reserved[2]; /* must be zero */ }; /* VBI flags */ @@ -1387,14 +1388,14 @@ struct v4l2_vbi_format { */ struct v4l2_sliced_vbi_format { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - __u32 io_size; - __u32 reserved[2]; /* must be zero */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 io_size; + __u32 reserved[2]; /* must be zero */ }; /* Teletext World System Teletext @@ -1411,22 +1412,22 @@ struct v4l2_sliced_vbi_format { #define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) struct v4l2_sliced_vbi_cap { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - enum v4l2_buf_type type; - __u32 reserved[3]; /* must be 0 */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + enum v4l2_buf_type type; + __u32 reserved[3]; /* must be 0 */ }; struct v4l2_sliced_vbi_data { - __u32 id; - __u32 field; /* 0: first field, 1: second field */ - __u32 line; /* 1-23 */ - __u32 reserved; /* must be 0 */ - __u8 data[48]; + __u32 id; + __u32 field; /* 0: first field, 1: second field */ + __u32 line; /* 1-23 */ + __u32 reserved; /* must be 0 */ + __u8 data[48]; }; /* @@ -1452,28 +1453,28 @@ struct v4l2_sliced_vbi_data { #define V4L2_MPEG_VBI_IVTV_VPS (7) struct v4l2_mpeg_vbi_itv0_line { - __u8 id; /* One of V4L2_MPEG_VBI_IVTV_* above */ - __u8 data[42]; /* Sliced VBI data for the line */ + __u8 id; /* One of V4L2_MPEG_VBI_IVTV_* above */ + __u8 data[42]; /* Sliced VBI data for the line */ } __attribute__ ((packed)); struct v4l2_mpeg_vbi_itv0 { - __le32 linemask[2]; /* Bitmasks of VBI service lines present */ - struct v4l2_mpeg_vbi_itv0_line line[35]; + __le32 linemask[2]; /* Bitmasks of VBI service lines present */ + struct v4l2_mpeg_vbi_itv0_line line[35]; } __attribute__ ((packed)); struct v4l2_mpeg_vbi_ITV0 { - struct v4l2_mpeg_vbi_itv0_line line[36]; + struct v4l2_mpeg_vbi_itv0_line line[36]; } __attribute__ ((packed)); #define V4L2_MPEG_VBI_IVTV_MAGIC0 "itv0" #define V4L2_MPEG_VBI_IVTV_MAGIC1 "ITV0" struct v4l2_mpeg_vbi_fmt_ivtv { - __u8 magic[4]; - union { - struct v4l2_mpeg_vbi_itv0 itv0; - struct v4l2_mpeg_vbi_ITV0 ITV0; - }; + __u8 magic[4]; + union { + struct v4l2_mpeg_vbi_itv0 itv0; + struct v4l2_mpeg_vbi_ITV0 ITV0; + }; } __attribute__ ((packed)); /* @@ -1483,26 +1484,26 @@ struct v4l2_mpeg_vbi_fmt_ivtv { /* Stream data format */ struct v4l2_format { - enum v4l2_buf_type type; - union { - struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ - struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ - struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ - struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ - __u8 raw_data[200]; /* user-defined */ - } fmt; + enum v4l2_buf_type type; + union { + struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ + struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ + struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ + struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ + __u8 raw_data[200]; /* user-defined */ + } fmt; }; /* Stream type-dependent parameters */ struct v4l2_streamparm { - enum v4l2_buf_type type; - union { - struct v4l2_captureparm capture; - struct v4l2_outputparm output; - __u8 raw_data[200]; /* user-defined */ - } parm; + enum v4l2_buf_type type; + union { + struct v4l2_captureparm capture; + struct v4l2_outputparm output; + __u8 raw_data[200]; /* user-defined */ + } parm; }; /* @@ -1520,25 +1521,25 @@ struct v4l2_streamparm { #define V4L2_CHIP_MATCH_AC97 3 /* Match against anciliary AC97 chip */ struct v4l2_dbg_match { - __u32 type; /* Match type */ - union { /* Match this chip, meaning determined by type */ - __u32 addr; - char name[32]; - }; + __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; + 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 <media/v4l2-chip-ident.h> */ - __u32 revision; /* chip revision, chip specific */ + struct v4l2_dbg_match match; + __u32 ident; /* chip identifier as specified in <media/v4l2-chip-ident.h> */ + __u32 revision; /* chip revision, chip specific */ } __attribute__ ((packed)); /* From 204e6ea981ac46974508ddf403dbb72dc804dcb3 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 9 Nov 2009 09:07:36 -0300 Subject: [PATCH 290/345] V4L/DVB (13463): Davinci VPFE Capture: Specify device pointer in videobuf_queue_dma_contig_init Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 6b31e59f47f3..c704a2637683 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1338,7 +1338,7 @@ static int vpfe_reqbufs(struct file *file, void *priv, vpfe_dev->memory = req_buf->memory; videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue, &vpfe_videobuf_qops, - NULL, + vpfe_dev->pdev, &vpfe_dev->irqlock, req_buf->type, vpfe_dev->fmt.fmt.pix.field, From e53a70b4725f0a5e10e659c8352696548b9b9478 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 9 Nov 2009 09:13:20 -0300 Subject: [PATCH 291/345] V4L/DVB (13464): Davinci VPFE Capture: add i2c adapter id in platform data The I2C adapter ID is actually depends on Board and may vary, Davinci uses id=1, but in case of AM3517 id=3. Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/davinci/vpfe_capture.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h index 71d8982e13ff..d863e5e8426d 100644 --- a/include/media/davinci/vpfe_capture.h +++ b/include/media/davinci/vpfe_capture.h @@ -83,6 +83,8 @@ struct vpfe_subdev_info { struct vpfe_config { /* Number of sub devices connected to vpfe */ int num_subdevs; + /* i2c bus adapter no */ + int i2c_adapter_id; /* information about each subdev */ struct vpfe_subdev_info *sub_devs; /* evm card info */ From 14cbaafe6f8587aed632de747322cd3add421a76 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 9 Nov 2009 09:14:16 -0300 Subject: [PATCH 292/345] V4L/DVB (13465): Davinci VPFE Capture: Take i2c adapter id through platform data The I2C adapter ID is actually depends on Board and may vary, Davinci uses id=1, but in case of AM3517 id=3. Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index c704a2637683..86f7e75f12c5 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1978,8 +1978,7 @@ static __init int vpfe_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vpfe_dev); /* set driver private data */ video_set_drvdata(vpfe_dev->video_dev, vpfe_dev); - i2c_adap = i2c_get_adapter(1); - vpfe_cfg = pdev->dev.platform_data; + i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id); num_subdevs = vpfe_cfg->num_subdevs; vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs, GFP_KERNEL); From 1ead696b4c1b719eeae313618bca89e7b37c7d9b Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 9 Nov 2009 09:15:07 -0300 Subject: [PATCH 293/345] V4L/DVB (13466): Davinci VPFE Capture:Replaced IRQ_VDINT1 with vpfe_dev->ccdc_irq1 Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 86f7e75f12c5..1c3bde7fcd5e 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -660,7 +660,7 @@ static void vpfe_detach_irq(struct vpfe_device *vpfe_dev) frame_format = ccdc_dev->hw_ops.get_frame_format(); if (frame_format == CCDC_FRMFMT_PROGRESSIVE) - free_irq(IRQ_VDINT1, vpfe_dev); + free_irq(vpfe_dev->ccdc_irq1, vpfe_dev); } static int vpfe_attach_irq(struct vpfe_device *vpfe_dev) From 85213630731605503c8fd4df9bf06beefb2cc7c4 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Tue, 10 Nov 2009 13:32:53 -0300 Subject: [PATCH 294/345] V4L/DVB (13467): V4L2: Added CID's V4L2_CID_ROTATE/BG_COLOR Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/videodev2.h.xml | 4 +++- drivers/media/video/v4l2-common.c | 9 +++++++++ include/linux/videodev2.h | 4 +++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index bb6b07f9ea14..7162b9ffc2b3 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml @@ -915,8 +915,10 @@ enum v4l2_colorfx { #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) +#define V4L2_CID_ROTATE (V4L2_CID_BASE+34) +#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35) /* last CID + 1 */ -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+34) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+36) /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index f5a93ae3cdf9..e8e5affbabce 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -431,6 +431,8 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; case V4L2_CID_COLOR_KILLER: return "Color Killer"; case V4L2_CID_COLORFX: return "Color Effects"; + case V4L2_CID_ROTATE: return "Rotate"; + case V4L2_CID_BG_COLOR: return "Background color"; /* MPEG controls */ case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; @@ -587,6 +589,13 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; min = max = step = def = 0; break; + case V4L2_CID_BG_COLOR: + qctrl->type = V4L2_CTRL_TYPE_INTEGER; + step = 1; + min = 0; + /* Max is calculated as RGB888 that is 2^24 */ + max = 0xFFFFFF; + break; default: qctrl->type = V4L2_CTRL_TYPE_INTEGER; break; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index b9a799a35763..54395460a414 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -913,8 +913,10 @@ enum v4l2_colorfx { #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) +#define V4L2_CID_ROTATE (V4L2_CID_BASE+34) +#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35) /* last CID + 1 */ -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+34) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+36) /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) From bd9778019b4bd52fe21b4e41b826b1282693687e Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 9 Nov 2009 10:04:06 -0300 Subject: [PATCH 295/345] V4L/DVB (13468): v4l2 doc: Added ROTATE and BG_COLOR control documentation Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/controls.xml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Documentation/DocBook/v4l/controls.xml b/Documentation/DocBook/v4l/controls.xml index f492accb691d..f46450610412 100644 --- a/Documentation/DocBook/v4l/controls.xml +++ b/Documentation/DocBook/v4l/controls.xml @@ -280,11 +280,29 @@ minimum value disables backlight compensation. V4L2_COLORFX_BW (1) and V4L2_COLORFX_SEPIA (2). + + V4L2_CID_ROTATE + integer + Rotates the image by specified angle. Common angles are 90, + 270 and 180. Rotating the image to 90 and 270 will reverse the height + and width of the display window. It is necessary to set the new height and + width of the picture using the &VIDIOC-S-FMT; ioctl according to + the rotation angle selected. + + + V4L2_CID_BG_COLOR + integer + Sets the background color on the current output device. + Background color needs to be specified in the RGB24 format. The + supplied 32 bit value is interpreted as bits 0-7 Red color information, + bits 8-15 Green color information, bits 16-23 Blue color + information and bits 24-31 must be zero. + V4L2_CID_LASTP1 End of the predefined control IDs (currently -V4L2_CID_COLORFX + 1). +V4L2_CID_BG_COLOR + 1). V4L2_CID_PRIVATE_BASE From d73bfc5fe625f6962d0ced84066e201249f14e53 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Tue, 10 Nov 2009 13:12:25 -0300 Subject: [PATCH 296/345] V4L/DVB (13469): Davinci VPFE Capture: Add support for Control ioctls Added support for Control IOCTL, - s_ctrl - g_ctrl - queryctrl Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 1c3bde7fcd5e..12a1b3d7132d 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1413,6 +1413,41 @@ static int vpfe_dqbuf(struct file *file, void *priv, buf, file->f_flags & O_NONBLOCK); } +static int vpfe_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qctrl) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + + sdinfo = vpfe_dev->current_subdev; + + return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, + core, queryctrl, qctrl); + +} + +static int vpfe_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + + sdinfo = vpfe_dev->current_subdev; + + return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, + core, g_ctrl, ctrl); +} + +static int vpfe_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + + sdinfo = vpfe_dev->current_subdev; + + return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, + core, s_ctrl, ctrl); +} + /* * vpfe_calculate_offsets : This function calculates buffers offset * for top and bottom field @@ -1710,6 +1745,9 @@ static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { .vidioc_querystd = vpfe_querystd, .vidioc_s_std = vpfe_s_std, .vidioc_g_std = vpfe_g_std, + .vidioc_queryctrl = vpfe_queryctrl, + .vidioc_g_ctrl = vpfe_g_ctrl, + .vidioc_s_ctrl = vpfe_s_ctrl, .vidioc_reqbufs = vpfe_reqbufs, .vidioc_querybuf = vpfe_querybuf, .vidioc_qbuf = vpfe_qbuf, From d8008562379b927758ca08eded1508c68d9beb4e Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Tue, 10 Nov 2009 13:46:36 -0300 Subject: [PATCH 297/345] V4L/DVB (13470): V4L2: Add Capability and Flag field for Chroma Key Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/videodev2.h.xml | 2 ++ include/linux/videodev2.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index 7162b9ffc2b3..228277bf9f10 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml @@ -566,6 +566,7 @@ struct v4l2_framebuffer { #define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010 #define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020 #define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040 +#define V4L2_FBUF_CAP_SRC_CHROMAKEY 0x0080 /* Flags for the 'flags' field. */ #define V4L2_FBUF_FLAG_PRIMARY 0x0001 #define V4L2_FBUF_FLAG_OVERLAY 0x0002 @@ -573,6 +574,7 @@ struct v4l2_framebuffer { #define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008 #define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010 #define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020 +#define V4L2_FBUF_FLAG_SRC_CHROMAKEY 0x0040 struct v4l2_clip { struct v4l2_rect c; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 54395460a414..e4eb403a3b00 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -564,6 +564,7 @@ struct v4l2_framebuffer { #define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010 #define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020 #define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040 +#define V4L2_FBUF_CAP_SRC_CHROMAKEY 0x0080 /* Flags for the 'flags' field. */ #define V4L2_FBUF_FLAG_PRIMARY 0x0001 #define V4L2_FBUF_FLAG_OVERLAY 0x0002 @@ -571,6 +572,7 @@ struct v4l2_framebuffer { #define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008 #define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010 #define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020 +#define V4L2_FBUF_FLAG_SRC_CHROMAKEY 0x0040 struct v4l2_clip { struct v4l2_rect c; From a4834cef185fbe73f26c864fe38badc4f890afb7 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Tue, 10 Nov 2009 13:14:51 -0300 Subject: [PATCH 298/345] V4L/DVB (13471): v4l2 doc: Added FBUF_CAP_SRC_CHROMAKEY/FLAG_SRC_CHROMAKEY Signed-off-by: Vaibhav Hiremath Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/vidioc-g-fbuf.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/DocBook/v4l/vidioc-g-fbuf.xml b/Documentation/DocBook/v4l/vidioc-g-fbuf.xml index f7017062656e..e7dda4822f04 100644 --- a/Documentation/DocBook/v4l/vidioc-g-fbuf.xml +++ b/Documentation/DocBook/v4l/vidioc-g-fbuf.xml @@ -336,6 +336,13 @@ alpha value. Alpha blending makes no sense for destructive overlays. inverted alpha channel of the framebuffer or VGA signal. Alpha blending makes no sense for destructive overlays. + + V4L2_FBUF_CAP_SRC_CHROMAKEY + 0x0080 + The device supports Source Chroma-keying. Framebuffer pixels +with the chroma-key colors are replaced by video pixels, which is exactly opposite of +V4L2_FBUF_CAP_CHROMAKEY + @@ -411,6 +418,16 @@ images, but with an inverted alpha value. The blend function is: output = framebuffer pixel * (1 - alpha) + video pixel * alpha. The actual alpha depth depends on the framebuffer pixel format. + + V4L2_FBUF_FLAG_SRC_CHROMAKEY + 0x0040 + Use source chroma-keying. The source chroma-key color is +determined by the chromakey field of +&v4l2-window; and negotiated with the &VIDIOC-S-FMT; ioctl, see and . +Both chroma-keying are mutual exclusive to each other, so same +chromakey field of &v4l2-window; is being used. + From 57f902d0f38ebc38ea0a00899743eb917c61a7db Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 11:27:16 -0300 Subject: [PATCH 299/345] V4L/DVB (13476): spec: remove old dvb-spec and v4l2-spec directories It was really confusing to have media-specs, v4l2-spec and dvb-spec. So this patch removes v4l2-spec and dvb-spec. The docs in dvb-spec and the V4L1_API.html file were moved to media-specs/old-docs. Removed all references to v4l2-spec and dvb-spec. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/si4713.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/video4linux/si4713.txt b/Documentation/video4linux/si4713.txt index 25abdb78209d..2e7392a4fee1 100644 --- a/Documentation/video4linux/si4713.txt +++ b/Documentation/video4linux/si4713.txt @@ -164,7 +164,7 @@ Stereo/Mono and RDS subchannels The device can also be configured using the available sub channels for transmission. To do that use S/G_MODULATOR ioctl and configure txsubchans properly. -Refer to v4l2-spec for proper use of this ioctl. +Refer to the V4L2 API specification for proper use of this ioctl. Testing ======= From dbc8e34a3265e7ec6b2a07c4337c60a947768891 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 9 Jun 2009 17:34:01 -0300 Subject: [PATCH 300/345] V4L/DVB (13477): v4l2-subdev: remove unnecessary check Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 88c13d6f7912..00bf17608453 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -385,7 +385,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd, 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) ? -ENODEV : (((sd)->ops->o && (sd)->ops->o->f) ? \ (sd)->ops->o->f((sd) , ##args) : -ENOIOCTLCMD)) /* Send a notification to v4l2_device. */ From 7f3ea4debb8106287af87dd0ee770e97b59c1ac4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 11:55:04 -0300 Subject: [PATCH 301/345] V4L/DVB (13478): cx18: remove bogus init call. The cx18 av core implemented an init call for no good reason. It's now turned into an internal function. Signed-off-by: Hans Verkuil Reviewed-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 14 +++++++------- drivers/media/video/cx18/cx18-driver.c | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 536dedb23ba3..4392c76af5df 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -99,10 +99,8 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask, or_value); } -static int cx18_av_init(struct v4l2_subdev *sd, u32 val) +static void cx18_av_init(struct cx18 *cx) { - struct cx18 *cx = v4l2_get_subdevdata(sd); - /* * The crystal freq used in calculations in this driver will be * 28.636360 MHz. @@ -125,7 +123,6 @@ static int cx18_av_init(struct v4l2_subdev *sd, u32 val) /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); - return 0; } static void cx18_av_initialize(struct v4l2_subdev *sd) @@ -198,7 +195,7 @@ static void cx18_av_initialize(struct v4l2_subdev *sd) cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000); /* Setup the Video and and Aux/Audio PLLs */ - cx18_av_init(sd, 0); + cx18_av_init(cx); /* set video to auto-detect */ /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */ @@ -1355,7 +1352,6 @@ static int cx18_av_s_register(struct v4l2_subdev *sd, static const struct v4l2_subdev_core_ops cx18_av_general_ops = { .g_chip_ident = cx18_av_g_chip_ident, .log_status = cx18_av_log_status, - .init = cx18_av_init, .load_fw = cx18_av_load_fw, .reset = cx18_av_reset, .queryctrl = cx18_av_queryctrl, @@ -1399,6 +1395,7 @@ int cx18_av_probe(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; struct v4l2_subdev *sd; + int err; state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) @@ -1417,5 +1414,8 @@ int cx18_av_probe(struct cx18 *cx) snprintf(sd->name, sizeof(sd->name), "%s %03x", cx->v4l2_dev.name, (state->rev >> 4)); sd->grp_id = CX18_HW_418_AV; - return v4l2_device_register_subdev(&cx->v4l2_dev, sd); + err = v4l2_device_register_subdev(&cx->v4l2_dev, sd); + if (!err) + cx18_av_init(cx); + return err; } diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 1a67ad5daad3..7f65a47f12e1 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -912,7 +912,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, CX18_ERR("Could not register A/V decoder subdevice\n"); goto free_map; } - cx18_call_hw(cx, CX18_HW_418_AV, core, init, 0); /* Initialize GPIO Reset Controller to do chip resets during i2c init */ if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) { From a7925eb3e4b5cf9f223cd30bbd3e93b9daa02816 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 14:29:33 -0300 Subject: [PATCH 302/345] V4L/DVB (13479): cxusb: fix compile warning Fix this trivial compile warning: v4l/cxusb.c:1195: warning: unused variable 'n' Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 542de171874a..05fb28e9c69e 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -1189,7 +1189,6 @@ static struct atbm8830_config mygica_d689_atbm8830_cfg = { static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap->dev; - int n; /* Select required USB configuration */ if (usb_set_interface(d->udev, 0, 0) < 0) From b8415f5314ce0b190b5963d2180441cd862efa26 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 14:30:53 -0300 Subject: [PATCH 303/345] V4L/DVB (13480): atbm8830: fix compile warning Fix this trivial compile warning: v4l/atbm8830.c:164: warning: 'set_agc_config' defined but not used Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/atbm8830.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c index 87fb3c23b80f..d77684893d99 100644 --- a/drivers/media/dvb/frontends/atbm8830.c +++ b/drivers/media/dvb/frontends/atbm8830.c @@ -114,7 +114,7 @@ static int set_osc_freq(struct atbm_state *priv, u32 freq /*in kHz*/) static int set_if_freq(struct atbm_state *priv, u32 freq /*in kHz*/) { - + u32 fs = priv->config->osc_clk_freq; double t; u32 val; @@ -161,15 +161,6 @@ static int is_locked(struct atbm_state *priv, u8 *locked) return 0; } -static int set_agc_config(struct atbm_state *priv, - u8 min, u8 max, u8 hold_loop) -{ - atbm8830_write_reg(priv, REG_AGC_MIN, min); - atbm8830_write_reg(priv, REG_AGC_MAX, max); - atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop); - - return 0; -} static int set_static_channel_mode(struct atbm_state *priv) { From 569691a5a0fe844e36890e49833130e665868136 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 14 Nov 2009 09:45:38 -0300 Subject: [PATCH 304/345] V4L/DVB (13487): gspca - ov534: Add svga, xga and sxga modes for ov965x. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 331 +++++++++++++++++++++++++----- 1 file changed, 278 insertions(+), 53 deletions(-) diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 193129a59ab7..4f0f60ebd6c7 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -274,7 +274,7 @@ static struct ctrl sd_ctrls_ov772x[] = { static struct ctrl sd_ctrls_ov965x[] = { }; -static const struct v4l2_pix_format vga_yuyv_mode[] = { +static const struct v4l2_pix_format ov772x_mode[] = { {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 320 * 2, .sizeimage = 320 * 240 * 2, @@ -287,16 +287,31 @@ static const struct v4l2_pix_format vga_yuyv_mode[] = { .priv = 0}, }; -static const struct v4l2_pix_format vga_jpeg_mode[] = { +static const struct v4l2_pix_format ov965x_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, + .priv = 4}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 3}, + {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 800, + .sizeimage = 800 * 600 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 2}, + {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 1024, + .sizeimage = 1024 * 768 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, + {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = 1280 * 1024 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; static const u8 bridge_init_ov772x[][2] = { @@ -773,7 +788,7 @@ static const u8 sensor_init_ov965x_2[][2] = { {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ }; -static const u8 sensor_start_ov965x[][2] = { +static const u8 sensor_start_ov965x_1_vga[][2] = { /* same for qvga */ {0x12, 0x62}, /* com7 - 30fps VGA YUV */ {0x36, 0xfa}, /* aref3 */ {0x69, 0x0a}, /* hv */ @@ -797,7 +812,78 @@ static const u8 sensor_start_ov965x[][2] = { {} }; -static const u8 bridge_start_ov965x[][2] = { +static const u8 sensor_start_ov965x_1_svga[][2] = { + {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */ + {0x36, 0xf8}, /* aref3 */ + {0x69, 0x02}, /* hv */ + {0x8c, 0x0d}, /* com22 */ + {0x3e, 0x0c}, /* com14 */ + {0x41, 0x40}, /* com16 */ + {0x72, 0x00}, + {0x73, 0x01}, + {0x74, 0x3a}, + {0x75, 0x35}, + {0x76, 0x01}, + {0xc7, 0x80}, /* com24 */ + {0x03, 0x1b}, /* vref */ + {0x17, 0x1d}, /* hstart */ + {0x18, 0xbd}, /* hstop */ + {0x19, 0x01}, /* vstrt */ + {0x1a, 0x81}, /* vstop */ + {0x32, 0xff}, /* href */ + {0xc0, 0xe2}, + {} +}; + +static const u8 sensor_start_ov965x_1_xga[][2] = { + {0x12, 0x02}, /* com7 */ + {0x36, 0xf8}, /* aref3 */ + {0x69, 0x02}, /* hv */ + {0x8c, 0x89}, /* com22 */ + {0x14, 0x28}, /* com9 */ + {0x3e, 0x0c}, /* com14 */ + {0x41, 0x40}, /* com16 */ + {0x72, 0x00}, + {0x73, 0x01}, + {0x74, 0x3a}, + {0x75, 0x35}, + {0x76, 0x01}, + {0xc7, 0x80}, /* com24 */ + {0x03, 0x1b}, /* vref */ + {0x17, 0x1d}, /* hstart */ + {0x18, 0xbd}, /* hstop */ + {0x19, 0x01}, /* vstrt */ + {0x1a, 0x81}, /* vstop */ + {0x32, 0xff}, /* href */ + {0xc0, 0xe2}, + {} +}; + +static const u8 sensor_start_ov965x_1_sxga[][2] = { + {0x12, 0x02}, /* com7 */ + {0x36, 0xf8}, /* aref3 */ + {0x69, 0x02}, /* hv */ + {0x8c, 0x89}, /* com22 */ + {0x14, 0x28}, /* com9 */ + {0x3e, 0x0c}, /* com14 */ + {0x41, 0x40}, /* com16 */ + {0x72, 0x00}, + {0x73, 0x01}, + {0x74, 0x3a}, + {0x75, 0x35}, + {0x76, 0x01}, + {0xc7, 0x80}, /* com24 */ + {0x03, 0x1b}, /* vref */ + {0x17, 0x1d}, /* hstart */ + {0x18, 0x02}, /* hstop */ + {0x19, 0x01}, /* vstrt */ + {0x1a, 0x81}, /* vstop */ + {0x32, 0xff}, /* href */ + {0xc0, 0xe2}, + {} +}; + +static const u8 bridge_start_ov965x_qvga[][2] = { {0x94, 0xaa}, {0xf1, 0x60}, {0xe5, 0x04}, @@ -806,30 +892,7 @@ static const u8 bridge_start_ov965x[][2] = { {0x8c, 0x00}, {0x8d, 0x1c}, {0x34, 0x05}, - {} -}; -static const u8 bridge_start_ov965x_vga[][2] = { - {0xc2, 0x0c}, - {0xc3, 0xf9}, - {0xda, 0x01}, - {0x50, 0x00}, - {0x51, 0xa0}, - {0x52, 0x3c}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x57, 0x00}, - {0x5c, 0x00}, - {0x5a, 0xa0}, - {0x5b, 0x78}, - {0x35, 0x02}, - {0xd9, 0x10}, - {0x94, 0x11}, - {} -}; - -static const u8 bridge_start_ov965x_qvga[][2] = { {0xc2, 0x4c}, {0xc3, 0xf9}, {0xda, 0x00}, @@ -849,7 +912,129 @@ static const u8 bridge_start_ov965x_qvga[][2] = { {} }; -static const u8 sensor_start_ov965x_vga[][2] = { +static const u8 bridge_start_ov965x_vga[][2] = { + {0x94, 0xaa}, + {0xf1, 0x60}, + {0xe5, 0x04}, + {0xc0, 0x50}, + {0xc1, 0x3c}, + {0x8c, 0x00}, + {0x8d, 0x1c}, + {0x34, 0x05}, + {0xc2, 0x0c}, + {0xc3, 0xf9}, + {0xda, 0x01}, + {0x50, 0x00}, + {0x51, 0xa0}, + {0x52, 0x3c}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x57, 0x00}, + {0x5c, 0x00}, + {0x5a, 0xa0}, + {0x5b, 0x78}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0x94, 0x11}, + {} +}; + +static const u8 bridge_start_ov965x_svga[][2] = { + {0x94, 0xaa}, + {0xf1, 0x60}, + {0xe5, 0x04}, + {0xc0, 0xa0}, + {0xc1, 0x80}, + {0x8c, 0x00}, + {0x8d, 0x1c}, + {0x34, 0x05}, + + {0xc2, 0x4c}, + {0xc3, 0xf9}, + {0x50, 0x00}, + {0x51, 0x40}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x88}, + {0x57, 0x00}, + {0x5c, 0x00}, + {0x5a, 0xc8}, + {0x5b, 0x96}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0xda, 0x00}, + {0x94, 0x11}, + {} +}; + +static const u8 bridge_start_ov965x_xga[][2] = { + {0x94, 0xaa}, + {0xf1, 0x60}, + {0xe5, 0x04}, + {0xc0, 0xa0}, + {0xc1, 0x80}, + {0x8c, 0x00}, + {0x8d, 0x1c}, + {0x34, 0x05}, + {0xc2, 0x4c}, + {0xc3, 0xf9}, + {0x50, 0x00}, + {0x51, 0x40}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x88}, + {0x57, 0x00}, + {0x5c, 0x01}, + {0x5a, 0x00}, + {0x5b, 0xc0}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0xda, 0x01}, + {0x94, 0x11}, + {} +}; + +static const u8 bridge_start_ov965x_sxga[][2] = { + {0x94, 0xaa}, + {0xf1, 0x60}, + {0xe5, 0x04}, + {0xc0, 0xa0}, + {0xc1, 0x80}, + {0x8c, 0x00}, + {0x8d, 0x1c}, + {0x34, 0x05}, + {0xc2, 0x0c}, + {0xc3, 0xf9}, + {0xda, 0x00}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0x94, 0x11}, + {} +}; + +static const u8 sensor_start_ov965x_2_qvga[][2] = { + {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ + {0x1e, 0x04}, /* mvfp */ + {0x13, 0xe0}, /* com8 */ + {0x00, 0x00}, + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x11, 0x01}, /* clkrc */ + {0x6b, 0x5a}, /* dblv */ + {0x6a, 0x02}, /* 50 Hz banding filter */ + {0xc5, 0x03}, /* 60 Hz banding filter */ + {0xa2, 0x96}, /* bd50 */ + {0xa3, 0x7d}, /* bd60 */ + + {0xff, 0x13}, /* read 13, write ff 00 */ + {0x13, 0xe7}, + {0x3a, 0x80}, /* tslb - yuyv */ + {} +}; + +static const u8 sensor_start_ov965x_2_vga[][2] = { {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ {0x1e, 0x04}, /* mvfp */ {0x13, 0xe0}, /* com8 */ @@ -866,22 +1051,35 @@ static const u8 sensor_start_ov965x_vga[][2] = { {} }; -static const u8 sensor_start_ov965x_qvga[][2] = { - {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ +static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */ + {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ {0x1e, 0x04}, /* mvfp */ {0x13, 0xe0}, /* com8 */ {0x00, 0x00}, {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ {0x11, 0x01}, /* clkrc */ {0x6b, 0x5a}, /* dblv */ - {0x6a, 0x02}, /* 50 Hz banding filter */ - {0xc5, 0x03}, /* 60 Hz banding filter */ - {0xa2, 0x96}, /* bd50 */ - {0xa3, 0x7d}, /* bd60 */ + {0x6a, 0x0c}, /* 50 Hz banding filter */ + {0xc5, 0x0f}, /* 60 Hz banding filter */ + {0xa2, 0x4e}, /* bd50 */ + {0xa3, 0x41}, /* bd60 */ + {0x2d, 0x00}, /* advfl */ + {} +}; - {0xff, 0x13}, /* read 13, write ff 00 */ - {0x13, 0xe7}, - {0x3a, 0x80}, /* tslb - yuyv */ +static const u8 sensor_start_ov965x_2_sxga[][2] = { + {0x13, 0xe0}, /* com8 */ + {0x00, 0x00}, + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ + {0x1e, 0x04}, /* mvfp */ + {0x11, 0x01}, /* clkrc */ + {0x6b, 0x5a}, /* dblv */ + {0x6a, 0x0c}, /* 50 Hz banding filter */ + {0xc5, 0x0f}, /* 60 Hz banding filter */ + {0xa2, 0x4e}, /* bd50 */ + {0xa3, 0x41}, /* bd60 */ + {0x2d, 0x00}, /* advfl */ {} }; @@ -1216,15 +1414,15 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; if (sd->sensor == SENSOR_OV772X) { - cam->cam_mode = vga_yuyv_mode; - cam->nmodes = ARRAY_SIZE(vga_yuyv_mode); + cam->cam_mode = ov772x_mode; + cam->nmodes = ARRAY_SIZE(ov772x_mode); cam->bulk = 1; cam->bulk_size = 16384; cam->bulk_nurbs = 2; } else { /* ov965x */ - cam->cam_mode = vga_jpeg_mode; - cam->nmodes = ARRAY_SIZE(vga_jpeg_mode); + cam->cam_mode = ov965x_mode; + cam->nmodes = ARRAY_SIZE(ov965x_mode); } sd->frame_rate = 30; @@ -1355,22 +1553,49 @@ static int sd_start_ov965x(struct gspca_dev *gspca_dev) { int mode; - sccb_w_array(gspca_dev, sensor_start_ov965x, - ARRAY_SIZE(sensor_start_ov965x)); - reg_w_array(gspca_dev, bridge_start_ov965x, - ARRAY_SIZE(bridge_start_ov965x)); - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - if (mode != 0) { /* 320x240 */ + switch (mode) { + default: +/* case 4: * 320x240 */ + sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga, + ARRAY_SIZE(sensor_start_ov965x_1_vga)); reg_w_array(gspca_dev, bridge_start_ov965x_qvga, ARRAY_SIZE(bridge_start_ov965x_qvga)); - sccb_w_array(gspca_dev, sensor_start_ov965x_qvga, - ARRAY_SIZE(sensor_start_ov965x_qvga)); - } else { /* 640x480 */ + sccb_w_array(gspca_dev, sensor_start_ov965x_2_qvga, + ARRAY_SIZE(sensor_start_ov965x_2_qvga)); + break; + case 3: /* 640x480 */ + sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga, + ARRAY_SIZE(sensor_start_ov965x_1_vga)); reg_w_array(gspca_dev, bridge_start_ov965x_vga, ARRAY_SIZE(bridge_start_ov965x_vga)); - sccb_w_array(gspca_dev, sensor_start_ov965x_vga, - ARRAY_SIZE(sensor_start_ov965x_vga)); + sccb_w_array(gspca_dev, sensor_start_ov965x_2_vga, + ARRAY_SIZE(sensor_start_ov965x_2_vga)); + break; + case 2: /* 800x600 */ + sccb_w_array(gspca_dev, sensor_start_ov965x_1_svga, + ARRAY_SIZE(sensor_start_ov965x_1_svga)); + reg_w_array(gspca_dev, bridge_start_ov965x_svga, + ARRAY_SIZE(bridge_start_ov965x_svga)); + sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga, + ARRAY_SIZE(sensor_start_ov965x_2_svga)); + break; + case 1: /* 1024x768 */ + sccb_w_array(gspca_dev, sensor_start_ov965x_1_xga, + ARRAY_SIZE(sensor_start_ov965x_1_xga)); + reg_w_array(gspca_dev, bridge_start_ov965x_xga, + ARRAY_SIZE(bridge_start_ov965x_xga)); + sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga, + ARRAY_SIZE(sensor_start_ov965x_2_svga)); + break; + case 0: /* 1280x1024 */ + sccb_w_array(gspca_dev, sensor_start_ov965x_1_sxga, + ARRAY_SIZE(sensor_start_ov965x_1_sxga)); + reg_w_array(gspca_dev, bridge_start_ov965x_sxga, + ARRAY_SIZE(bridge_start_ov965x_sxga)); + sccb_w_array(gspca_dev, sensor_start_ov965x_2_sxga, + ARRAY_SIZE(sensor_start_ov965x_2_sxga)); + break; } sccb_w_array(gspca_dev, sensor_start_ov965x_2, ARRAY_SIZE(sensor_start_ov965x_2)); From 4e5cf58ecf98f7cce8033d5b8249c3e9d7ada3f0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 15 Nov 2009 05:21:09 -0300 Subject: [PATCH 305/345] V4L/DVB (13488): gspca - ov534: Remove extra values at end of ov965x sequences. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4f0f60ebd6c7..6817fccd6fd8 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -809,7 +809,6 @@ static const u8 sensor_start_ov965x_1_vga[][2] = { /* same for qvga */ {0x1a, 0x3d}, /* vstop */ {0x32, 0xff}, /* href */ {0xc0, 0xaa}, - {} }; static const u8 sensor_start_ov965x_1_svga[][2] = { @@ -832,7 +831,6 @@ static const u8 sensor_start_ov965x_1_svga[][2] = { {0x1a, 0x81}, /* vstop */ {0x32, 0xff}, /* href */ {0xc0, 0xe2}, - {} }; static const u8 sensor_start_ov965x_1_xga[][2] = { @@ -856,7 +854,6 @@ static const u8 sensor_start_ov965x_1_xga[][2] = { {0x1a, 0x81}, /* vstop */ {0x32, 0xff}, /* href */ {0xc0, 0xe2}, - {} }; static const u8 sensor_start_ov965x_1_sxga[][2] = { @@ -880,7 +877,6 @@ static const u8 sensor_start_ov965x_1_sxga[][2] = { {0x1a, 0x81}, /* vstop */ {0x32, 0xff}, /* href */ {0xc0, 0xe2}, - {} }; static const u8 bridge_start_ov965x_qvga[][2] = { @@ -909,7 +905,6 @@ static const u8 bridge_start_ov965x_qvga[][2] = { {0x35, 0x02}, {0xd9, 0x10}, {0x94, 0x11}, - {} }; static const u8 bridge_start_ov965x_vga[][2] = { @@ -937,7 +932,6 @@ static const u8 bridge_start_ov965x_vga[][2] = { {0x35, 0x02}, {0xd9, 0x10}, {0x94, 0x11}, - {} }; static const u8 bridge_start_ov965x_svga[][2] = { @@ -966,7 +960,6 @@ static const u8 bridge_start_ov965x_svga[][2] = { {0xd9, 0x10}, {0xda, 0x00}, {0x94, 0x11}, - {} }; static const u8 bridge_start_ov965x_xga[][2] = { @@ -994,7 +987,6 @@ static const u8 bridge_start_ov965x_xga[][2] = { {0xd9, 0x10}, {0xda, 0x01}, {0x94, 0x11}, - {} }; static const u8 bridge_start_ov965x_sxga[][2] = { @@ -1012,7 +1004,6 @@ static const u8 bridge_start_ov965x_sxga[][2] = { {0x35, 0x02}, {0xd9, 0x10}, {0x94, 0x11}, - {} }; static const u8 sensor_start_ov965x_2_qvga[][2] = { @@ -1031,7 +1022,6 @@ static const u8 sensor_start_ov965x_2_qvga[][2] = { {0xff, 0x13}, /* read 13, write ff 00 */ {0x13, 0xe7}, {0x3a, 0x80}, /* tslb - yuyv */ - {} }; static const u8 sensor_start_ov965x_2_vga[][2] = { @@ -1048,7 +1038,6 @@ static const u8 sensor_start_ov965x_2_vga[][2] = { {0xa3, 0x3e}, /* bd60 */ {0x2d, 0x00}, /* advfl */ - {} }; static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */ @@ -1064,7 +1053,6 @@ static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */ {0xa2, 0x4e}, /* bd50 */ {0xa3, 0x41}, /* bd60 */ {0x2d, 0x00}, /* advfl */ - {} }; static const u8 sensor_start_ov965x_2_sxga[][2] = { @@ -1080,13 +1068,11 @@ static const u8 sensor_start_ov965x_2_sxga[][2] = { {0xa2, 0x4e}, /* bd50 */ {0xa3, 0x41}, /* bd60 */ {0x2d, 0x00}, /* advfl */ - {} }; static const u8 sensor_start_ov965x_2[][2] = { {0xff, 0x42}, /* read 42, write ff 00 */ {0x42, 0xc1}, /* com17 - 50 Hz filter */ - {} }; From b8c8a5bf833db5ad80266a6a9e5ad496ab01d434 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 23 Nov 2009 06:46:35 -0300 Subject: [PATCH 306/345] V4L/DVB (13489): gspca - sonixj: Add the sensor po1030. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 153 ++++++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 282c707e5e81..0bd36a00dd2a 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -72,7 +72,8 @@ struct sd { #define SENSOR_OV7630 5 #define SENSOR_OV7648 6 #define SENSOR_OV7660 7 -#define SENSOR_SP80708 8 +#define SENSOR_PO1030 8 +#define SENSOR_SP80708 9 u8 i2c_addr; u8 *jpeg_hdr; @@ -250,7 +251,7 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ .step = 1, -#define FREQ_DEF 2 +#define FREQ_DEF 1 .default_value = FREQ_DEF, }, .set = sd_setfreq, @@ -277,7 +278,9 @@ static __u32 ctrl_dis[] = { (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OV7660 7 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | - (1 << FREQ_IDX), /* SENSOR_SP80708 8 */ + (1 << FREQ_IDX), /* SENSOR_PO1030 8 */ + (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | + (1 << FREQ_IDX), /* SENSOR_SP80708 9 */ }; static const struct v4l2_pix_format vga_mode[] = { @@ -388,6 +391,17 @@ static const u8 sn_ov7660[0x1c] = { 0x07, 0x00, 0x00, 0x00 }; +static const u8 sn_po1030[0x1c] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x00, +/* reg18 reg19 reg1a reg1b */ + 0x07, 0x00, 0x00, 0x00 +}; + static const u8 sn_sp80708[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, @@ -409,6 +423,7 @@ static const u8 *sn_tb[] = { sn_ov7630, sn_ov7648, sn_ov7660, + sn_po1030, sn_sp80708 }; @@ -832,6 +847,60 @@ static const u8 ov7660_sensor_param1[][8] = { {} }; +static const u8 po1030_sensor_init[][8] = { +/* the sensor registers are described in m5602/m5602_po1030.h */ + {0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */ + {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ + {0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10}, + {0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10}, + {0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10}, + {0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */ + {0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10}, + {0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */ + {0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10}, + {0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */ + {0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10}, + {0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10}, + {0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10}, + {0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10}, + {0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10}, + {0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10}, + {0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10}, + {0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */ + {0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10}, + + {0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10}, + {} +}; +static const u8 po1030_sensor_param1[][8] = { +/* from ms-win traces - these values change with auto gain/expo/wb.. */ + {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10}, +/* mean values */ + {0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */ + {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */ + {0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */ + + {0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */ + {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */ + {0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10}, +/* {0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */ + {} +}; + static const u8 sp80708_sensor_init[][8] = { {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, @@ -917,7 +986,7 @@ static const u8 sp80708_sensor_param1[][8] = { {} }; -static const u8 (*sensor_init[9])[8] = { +static const u8 (*sensor_init[10])[8] = { hv7131r_sensor_init, /* HV7131R 0 */ mi0360_sensor_init, /* MI0360 1 */ mo4000_sensor_init, /* MO4000 2 */ @@ -926,7 +995,8 @@ static const u8 (*sensor_init[9])[8] = { ov7630_sensor_init, /* OV7630 5 */ ov7648_sensor_init, /* OV7648 6 */ ov7660_sensor_init, /* OV7660 7 */ - sp80708_sensor_init, /* SP80708 8 */ + po1030_sensor_init, /* PO1030 8 */ + sp80708_sensor_init, /* SP80708 9 */ }; /* read bytes to gspca_dev->usb_buf */ @@ -1033,8 +1103,8 @@ static void i2c_w8(struct gspca_dev *gspca_dev, msleep(2); } -/* read 5 bytes in gspca_dev->usb_buf */ -static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) +/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */ +static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len) { struct sd *sd = (struct sd *) gspca_dev; u8 mode[8]; @@ -1056,7 +1126,7 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) mode[7] = 0x10; i2c_w8(gspca_dev, mode); msleep(2); - mode[0] = (mode[0] & 0x81) | (5 << 4) | 0x02; + mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02; mode[2] = 0; i2c_w8(gspca_dev, mode); msleep(2); @@ -1081,7 +1151,7 @@ static void hv7131r_probe(struct gspca_dev *gspca_dev) msleep(10); reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ msleep(10); - i2c_r5(gspca_dev, 0); /* read sensor id */ + i2c_r(gspca_dev, 0, 5); /* read sensor id */ if (gspca_dev->usb_buf[0] == 0x02 && gspca_dev->usb_buf[1] == 0x09 && gspca_dev->usb_buf[2] == 0x01 @@ -1144,6 +1214,41 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) } } +static void ov7648_probe(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + /* check ov76xx */ + reg_w1(gspca_dev, 0x17, 0x62); + reg_w1(gspca_dev, 0x01, 0x08); + sd->i2c_addr = 0x21; + i2c_r(gspca_dev, 0x0a, 2); + if (gspca_dev->usb_buf[3] == 0x76) { /* ov76xx */ + PDEBUG(D_PROBE, "Sensor ov%02x%02x", + gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); + return; + } + + /* reset */ + reg_w1(gspca_dev, 0x01, 0x29); + reg_w1(gspca_dev, 0x17, 0x42); + + /* check po1030 */ + reg_w1(gspca_dev, 0x17, 0x62); + reg_w1(gspca_dev, 0x01, 0x08); + sd->i2c_addr = 0x6e; + i2c_r(gspca_dev, 0x00, 2); + if (gspca_dev->usb_buf[3] == 0x10 /* po1030 */ + && gspca_dev->usb_buf[4] == 0x30) { + PDEBUG(D_PROBE, "Sensor po1030"); + sd->sensor = SENSOR_PO1030; + return; + } + + PDEBUG(D_PROBE, "Unknown sensor %02x%02x", + gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); +} + static void bridge_init(struct gspca_dev *gspca_dev, const u8 *sn9c1xx) { @@ -1164,6 +1269,7 @@ static void bridge_init(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); switch (sd->sensor) { case SENSOR_OV7660: + case SENSOR_PO1030: case SENSOR_SP80708: reg9a = reg9a_spec; break; @@ -1214,7 +1320,14 @@ static void bridge_init(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x62); reg_w1(gspca_dev, 0x01, 0x42); break; + case SENSOR_PO1030: + reg_w1(gspca_dev, 0x01, 0x61); + reg_w1(gspca_dev, 0x17, 0x20); + reg_w1(gspca_dev, 0x01, 0x60); + reg_w1(gspca_dev, 0x01, 0x40); + break; case SENSOR_OV7660: + /* fall thru */ case SENSOR_SP80708: reg_w1(gspca_dev, 0x01, 0x63); reg_w1(gspca_dev, 0x17, 0x20); @@ -1266,7 +1379,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->quality = QUALITY_DEF; sd->jpegqual = 80; - gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; return 0; } @@ -1301,8 +1413,14 @@ static int sd_init(struct gspca_dev *gspca_dev) case BRIDGE_SN9C120: if (regF1 != 0x12) return -ENODEV; - if (sd->sensor == SENSOR_MI0360) + switch (sd->sensor) { + case SENSOR_MI0360: mi0360_probe(gspca_dev); + break; + case SENSOR_OV7648: + ov7648_probe(gspca_dev); + break; + } regGpio[1] = 0x70; reg_w(gspca_dev, 0x01, regGpio, 2); break; @@ -1321,6 +1439,8 @@ static int sd_init(struct gspca_dev *gspca_dev) sn9c1xx = sn_tb[sd->sensor]; sd->i2c_addr = sn9c1xx[9]; + gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; + return 0; } @@ -1742,6 +1862,9 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7660: reg17 = 0xa0; break; + case SENSOR_PO1030: + reg17 = 0xa0; + break; default: reg17 = 0x60; break; @@ -1839,6 +1962,11 @@ static int sd_start(struct gspca_dev *gspca_dev) * inverse power down */ } break; + case SENSOR_PO1030: + init = po1030_sensor_param1; + reg17 = 0xa2; + reg1 = 0x44; + break; default: /* case SENSOR_SP80708: */ init = sp80708_sensor_param1; @@ -1919,6 +2047,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) /* fall thru */ case SENSOR_MT9V111: case SENSOR_OV7630: + case SENSOR_PO1030: data = 0x29; break; } @@ -2325,7 +2454,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */ {USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)}, /*sn9c325?*/ /*bw600.inf:*/ - {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)}, /*sn9c110?*/ + {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)}, /*sn9c325?*/ {USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)}, {USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)}, /* {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */ From c22c4a20a6ac7b10e43eab6963f941795c5e92aa Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 24 Nov 2009 05:22:05 -0300 Subject: [PATCH 307/345] V4L/DVB (13490): gspca - ov534: Add controls for sensor ov965x. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 479 +++++++++++++++++++++++++----- 1 file changed, 407 insertions(+), 72 deletions(-) diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 6817fccd6fd8..4dbb882c83dc 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -65,9 +65,11 @@ struct sd { u8 hue; u8 autogain; u8 awb; - u8 sharpness; + s8 sharpness; u8 hflip; u8 vflip; + u8 satur; + u8 lightfreq; u8 sensor; #define SENSOR_OV772X 0 @@ -99,6 +101,10 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 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_setsatur(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getsatur(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 struct ctrl sd_ctrls_ov772x[] = { { /* 0 */ @@ -109,8 +115,8 @@ static struct ctrl sd_ctrls_ov772x[] = { .minimum = 0, .maximum = 255, .step = 1, -#define BRIGHTNESS_DEF 20 - .default_value = BRIGHTNESS_DEF, +#define BRIGHTNESS_77_DEF 20 + .default_value = BRIGHTNESS_77_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, @@ -123,8 +129,8 @@ static struct ctrl sd_ctrls_ov772x[] = { .minimum = 0, .maximum = 255, .step = 1, -#define CONTRAST_DEF 37 - .default_value = CONTRAST_DEF, +#define CONTRAST_77_DEF 37 + .default_value = CONTRAST_77_DEF, }, .set = sd_setcontrast, .get = sd_getcontrast, @@ -151,8 +157,8 @@ static struct ctrl sd_ctrls_ov772x[] = { .minimum = 0, .maximum = 255, .step = 1, -#define EXPO_DEF 120 - .default_value = EXPO_DEF, +#define EXPO_77_DEF 120 + .default_value = EXPO_77_DEF, }, .set = sd_setexposure, .get = sd_getexposure, @@ -207,13 +213,13 @@ static struct ctrl sd_ctrls_ov772x[] = { .minimum = 0, .maximum = 1, .step = 1, -#define AUTOGAIN_DEF 0 - .default_value = AUTOGAIN_DEF, +#define AUTOGAIN_77_DEF 0 + .default_value = AUTOGAIN_77_DEF, }, .set = sd_setautogain, .get = sd_getautogain, }, -#define AWB_IDX 8 +#define AWB_77_IDX 8 { /* 8 */ { .id = V4L2_CID_AUTO_WHITE_BALANCE, @@ -236,8 +242,8 @@ static struct ctrl sd_ctrls_ov772x[] = { .minimum = 0, .maximum = 63, .step = 1, -#define SHARPNESS_DEF 0 - .default_value = SHARPNESS_DEF, +#define SHARPNESS_77_DEF 0 + .default_value = SHARPNESS_77_DEF, }, .set = sd_setsharpness, .get = sd_getsharpness, @@ -272,6 +278,105 @@ static struct ctrl sd_ctrls_ov772x[] = { }, }; static struct ctrl sd_ctrls_ov965x[] = { + { /* 0 */ + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 15, + .step = 1, +#define BRIGHTNESS_96_DEF 7 + .default_value = BRIGHTNESS_96_DEF, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, + { /* 1 */ + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 15, + .step = 1, +#define CONTRAST_96_DEF 3 + .default_value = CONTRAST_96_DEF, + }, + .set = sd_setcontrast, + .get = sd_getcontrast, + }, + { /* 2 */ + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Autogain", + .minimum = 0, + .maximum = 1, + .step = 1, +#define AUTOGAIN_96_DEF 1 + .default_value = AUTOGAIN_96_DEF, + }, + .set = sd_setautogain, + .get = sd_getautogain, + }, +#define EXPO_96_IDX 3 + { /* 3 */ + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 3, + .step = 1, +#define EXPO_96_DEF 0 + .default_value = EXPO_96_DEF, + }, + .set = sd_setexposure, + .get = sd_getexposure, + }, + { /* 4 */ + { + .id = V4L2_CID_SHARPNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Sharpness", + .minimum = -1, /* -1 = auto */ + .maximum = 4, + .step = 1, +#define SHARPNESS_96_DEF -1 + .default_value = SHARPNESS_96_DEF, + }, + .set = sd_setsharpness, + .get = sd_getsharpness, + }, + { /* 5 */ + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 4, + .step = 1, +#define SATUR_DEF 2 + .default_value = SATUR_DEF, + }, + .set = sd_setsatur, + .get = sd_getsatur, + }, + { + { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Light frequency filter", + .minimum = 0, + .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ + .step = 1, +#define FREQ_DEF 0 + .default_value = FREQ_DEF, + }, + .set = sd_setfreq, + .get = sd_getfreq, + }, }; static const struct v4l2_pix_format ov772x_mode[] = { @@ -314,6 +419,7 @@ static const struct v4l2_pix_format ov965x_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; + static const u8 bridge_init_ov772x[][2] = { { 0xc2, 0x0c }, { 0x88, 0xf8 }, @@ -689,7 +795,7 @@ static const u8 sensor_init_ov965x[][2] = { {0xcb, 0xf0}, {0xcc, 0xd8}, {0xcd, 0xf1}, - {0x4f, 0x98}, + {0x4f, 0x98}, /* matrix */ {0x50, 0x98}, {0x51, 0x00}, {0x52, 0x28}, @@ -698,6 +804,7 @@ static const u8 sensor_init_ov965x[][2] = { {0x58, 0x1a}, {0xff, 0x41}, /* read 41, write ff 00 */ {0x41, 0x40}, /* com16 */ + {0xc5, 0x03}, /* 60 Hz banding filter */ {0x6a, 0x02}, /* 50 Hz banding filter */ @@ -741,8 +848,8 @@ static const u8 bridge_init_ov965x_2[][2] = { {0x52, 0x3c}, {0x53, 0x00}, {0x54, 0x00}, - {0x55, 0x00}, /* brightness */ - {0x57, 0x00}, /* contrast 2 */ + {0x55, 0x00}, + {0x57, 0x00}, {0x5c, 0x00}, {0x5a, 0xa0}, {0x5b, 0x78}, @@ -765,14 +872,16 @@ static const u8 sensor_init_ov965x_2[][2] = { {0xa3, 0x3e}, {0x2d, 0x00}, {0xff, 0x42}, /* read 42, write ff 00 */ - {0x42, 0xc0}, + {0x42, 0xc0}, /* com17 */ {0x2d, 0x00}, {0xff, 0x42}, /* read 42, write ff 00 */ - {0x42, 0xc1}, + {0x42, 0xc1}, /* com17 */ +/* sharpness */ {0x3f, 0x01}, {0xff, 0x42}, /* read 42, write ff 00 */ - {0x42, 0xc1}, - {0x4f, 0x98}, + {0x42, 0xc1}, /* com17 */ +/* saturation */ + {0x4f, 0x98}, /* matrix */ {0x50, 0x98}, {0x51, 0x00}, {0x52, 0x28}, @@ -781,8 +890,11 @@ static const u8 sensor_init_ov965x_2[][2] = { {0x58, 0x1a}, {0xff, 0x41}, /* read 41, write ff 00 */ {0x41, 0x40}, /* com16 */ +/* contrast */ {0x56, 0x40}, +/* brightness */ {0x55, 0x8f}, +/* expo */ {0x10, 0x25}, /* aech - exposure high bits */ {0xff, 0x13}, /* read 13, write ff 00 */ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ @@ -943,7 +1055,6 @@ static const u8 bridge_start_ov965x_svga[][2] = { {0x8c, 0x00}, {0x8d, 0x1c}, {0x34, 0x05}, - {0xc2, 0x4c}, {0xc3, 0xf9}, {0x50, 0x00}, @@ -1052,7 +1163,6 @@ static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */ {0xc5, 0x0f}, /* 60 Hz banding filter */ {0xa2, 0x4e}, /* bd50 */ {0xa3, 0x41}, /* bd60 */ - {0x2d, 0x00}, /* advfl */ }; static const u8 sensor_start_ov965x_2_sxga[][2] = { @@ -1067,15 +1177,8 @@ static const u8 sensor_start_ov965x_2_sxga[][2] = { {0xc5, 0x0f}, /* 60 Hz banding filter */ {0xa2, 0x4e}, /* bd50 */ {0xa3, 0x41}, /* bd60 */ - {0x2d, 0x00}, /* advfl */ }; -static const u8 sensor_start_ov965x_2[][2] = { - {0xff, 0x42}, /* read 42, write ff 00 */ - {0x42, 0xc1}, /* com17 - 50 Hz filter */ -}; - - static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) { struct usb_device *udev = gspca_dev->dev; @@ -1257,14 +1360,14 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "frame_rate: %d", r->fps); } -static void setbrightness(struct gspca_dev *gspca_dev) +static void setbrightness_77(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; sccb_reg_write(gspca_dev, 0x9B, sd->brightness); } -static void setcontrast(struct gspca_dev *gspca_dev) +static void setcontrast_77(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1298,7 +1401,7 @@ static void setgain(struct gspca_dev *gspca_dev) sccb_reg_write(gspca_dev, 0x00, val); } -static void setexposure(struct gspca_dev *gspca_dev) +static void setexposure_77(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; u8 val; @@ -1329,7 +1432,7 @@ static void sethue(struct gspca_dev *gspca_dev) sccb_reg_write(gspca_dev, 0x01, sd->hue); } -static void setautogain(struct gspca_dev *gspca_dev) +static void setautogain_77(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1354,7 +1457,7 @@ static void setawb(struct gspca_dev *gspca_dev) sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ } -static void setsharpness(struct gspca_dev *gspca_dev) +static void setsharpness_77(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; u8 val; @@ -1388,6 +1491,132 @@ static void setvflip(struct gspca_dev *gspca_dev) sccb_reg_read(gspca_dev, 0x0c) & 0x7f); } +/* ov965x specific controls */ +static void setbrightness_96(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + + val = sd->brightness; + if (val < 8) + val = 15 - val; /* f .. 8 */ + else + val = val - 8; /* 0 .. 7 */ + sccb_reg_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ + 0x0f | (val << 4)); +} + +static void setcontrast_96(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sccb_reg_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */ + sd->contrast << 4); +} + +static void setexposure_96(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e}; + + sccb_reg_write(gspca_dev, 0x10, /* aec[9:2] */ + expo[sd->exposure]); + val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ + sccb_reg_write(gspca_dev, 0xff, 0x00); + sccb_reg_write(gspca_dev, 0x13, val); + val = sccb_reg_read(gspca_dev, 0xa1); /* aech */ + sccb_reg_write(gspca_dev, 0xff, 0x00); + sccb_reg_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */ +} + +static void setsharpness_96(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + + val = sd->sharpness; + if (val < 0) { /* auto */ + val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ + sccb_reg_write(gspca_dev, 0xff, 0x00); + sccb_reg_write(gspca_dev, 0x42, val | 0x40); + /* Edge enhancement strength auto adjust */ + return; + } + if (val != 0) + val = 1 << (val - 1); + sccb_reg_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */ + val); + val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ + sccb_reg_write(gspca_dev, 0xff, 0x00); + sccb_reg_write(gspca_dev, 0x42, val & 0xbf); +} + +static void setautogain_96(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + +/*fixme: should adjust agc/awb/aec by different controls */ + val = sd->autogain; + val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ + sccb_reg_write(gspca_dev, 0xff, 0x00); + if (sd->autogain) + val |= 0x05; /* agc & aec */ + else + val &= 0xfa; + sccb_reg_write(gspca_dev, 0x13, val); +} + +static void setsatur(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val1, val2, val3; + static const u8 matrix[5][2] = { + {0x14, 0x38}, + {0x1e, 0x54}, + {0x28, 0x70}, + {0x32, 0x8c}, + {0x48, 0x90} + }; + + val1 = matrix[sd->satur][0]; + val2 = matrix[sd->satur][1]; + val3 = val1 + val2; + sccb_reg_write(gspca_dev, 0x4f, val3); /* matrix coeff */ + sccb_reg_write(gspca_dev, 0x50, val3); + sccb_reg_write(gspca_dev, 0x51, 0x00); + sccb_reg_write(gspca_dev, 0x52, val1); + sccb_reg_write(gspca_dev, 0x53, val2); + sccb_reg_write(gspca_dev, 0x54, val3); + sccb_reg_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */ + val1 = sccb_reg_read(gspca_dev, 0x41); /* com16 */ + sccb_reg_write(gspca_dev, 0xff, 0x00); + sccb_reg_write(gspca_dev, 0x41, val1); +} + +static void setfreq(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + + val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ + sccb_reg_write(gspca_dev, 0xff, 0x00); + if (sd->lightfreq == 0) { + sccb_reg_write(gspca_dev, 0x13, val & 0xdf); + return; + } + sccb_reg_write(gspca_dev, 0x13, val | 0x20); + + val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ + sccb_reg_write(gspca_dev, 0xff, 0x00); + if (sd->lightfreq == 1) + val |= 0x01; + else + val &= 0xfe; + sccb_reg_write(gspca_dev, 0x42, val); +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -1413,28 +1642,47 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->frame_rate = 30; - sd->brightness = BRIGHTNESS_DEF; - sd->contrast = CONTRAST_DEF; - sd->gain = GAIN_DEF; - sd->exposure = EXPO_DEF; - sd->redblc = RED_BALANCE_DEF; - sd->blueblc = BLUE_BALANCE_DEF; - sd->hue = HUE_DEF; -#if AUTOGAIN_DEF != 0 - sd->autogain = AUTOGAIN_DEF; + if (sd->sensor == SENSOR_OV772X) { + sd->brightness = BRIGHTNESS_77_DEF; + sd->contrast = CONTRAST_77_DEF; + sd->gain = GAIN_DEF; + sd->exposure = EXPO_77_DEF; + sd->redblc = RED_BALANCE_DEF; + sd->blueblc = BLUE_BALANCE_DEF; + sd->hue = HUE_DEF; +#if AUTOGAIN_77_DEF != 0 + sd->autogain = AUTOGAIN_77_DEF; #else - gspca_dev->ctrl_inac |= (1 << AWB_IDX); + gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); #endif #if AWB_DEF != 0 - sd->awb = AWB_DEF + sd->awb = AWB_DEF +#endif +#if SHARPNESS_77_DEF != 0 + sd->sharpness = SHARPNESS_77_DEF; #endif - sd->sharpness = SHARPNESS_DEF; #if HFLIP_DEF != 0 - sd->hflip = HFLIP_DEF; + sd->hflip = HFLIP_DEF; #endif #if VFLIP_DEF != 0 - sd->vflip = VFLIP_DEF; + sd->vflip = VFLIP_DEF; #endif + } else { + sd->brightness = BRIGHTNESS_96_DEF; + sd->contrast = CONTRAST_96_DEF; +#if AUTOGAIN_96_DEF != 0 + sd->autogain = AUTOGAIN_96_DEF; + gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX); +#endif +#if EXPO_96_DEF != 0 + sd->exposure = EXPO_96_DEF; +#endif +#if SHARPNESS_96_DEF != 0 + sd->sharpness = SHARPNESS_96_DEF; +#endif + sd->satur = SATUR_DEF; + sd->lightfreq = FREQ_DEF; + } return 0; } @@ -1517,16 +1765,16 @@ static int sd_start_ov772x(struct gspca_dev *gspca_dev) } set_frame_rate(gspca_dev); - setautogain(gspca_dev); + setautogain_77(gspca_dev); setawb(gspca_dev); setgain(gspca_dev); setredblc(gspca_dev); setblueblc(gspca_dev); sethue(gspca_dev); - setexposure(gspca_dev); - setbrightness(gspca_dev); - setcontrast(gspca_dev); - setsharpness(gspca_dev); + setexposure_77(gspca_dev); + setbrightness_77(gspca_dev); + setcontrast_77(gspca_dev); + setsharpness_77(gspca_dev); setvflip(gspca_dev); sethflip(gspca_dev); @@ -1583,8 +1831,14 @@ static int sd_start_ov965x(struct gspca_dev *gspca_dev) ARRAY_SIZE(sensor_start_ov965x_2_sxga)); break; } - sccb_w_array(gspca_dev, sensor_start_ov965x_2, - ARRAY_SIZE(sensor_start_ov965x_2)); + setfreq(gspca_dev); + setautogain_96(gspca_dev); + setbrightness_96(gspca_dev); + setcontrast_96(gspca_dev); + setexposure_96(gspca_dev); + setsharpness_96(gspca_dev); + setsatur(gspca_dev); + ov534_reg_write(gspca_dev, 0xe0, 0x00); ov534_reg_write(gspca_dev, 0xe0, 0x00); ov534_set_led(gspca_dev, 1); @@ -1687,7 +1941,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } while (remaining_len > 0); } -/* ov772x controls */ +/* controls */ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1711,8 +1965,12 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->exposure = val; - if (gspca_dev->streaming) - setexposure(gspca_dev); + if (gspca_dev->streaming) { + if (sd->sensor == SENSOR_OV772X) + setexposure_77(gspca_dev); + else + setexposure_96(gspca_dev); + } return 0; } @@ -1729,8 +1987,12 @@ 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) - setbrightness(gspca_dev); + if (gspca_dev->streaming) { + if (sd->sensor == SENSOR_OV772X) + setbrightness_77(gspca_dev); + else + setbrightness_96(gspca_dev); + } return 0; } @@ -1747,8 +2009,12 @@ 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) - setcontrast(gspca_dev); + if (gspca_dev->streaming) { + if (sd->sensor == SENSOR_OV772X) + setcontrast_77(gspca_dev); + else + setcontrast_96(gspca_dev); + } return 0; } @@ -1760,6 +2026,41 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->satur = val; + if (gspca_dev->streaming) + setsatur(gspca_dev); + return 0; +} + +static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->satur; + return 0; +} +static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->lightfreq = val; + if (gspca_dev->streaming) + setfreq(gspca_dev); + return 0; +} + +static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->lightfreq; + return 0; +} + static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1820,14 +2121,24 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) sd->autogain = val; - /* the auto white balance control works only when auto gain is set */ - if (val) - gspca_dev->ctrl_inac &= ~(1 << AWB_IDX); - else - gspca_dev->ctrl_inac |= (1 << AWB_IDX); + if (gspca_dev->streaming) { + if (sd->sensor == SENSOR_OV772X) { - if (gspca_dev->streaming) - setautogain(gspca_dev); + /* the auto white balance control works only + * when auto gain is set */ + if (val) + gspca_dev->ctrl_inac &= ~(1 << AWB_77_IDX); + else + gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); + setautogain_77(gspca_dev); + } else { + if (val) + gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX); + else + gspca_dev->ctrl_inac &= ~(1 << EXPO_96_IDX); + setautogain_96(gspca_dev); + } + } return 0; } @@ -1862,8 +2173,12 @@ 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); + if (gspca_dev->streaming) { + if (sd->sensor == SENSOR_OV772X) + setsharpness_77(gspca_dev); + else + setsharpness_96(gspca_dev); + } return 0; } @@ -1952,6 +2267,27 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, return 0; } +static int sd_querymenu(struct gspca_dev *gspca_dev, + struct v4l2_querymenu *menu) +{ + switch (menu->id) { + case V4L2_CID_POWER_LINE_FREQUENCY: + switch (menu->index) { + case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ + strcpy((char *) menu->name, "NoFliker"); + return 0; + case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ + strcpy((char *) menu->name, "50 Hz"); + return 0; + case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ + strcpy((char *) menu->name, "60 Hz"); + return 0; + } + break; + } + return -EINVAL; +} + /* sub-driver description */ static const struct sd_desc sd_desc_ov772x = { .name = MODULE_NAME, @@ -1975,8 +2311,7 @@ static const struct sd_desc sd_desc_ov965x = { .start = sd_start_ov965x, .stopN = sd_stopN_ov965x, .pkt_scan = sd_pkt_scan, - .get_streamparm = sd_get_streamparm, - .set_streamparm = sd_set_streamparm, + .querymenu = sd_querymenu, }; /* -- module initialisation -- */ From 6afd2aa856eba0706176cecea1f989b1081c96dc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 24 Nov 2009 06:13:28 -0300 Subject: [PATCH 308/345] V4L/DVB (13491): gspca - vc032x: Avoid crash on querymenu. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 26675236fbd2..c090efcd8045 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -3095,6 +3095,8 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, switch (menu->id) { case V4L2_CID_POWER_LINE_FREQUENCY: + if (menu->index >= ARRAY_SIZE(freq_nm)) + break; strcpy((char *) menu->name, freq_nm[menu->index]); return 0; } From 09ea33e5c696958e8b1ae6d5ab184476b16592f1 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 24 Nov 2009 20:16:04 -0300 Subject: [PATCH 309/345] V4L/DVB (13493): TeVii S470 and TBS 6920 fixes The new hardware design applied for this cards. Silicon Labs C8051F300 microcontroller is used for LNB power control. It connected to cx23885 GPIO pins: GPIO0 - P0.3 data GPIO1 - P0.2 reset GPIO2 - P0.1 clk GPIO3 - P0.0 busy Tevii S470 based on Montage Technology M88TS2020 digital satellite tuner and M88DS3000 advanced DVB-S/S2 demodulator. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/ds3000.c | 1367 +++++++++++++++++++ drivers/media/dvb/frontends/ds3000.h | 45 + drivers/media/video/cx23885/Kconfig | 2 + drivers/media/video/cx23885/Makefile | 2 +- drivers/media/video/cx23885/cx23885-cards.c | 14 +- drivers/media/video/cx23885/cx23885-core.c | 20 + drivers/media/video/cx23885/cx23885-dvb.c | 38 +- drivers/media/video/cx23885/cx23885-f300.c | 177 +++ drivers/media/video/cx23885/cx23885-f300.h | 2 + drivers/media/video/cx23885/cx23885.h | 1 + 12 files changed, 1647 insertions(+), 29 deletions(-) create mode 100644 drivers/media/dvb/frontends/ds3000.c create mode 100644 drivers/media/dvb/frontends/ds3000.h create mode 100644 drivers/media/video/cx23885/cx23885-f300.c create mode 100644 drivers/media/video/cx23885/cx23885-f300.h diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index fdc7926cb2db..58aac018f109 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -201,6 +201,13 @@ config DVB_SI21XX help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_DS3000 + tristate "Montage Tehnology DS3000 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S/S2 tuner module. Say Y when you want to support this frontend. + comment "DVB-T (terrestrial) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 390eec6d5d84..823482535d11 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -78,3 +78,4 @@ obj-$(CONFIG_DVB_STV090x) += stv090x.o obj-$(CONFIG_DVB_STV6110x) += stv6110x.o obj-$(CONFIG_DVB_ISL6423) += isl6423.o obj-$(CONFIG_DVB_EC100) += ec100.o +obj-$(CONFIG_DVB_DS3000) += ds3000.o diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c new file mode 100644 index 000000000000..cff3535566fe --- /dev/null +++ b/drivers/media/dvb/frontends/ds3000.c @@ -0,0 +1,1367 @@ +/* + Montage Technology DS3000/TS2020 - DVBS/S2 Demodulator/Tuner driver + Copyright (C) 2009 Konstantin Dimitrov + + Copyright (C) 2009 TurboSight.com + + 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 +#include + +#include "dvb_frontend.h" +#include "ds3000.h" + +static int debug; + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(args); \ + } while (0) + +/* as of March 2009 current DS3000 firmware version is 1.78 */ +/* DS3000 FW v1.78 MD5: a32d17910c4f370073f9346e71d34b80 */ +#define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds3000.fw" + +#define DS3000_SAMPLE_RATE 96000 /* in kHz */ +#define DS3000_XTAL_FREQ 27000 /* in kHz */ + +/* Register values to initialise the demod in DVB-S mode */ +static u8 ds3000_dvbs_init_tab[] = { + 0x23, 0x05, + 0x08, 0x03, + 0x0c, 0x00, + 0x21, 0x54, + 0x25, 0x82, + 0x27, 0x31, + 0x30, 0x08, + 0x31, 0x40, + 0x32, 0x32, + 0x33, 0x35, + 0x35, 0xff, + 0x3a, 0x00, + 0x37, 0x10, + 0x38, 0x10, + 0x39, 0x02, + 0x42, 0x60, + 0x4a, 0x40, + 0x4b, 0x04, + 0x4d, 0x91, + 0x5d, 0xc8, + 0x50, 0x77, + 0x51, 0x77, + 0x52, 0x36, + 0x53, 0x36, + 0x56, 0x01, + 0x63, 0x43, + 0x64, 0x30, + 0x65, 0x40, + 0x68, 0x26, + 0x69, 0x4c, + 0x70, 0x20, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0x40, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0x60, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0x80, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0xa0, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0x1f, + 0x76, 0x00, + 0x77, 0xd1, + 0x78, 0x0c, + 0x79, 0x80, + 0x7f, 0x04, + 0x7c, 0x00, + 0x80, 0x86, + 0x81, 0xa6, + 0x85, 0x04, + 0xcd, 0xf4, + 0x90, 0x33, + 0xa0, 0x44, + 0xc0, 0x18, + 0xc3, 0x10, + 0xc4, 0x08, + 0xc5, 0x80, + 0xc6, 0x80, + 0xc7, 0x0a, + 0xc8, 0x1a, + 0xc9, 0x80, + 0xfe, 0x92, + 0xe0, 0xf8, + 0xe6, 0x8b, + 0xd0, 0x40, + 0xf8, 0x20, + 0xfa, 0x0f, + 0xfd, 0x20, + 0xad, 0x20, + 0xae, 0x07, + 0xb8, 0x00, +}; + +/* Register values to initialise the demod in DVB-S2 mode */ +static u8 ds3000_dvbs2_init_tab[] = { + 0x23, 0x0f, + 0x08, 0x07, + 0x0c, 0x00, + 0x21, 0x54, + 0x25, 0x82, + 0x27, 0x31, + 0x30, 0x08, + 0x31, 0x32, + 0x32, 0x32, + 0x33, 0x35, + 0x35, 0xff, + 0x3a, 0x00, + 0x37, 0x10, + 0x38, 0x10, + 0x39, 0x02, + 0x42, 0x60, + 0x4a, 0x80, + 0x4b, 0x04, + 0x4d, 0x81, + 0x5d, 0x88, + 0x50, 0x36, + 0x51, 0x36, + 0x52, 0x36, + 0x53, 0x36, + 0x63, 0x60, + 0x64, 0x10, + 0x65, 0x10, + 0x68, 0x04, + 0x69, 0x29, + 0x70, 0x20, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0x40, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0x60, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0x80, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0xa0, + 0x71, 0x70, + 0x72, 0x04, + 0x73, 0x00, + 0x70, 0x1f, + 0xa0, 0x44, + 0xc0, 0x08, + 0xc1, 0x10, + 0xc2, 0x08, + 0xc3, 0x10, + 0xc4, 0x08, + 0xc5, 0xf0, + 0xc6, 0xf0, + 0xc7, 0x0a, + 0xc8, 0x1a, + 0xc9, 0x80, + 0xca, 0x23, + 0xcb, 0x24, + 0xce, 0x74, + 0x90, 0x03, + 0x76, 0x80, + 0x77, 0x42, + 0x78, 0x0a, + 0x79, 0x80, + 0xad, 0x40, + 0xae, 0x07, + 0x7f, 0xd4, + 0x7c, 0x00, + 0x80, 0xa8, + 0x81, 0xda, + 0x7c, 0x01, + 0x80, 0xda, + 0x81, 0xec, + 0x7c, 0x02, + 0x80, 0xca, + 0x81, 0xeb, + 0x7c, 0x03, + 0x80, 0xba, + 0x81, 0xdb, + 0x85, 0x08, + 0x86, 0x00, + 0x87, 0x02, + 0x89, 0x80, + 0x8b, 0x44, + 0x8c, 0xaa, + 0x8a, 0x10, + 0xba, 0x00, + 0xf5, 0x04, + 0xfe, 0x44, + 0xd2, 0x32, + 0xb8, 0x00, +}; + +/* DS3000 doesn't need some parameters as input and auto-detects them */ +/* save input from the application of those parameters */ +struct ds3000_tuning { + u32 frequency; + u32 symbol_rate; + fe_spectral_inversion_t inversion; + enum fe_code_rate fec; + + /* input values */ + u8 inversion_val; + fe_modulation_t delivery; + u8 rolloff; +}; + +struct ds3000_state { + struct i2c_adapter *i2c; + const struct ds3000_config *config; + + struct dvb_frontend frontend; + + struct ds3000_tuning dcur; + struct ds3000_tuning dnxt; + + u8 skip_fw_load; + + /* previous uncorrected block counter for DVB-S2 */ + u16 prevUCBS2; +}; + +static int ds3000_writereg(struct ds3000_state *state, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = state->config->demod_address, + .flags = 0, .buf = buf, .len = 2 }; + int err; + + dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); + + err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) { + printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x," + " value == 0x%02x)\n", __func__, err, reg, data); + return -EREMOTEIO; + } + + return 0; +} + +static int ds3000_tuner_writereg(struct ds3000_state *state, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = 0x60, + .flags = 0, .buf = buf, .len = 2 }; + int err; + + dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); + + ds3000_writereg(state, 0x03, 0x11); + err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) { + printk("%s: writereg error(err == %i, reg == 0x%02x," + " value == 0x%02x)\n", __func__, err, reg, data); + return -EREMOTEIO; + } + + return 0; +} + +/* I2C write for 8k firmware load */ +static int ds3000_writeFW(struct ds3000_state *state, int reg, + const u8 *data, u16 len) +{ + int i, ret = -EREMOTEIO; + struct i2c_msg msg; + u8 *buf; + + buf = kmalloc(3, GFP_KERNEL); + if (buf == NULL) { + printk(KERN_ERR "Unable to kmalloc\n"); + ret = -ENOMEM; + goto error; + } + + *(buf) = reg; + + msg.addr = state->config->demod_address; + msg.flags = 0; + msg.buf = buf; + msg.len = 3; + + for (i = 0; i < len; i += 2) { + memcpy(buf + 1, data + i, 2); + + dprintk("%s: write reg 0x%02x, len = %d\n", __func__, reg, len); + + ret = i2c_transfer(state->i2c, &msg, 1); + if (ret != 1) { + printk(KERN_ERR "%s: write error(err == %i, " + "reg == 0x%02x\n", __func__, ret, reg); + ret = -EREMOTEIO; + } + } + +error: + kfree(buf); + + return ret; +} + +static int ds3000_readreg(struct ds3000_state *state, u8 reg) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = b0, + .len = 1 + }, { + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) { + printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret); + return ret; + } + + dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]); + + return b1[0]; +} + +static int ds3000_tuner_readreg(struct ds3000_state *state, u8 reg) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { + .addr = 0x60, + .flags = 0, + .buf = b0, + .len = 1 + }, { + .addr = 0x60, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + + ds3000_writereg(state, 0x03, 0x12); + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) { + printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret); + return ret; + } + + dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]); + + return b1[0]; +} + +static int ds3000_set_inversion(struct ds3000_state *state, + fe_spectral_inversion_t inversion) +{ + dprintk("%s(%d)\n", __func__, inversion); + + switch (inversion) { + case INVERSION_OFF: + case INVERSION_ON: + case INVERSION_AUTO: + break; + default: + return -EINVAL; + } + + state->dnxt.inversion = inversion; + + return 0; +} + +static int ds3000_set_symbolrate(struct ds3000_state *state, u32 rate) +{ + int ret = 0; + + dprintk("%s()\n", __func__); + + dprintk("%s() symbol_rate = %d\n", __func__, state->dnxt.symbol_rate); + + /* check if symbol rate is within limits */ + if ((state->dnxt.symbol_rate > + state->frontend.ops.info.symbol_rate_max) || + (state->dnxt.symbol_rate < + state->frontend.ops.info.symbol_rate_min)) + ret = -EOPNOTSUPP; + + state->dnxt.symbol_rate = rate; + + return ret; +} + +static int ds3000_load_firmware(struct dvb_frontend *fe, + const struct firmware *fw); + +static int ds3000_firmware_ondemand(struct dvb_frontend *fe) +{ + struct ds3000_state *state = fe->demodulator_priv; + const struct firmware *fw; + int ret = 0; + + dprintk("%s()\n", __func__); + + if (ds3000_readreg(state, 0xb2) <= 0) + return ret; + + if (state->skip_fw_load) + return 0; + /* Load firmware */ + /* request the firmware, this will block until someone uploads it */ + printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, + DS3000_DEFAULT_FIRMWARE); + ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE, + state->i2c->dev.parent); + printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); + if (ret) { + printk(KERN_ERR "%s: No firmware uploaded (timeout or file not " + "found?)\n", __func__); + return ret; + } + + /* Make sure we don't recurse back through here during loading */ + state->skip_fw_load = 1; + + ret = ds3000_load_firmware(fe, fw); + if (ret) + printk("%s: Writing firmware to device failed\n", __func__); + + release_firmware(fw); + + dprintk("%s: Firmware upload %s\n", __func__, + ret == 0 ? "complete" : "failed"); + + /* Ensure firmware is always loaded if required */ + state->skip_fw_load = 0; + + return ret; +} + +static int ds3000_load_firmware(struct dvb_frontend *fe, + const struct firmware *fw) +{ + struct ds3000_state *state = fe->demodulator_priv; + + dprintk("%s\n", __func__); + dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n", + fw->size, + fw->data[0], + fw->data[1], + fw->data[fw->size - 2], + fw->data[fw->size - 1]); + + /* Begin the firmware load process */ + ds3000_writereg(state, 0xb2, 0x01); + /* write the entire firmware */ + ds3000_writeFW(state, 0xb0, fw->data, fw->size); + ds3000_writereg(state, 0xb2, 0x00); + + return 0; +} + +static void ds3000_dump_registers(struct dvb_frontend *fe) +{ + struct ds3000_state *state = fe->demodulator_priv; + int x, y, reg = 0, val; + + for (y = 0; y < 16; y++) { + dprintk("%s: %02x: ", __func__, y); + for (x = 0; x < 16; x++) { + reg = (y << 4) + x; + val = ds3000_readreg(state, reg); + if (x != 15) + dprintk("%02x ", val); + else + dprintk("%02x\n", val); + } + } + dprintk("%s: -- DS3000 DUMP DONE --\n", __func__); +} + +static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status) +{ + struct ds3000_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int lock; + + *status = 0; + + switch (c->delivery_system) { + case SYS_DVBS: + lock = ds3000_readreg(state, 0xd1); + if ((lock & 0x07) == 0x07) + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | + FE_HAS_LOCK; + + break; + case SYS_DVBS2: + lock = ds3000_readreg(state, 0x0d); + if ((lock & 0x8f) == 0x8f) + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | + FE_HAS_LOCK; + + break; + default: + return 1; + } + + dprintk("%s: status = 0x%02x\n", __func__, lock); + + return 0; +} + +#define FE_IS_TUNED (FE_HAS_SIGNAL + FE_HAS_LOCK) +static int ds3000_is_tuned(struct dvb_frontend *fe) +{ + fe_status_t tunerstat; + + ds3000_read_status(fe, &tunerstat); + + return ((tunerstat & FE_IS_TUNED) == FE_IS_TUNED); +} + +/* read DS3000 BER value */ +static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber) +{ + struct ds3000_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u8 data; + u32 ber_reading, lpdc_frames; + + dprintk("%s()\n", __func__); + + switch (c->delivery_system) { + case SYS_DVBS: + /* set the number of bytes checked during + BER estimation */ + ds3000_writereg(state, 0xf9, 0x04); + /* read BER estimation status */ + data = ds3000_readreg(state, 0xf8); + /* check if BER estimation is ready */ + if ((data & 0x10) == 0) { + /* this is the number of error bits, + to calculate the bit error rate + divide to 8388608 */ + *ber = (ds3000_readreg(state, 0xf7) << 8) | + ds3000_readreg(state, 0xf6); + /* start counting error bits */ + /* need to be set twice + otherwise it fails sometimes */ + data |= 0x10; + ds3000_writereg(state, 0xf8, data); + ds3000_writereg(state, 0xf8, data); + } else + /* used to indicate that BER estimation + is not ready, i.e. BER is unknown */ + *ber = 0xffffffff; + break; + case SYS_DVBS2: + /* read the number of LPDC decoded frames */ + lpdc_frames = (ds3000_readreg(state, 0xd7) << 16) | + (ds3000_readreg(state, 0xd6) << 8) | + ds3000_readreg(state, 0xd5); + /* read the number of packets with bad CRC */ + ber_reading = (ds3000_readreg(state, 0xf8) << 8) | + ds3000_readreg(state, 0xf7); + if (lpdc_frames > 750) { + /* clear LPDC frame counters */ + ds3000_writereg(state, 0xd1, 0x01); + /* clear bad packets counter */ + ds3000_writereg(state, 0xf9, 0x01); + /* enable bad packets counter */ + ds3000_writereg(state, 0xf9, 0x00); + /* enable LPDC frame counters */ + ds3000_writereg(state, 0xd1, 0x00); + *ber = ber_reading; + } else + /* used to indicate that BER estimation is not ready, + i.e. BER is unknown */ + *ber = 0xffffffff; + break; + default: + return 1; + } + + return 0; +} + +/* read TS2020 signal strength */ +static int ds3000_read_signal_strength(struct dvb_frontend *fe, + u16 *signal_strength) +{ + struct ds3000_state *state = fe->demodulator_priv; + u16 sig_reading, sig_strength; + u8 rfgain, bbgain; + + dprintk("%s()\n", __func__); + + rfgain = ds3000_tuner_readreg(state, 0x3d) & 0x1f; + bbgain = ds3000_tuner_readreg(state, 0x21) & 0x1f; + + if (rfgain > 15) + rfgain = 15; + if (bbgain > 13) + bbgain = 13; + + sig_reading = rfgain * 2 + bbgain * 3; + + sig_strength = 40 + (64 - sig_reading) * 50 / 64 ; + + /* cook the value to be suitable for szap-s2 human readable output */ + *signal_strength = sig_strength * 1000; + + dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, + sig_reading, *signal_strength); + + return 0; +} + +/* calculate DS3000 snr value in dB */ +static int ds3000_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct ds3000_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u8 snr_reading, snr_value; + u32 dvbs2_signal_reading, dvbs2_noise_reading, tmp; + static const u16 dvbs_snr_tab[] = { /* 20 x Table (rounded up) */ + 0x0000, 0x1b13, 0x2aea, 0x3627, 0x3ede, 0x45fe, 0x4c03, + 0x513a, 0x55d4, 0x59f2, 0x5dab, 0x6111, 0x6431, 0x6717, + 0x69c9, 0x6c4e, 0x6eac, 0x70e8, 0x7304, 0x7505 + }; + static const u16 dvbs2_snr_tab[] = { /* 80 x Table (rounded up) */ + 0x0000, 0x0bc2, 0x12a3, 0x1785, 0x1b4e, 0x1e65, 0x2103, + 0x2347, 0x2546, 0x2710, 0x28ae, 0x2a28, 0x2b83, 0x2cc5, + 0x2df1, 0x2f09, 0x3010, 0x3109, 0x31f4, 0x32d2, 0x33a6, + 0x3470, 0x3531, 0x35ea, 0x369b, 0x3746, 0x37ea, 0x3888, + 0x3920, 0x39b3, 0x3a42, 0x3acc, 0x3b51, 0x3bd3, 0x3c51, + 0x3ccb, 0x3d42, 0x3db6, 0x3e27, 0x3e95, 0x3f00, 0x3f68, + 0x3fcf, 0x4033, 0x4094, 0x40f4, 0x4151, 0x41ac, 0x4206, + 0x425e, 0x42b4, 0x4308, 0x435b, 0x43ac, 0x43fc, 0x444a, + 0x4497, 0x44e2, 0x452d, 0x4576, 0x45bd, 0x4604, 0x4649, + 0x468e, 0x46d1, 0x4713, 0x4755, 0x4795, 0x47d4, 0x4813, + 0x4851, 0x488d, 0x48c9, 0x4904, 0x493f, 0x4978, 0x49b1, + 0x49e9, 0x4a20, 0x4a57 + }; + + dprintk("%s()\n", __func__); + + switch (c->delivery_system) { + case SYS_DVBS: + snr_reading = ds3000_readreg(state, 0xff); + snr_reading /= 8; + if (snr_reading == 0) + *snr = 0x0000; + else { + if (snr_reading > 20) + snr_reading = 20; + snr_value = dvbs_snr_tab[snr_reading - 1] * 10 / 23026; + /* cook the value to be suitable for szap-s2 + human readable output */ + *snr = snr_value * 8 * 655; + } + dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__, + snr_reading, *snr); + break; + case SYS_DVBS2: + dvbs2_noise_reading = (ds3000_readreg(state, 0x8c) & 0x3f) + + (ds3000_readreg(state, 0x8d) << 4); + dvbs2_signal_reading = ds3000_readreg(state, 0x8e); + tmp = dvbs2_signal_reading * dvbs2_signal_reading >> 1; + if (dvbs2_signal_reading == 0) { + *snr = 0x0000; + return 0; + } + if (dvbs2_noise_reading == 0) { + snr_value = 0x0013; + /* cook the value to be suitable for szap-s2 + human readable output */ + *snr = 0xffff; + return 0; + } + if (tmp > dvbs2_noise_reading) { + snr_reading = tmp / dvbs2_noise_reading; + if (snr_reading > 80) + snr_reading = 80; + snr_value = dvbs2_snr_tab[snr_reading - 1] / 1000; + /* cook the value to be suitable for szap-s2 + human readable output */ + *snr = snr_value * 5 * 655; + } else { + snr_reading = dvbs2_noise_reading / tmp; + if (snr_reading > 80) + snr_reading = 80; + *snr = -(dvbs2_snr_tab[snr_reading] / 1000); + } + dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__, + snr_reading, *snr); + break; + default: + return 1; + } + + return 0; +} + +/* read DS3000 uncorrected blocks */ +static int ds3000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct ds3000_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u8 data; + u16 _ucblocks; + + dprintk("%s()\n", __func__); + + switch (c->delivery_system) { + case SYS_DVBS: + *ucblocks = (ds3000_readreg(state, 0xf5) << 8) | + ds3000_readreg(state, 0xf4); + data = ds3000_readreg(state, 0xf8); + /* clear packet counters */ + data &= ~0x20; + ds3000_writereg(state, 0xf8, data); + /* enable packet counters */ + data |= 0x20; + ds3000_writereg(state, 0xf8, data); + break; + case SYS_DVBS2: + _ucblocks = (ds3000_readreg(state, 0xe2) << 8) | + ds3000_readreg(state, 0xe1); + if (_ucblocks > state->prevUCBS2) + *ucblocks = _ucblocks - state->prevUCBS2; + else + *ucblocks = state->prevUCBS2 - _ucblocks; + state->prevUCBS2 = _ucblocks; + break; + default: + return 1; + } + + return 0; +} + +/* Overwrite the current tuning params, we are about to tune */ +static void ds3000_clone_params(struct dvb_frontend *fe) +{ + struct ds3000_state *state = fe->demodulator_priv; + memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur)); +} + +static int ds3000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct ds3000_state *state = fe->demodulator_priv; + u8 data; + + dprintk("%s(%d)\n", __func__, tone); + if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { + printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone); + return -EINVAL; + } + + data = ds3000_readreg(state, 0xa2); + data &= ~0xc0; + ds3000_writereg(state, 0xa2, data); + + switch (tone) { + case SEC_TONE_ON: + dprintk("%s: setting tone on\n", __func__); + data = ds3000_readreg(state, 0xa1); + data &= ~0x43; + data |= 0x04; + ds3000_writereg(state, 0xa1, data); + break; + case SEC_TONE_OFF: + dprintk("%s: setting tone off\n", __func__); + data = ds3000_readreg(state, 0xa2); + data |= 0x80; + ds3000_writereg(state, 0xa2, data); + break; + } + + return 0; +} + +static int ds3000_send_diseqc_msg(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *d) +{ + struct ds3000_state *state = fe->demodulator_priv; + int i; + u8 data; + + /* Dump DiSEqC message */ + dprintk("%s(", __func__); + for (i = 0 ; i < d->msg_len;) { + dprintk("0x%02x", d->msg[i]); + if (++i < d->msg_len) + dprintk(", "); + } + + /* enable DiSEqC message send pin */ + data = ds3000_readreg(state, 0xa2); + data &= ~0xc0; + ds3000_writereg(state, 0xa2, data); + + /* DiSEqC message */ + for (i = 0; i < d->msg_len; i++) + ds3000_writereg(state, 0xa3 + i, d->msg[i]); + + data = ds3000_readreg(state, 0xa1); + /* clear DiSEqC message length and status, + enable DiSEqC message send */ + data &= ~0xf8; + /* set DiSEqC mode, modulation active during 33 pulses, + set DiSEqC message length */ + data |= ((d->msg_len - 1) << 3) | 0x07; + ds3000_writereg(state, 0xa1, data); + + /* wait up to 150ms for DiSEqC transmission to complete */ + for (i = 0; i < 15; i++) { + data = ds3000_readreg(state, 0xa1); + if ((data & 0x40) == 0) + break; + msleep(10); + } + + /* DiSEqC timeout after 150ms */ + if (i == 15) { + data = ds3000_readreg(state, 0xa1); + data &= ~0x80; + data |= 0x40; + ds3000_writereg(state, 0xa1, data); + + data = ds3000_readreg(state, 0xa2); + data &= ~0xc0; + data |= 0x80; + ds3000_writereg(state, 0xa2, data); + + return 1; + } + + data = ds3000_readreg(state, 0xa2); + data &= ~0xc0; + data |= 0x80; + ds3000_writereg(state, 0xa2, data); + + return 0; +} + +/* Send DiSEqC burst */ +static int ds3000_diseqc_send_burst(struct dvb_frontend *fe, + fe_sec_mini_cmd_t burst) +{ + struct ds3000_state *state = fe->demodulator_priv; + int i; + u8 data; + + dprintk("%s()\n", __func__); + + data = ds3000_readreg(state, 0xa2); + data &= ~0xc0; + ds3000_writereg(state, 0xa2, data); + + /* DiSEqC burst */ + if (burst == SEC_MINI_A) + /* Unmodulated tone burst */ + ds3000_writereg(state, 0xa1, 0x02); + else if (burst == SEC_MINI_B) + /* Modulated tone burst */ + ds3000_writereg(state, 0xa1, 0x01); + else + return -EINVAL; + + msleep(13); + for (i = 0; i < 5; i++) { + data = ds3000_readreg(state, 0xa1); + if ((data & 0x40) == 0) + break; + msleep(1); + } + + if (i == 5) { + data = ds3000_readreg(state, 0xa1); + data &= ~0x80; + data |= 0x40; + ds3000_writereg(state, 0xa1, data); + + data = ds3000_readreg(state, 0xa2); + data &= ~0xc0; + data |= 0x80; + ds3000_writereg(state, 0xa2, data); + + return 1; + } + + data = ds3000_readreg(state, 0xa2); + data &= ~0xc0; + data |= 0x80; + ds3000_writereg(state, 0xa2, data); + + return 0; +} + +static void ds3000_release(struct dvb_frontend *fe) +{ + struct ds3000_state *state = fe->demodulator_priv; + dprintk("%s\n", __func__); + kfree(state); +} + +static struct dvb_frontend_ops ds3000_ops; + +struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, + struct i2c_adapter *i2c) +{ + struct ds3000_state *state = NULL; + int ret; + + dprintk("%s\n", __func__); + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct ds3000_state), GFP_KERNEL); + if (state == NULL) { + printk(KERN_ERR "Unable to kmalloc\n"); + goto error2; + } + + /* setup the state */ + memset(state, 0, sizeof(struct ds3000_state)); + + state->config = config; + state->i2c = i2c; + state->prevUCBS2 = 0; + + /* check if the demod is present */ + ret = ds3000_readreg(state, 0x00) & 0xfe; + if (ret != 0xe0) { + printk(KERN_ERR "Invalid probe, probably not a DS3000\n"); + goto error3; + } + + printk(KERN_INFO "DS3000 chip version: %d.%d attached.\n", + ds3000_readreg(state, 0x02), + ds3000_readreg(state, 0x01)); + + memcpy(&state->frontend.ops, &ds3000_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + return &state->frontend; + +error3: + kfree(state); +error2: + return NULL; +} +EXPORT_SYMBOL(ds3000_attach); + +static int ds3000_set_property(struct dvb_frontend *fe, + struct dtv_property *tvp) +{ + dprintk("%s(..)\n", __func__); + return 0; +} + +static int ds3000_get_property(struct dvb_frontend *fe, + struct dtv_property *tvp) +{ + dprintk("%s(..)\n", __func__); + return 0; +} + +static int ds3000_tune(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct ds3000_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + + int ret = 0, retune, i; + u8 status, mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf; + u16 value, ndiv; + u32 f3db; + + dprintk("%s() ", __func__); + + /* Load the firmware if required */ + ret = ds3000_firmware_ondemand(fe); + if (ret != 0) { + printk(KERN_ERR "%s: Unable initialise the firmware\n", + __func__); + return ret; + } + + state->dnxt.delivery = c->modulation; + state->dnxt.frequency = c->frequency; + state->dnxt.rolloff = 2; /* fixme */ + state->dnxt.fec = c->fec_inner; + + ret = ds3000_set_inversion(state, p->inversion); + if (ret != 0) + return ret; + + ret = ds3000_set_symbolrate(state, c->symbol_rate); + if (ret != 0) + return ret; + + /* discard the 'current' tuning parameters and prepare to tune */ + ds3000_clone_params(fe); + + retune = 1; /* try 1 times */ + dprintk("%s: retune = %d\n", __func__, retune); + dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency); + dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate); + dprintk("%s: FEC = %d \n", __func__, + state->dcur.fec); + dprintk("%s: Inversion = %d\n", __func__, state->dcur.inversion); + + do { + /* Reset status register */ + status = 0; + /* Tune */ + /* TS2020 init */ + ds3000_tuner_writereg(state, 0x42, 0x73); + ds3000_tuner_writereg(state, 0x05, 0x01); + ds3000_tuner_writereg(state, 0x62, 0xf5); + /* unknown */ + ds3000_tuner_writereg(state, 0x07, 0x02); + ds3000_tuner_writereg(state, 0x10, 0x00); + ds3000_tuner_writereg(state, 0x60, 0x79); + ds3000_tuner_writereg(state, 0x08, 0x01); + ds3000_tuner_writereg(state, 0x00, 0x01); + /* calculate and set freq divider */ + if (state->dcur.frequency < 1146000) { + ds3000_tuner_writereg(state, 0x10, 0x11); + ndiv = ((state->dcur.frequency * (6 + 8) * 4) + + (DS3000_XTAL_FREQ / 2)) / + DS3000_XTAL_FREQ - 1024; + } else { + ds3000_tuner_writereg(state, 0x10, 0x01); + ndiv = ((state->dcur.frequency * (6 + 8) * 2) + + (DS3000_XTAL_FREQ / 2)) / + DS3000_XTAL_FREQ - 1024; + } + + ds3000_tuner_writereg(state, 0x01, (ndiv & 0x0f00) >> 8); + ds3000_tuner_writereg(state, 0x02, ndiv & 0x00ff); + + /* set pll */ + ds3000_tuner_writereg(state, 0x03, 0x06); + ds3000_tuner_writereg(state, 0x51, 0x0f); + ds3000_tuner_writereg(state, 0x51, 0x1f); + ds3000_tuner_writereg(state, 0x50, 0x10); + ds3000_tuner_writereg(state, 0x50, 0x00); + msleep(5); + + /* unknown */ + ds3000_tuner_writereg(state, 0x51, 0x17); + ds3000_tuner_writereg(state, 0x51, 0x1f); + ds3000_tuner_writereg(state, 0x50, 0x08); + ds3000_tuner_writereg(state, 0x50, 0x00); + msleep(5); + + value = ds3000_tuner_readreg(state, 0x3d); + value &= 0x0f; + if ((value > 4) && (value < 15)) { + value -= 3; + if (value < 4) + value = 4; + value = ((value << 3) | 0x01) & 0x79; + } + + ds3000_tuner_writereg(state, 0x60, value); + ds3000_tuner_writereg(state, 0x51, 0x17); + ds3000_tuner_writereg(state, 0x51, 0x1f); + ds3000_tuner_writereg(state, 0x50, 0x08); + ds3000_tuner_writereg(state, 0x50, 0x00); + + /* set low-pass filter period */ + ds3000_tuner_writereg(state, 0x04, 0x2e); + ds3000_tuner_writereg(state, 0x51, 0x1b); + ds3000_tuner_writereg(state, 0x51, 0x1f); + ds3000_tuner_writereg(state, 0x50, 0x04); + ds3000_tuner_writereg(state, 0x50, 0x00); + msleep(5); + + f3db = ((state->dcur.symbol_rate / 1000) << 2) / 5 + 2000; + if ((state->dcur.symbol_rate / 1000) < 5000) + f3db += 3000; + if (f3db < 7000) + f3db = 7000; + if (f3db > 40000) + f3db = 40000; + + /* set low-pass filter baseband */ + value = ds3000_tuner_readreg(state, 0x26); + mlpf = 0x2e * 207 / ((value << 1) + 151); + mlpf_max = mlpf * 135 / 100; + mlpf_min = mlpf * 78 / 100; + if (mlpf_max > 63) + mlpf_max = 63; + + /* rounded to the closest integer */ + nlpf = ((mlpf * f3db * 1000) + (2766 * DS3000_XTAL_FREQ / 2)) + / (2766 * DS3000_XTAL_FREQ); + if (nlpf > 23) + nlpf = 23; + if (nlpf < 1) + nlpf = 1; + + /* rounded to the closest integer */ + mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) + + (1000 * f3db / 2)) / (1000 * f3db); + + if (mlpf_new < mlpf_min) { + nlpf++; + mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) + + (1000 * f3db / 2)) / (1000 * f3db); + } + + if (mlpf_new > mlpf_max) + mlpf_new = mlpf_max; + + ds3000_tuner_writereg(state, 0x04, mlpf_new); + ds3000_tuner_writereg(state, 0x06, nlpf); + ds3000_tuner_writereg(state, 0x51, 0x1b); + ds3000_tuner_writereg(state, 0x51, 0x1f); + ds3000_tuner_writereg(state, 0x50, 0x04); + ds3000_tuner_writereg(state, 0x50, 0x00); + msleep(5); + + /* unknown */ + ds3000_tuner_writereg(state, 0x51, 0x1e); + ds3000_tuner_writereg(state, 0x51, 0x1f); + ds3000_tuner_writereg(state, 0x50, 0x01); + ds3000_tuner_writereg(state, 0x50, 0x00); + msleep(60); + + /* ds3000 global reset */ + ds3000_writereg(state, 0x07, 0x80); + ds3000_writereg(state, 0x07, 0x00); + /* ds3000 build-in uC reset */ + ds3000_writereg(state, 0xb2, 0x01); + /* ds3000 software reset */ + ds3000_writereg(state, 0x00, 0x01); + + switch (c->delivery_system) { + case SYS_DVBS: + /* initialise the demod in DVB-S mode */ + for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2) + ds3000_writereg(state, + ds3000_dvbs_init_tab[i], + ds3000_dvbs_init_tab[i + 1]); + value = ds3000_readreg(state, 0xfe); + value &= 0xc0; + value |= 0x1b; + ds3000_writereg(state, 0xfe, value); + break; + case SYS_DVBS2: + /* initialise the demod in DVB-S2 mode */ + for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2) + ds3000_writereg(state, + ds3000_dvbs2_init_tab[i], + ds3000_dvbs2_init_tab[i + 1]); + ds3000_writereg(state, 0xfe, 0x54); + break; + default: + return 1; + } + + /* enable 27MHz clock output */ + ds3000_writereg(state, 0x29, 0x80); + /* enable ac coupling */ + ds3000_writereg(state, 0x25, 0x8a); + + /* enhance symbol rate performance */ + if ((state->dcur.symbol_rate / 1000) <= 5000) { + value = 29777 / (state->dcur.symbol_rate / 1000) + 1; + if (value % 2 != 0) + value++; + ds3000_writereg(state, 0xc3, 0x0d); + ds3000_writereg(state, 0xc8, value); + ds3000_writereg(state, 0xc4, 0x10); + ds3000_writereg(state, 0xc7, 0x0e); + } else if ((state->dcur.symbol_rate / 1000) <= 10000) { + value = 92166 / (state->dcur.symbol_rate / 1000) + 1; + if (value % 2 != 0) + value++; + ds3000_writereg(state, 0xc3, 0x07); + ds3000_writereg(state, 0xc8, value); + ds3000_writereg(state, 0xc4, 0x09); + ds3000_writereg(state, 0xc7, 0x12); + } else if ((state->dcur.symbol_rate / 1000) <= 20000) { + value = 64516 / (state->dcur.symbol_rate / 1000) + 1; + ds3000_writereg(state, 0xc3, value); + ds3000_writereg(state, 0xc8, 0x0e); + ds3000_writereg(state, 0xc4, 0x07); + ds3000_writereg(state, 0xc7, 0x18); + } else { + value = 129032 / (state->dcur.symbol_rate / 1000) + 1; + ds3000_writereg(state, 0xc3, value); + ds3000_writereg(state, 0xc8, 0x0a); + ds3000_writereg(state, 0xc4, 0x05); + ds3000_writereg(state, 0xc7, 0x24); + } + + /* normalized symbol rate rounded to the closest integer */ + value = (((state->dcur.symbol_rate / 1000) << 16) + + (DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE; + ds3000_writereg(state, 0x61, value & 0x00ff); + ds3000_writereg(state, 0x62, (value & 0xff00) >> 8); + + /* co-channel interference cancellation disabled */ + ds3000_writereg(state, 0x56, 0x00); + + /* equalizer disabled */ + ds3000_writereg(state, 0x76, 0x00); + + /*ds3000_writereg(state, 0x08, 0x03); + ds3000_writereg(state, 0xfd, 0x22); + ds3000_writereg(state, 0x08, 0x07); + ds3000_writereg(state, 0xfd, 0x42); + ds3000_writereg(state, 0x08, 0x07);*/ + + /* ds3000 out of software reset */ + ds3000_writereg(state, 0x00, 0x00); + /* start ds3000 build-in uC */ + ds3000_writereg(state, 0xb2, 0x00); + + /* TODO: calculate and set carrier offset */ + + /* wait before retrying */ + for (i = 0; i < 30 ; i++) { + if (ds3000_is_tuned(fe)) { + dprintk("%s: Tuned\n", __func__); + ds3000_dump_registers(fe); + goto tuned; + } + msleep(1); + } + + dprintk("%s: Not tuned\n", __func__); + ds3000_dump_registers(fe); + + } while (--retune); + +tuned: + return ret; +} + +static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe) +{ + dprintk("%s()\n", __func__); + return DVBFE_ALGO_SW; +} + +/* + * Initialise or wake up device + * + * Power config will reset and load initial firmware if required + */ +static int ds3000_initfe(struct dvb_frontend *fe) +{ + dprintk("%s()\n", __func__); + return 0; +} + +/* Put device to sleep */ +static int ds3000_sleep(struct dvb_frontend *fe) +{ + dprintk("%s()\n", __func__); + return 0; +} + +static struct dvb_frontend_ops ds3000_ops = { + + .info = { + .name = "Montage Technology DS3000/TS2020", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1011, /* kHz for QPSK frontends */ + .frequency_tolerance = 5000, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + 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 + }, + + .release = ds3000_release, + + .init = ds3000_initfe, + .sleep = ds3000_sleep, + .read_status = ds3000_read_status, + .read_ber = ds3000_read_ber, + .read_signal_strength = ds3000_read_signal_strength, + .read_snr = ds3000_read_snr, + .read_ucblocks = ds3000_read_ucblocks, + .set_tone = ds3000_set_tone, + .diseqc_send_master_cmd = ds3000_send_diseqc_msg, + .diseqc_send_burst = ds3000_diseqc_send_burst, + .get_frontend_algo = ds3000_get_algo, + + .set_property = ds3000_set_property, + .get_property = ds3000_get_property, + .set_frontend = ds3000_tune, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +MODULE_DESCRIPTION("DVB Frontend module for Montage Technology " + "DS3000/TS2020 hardware"); +MODULE_AUTHOR("Konstantin Dimitrov"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/ds3000.h b/drivers/media/dvb/frontends/ds3000.h new file mode 100644 index 000000000000..67f67038740a --- /dev/null +++ b/drivers/media/dvb/frontends/ds3000.h @@ -0,0 +1,45 @@ +/* + Montage Technology DS3000/TS2020 - DVBS/S2 Satellite demod/tuner driver + Copyright (C) 2009 Konstantin Dimitrov + + Copyright (C) 2009 TurboSight.com + + 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. +*/ + +#ifndef DS3000_H +#define DS3000_H + +#include + +struct ds3000_config { + /* the demodulator's i2c address */ + u8 demod_address; +}; + +#if defined(CONFIG_DVB_DS3000) || \ + (defined(CONFIG_DVB_DS3000_MODULE) && defined(MODULE)) +extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, + struct i2c_adapter *i2c); +#else +static inline +struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_DS3000 */ +#endif /* DS3000_H */ diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index fd3fc3e3198a..bcdda9a9aa96 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -18,7 +18,9 @@ config VIDEO_CX23885 select DVB_TDA10048 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_STV6110 if !DVB_FE_CUSTOMISE + select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE + select DVB_DS3000 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index bb462589b53b..5787ae243631 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile @@ -1,7 +1,7 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ cx23885-ioctl.o cx23885-ir.o cx23885-input.o cx23888-ir.o \ - netup-init.o cimax2.o netup-eeprom.o + netup-init.o cimax2.o netup-eeprom.o cx23885-f300.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 23302ddf4187..1ec48169277d 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -782,10 +782,14 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00040004); break; case CX23885_BOARD_TBS_6920: - case CX23885_BOARD_TEVII_S470: cx_write(MC417_CTL, 0x00000036); cx_write(MC417_OEN, 0x00001000); - cx_write(MC417_RWD, 0x00001800); + cx_set(MC417_RWD, 0x00000002); + mdelay(200); + cx_clear(MC417_RWD, 0x00000800); + mdelay(200); + cx_set(MC417_RWD, 0x00000800); + mdelay(200); break; case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: /* GPIO-0 INTA from CiMax1 @@ -1002,8 +1006,12 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; - case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_TBS_6920: + ts1->gen_ctrl_val = 0x4; /* Parallel */ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; + case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_DVBWORLD_2005: ts1->gen_ctrl_val = 0x5; /* Parallel */ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index e8eb4ec0c30a..04b12d27bc13 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -1871,6 +1871,26 @@ void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask) printk(KERN_INFO "%s: Unsupported\n", dev->name); } +u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask) +{ + if (mask & 0x00000007) + return (cx_read(GP0_IO) >> 8) & mask & 0x7; + + if (mask & 0x0007fff8) { + if (encoder_on_portb(dev) || encoder_on_portc(dev)) + printk(KERN_ERR + "%s: Reading GPIO moving on encoder ports\n", + dev->name); + return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3; + } + + /* TODO: 23-19 */ + if (mask & 0x00f80000) + printk(KERN_INFO "%s: Unsupported\n", dev->name); + + return 0; +} + void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput) { if ((mask & 0x00000007) && asoutput) diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index bf24e86293c6..2607de134fa6 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -56,6 +56,8 @@ #include "netup-init.h" #include "lgdt3305.h" #include "atbm8830.h" +#include "ds3000.h" +#include "cx23885-f300.h" static unsigned int debug; @@ -427,26 +429,12 @@ static struct stv6110_config netup_stv6110_tunerconfig_b = { .gain = 8, /* +16 dB - maximum gain */ }; -static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -{ - struct cx23885_tsport *port = fe->dvb->priv; - struct cx23885_dev *dev = port->dev; - - if (voltage == SEC_VOLTAGE_18) - cx_write(MC417_RWD, 0x00001e00);/* GPIO-13 high */ - else if (voltage == SEC_VOLTAGE_13) - cx_write(MC417_RWD, 0x00001a00);/* GPIO-13 low */ - else - cx_write(MC417_RWD, 0x00001800);/* GPIO-12 low */ - return 0; -} - static struct cx24116_config tbs_cx24116_config = { - .demod_address = 0x05, + .demod_address = 0x55, }; -static struct cx24116_config tevii_cx24116_config = { - .demod_address = 0x55, +static struct ds3000_config tevii_ds3000_config = { + .demod_address = 0x68, }; static struct cx24116_config dvbworld_cx24116_config = { @@ -832,23 +820,23 @@ static int dvb_register(struct cx23885_tsport *port) } break; case CX23885_BOARD_TBS_6920: - i2c_bus = &dev->i2c_bus[0]; + i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, - &tbs_cx24116_config, - &i2c_bus->i2c_adap); + &tbs_cx24116_config, + &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) - fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; + fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; break; case CX23885_BOARD_TEVII_S470: i2c_bus = &dev->i2c_bus[1]; - fe0->dvb.frontend = dvb_attach(cx24116_attach, - &tevii_cx24116_config, - &i2c_bus->i2c_adap); + fe0->dvb.frontend = dvb_attach(ds3000_attach, + &tevii_ds3000_config, + &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) - fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; + fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; break; case CX23885_BOARD_DVBWORLD_2005: diff --git a/drivers/media/video/cx23885/cx23885-f300.c b/drivers/media/video/cx23885/cx23885-f300.c new file mode 100644 index 000000000000..93998f220986 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-f300.c @@ -0,0 +1,177 @@ +/* + * Driver for Silicon Labs C8051F300 microcontroller. + * + * It is used for LNB power control in TeVii S470, + * TBS 6920 PCIe DVB-S2 cards. + * + * Microcontroller connected to cx23885 GPIO pins: + * GPIO0 - data - P0.3 F300 + * GPIO1 - reset - P0.2 F300 + * GPIO2 - clk - P0.1 F300 + * GPIO3 - busy - P0.0 F300 + * + * Copyright (C) 2009 Igor M. Liplianin + * + * 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 "cx23885.h" + +#define F300_DATA GPIO_0 +#define F300_RESET GPIO_1 +#define F300_CLK GPIO_2 +#define F300_BUSY GPIO_3 + +static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl) +{ + cx23885_gpio_enable(dev, line, 1); + if (lvl == 1) + cx23885_gpio_set(dev, line); + else + cx23885_gpio_clear(dev, line); +} + +static u8 f300_get_line(struct cx23885_dev *dev, u32 line) +{ + cx23885_gpio_enable(dev, line, 0); + + return cx23885_gpio_get(dev, line); +} + +static void f300_send_byte(struct cx23885_dev *dev, u8 dta) +{ + u8 i; + + for (i = 0; i < 8; i++) { + f300_set_line(dev, F300_CLK, 0); + udelay(30); + f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */ + udelay(30); + dta <<= 1; + f300_set_line(dev, F300_CLK, 1); + udelay(30); + } +} + +static u8 f300_get_byte(struct cx23885_dev *dev) +{ + u8 i, dta = 0; + + for (i = 0; i < 8; i++) { + f300_set_line(dev, F300_CLK, 0); + udelay(30); + dta <<= 1; + f300_set_line(dev, F300_CLK, 1); + udelay(30); + dta |= f300_get_line(dev, F300_DATA);/* msb first */ + + } + + return dta; +} + +static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf) +{ + struct cx23885_tsport *port = fe->dvb->priv; + struct cx23885_dev *dev = port->dev; + u8 i, temp, ret = 0; + + temp = buf[0]; + for (i = 0; i < buf[0]; i++) + temp += buf[i + 1]; + temp = (~temp + 1);/* get check sum */ + buf[1 + buf[0]] = temp; + + f300_set_line(dev, F300_RESET, 1); + f300_set_line(dev, F300_CLK, 1); + udelay(30); + f300_set_line(dev, F300_DATA, 1); + msleep(1); + + /* question: */ + f300_set_line(dev, F300_RESET, 0);/* begin to send data */ + msleep(1); + + f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */ + msleep(1); + + temp = buf[0]; + temp += 2; + for (i = 0; i < temp; i++) + f300_send_byte(dev, buf[i]); + + f300_set_line(dev, F300_RESET, 1);/* sent data over */ + f300_set_line(dev, F300_DATA, 1); + + /* answer: */ + temp = 0; + for (i = 0; ((i < 8) & (temp == 0)); i++) { + msleep(1); + if (f300_get_line(dev, F300_BUSY) == 0) + temp = 1; + } + + if (i > 7) { + printk(KERN_ERR "%s: timeout, the slave no response\n", + __func__); + ret = 1; /* timeout, the slave no response */ + } else { /* the slave not busy, prepare for getting data */ + f300_set_line(dev, F300_RESET, 0);/*ready...*/ + msleep(1); + f300_send_byte(dev, 0xe1);/* 0xe1 is Read */ + msleep(1); + temp = f300_get_byte(dev);/*get the data length */ + if (temp > 14) + temp = 14; + + for (i = 0; i < (temp + 1); i++) + f300_get_byte(dev);/* get data to empty buffer */ + + f300_set_line(dev, F300_RESET, 1);/* received data over */ + f300_set_line(dev, F300_DATA, 1); + } + + return ret; +} + +int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + u8 buf[16]; + + buf[0] = 0x05; + buf[1] = 0x38;/* write port */ + buf[2] = 0x01;/* A port, lnb power */ + + switch (voltage) { + case SEC_VOLTAGE_13: + buf[3] = 0x01;/* power on */ + buf[4] = 0x02;/* B port, H/V */ + buf[5] = 0x00;/*13V v*/ + break; + case SEC_VOLTAGE_18: + buf[3] = 0x01; + buf[4] = 0x02; + buf[5] = 0x01;/* 18V h*/ + break; + case SEC_VOLTAGE_OFF: + buf[3] = 0x00;/* power off */ + buf[4] = 0x00; + buf[5] = 0x00; + break; + } + + return f300_xfer(fe, buf); +} diff --git a/drivers/media/video/cx23885/cx23885-f300.h b/drivers/media/video/cx23885/cx23885-f300.h new file mode 100644 index 000000000000..e73344c94963 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-f300.h @@ -0,0 +1,2 @@ +extern int f300_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t voltage); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 338320025529..fa744764dc8b 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -471,6 +471,7 @@ extern void cx23885_wakeup(struct cx23885_tsport *port, extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask); extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask); +extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask); extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); From c21c2db414bb38086f99c586ffdf019eedb9cad8 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 25 Nov 2009 02:49:21 -0300 Subject: [PATCH 310/345] V4L/DVB (13495): pvrusb2: Support 16KB FX2 firmware New FX2 firmware from Hauppauge is no longer 8KB in size - it's 16KB. This is true for HVR-1950 and HVR-1900 devices. Without this change, new pvrusb2 users with that hardware are unable to use the driver (because the CD shipped with the hardware only has the 16KB firmware). Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 2 ++ drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index e4d7c13cab87..ef4ff411b39d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -456,6 +456,7 @@ static const struct pvr2_device_desc pvr2_device_750xx = { .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, + .flag_fx2_16kb = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, .default_std_mask = V4L2_STD_NTSC_M, @@ -478,6 +479,7 @@ static const struct pvr2_device_desc pvr2_device_751xx = { .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, + .flag_fx2_16kb = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, .default_std_mask = V4L2_STD_NTSC_M, diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index ea04ecf8aa39..e5b9594eb5f6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -176,6 +176,7 @@ struct pvr2_device_desc { unsigned int flag_has_analogtuner:1; /* Has analog tuner */ unsigned int flag_has_composite:1; /* Has composite input */ unsigned int flag_has_svideo:1; /* Has s-video input */ + unsigned int flag_fx2_16kb:1; /* 16KB FX2 firmware OK here */ }; extern struct usb_device_id pvr2_device_table[]; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 4c1a2a534427..9be04772c723 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1474,8 +1474,19 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) pipe = usb_sndctrlpipe(hdw->usb_dev, 0); - if (fw_entry->size != 0x2000){ - pvr2_trace(PVR2_TRACE_ERROR_LEGS,"wrong fx2 firmware size"); + if ((fw_entry->size != 0x2000) && + (!(hdw->hdw_desc->flag_fx2_16kb && (fw_entry->size == 0x4000)))) { + if (hdw->hdw_desc->flag_fx2_16kb) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Wrong fx2 firmware size" + " (expected 8192 or 16384, got %u)", + fw_entry->size); + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Wrong fx2 firmware size" + " (expected 8192, got %u)", + fw_entry->size); + } release_firmware(fw_entry); return -ENOMEM; } From 568efaa2f704f72eef9b70ac0f895e9b961f15a6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 25 Nov 2009 02:52:06 -0300 Subject: [PATCH 311/345] V4L/DVB (13496): pvrusb2: Support manual extraction of 16KB FX2 firmware This pvrusb2 change is in support of an existing feature used to help identify and locate newer vendor supplied firmware. This change makes the feature work for the newer larger firmware size. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-debugifc.c | 14 +++++++++----- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 9 +++++---- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index 010018bc8383..ae977668c496 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -252,11 +252,15 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf, scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); if (scnt && wptr) { count -= scnt; buf += scnt; - if (debugifc_match_keyword(wptr,wlen,"prom")) { - pvr2_hdw_cpufw_set_enabled(hdw,!0,!0); - } else if (debugifc_match_keyword(wptr,wlen, - "ram")) { - pvr2_hdw_cpufw_set_enabled(hdw,0,!0); + if (debugifc_match_keyword(wptr, wlen, + "prom")) { + pvr2_hdw_cpufw_set_enabled(hdw, 2, !0); + } else if (debugifc_match_keyword(wptr, wlen, + "ram8k")) { + pvr2_hdw_cpufw_set_enabled(hdw, 0, !0); + } else if (debugifc_match_keyword(wptr, wlen, + "ram16k")) { + pvr2_hdw_cpufw_set_enabled(hdw, 1, !0); } else { return -EINVAL; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 9be04772c723..bd05ec7b1cbe 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3514,7 +3514,7 @@ static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw) void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, - int prom_flag, + int mode, int enable_flag) { int ret; @@ -3537,11 +3537,12 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, break; } - hdw->fw_cpu_flag = (prom_flag == 0); + hdw->fw_cpu_flag = (mode != 2); if (hdw->fw_cpu_flag) { + hdw->fw_size = (mode == 1) ? 0x4000 : 0x2000; pvr2_trace(PVR2_TRACE_FIRMWARE, - "Preparing to suck out CPU firmware"); - hdw->fw_size = 0x2000; + "Preparing to suck out CPU firmware" + " (size=%u)", hdw->fw_size); hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); if (!hdw->fw_buffer) { hdw->fw_size = 0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 7b6940554e9a..56e70eae20c1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -219,7 +219,7 @@ int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std, this may prevent the device from running (and leaving this mode may imply a device reset). */ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, - int prom_flag, + int mode, /* 0=8KB FX2, 1=16KB FX2, 2=PROM */ int enable_flag); /* Return true if we're in a mode for retrieval CPU firmware */ From 1d70c7fdbb78b0cd40b850a14225aed454c0a062 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 25 Nov 2009 02:55:38 -0300 Subject: [PATCH 312/345] V4L/DVB (13497): pvrusb2: Shorten device hardware description text to work around V4L shortcoming The device text description in pvrusb2-devattr.c get mapped into a V4L API string field that is unfortunately shorter than I expected. No sense fighting City Hall here - this change shortens the descriptions to fit the limit. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index ef4ff411b39d..bd3b7932f23e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -58,7 +58,7 @@ static const char *pvr2_fw1_names_29xxx[] = { }; static const struct pvr2_device_desc pvr2_device_29xxx = { - .description = "WinTV PVR USB2 Model Category 29xxx", + .description = "WinTV PVR USB2 Model 29xxx", .shortname = "29xxx", .client_table.lst = pvr2_cli_29xxx, .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx), @@ -91,7 +91,7 @@ static const char *pvr2_fw1_names_24xxx[] = { }; static const struct pvr2_device_desc pvr2_device_24xxx = { - .description = "WinTV PVR USB2 Model Category 24xxx", + .description = "WinTV PVR USB2 Model 24xxx", .shortname = "24xxx", .client_table.lst = pvr2_cli_24xxx, .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx), @@ -340,7 +340,7 @@ static const char *pvr2_fw1_names_73xxx[] = { }; static const struct pvr2_device_desc pvr2_device_73xxx = { - .description = "WinTV HVR-1900 Model Category 73xxx", + .description = "WinTV HVR-1900 Model 73xxx", .shortname = "73xxx", .client_table.lst = pvr2_cli_73xxx, .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), @@ -445,7 +445,7 @@ static const char *pvr2_fw1_names_75xxx[] = { }; static const struct pvr2_device_desc pvr2_device_750xx = { - .description = "WinTV HVR-1950 Model Category 750xx", + .description = "WinTV HVR-1950 Model 750xx", .shortname = "750xx", .client_table.lst = pvr2_cli_73xxx, .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), @@ -468,7 +468,7 @@ static const struct pvr2_device_desc pvr2_device_750xx = { }; static const struct pvr2_device_desc pvr2_device_751xx = { - .description = "WinTV HVR-1950 Model Category 751xx", + .description = "WinTV HVR-1950 Model 751xx", .shortname = "751xx", .client_table.lst = pvr2_cli_73xxx, .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), From 4b1c83cc51381c3d523452353204247398f5116c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 25 Nov 2009 02:57:21 -0300 Subject: [PATCH 313/345] V4L/DVB (13498): pvrusb2: Bind I2C address 0x71 for Zilog IR devices Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index a334b1a966a2..7cbe18c4ca95 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -50,6 +50,7 @@ MODULE_PARM_DESC(disable_autoload_ir_video, /* Mapping of IR schemes to known I2C addresses - if any */ static const unsigned char ir_video_addresses[] = { + [PVR2_IR_SCHEME_ZILOG] = 0x71, [PVR2_IR_SCHEME_29XXX] = 0x18, [PVR2_IR_SCHEME_24XXX] = 0x18, }; From 9081d9018581e01eec9085a80c86bc07e7168f18 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 25 Nov 2009 02:59:34 -0300 Subject: [PATCH 314/345] V4L/DVB (13499): pvrusb2: Cosmetic tweak to minimize size_t exposure Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index bd05ec7b1cbe..e93f3e2c25e7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1447,6 +1447,7 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) const struct firmware *fw_entry = NULL; void *fw_ptr; unsigned int pipe; + unsigned int fwsize; int ret; u16 address; @@ -1473,19 +1474,20 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f)); pipe = usb_sndctrlpipe(hdw->usb_dev, 0); + fwsize = fw_entry->size; - if ((fw_entry->size != 0x2000) && - (!(hdw->hdw_desc->flag_fx2_16kb && (fw_entry->size == 0x4000)))) { + if ((fwsize != 0x2000) && + (!(hdw->hdw_desc->flag_fx2_16kb && (fwsize == 0x4000)))) { if (hdw->hdw_desc->flag_fx2_16kb) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Wrong fx2 firmware size" " (expected 8192 or 16384, got %u)", - fw_entry->size); + fwsize); } else { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Wrong fx2 firmware size" " (expected 8192, got %u)", - fw_entry->size); + fwsize); } release_firmware(fw_entry); return -ENOMEM; @@ -1504,7 +1506,7 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) chunk. */ ret = 0; - for(address = 0; address < fw_entry->size; address += 0x800) { + for (address = 0; address < fwsize; address += 0x800) { memcpy(fw_ptr, fw_entry->data + address, 0x800); ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address, 0, fw_ptr, 0x800, HZ); From 75727460a6dfa4c7fd8472a99269982ec4662e64 Mon Sep 17 00:00:00 2001 From: Gary Francis Date: Wed, 25 Nov 2009 03:03:31 -0300 Subject: [PATCH 315/345] V4L/DVB (13500): pvrusb2: Fix lingering 16KB FX2 Firmware issues These are additional fixes to enable proper pvrusb2 support of 16KB sized FX2 firmware. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index bd3b7932f23e..6bc16c13ccef 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -351,6 +351,7 @@ static const struct pvr2_device_desc pvr2_device_73xxx = { .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, + .flag_fx2_16kb = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e93f3e2c25e7..1bbdab08fe0e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1522,8 +1522,8 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) trace_firmware("Upload done (%d bytes sent)",ret); - /* We should have written 8192 bytes */ - if (ret == 8192) { + /* We should have written fwsize bytes */ + if (ret == fwsize) { hdw->fw1_state = FW1_STATE_RELOAD; return 0; } From bce039c099e97b07534518b5f3c0ce31b1606ff6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 Nov 2009 11:15:56 -0300 Subject: [PATCH 316/345] V4L/DVB (13502): uvcvideo: Add support for Genius eFace 2025 webcams The Genius eFace 2025 (0458:706e) requires the MINMAX quirk. Add a corresponding entry in the device IDs list. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 782faf6970b4..b8b33a05cabd 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1912,6 +1912,15 @@ static int uvc_reset_resume(struct usb_interface *intf) * though they are compliant. */ static struct usb_device_id uvc_ids[] = { + /* Genius eFace 2025 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0458, + .idProduct = 0x706e, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Microsoft Lifecam NX-6000 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, From 6241d8ca1dc27356180011dff4d93a3c5b3cbd76 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 Nov 2009 12:00:22 -0300 Subject: [PATCH 317/345] V4L/DVB (13503): uvcvideo: Merge iterms, oterms and units linked lists All terminals and units are now added to a single linked list of entities per chain. This makes terminals and units handling code more generic. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 29 +++-------------- drivers/media/video/uvc/uvc_driver.c | 48 +++++++++++++--------------- drivers/media/video/uvc/uvc_v4l2.c | 10 ++++-- drivers/media/video/uvc/uvcvideo.h | 5 ++- 4 files changed, 36 insertions(+), 56 deletions(-) diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 6f1487fc3d7c..0469d7a876a8 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -742,17 +742,7 @@ struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, v4l2_id &= V4L2_CTRL_ID_MASK; /* Find the control. */ - __uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next); - if (ctrl && !next) - return ctrl; - - list_for_each_entry(entity, &chain->iterms, chain) { - __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); - if (ctrl && !next) - return ctrl; - } - - list_for_each_entry(entity, &chain->extensions, chain) { + list_for_each_entry(entity, &chain->entities, chain) { __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); if (ctrl && !next) return ctrl; @@ -951,17 +941,7 @@ int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback) int ret = 0; /* Find the control. */ - ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback); - if (ret < 0) - goto done; - - list_for_each_entry(entity, &chain->iterms, chain) { - ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); - if (ret < 0) - goto done; - } - - list_for_each_entry(entity, &chain->extensions, chain) { + list_for_each_entry(entity, &chain->entities, chain) { ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); if (ret < 0) goto done; @@ -1075,8 +1055,9 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, int ret; /* Find the extension unit. */ - list_for_each_entry(entity, &chain->extensions, chain) { - if (entity->id == xctrl->unit) + list_for_each_entry(entity, &chain->entities, chain) { + if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT && + entity->id == xctrl->unit) break; } diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index b8b33a05cabd..db28311d6ec8 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1224,7 +1224,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, return -1; } - list_add_tail(&entity->chain, &chain->extensions); break; case UVC_VC_PROCESSING_UNIT: @@ -1263,7 +1262,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- IT %d\n", entity->id); - list_add_tail(&entity->chain, &chain->iterms); break; case UVC_TT_STREAMING: @@ -1276,7 +1274,6 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, return -1; } - list_add_tail(&entity->chain, &chain->iterms); break; default: @@ -1285,6 +1282,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, return -1; } + list_add_tail(&entity->chain, &chain->entities); return 0; } @@ -1315,7 +1313,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, return -EINVAL; } - list_add_tail(&forward->chain, &chain->extensions); + list_add_tail(&forward->chain, &chain->entities); if (uvc_trace_param & UVC_TRACE_PROBE) { if (!found) printk(" (->"); @@ -1335,7 +1333,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, return -EINVAL; } - list_add_tail(&forward->chain, &chain->oterms); + list_add_tail(&forward->chain, &chain->entities); if (uvc_trace_param & UVC_TRACE_PROBE) { if (!found) printk(" (->"); @@ -1391,7 +1389,7 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" %d", term->id); - list_add_tail(&term->chain, &chain->iterms); + list_add_tail(&term->chain, &chain->entities); uvc_scan_chain_forward(chain, term, entity); } @@ -1412,7 +1410,7 @@ static int uvc_scan_chain(struct uvc_video_chain *chain, int id; entity = oterm; - list_add_tail(&entity->chain, &chain->oterms); + list_add_tail(&entity->chain, &chain->entities); uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); id = entity->output.bSourceID; @@ -1452,21 +1450,25 @@ static int uvc_scan_chain(struct uvc_video_chain *chain, return 0; } -static unsigned int uvc_print_terms(struct list_head *terms, char *buffer) +static unsigned int uvc_print_terms(struct list_head *terms, u16 dir, + char *buffer) { struct uvc_entity *term; unsigned int nterms = 0; char *p = buffer; list_for_each_entry(term, terms, chain) { - p += sprintf(p, "%u", term->id); - if (term->chain.next != terms) { + if (!UVC_ENTITY_IS_TERM(term) || + UVC_TERM_DIRECTION(term) != dir) + continue; + + if (nterms) p += sprintf(p, ","); - if (++nterms >= 4) { - p += sprintf(p, "..."); - break; - } + if (++nterms >= 4) { + p += sprintf(p, "..."); + break; } + p += sprintf(p, "%u", term->id); } return p - buffer; @@ -1477,9 +1479,9 @@ static const char *uvc_print_chain(struct uvc_video_chain *chain) static char buffer[43]; char *p = buffer; - p += uvc_print_terms(&chain->iterms, p); + p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p); p += sprintf(p, " -> "); - uvc_print_terms(&chain->oterms, p); + uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p); return buffer; } @@ -1510,9 +1512,7 @@ static int uvc_scan_device(struct uvc_device *dev) if (chain == NULL) return -ENOMEM; - INIT_LIST_HEAD(&chain->iterms); - INIT_LIST_HEAD(&chain->oterms); - INIT_LIST_HEAD(&chain->extensions); + INIT_LIST_HEAD(&chain->entities); mutex_init(&chain->ctrl_mutex); chain->dev = dev; @@ -1685,13 +1685,13 @@ static int uvc_register_video(struct uvc_device *dev, * Register all video devices in all chains. */ static int uvc_register_terms(struct uvc_device *dev, - struct uvc_video_chain *chain, struct list_head *terms) + struct uvc_video_chain *chain) { struct uvc_streaming *stream; struct uvc_entity *term; int ret; - list_for_each_entry(term, terms, chain) { + list_for_each_entry(term, &chain->entities, chain) { if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) continue; @@ -1717,11 +1717,7 @@ static int uvc_register_chains(struct uvc_device *dev) int ret; list_for_each_entry(chain, &dev->chains, list) { - ret = uvc_register_terms(dev, chain, &chain->iterms); - if (ret < 0) - return ret; - - ret = uvc_register_terms(dev, chain, &chain->oterms); + ret = uvc_register_terms(dev, chain); if (ret < 0) return ret; } diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index be3da56d4db3..9e1f2c208ed8 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -620,12 +620,16 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { if (index != 0) return -EINVAL; - iterm = list_first_entry(&chain->iterms, - struct uvc_entity, chain); + list_for_each_entry(iterm, &chain->entities, chain) { + if (UVC_ENTITY_IS_ITERM(iterm)) + break; + } pin = iterm->id; } else if (pin < selector->selector.bNrInPins) { pin = selector->selector.baSourceID[index]; - list_for_each_entry(iterm, chain->iterms.next, chain) { + list_for_each_entry(iterm, &chain->entities, chain) { + if (!UVC_ENTITY_IS_ITERM(iterm)) + continue; if (iterm->id == pin) break; } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index fb3342ae6d7c..9e6948fb3e61 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -75,6 +75,7 @@ struct uvc_xu_control { #define UVC_TERM_INPUT 0x0000 #define UVC_TERM_OUTPUT 0x8000 +#define UVC_TERM_DIRECTION(term) ((term)->type & 0x8000) #define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) @@ -408,11 +409,9 @@ struct uvc_video_chain { struct uvc_device *dev; struct list_head list; - struct list_head iterms; /* Input terminals */ - struct list_head oterms; /* Output terminals */ + struct list_head entities; /* All entities */ struct uvc_entity *processing; /* Processing unit */ struct uvc_entity *selector; /* Selector unit */ - struct list_head extensions; /* Extension units */ struct mutex ctrl_mutex; }; From fd3e921739aff709bbaae6d75d9f64542f47c850 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 Nov 2009 12:00:27 -0300 Subject: [PATCH 318/345] V4L/DVB (13504): uvcvideo: Fix extension units parsing The bNrInPins field is an 8 bit integer, not a 16 bit integer. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index db28311d6ec8..8d51a6a130b0 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -844,7 +844,7 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, unit->type = UVC_VC_EXTENSION_UNIT; memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; - unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]); + unit->extension.bNrInPins = buffer[21]; unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; memcpy(unit->extension.baSourceID, &buffer[22], p); unit->extension.bControlSize = buffer[22+p]; @@ -1108,7 +1108,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, unit->type = buffer[2]; memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; - unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]); + unit->extension.bNrInPins = buffer[21]; unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; memcpy(unit->extension.baSourceID, &buffer[22], p); unit->extension.bControlSize = buffer[22+p]; From 4057ac6ca9a77c4275b34b5925ab5c99557913b1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 Nov 2009 12:00:29 -0300 Subject: [PATCH 319/345] V4L/DVB (13505): uvcvideo: Refactor chain scan Don't handle the first output terminal in a chain in a special way. Use uvc_scan_chain_entity() like for all other entities, making the chain scan code more generic. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 75 ++++++++++++++++------------ 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 8d51a6a130b0..e7ce898ad706 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1265,13 +1265,12 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, break; case UVC_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 (UVC_ENTITY_IS_ITERM(entity)) { + if (uvc_trace_param & UVC_TRACE_PROBE) + printk(" <- IT %d\n", entity->id); + } else { + if (uvc_trace_param & UVC_TRACE_PROBE) + printk(" OT %d", entity->id); } break; @@ -1351,10 +1350,11 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, } static int uvc_scan_chain_backward(struct uvc_video_chain *chain, - struct uvc_entity *entity) + struct uvc_entity **_entity) { + struct uvc_entity *entity = *_entity; struct uvc_entity *term; - int id = -1, i; + int id = -EINVAL, i; switch (UVC_ENTITY_TYPE(entity)) { case UVC_VC_EXTENSION_UNIT: @@ -1398,34 +1398,49 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, id = 0; break; + + case UVC_ITT_VENDOR_SPECIFIC: + case UVC_ITT_CAMERA: + case UVC_ITT_MEDIA_TRANSPORT_INPUT: + case UVC_OTT_VENDOR_SPECIFIC: + case UVC_OTT_DISPLAY: + case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: + case UVC_TT_STREAMING: + id = UVC_ENTITY_IS_OTERM(entity) ? entity->output.bSourceID : 0; + break; } - return id; + if (id <= 0) { + *_entity = NULL; + return id; + } + + entity = uvc_entity_by_id(chain->dev, id); + if (entity == NULL) { + uvc_trace(UVC_TRACE_DESCR, "Found reference to " + "unknown entity %d.\n", id); + return -EINVAL; + } + + *_entity = entity; + return 0; } static int uvc_scan_chain(struct uvc_video_chain *chain, - struct uvc_entity *oterm) + struct uvc_entity *term) { struct uvc_entity *entity, *prev; - int id; - entity = oterm; - list_add_tail(&entity->chain, &chain->entities); - uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); + uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:"); - id = entity->output.bSourceID; - while (id != 0) { - prev = entity; - entity = uvc_entity_by_id(chain->dev, id); - if (entity == NULL) { - uvc_trace(UVC_TRACE_DESCR, "Found reference to " - "unknown entity %d.\n", id); - return -EINVAL; - } + entity = term; + prev = NULL; + while (entity != NULL) { + /* Entity must not be part of an existing chain */ if (entity->chain.next || entity->chain.prev) { uvc_trace(UVC_TRACE_DESCR, "Found reference to " - "entity %d already in chain.\n", id); + "entity %d already in chain.\n", entity->id); return -EINVAL; } @@ -1437,14 +1452,10 @@ static int uvc_scan_chain(struct uvc_video_chain *chain, if (uvc_scan_chain_forward(chain, entity, prev) < 0) return -EINVAL; - /* Stop when a terminal is found. */ - if (UVC_ENTITY_IS_TERM(entity)) - break; - /* Backward scan */ - id = uvc_scan_chain_backward(chain, entity); - if (id < 0) - return id; + prev = entity; + if (uvc_scan_chain_backward(chain, &entity) < 0) + return -EINVAL; } return 0; From 8ca5a639f4f3eb8958a7e270fcff7516374637a5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 Nov 2009 12:00:30 -0300 Subject: [PATCH 320/345] V4L/DVB (13506): uvcvideo: Factorize common field in uvc_entity structure The bNrInPins and baSourceID fields are common among all entities (some of use bSourceID but this is conceptually the same). Move those two fields out of entity type-specific unions into the uvc_entity structure top level. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 119 ++++++++++++--------------- drivers/media/video/uvc/uvc_v4l2.c | 6 +- drivers/media/video/uvc/uvcvideo.h | 9 +- 3 files changed, 57 insertions(+), 77 deletions(-) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index e7ce898ad706..c31bc50113bc 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -249,29 +249,9 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, entity = list_entry(&dev->entities, struct uvc_entity, list); list_for_each_entry_continue(entity, &dev->entities, list) { - switch (UVC_ENTITY_TYPE(entity)) { - case UVC_TT_STREAMING: - if (entity->output.bSourceID == id) + for (i = 0; i < entity->bNrInPins; ++i) + if (entity->baSourceID[i] == id) return entity; - break; - - case UVC_VC_PROCESSING_UNIT: - if (entity->processing.bSourceID == id) - return entity; - break; - - case UVC_VC_SELECTOR_UNIT: - for (i = 0; i < entity->selector.bNrInPins; ++i) - if (entity->selector.baSourceID[i] == id) - return entity; - break; - - case UVC_VC_EXTENSION_UNIT: - for (i = 0; i < entity->extension.bNrInPins; ++i) - if (entity->extension.baSourceID[i] == id) - return entity; - break; - } } return NULL; @@ -785,6 +765,28 @@ static int uvc_parse_streaming(struct uvc_device *dev, return ret; } +static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, + unsigned int num_pads, unsigned int extra_size) +{ + struct uvc_entity *entity; + unsigned int num_inputs; + unsigned int size; + + num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; + size = sizeof(*entity) + extra_size + num_inputs; + entity = kzalloc(size, GFP_KERNEL); + if (entity == NULL) + return NULL; + + entity->id = id; + entity->type = type; + + entity->bNrInPins = num_inputs; + entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size; + + return entity; +} + /* Parse vendor-specific extensions. */ static int uvc_parse_vendor_control(struct uvc_device *dev, const unsigned char *buffer, int buflen) @@ -836,21 +838,18 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, break; } - unit = kzalloc(sizeof *unit + p + 2*n, GFP_KERNEL); + unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], + p + 1, 2*n); if (unit == NULL) return -ENOMEM; - unit->id = buffer[3]; - unit->type = UVC_VC_EXTENSION_UNIT; memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; - unit->extension.bNrInPins = buffer[21]; - unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; - memcpy(unit->extension.baSourceID, &buffer[22], p); + memcpy(unit->baSourceID, &buffer[22], p); unit->extension.bControlSize = buffer[22+p]; - unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; - unit->extension.bmControlsType = (__u8 *)unit + sizeof *unit - + p + n; + unit->extension.bmControls = (__u8 *)unit + sizeof(*unit); + unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit) + + n; memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); if (buffer[24+p+2*n] != 0) @@ -947,13 +946,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - term = kzalloc(sizeof *term + n + p, GFP_KERNEL); + term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], + 1, n + p); if (term == NULL) return -ENOMEM; - term->id = buffer[3]; - term->type = type | UVC_TERM_INPUT; - if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { term->camera.bControlSize = n; term->camera.bmControls = (__u8 *)term + sizeof *term; @@ -1008,13 +1005,12 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return 0; } - term = kzalloc(sizeof *term, GFP_KERNEL); + term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], + 1, 0); if (term == NULL) return -ENOMEM; - term->id = buffer[3]; - term->type = type | UVC_TERM_OUTPUT; - term->output.bSourceID = buffer[7]; + memcpy(term->baSourceID, &buffer[7], 1); if (buffer[8] != 0) usb_string(udev, buffer[8], term->name, @@ -1035,15 +1031,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = kzalloc(sizeof *unit + p, GFP_KERNEL); + unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); if (unit == NULL) return -ENOMEM; - unit->id = buffer[3]; - unit->type = buffer[2]; - unit->selector.bNrInPins = buffer[4]; - unit->selector.baSourceID = (__u8 *)unit + sizeof *unit; - memcpy(unit->selector.baSourceID, &buffer[5], p); + memcpy(unit->baSourceID, &buffer[5], p); if (buffer[5+p] != 0) usb_string(udev, buffer[5+p], unit->name, @@ -1065,13 +1057,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = kzalloc(sizeof *unit + n, GFP_KERNEL); + unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); if (unit == NULL) return -ENOMEM; - unit->id = buffer[3]; - unit->type = buffer[2]; - unit->processing.bSourceID = buffer[4]; + memcpy(unit->baSourceID, &buffer[4], 1); unit->processing.wMaxMultiplier = get_unaligned_le16(&buffer[5]); unit->processing.bControlSize = buffer[7]; @@ -1100,19 +1090,15 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL); + unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); if (unit == NULL) return -ENOMEM; - unit->id = buffer[3]; - unit->type = buffer[2]; memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; - unit->extension.bNrInPins = buffer[21]; - unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; - memcpy(unit->extension.baSourceID, &buffer[22], p); + memcpy(unit->baSourceID, &buffer[22], p); unit->extension.bControlSize = buffer[22+p]; - unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; + unit->extension.bmControls = (__u8 *)unit + sizeof *unit; memcpy(unit->extension.bmControls, &buffer[23+p], n); if (buffer[23+p+n] != 0) @@ -1218,7 +1204,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- XU %d", entity->id); - if (entity->extension.bNrInPins != 1) { + if (entity->bNrInPins != 1) { uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more " "than 1 input pin.\n", entity->id); return -1; @@ -1244,7 +1230,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, printk(" <- SU %d", entity->id); /* Single-input selector units are ignored. */ - if (entity->selector.bNrInPins == 1) + if (entity->bNrInPins == 1) break; if (chain->selector != NULL) { @@ -1305,7 +1291,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, switch (UVC_ENTITY_TYPE(forward)) { case UVC_VC_EXTENSION_UNIT: - if (forward->extension.bNrInPins != 1) { + if (forward->bNrInPins != 1) { uvc_trace(UVC_TRACE_DESCR, "Extension unit %d " "has more than 1 input pin.\n", entity->id); @@ -1358,17 +1344,14 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, switch (UVC_ENTITY_TYPE(entity)) { case UVC_VC_EXTENSION_UNIT: - id = entity->extension.baSourceID[0]; - break; - case UVC_VC_PROCESSING_UNIT: - id = entity->processing.bSourceID; + id = entity->baSourceID[0]; break; case UVC_VC_SELECTOR_UNIT: /* Single-input selector units are ignored. */ - if (entity->selector.bNrInPins == 1) { - id = entity->selector.baSourceID[0]; + if (entity->bNrInPins == 1) { + id = entity->baSourceID[0]; break; } @@ -1376,8 +1359,8 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, printk(" <- IT"); chain->selector = entity; - for (i = 0; i < entity->selector.bNrInPins; ++i) { - id = entity->selector.baSourceID[i]; + for (i = 0; i < entity->bNrInPins; ++i) { + id = entity->baSourceID[i]; term = uvc_entity_by_id(chain->dev, id); if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " @@ -1406,7 +1389,7 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, case UVC_OTT_DISPLAY: case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: case UVC_TT_STREAMING: - id = UVC_ENTITY_IS_OTERM(entity) ? entity->output.bSourceID : 0; + id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0; break; } diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 9e1f2c208ed8..23239a4adefe 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -625,8 +625,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) break; } pin = iterm->id; - } else if (pin < selector->selector.bNrInPins) { - pin = selector->selector.baSourceID[index]; + } else if (pin < selector->bNrInPins) { + pin = selector->baSourceID[index]; list_for_each_entry(iterm, &chain->entities, chain) { if (!UVC_ENTITY_IS_ITERM(iterm)) continue; @@ -680,7 +680,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) break; } - if (input == 0 || input > chain->selector->selector.bNrInPins) + if (input == 0 || input > chain->selector->bNrInPins) return -EINVAL; return uvc_query_ctrl(chain->dev, UVC_SET_CUR, diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 9e6948fb3e61..7ec9a04ced50 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -293,11 +293,9 @@ struct uvc_entity { } media; struct { - __u8 bSourceID; } output; struct { - __u8 bSourceID; __u16 wMaxMultiplier; __u8 bControlSize; __u8 *bmControls; @@ -305,21 +303,20 @@ struct uvc_entity { } processing; struct { - __u8 bNrInPins; - __u8 *baSourceID; } selector; struct { __u8 guidExtensionCode[16]; __u8 bNumControls; - __u8 bNrInPins; - __u8 *baSourceID; __u8 bControlSize; __u8 *bmControls; __u8 *bmControlsType; } extension; }; + __u8 bNrInPins; + __u8 *baSourceID; + unsigned int ncontrols; struct uvc_control *controls; }; From 1ce7981be36e05216df64ffeceb8230d9b569b87 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 12:37:00 -0300 Subject: [PATCH 321/345] V4L/DVB (13508): pms: source code cleanup, use struct v4l2_device. This prepares the pms driver for the v4l1 -> v4l2 conversion. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pms.c | 1299 ++++++++++++++++++------------------- 1 file changed, 637 insertions(+), 662 deletions(-) diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index a1ad38fc49c1..2919aa42c94e 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -31,171 +31,175 @@ #include #include #include +#include #include #include +MODULE_LICENSE("GPL"); + #define MOTOROLA 1 #define PHILIPS2 2 #define PHILIPS1 3 #define MVVMEMORYWIDTH 0x40 /* 512 bytes */ -struct pms_device -{ - struct video_device v; - struct video_picture picture; - int height; - int width; - unsigned long in_use; - struct mutex lock; -}; - -struct i2c_info -{ +struct i2c_info { u8 slave; u8 sub; u8 data; u8 hits; }; -static int i2c_count; -static struct i2c_info i2cinfo[64]; +struct pms { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct video_picture picture; + int height; + int width; + unsigned long in_use; + struct mutex lock; + int i2c_count; + struct i2c_info i2cinfo[64]; -static int decoder = PHILIPS2; -static int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ + int decoder; + int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ + int io; + int data; + void __iomem *mem; +}; + +static struct pms pms_card; /* * I/O ports and Shared Memory */ -static int io_port = 0x250; -static int data_port = 0x251; -static int mem_base = 0xC8000; -static void __iomem *mem; -static int video_nr = -1; +static int io_port = 0x250; +module_param(io_port, int, 0); + +static int mem_base = 0xc8000; +module_param(mem_base, int, 0); + +static int video_nr = -1; +module_param(video_nr, int, 0); - -static inline void mvv_write(u8 index, u8 value) +static inline void mvv_write(struct pms *dev, u8 index, u8 value) { - outw(index|(value<<8), io_port); + outw(index | (value << 8), dev->io); } -static inline u8 mvv_read(u8 index) +static inline u8 mvv_read(struct pms *dev, u8 index) { - outb(index, io_port); - return inb(data_port); + outb(index, dev->io); + return inb(dev->data); } -static int pms_i2c_stat(u8 slave) +static int pms_i2c_stat(struct pms *dev, u8 slave) { - int counter; + int counter = 0; int i; - outb(0x28, io_port); + outb(0x28, dev->io); - counter=0; - while((inb(data_port)&0x01)==0) - if(counter++==256) + while ((inb(dev->data) & 0x01) == 0) + if (counter++ == 256) break; - while((inb(data_port)&0x01)!=0) - if(counter++==256) + while ((inb(dev->data) & 0x01) != 0) + if (counter++ == 256) break; - outb(slave, io_port); + outb(slave, dev->io); - counter=0; - while((inb(data_port)&0x01)==0) - if(counter++==256) + counter = 0; + while ((inb(dev->data) & 0x01) == 0) + if (counter++ == 256) break; - while((inb(data_port)&0x01)!=0) - if(counter++==256) + while ((inb(dev->data) & 0x01) != 0) + if (counter++ == 256) break; - for(i=0;i<12;i++) - { - char st=inb(data_port); - if((st&2)!=0) + for (i = 0; i < 12; i++) { + char st = inb(dev->data); + + if ((st & 2) != 0) return -1; - if((st&1)==0) + if ((st & 1) == 0) break; } - outb(0x29, io_port); - return inb(data_port); + outb(0x29, dev->io); + return inb(dev->data); } -static int pms_i2c_write(u16 slave, u16 sub, u16 data) +static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data) { - int skip=0; + int skip = 0; int count; int i; - for(i=0;ii2c_count; i++) { + if ((dev->i2cinfo[i].slave == slave) && + (dev->i2cinfo[i].sub == sub)) { + if (dev->i2cinfo[i].data == data) + skip = 1; + dev->i2cinfo[i].data = data; + i = dev->i2c_count + 1; } } - if(i==i2c_count && i2c_count<64) - { - i2cinfo[i2c_count].slave=slave; - i2cinfo[i2c_count].sub=sub; - i2cinfo[i2c_count].data=data; - i2c_count++; + if (i == dev->i2c_count && dev->i2c_count < 64) { + dev->i2cinfo[dev->i2c_count].slave = slave; + dev->i2cinfo[dev->i2c_count].sub = sub; + dev->i2cinfo[dev->i2c_count].data = data; + dev->i2c_count++; } - if(skip) + if (skip) return 0; - mvv_write(0x29, sub); - mvv_write(0x2A, data); - mvv_write(0x28, slave); + mvv_write(dev, 0x29, sub); + mvv_write(dev, 0x2A, data); + mvv_write(dev, 0x28, slave); - outb(0x28, io_port); + outb(0x28, dev->io); - count=0; - while((inb(data_port)&1)==0) - if(count>255) + count = 0; + while ((inb(dev->data) & 1) == 0) + if (count > 255) break; - while((inb(data_port)&1)!=0) - if(count>255) + while ((inb(dev->data) & 1) != 0) + if (count > 255) break; - count=inb(data_port); + count = inb(dev->data); - if(count&2) + if (count & 2) return -1; return count; } -static int pms_i2c_read(int slave, int sub) +static int pms_i2c_read(struct pms *dev, int slave, int sub) { - int i=0; - for(i=0;ii2c_count; i++) { + if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub) + return dev->i2cinfo[i].data; } return 0; } -static void pms_i2c_andor(int slave, int sub, int and, int or) +static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or) { u8 tmp; - tmp=pms_i2c_read(slave, sub); - tmp = (tmp&and)|or; - pms_i2c_write(slave, sub, tmp); + tmp = pms_i2c_read(dev, slave, sub); + tmp = (tmp & and) | or; + pms_i2c_write(dev, slave, sub, tmp); } /* @@ -203,100 +207,96 @@ static void pms_i2c_andor(int slave, int sub, int and, int or) */ -static void pms_videosource(short source) +static void pms_videosource(struct pms *dev, short source) { - mvv_write(0x2E, source?0x31:0x30); + mvv_write(dev, 0x2E, source ? 0x31 : 0x30); } -static void pms_hue(short hue) +static void pms_hue(struct pms *dev, short hue) { - switch(decoder) - { - case MOTOROLA: - pms_i2c_write(0x8A, 0x00, hue); - break; - case PHILIPS2: - pms_i2c_write(0x8A, 0x07, hue); - break; - case PHILIPS1: - pms_i2c_write(0x42, 0x07, hue); - break; + switch (dev->decoder) { + case MOTOROLA: + pms_i2c_write(dev, 0x8a, 0x00, hue); + break; + case PHILIPS2: + pms_i2c_write(dev, 0x8a, 0x07, hue); + break; + case PHILIPS1: + pms_i2c_write(dev, 0x42, 0x07, hue); + break; } } -static void pms_colour(short colour) +static void pms_colour(struct pms *dev, short colour) { - switch(decoder) - { - case MOTOROLA: - pms_i2c_write(0x8A, 0x00, colour); - break; - case PHILIPS1: - pms_i2c_write(0x42, 0x12, colour); - break; + switch (dev->decoder) { + case MOTOROLA: + pms_i2c_write(dev, 0x8a, 0x00, colour); + break; + case PHILIPS1: + pms_i2c_write(dev, 0x42, 0x12, colour); + break; } } -static void pms_contrast(short contrast) +static void pms_contrast(struct pms *dev, short contrast) { - switch(decoder) - { - case MOTOROLA: - pms_i2c_write(0x8A, 0x00, contrast); - break; - case PHILIPS1: - pms_i2c_write(0x42, 0x13, contrast); - break; + switch (dev->decoder) { + case MOTOROLA: + pms_i2c_write(dev, 0x8a, 0x00, contrast); + break; + case PHILIPS1: + pms_i2c_write(dev, 0x42, 0x13, contrast); + break; } } -static void pms_brightness(short brightness) +static void pms_brightness(struct pms *dev, short brightness) { - switch(decoder) - { - case MOTOROLA: - pms_i2c_write(0x8A, 0x00, brightness); - pms_i2c_write(0x8A, 0x00, brightness); - pms_i2c_write(0x8A, 0x00, brightness); - break; - case PHILIPS1: - pms_i2c_write(0x42, 0x19, brightness); - break; + switch (dev->decoder) { + case MOTOROLA: + pms_i2c_write(dev, 0x8a, 0x00, brightness); + pms_i2c_write(dev, 0x8a, 0x00, brightness); + pms_i2c_write(dev, 0x8a, 0x00, brightness); + break; + case PHILIPS1: + pms_i2c_write(dev, 0x42, 0x19, brightness); + break; } } -static void pms_format(short format) +static void pms_format(struct pms *dev, short format) { int target; - standard = format; - if(decoder==PHILIPS1) - target=0x42; - else if(decoder==PHILIPS2) - target=0x8A; + dev->standard = format; + + if (dev->decoder == PHILIPS1) + target = 0x42; + else if (dev->decoder == PHILIPS2) + target = 0x8a; else return; - switch(format) - { - case 0: /* Auto */ - pms_i2c_andor(target, 0x0D, 0xFE,0x00); - pms_i2c_andor(target, 0x0F, 0x3F,0x80); - break; - case 1: /* NTSC */ - pms_i2c_andor(target, 0x0D, 0xFE, 0x00); - pms_i2c_andor(target, 0x0F, 0x3F, 0x40); - break; - case 2: /* PAL */ - pms_i2c_andor(target, 0x0D, 0xFE, 0x00); - pms_i2c_andor(target, 0x0F, 0x3F, 0x00); - break; - case 3: /* SECAM */ - pms_i2c_andor(target, 0x0D, 0xFE, 0x01); - pms_i2c_andor(target, 0x0F, 0x3F, 0x00); - break; + switch (format) { + case 0: /* Auto */ + pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); + pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80); + break; + case 1: /* NTSC */ + pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); + pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40); + break; + case 2: /* PAL */ + pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); + pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00); + break; + case 3: /* SECAM */ + pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01); + pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00); + break; } } @@ -308,18 +308,17 @@ static void pms_format(short format) * people need it. We also don't yet use the PMS interrupt. */ -static void pms_hstart(short start) +static void pms_hstart(struct pms *dev, short start) { - switch(decoder) - { - case PHILIPS1: - pms_i2c_write(0x8A, 0x05, start); - pms_i2c_write(0x8A, 0x18, start); - break; - case PHILIPS2: - pms_i2c_write(0x42, 0x05, start); - pms_i2c_write(0x42, 0x18, start); - break; + switch (dev->decoder) { + case PHILIPS1: + pms_i2c_write(dev, 0x8a, 0x05, start); + pms_i2c_write(dev, 0x8a, 0x18, start); + break; + case PHILIPS2: + pms_i2c_write(dev, 0x42, 0x05, start); + pms_i2c_write(dev, 0x42, 0x18, start); + break; } } @@ -327,293 +326,271 @@ static void pms_hstart(short start) * Bandpass filters */ -static void pms_bandpass(short pass) +static void pms_bandpass(struct pms *dev, short pass) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4); } -static void pms_antisnow(short snow) +static void pms_antisnow(struct pms *dev, short snow) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2); } -static void pms_sharpness(short sharp) +static void pms_sharpness(struct pms *dev, short sharp) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x06, 0xFC, sharp&0x03); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03); } -static void pms_chromaagc(short agc) +static void pms_chromaagc(struct pms *dev, short agc) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5); } -static void pms_vertnoise(short noise) +static void pms_vertnoise(struct pms *dev, short noise) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x10, 0xFC, noise&3); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x10, 0xFC, noise&3); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3); } -static void pms_forcecolour(short colour) +static void pms_forcecolour(struct pms *dev, short colour) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7); } -static void pms_antigamma(short gamma) +static void pms_antigamma(struct pms *dev, short gamma) { - if(decoder==PHILIPS2) - pms_i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7); } -static void pms_prefilter(short filter) +static void pms_prefilter(struct pms *dev, short filter) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6); } -static void pms_hfilter(short filter) +static void pms_hfilter(struct pms *dev, short filter) { - if(decoder==PHILIPS2) - pms_i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5); } -static void pms_vfilter(short filter) +static void pms_vfilter(struct pms *dev, short filter) { - if(decoder==PHILIPS2) - pms_i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5); } -static void pms_killcolour(short colour) +static void pms_killcolour(struct pms *dev, short colour) { - if(decoder==PHILIPS2) - { - pms_i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3); - pms_i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3); - } - else if(decoder==PHILIPS1) - { - pms_i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3); - pms_i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3); + if (dev->decoder == PHILIPS2) { + pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3); + pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3); + } else if (dev->decoder == PHILIPS1) { + pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3); + pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3); } } -static void pms_chromagain(short chroma) +static void pms_chromagain(struct pms *dev, short chroma) { - if(decoder==PHILIPS2) - { - pms_i2c_write(0x8A, 0x11, chroma); - } - else if(decoder==PHILIPS1) - { - pms_i2c_write(0x42, 0x11, chroma); - } + if (dev->decoder == PHILIPS2) + pms_i2c_write(dev, 0x8a, 0x11, chroma); + else if (dev->decoder == PHILIPS1) + pms_i2c_write(dev, 0x42, 0x11, chroma); } -static void pms_spacialcompl(short data) +static void pms_spacialcompl(struct pms *dev, short data) { - mvv_write(0x3B, data); + mvv_write(dev, 0x3b, data); } -static void pms_spacialcomph(short data) +static void pms_spacialcomph(struct pms *dev, short data) { - mvv_write(0x3A, data); + mvv_write(dev, 0x3a, data); } -static void pms_vstart(short start) +static void pms_vstart(struct pms *dev, short start) { - mvv_write(0x16, start); - mvv_write(0x17, (start>>8)&0x01); + mvv_write(dev, 0x16, start); + mvv_write(dev, 0x17, (start >> 8) & 0x01); } #endif -static void pms_secamcross(short cross) +static void pms_secamcross(struct pms *dev, short cross) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5); } -static void pms_swsense(short sense) +static void pms_swsense(struct pms *dev, short sense) { - if(decoder==PHILIPS2) - { - pms_i2c_write(0x8A, 0x0A, sense); - pms_i2c_write(0x8A, 0x0B, sense); - } - else if(decoder==PHILIPS1) - { - pms_i2c_write(0x42, 0x0A, sense); - pms_i2c_write(0x42, 0x0B, sense); + if (dev->decoder == PHILIPS2) { + pms_i2c_write(dev, 0x8a, 0x0a, sense); + pms_i2c_write(dev, 0x8a, 0x0b, sense); + } else if (dev->decoder == PHILIPS1) { + pms_i2c_write(dev, 0x42, 0x0a, sense); + pms_i2c_write(dev, 0x42, 0x0b, sense); } } -static void pms_framerate(short frr) +static void pms_framerate(struct pms *dev, short frr) { - int fps=(standard==1)?30:25; - if(frr==0) + int fps = (dev->standard == 1) ? 30 : 25; + + if (frr == 0) return; - fps=fps/frr; - mvv_write(0x14,0x80|fps); - mvv_write(0x15,1); + fps = fps/frr; + mvv_write(dev, 0x14, 0x80 | fps); + mvv_write(dev, 0x15, 1); } -static void pms_vert(u8 deciden, u8 decinum) +static void pms_vert(struct pms *dev, u8 deciden, u8 decinum) { - mvv_write(0x1C, deciden); /* Denominator */ - mvv_write(0x1D, decinum); /* Numerator */ + mvv_write(dev, 0x1c, deciden); /* Denominator */ + mvv_write(dev, 0x1d, decinum); /* Numerator */ } /* * Turn 16bit ratios into best small ratio the chipset can grok */ -static void pms_vertdeci(unsigned short decinum, unsigned short deciden) +static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden) { - /* Knock it down by /5 once */ - if(decinum%5==0) - { - deciden/=5; - decinum/=5; + /* Knock it down by / 5 once */ + if (decinum % 5 == 0) { + deciden /= 5; + decinum /= 5; } /* * 3's */ - while(decinum%3==0 && deciden%3==0) - { - deciden/=3; - decinum/=3; + while (decinum % 3 == 0 && deciden % 3 == 0) { + deciden /= 3; + decinum /= 3; } /* * 2's */ - while(decinum%2==0 && deciden%2==0) - { - decinum/=2; - deciden/=2; + while (decinum % 2 == 0 && deciden % 2 == 0) { + decinum /= 2; + deciden /= 2; } /* * Fudgyify */ - while(deciden>32) - { - deciden/=2; - decinum=(decinum+1)/2; + while (deciden > 32) { + deciden /= 2; + decinum = (decinum + 1) / 2; } - if(deciden==32) + if (deciden == 32) deciden--; - pms_vert(deciden,decinum); + pms_vert(dev, deciden, decinum); } -static void pms_horzdeci(short decinum, short deciden) +static void pms_horzdeci(struct pms *dev, short decinum, short deciden) { - if(decinum<=512) - { - if(decinum%5==0) - { - decinum/=5; - deciden/=5; + if (decinum <= 512) { + if (decinum % 5 == 0) { + decinum /= 5; + deciden /= 5; } - } - else - { - decinum=512; - deciden=640; /* 768 would be ideal */ + } else { + decinum = 512; + deciden = 640; /* 768 would be ideal */ } - while(((decinum|deciden)&1)==0) - { - decinum>>=1; - deciden>>=1; + while (((decinum | deciden) & 1) == 0) { + decinum >>= 1; + deciden >>= 1; } - while(deciden>32) - { - deciden>>=1; - decinum=(decinum+1)>>1; + while (deciden > 32) { + deciden >>= 1; + decinum = (decinum + 1) >> 1; } - if(deciden==32) + if (deciden == 32) deciden--; - mvv_write(0x24, 0x80|deciden); - mvv_write(0x25, decinum); + mvv_write(dev, 0x24, 0x80 | deciden); + mvv_write(dev, 0x25, decinum); } -static void pms_resolution(short width, short height) +static void pms_resolution(struct pms *dev, short width, short height) { int fg_height; - fg_height=height; - if(fg_height>280) - fg_height=280; + fg_height = height; + if (fg_height > 280) + fg_height = 280; - mvv_write(0x18, fg_height); - mvv_write(0x19, fg_height>>8); + mvv_write(dev, 0x18, fg_height); + mvv_write(dev, 0x19, fg_height >> 8); - if(standard==1) - { - mvv_write(0x1A, 0xFC); - mvv_write(0x1B, 0x00); - if(height>fg_height) - pms_vertdeci(240,240); + if (dev->standard == 1) { + mvv_write(dev, 0x1a, 0xfc); + mvv_write(dev, 0x1b, 0x00); + if (height > fg_height) + pms_vertdeci(dev, 240, 240); else - pms_vertdeci(fg_height,240); - } - else - { - mvv_write(0x1A, 0x1A); - mvv_write(0x1B, 0x01); - if(fg_height>256) - pms_vertdeci(270,270); + pms_vertdeci(dev, fg_height, 240); + } else { + mvv_write(dev, 0x1a, 0x1a); + mvv_write(dev, 0x1b, 0x01); + if (fg_height > 256) + pms_vertdeci(dev, 270, 270); else - pms_vertdeci(fg_height, 270); + pms_vertdeci(dev, fg_height, 270); } - mvv_write(0x12,0); - mvv_write(0x13, MVVMEMORYWIDTH); - mvv_write(0x42, 0x00); - mvv_write(0x43, 0x00); - mvv_write(0x44, MVVMEMORYWIDTH); + mvv_write(dev, 0x12, 0); + mvv_write(dev, 0x13, MVVMEMORYWIDTH); + mvv_write(dev, 0x42, 0x00); + mvv_write(dev, 0x43, 0x00); + mvv_write(dev, 0x44, MVVMEMORYWIDTH); - mvv_write(0x22, width+8); - mvv_write(0x23, (width+8)>> 8); + mvv_write(dev, 0x22, width + 8); + mvv_write(dev, 0x23, (width + 8) >> 8); - if(standard==1) - pms_horzdeci(width,640); + if (dev->standard == 1) + pms_horzdeci(dev, width, 640); else - pms_horzdeci(width+8, 768); + pms_horzdeci(dev, width + 8, 768); - mvv_write(0x30, mvv_read(0x30)&0xFE); - mvv_write(0x08, mvv_read(0x08)|0x01); - mvv_write(0x01, mvv_read(0x01)&0xFD); - mvv_write(0x32, 0x00); - mvv_write(0x33, MVVMEMORYWIDTH); + mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe); + mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01); + mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd); + mvv_write(dev, 0x32, 0x00); + mvv_write(dev, 0x33, MVVMEMORYWIDTH); } @@ -621,52 +598,49 @@ static void pms_resolution(short width, short height) * Set Input */ -static void pms_vcrinput(short input) +static void pms_vcrinput(struct pms *dev, short input) { - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42,0x0D,0x7F,(input&1)<<7); + if (dev->decoder == PHILIPS2) + pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7); + else if (dev->decoder == PHILIPS1) + pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7); } -static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int count) +static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count) { int y; - int dw = 2*dev->width; - - char tmp[dw+32]; /* using a temp buffer is faster than direct */ + int dw = 2 * dev->width; + char tmp[dw + 32]; /* using a temp buffer is faster than direct */ int cnt = 0; - int len=0; + int len = 0; unsigned char r8 = 0x5; /* value for reg8 */ if (rgb555) r8 |= 0x20; /* else use untranslated rgb = 565 */ - mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */ + mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */ /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */ - for (y = 0; y < dev->height; y++ ) - { - writeb(0, mem); /* synchronisiert neue Zeile */ + for (y = 0; y < dev->height; y++) { + writeb(0, dev->mem); /* synchronisiert neue Zeile */ /* * This is in truth a fifo, be very careful as if you * forgot this odd things will occur 8) */ - memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */ + memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word */ cnt -= dev->height; - while (cnt <= 0) - { + while (cnt <= 0) { /* * Don't copy too far */ - int dt=dw; - if(dt+len>count) - dt=count-len; + int dt = dw; + if (dt + len > count) + dt = count - len; cnt += dev->height; - if (copy_to_user(buf, tmp+32, dt)) + if (copy_to_user(buf, tmp + 32, dt)) return len ? len : -EFAULT; buf += dt; len += dt; @@ -682,182 +656,182 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int 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; + struct pms *dev = video_drvdata(file); - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - strcpy(b->name, "Mediavision PMS"); - b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES; - b->channels = 4; - b->audios = 0; - b->maxwidth = 640; - b->maxheight = 480; - b->minwidth = 16; - b->minheight = 16; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - if(v->channel<0 || v->channel>3) - return -EINVAL; - v->flags=0; - v->tuners=1; - /* Good question.. its composite or SVHS so.. */ - v->type = VIDEO_TYPE_CAMERA; - switch(v->channel) - { - case 0: - strcpy(v->name, "Composite");break; - case 1: - strcpy(v->name, "SVideo");break; - case 2: - strcpy(v->name, "Composite(VCR)");break; - case 3: - strcpy(v->name, "SVideo(VCR)");break; - } - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - if(v->channel<0 || v->channel>3) - return -EINVAL; - mutex_lock(&pd->lock); - pms_videosource(v->channel&1); - pms_vcrinput(v->channel>>1); - mutex_unlock(&pd->lock); - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; - if(v->tuner) - return -EINVAL; - strcpy(v->name, "Format"); - v->rangelow=0; - v->rangehigh=0; - v->flags= VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; - switch(standard) - { - case 0: - v->mode = VIDEO_MODE_AUTO; - break; - case 1: - v->mode = VIDEO_MODE_NTSC; - break; - case 2: - v->mode = VIDEO_MODE_PAL; - break; - case 3: - v->mode = VIDEO_MODE_SECAM; - break; - } - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner *v = arg; - if(v->tuner) - return -EINVAL; - mutex_lock(&pd->lock); - switch(v->mode) - { - case VIDEO_MODE_AUTO: - pms_framerate(25); - pms_secamcross(0); - pms_format(0); - break; - case VIDEO_MODE_NTSC: - pms_framerate(30); - pms_secamcross(0); - pms_format(1); - break; - case VIDEO_MODE_PAL: - pms_framerate(25); - pms_secamcross(0); - pms_format(2); - break; - case VIDEO_MODE_SECAM: - pms_framerate(25); - pms_secamcross(1); - pms_format(2); - break; - default: - mutex_unlock(&pd->lock); - return -EINVAL; - } - mutex_unlock(&pd->lock); - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - *p = pd->picture; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16) - ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15))) - return -EINVAL; - pd->picture= *p; + switch (cmd) { + case VIDIOCGCAP: { + struct video_capability *b = arg; - /* - * Now load the card. - */ + strcpy(b->name, "Mediavision PMS"); + b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; + b->channels = 4; + b->audios = 0; + b->maxwidth = 640; + b->maxheight = 480; + b->minwidth = 16; + b->minheight = 16; + return 0; + } + case VIDIOCGCHAN: { + struct video_channel *v = arg; - mutex_lock(&pd->lock); - pms_brightness(p->brightness>>8); - pms_hue(p->hue>>8); - pms_colour(p->colour>>8); - pms_contrast(p->contrast>>8); - mutex_unlock(&pd->lock); - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - if(vw->flags) - return -EINVAL; - if(vw->clipcount) - return -EINVAL; - if(vw->height<16||vw->height>480) - return -EINVAL; - if(vw->width<16||vw->width>640) - return -EINVAL; - pd->width=vw->width; - pd->height=vw->height; - mutex_lock(&pd->lock); - pms_resolution(pd->width, pd->height); - mutex_unlock(&pd->lock); /* Ok we figured out what to use from our wide choice */ - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - memset(vw,0,sizeof(*vw)); - vw->width=pd->width; - vw->height=pd->height; - return 0; - } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: + if (v->channel < 0 || v->channel > 3) return -EINVAL; + v->flags = 0; + v->tuners = 1; + /* Good question.. its composite or SVHS so.. */ + v->type = VIDEO_TYPE_CAMERA; + switch (v->channel) { + case 0: + strcpy(v->name, "Composite"); + break; + case 1: + strcpy(v->name, "SVideo"); + break; + case 2: + strcpy(v->name, "Composite(VCR)"); + break; + case 3: + strcpy(v->name, "SVideo(VCR)"); + break; + } + return 0; + } + case VIDIOCSCHAN: { + struct video_channel *v = arg; + + if (v->channel < 0 || v->channel > 3) + return -EINVAL; + mutex_lock(&dev->lock); + pms_videosource(dev, v->channel & 1); + pms_vcrinput(dev, v->channel >> 1); + mutex_unlock(&dev->lock); + return 0; + } + case VIDIOCGTUNER: { + struct video_tuner *v = arg; + + if (v->tuner) + return -EINVAL; + strcpy(v->name, "Format"); + v->rangelow = 0; + v->rangehigh = 0; + v->flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC | VIDEO_TUNER_SECAM; + switch (dev->standard) { + case 0: + v->mode = VIDEO_MODE_AUTO; + break; + case 1: + v->mode = VIDEO_MODE_NTSC; + break; + case 2: + v->mode = VIDEO_MODE_PAL; + break; + case 3: + v->mode = VIDEO_MODE_SECAM; + break; + } + return 0; + } + case VIDIOCSTUNER: { + struct video_tuner *v = arg; + + if (v->tuner) + return -EINVAL; + mutex_lock(&dev->lock); + switch (v->mode) { + case VIDEO_MODE_AUTO: + pms_framerate(dev, 25); + pms_secamcross(dev, 0); + pms_format(dev, 0); + break; + case VIDEO_MODE_NTSC: + pms_framerate(dev, 30); + pms_secamcross(dev, 0); + pms_format(dev, 1); + break; + case VIDEO_MODE_PAL: + pms_framerate(dev, 25); + pms_secamcross(dev, 0); + pms_format(dev, 2); + break; + case VIDEO_MODE_SECAM: + pms_framerate(dev, 25); + pms_secamcross(dev, 1); + pms_format(dev, 2); + break; default: - return -ENOIOCTLCMD; + mutex_unlock(&dev->lock); + return -EINVAL; + } + mutex_unlock(&dev->lock); + return 0; + } + case VIDIOCGPICT: { + struct video_picture *p = arg; + + *p = dev->picture; + return 0; + } + case VIDIOCSPICT: { + struct video_picture *p = arg; + + if (!((p->palette == VIDEO_PALETTE_RGB565 && p->depth == 16) || + (p->palette == VIDEO_PALETTE_RGB555 && p->depth == 15))) + return -EINVAL; + dev->picture = *p; + + /* + * Now load the card. + */ + + mutex_lock(&dev->lock); + pms_brightness(dev, p->brightness >> 8); + pms_hue(dev, p->hue >> 8); + pms_colour(dev, p->colour >> 8); + pms_contrast(dev, p->contrast >> 8); + mutex_unlock(&dev->lock); + return 0; + } + case VIDIOCSWIN: { + struct video_window *vw = arg; + + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (vw->height < 16 || vw->height > 480) + return -EINVAL; + if (vw->width < 16 || vw->width > 640) + return -EINVAL; + dev->width = vw->width; + dev->height = vw->height; + mutex_lock(&dev->lock); + pms_resolution(dev, dev->width, dev->height); + /* Ok we figured out what to use from our wide choice */ + mutex_unlock(&dev->lock); + return 0; + } + case VIDIOCGWIN: { + struct video_window *vw = arg; + + memset(vw, 0, sizeof(*vw)); + vw->width = dev->width; + vw->height = dev->height; + return 0; + } + case VIDIOCKEY: + return 0; + case VIDIOCCAPTURE: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + default: + return -ENOIOCTLCMD; } return 0; } @@ -871,30 +845,27 @@ static long pms_ioctl(struct file *file, static ssize_t pms_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct video_device *v = video_devdata(file); - struct pms_device *pd=(struct pms_device *)v; + struct pms *dev = video_drvdata(file); int len; - mutex_lock(&pd->lock); - len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); - mutex_unlock(&pd->lock); + mutex_lock(&dev->lock); + len = pms_capture(dev, buf, (dev->picture.depth == 16) ? 0 : 1, count); + mutex_unlock(&dev->lock); return len; } static int pms_exclusive_open(struct file *file) { - struct video_device *v = video_devdata(file); - struct pms_device *pd = (struct pms_device *)v; + struct pms *dev = video_drvdata(file); - return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0; + return test_and_set_bit(0, &dev->in_use) ? -EBUSY : 0; } static int pms_exclusive_release(struct file *file) { - struct video_device *v = video_devdata(file); - struct pms_device *pd = (struct pms_device *)v; + struct pms *dev = video_drvdata(file); - clear_bit(0, &pd->in_use); + clear_bit(0, &dev->in_use); return 0; } @@ -906,74 +877,62 @@ static const struct v4l2_file_operations pms_fops = { .read = pms_read, }; -static struct video_device pms_template= -{ - .name = "Mediavision PMS", - .fops = &pms_fops, - .release = video_device_release_empty, -}; - -static struct pms_device pms_device; - /* * Probe for and initialise the Mediavision PMS */ -static int init_mediavision(void) +static int init_mediavision(struct pms *dev) { int id; int idec, decst; int i; - - unsigned char i2c_defs[]={ - 0x4C,0x30,0x00,0xE8, - 0xB6,0xE2,0x00,0x00, - 0xFF,0xFF,0x00,0x00, - 0x00,0x00,0x78,0x98, - 0x00,0x00,0x00,0x00, - 0x34,0x0A,0xF4,0xCE, - 0xE4 + static const unsigned char i2c_defs[] = { + 0x4c, 0x30, 0x00, 0xe8, + 0xb6, 0xe2, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x98, + 0x00, 0x00, 0x00, 0x00, + 0x34, 0x0a, 0xf4, 0xce, + 0xe4 }; - mem = ioremap(mem_base, 0x800); - if (!mem) + dev->mem = ioremap(mem_base, 0x800); + if (!dev->mem) return -ENOMEM; - if (!request_region(0x9A01, 1, "Mediavision PMS config")) - { - printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n"); - iounmap(mem); + if (!request_region(0x9a01, 1, "Mediavision PMS config")) { + printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n"); + iounmap(dev->mem); return -EBUSY; } - if (!request_region(io_port, 3, "Mediavision PMS")) - { - printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port); - release_region(0x9A01, 1); - iounmap(mem); + if (!request_region(dev->io, 3, "Mediavision PMS")) { + printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io); + release_region(0x9a01, 1); + iounmap(dev->mem); return -EBUSY; } - outb(0xB8, 0x9A01); /* Unlock */ - outb(io_port>>4, 0x9A01); /* Set IO port */ + outb(0xb8, 0x9a01); /* Unlock */ + outb(dev->io >> 4, 0x9a01); /* Set IO port */ - id=mvv_read(3); - decst=pms_i2c_stat(0x43); + id = mvv_read(dev, 3); + decst = pms_i2c_stat(dev, 0x43); - if(decst!=-1) - idec=2; - else if(pms_i2c_stat(0xb9)!=-1) - idec=3; - else if(pms_i2c_stat(0x8b)!=-1) - idec=1; + if (decst != -1) + idec = 2; + else if (pms_i2c_stat(dev, 0xb9) != -1) + idec = 3; + else if (pms_i2c_stat(dev, 0x8b) != -1) + idec = 1; else - idec=0; + idec = 0; printk(KERN_INFO "PMS type is %d\n", idec); - if(idec == 0) { - release_region(io_port, 3); - release_region(0x9A01, 1); - iounmap(mem); + if (idec == 0) { + release_region(dev->io, 3); + release_region(0x9a01, 1); + iounmap(dev->mem); return -ENODEV; } @@ -981,51 +940,50 @@ static int init_mediavision(void) * Ok we have a PMS of some sort */ - mvv_write(0x04, mem_base>>12); /* Set the memory area */ + mvv_write(dev, 0x04, mem_base >> 12); /* Set the memory area */ /* Ok now load the defaults */ - for(i=0;i<0x19;i++) - { - if(i2c_defs[i]==0xFF) - pms_i2c_andor(0x8A, i, 0x07,0x00); + for (i = 0; i < 0x19; i++) { + if (i2c_defs[i] == 0xff) + pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00); else - pms_i2c_write(0x8A, i, i2c_defs[i]); + pms_i2c_write(dev, 0x8a, i, i2c_defs[i]); } - pms_i2c_write(0xB8,0x00,0x12); - pms_i2c_write(0xB8,0x04,0x00); - pms_i2c_write(0xB8,0x07,0x00); - pms_i2c_write(0xB8,0x08,0x00); - pms_i2c_write(0xB8,0x09,0xFF); - pms_i2c_write(0xB8,0x0A,0x00); - pms_i2c_write(0xB8,0x0B,0x10); - pms_i2c_write(0xB8,0x10,0x03); + pms_i2c_write(dev, 0xb8, 0x00, 0x12); + pms_i2c_write(dev, 0xb8, 0x04, 0x00); + pms_i2c_write(dev, 0xb8, 0x07, 0x00); + pms_i2c_write(dev, 0xb8, 0x08, 0x00); + pms_i2c_write(dev, 0xb8, 0x09, 0xff); + pms_i2c_write(dev, 0xb8, 0x0a, 0x00); + pms_i2c_write(dev, 0xb8, 0x0b, 0x10); + pms_i2c_write(dev, 0xb8, 0x10, 0x03); - mvv_write(0x01, 0x00); - mvv_write(0x05, 0xA0); - mvv_write(0x08, 0x25); - mvv_write(0x09, 0x00); - mvv_write(0x0A, 0x20|MVVMEMORYWIDTH); + mvv_write(dev, 0x01, 0x00); + mvv_write(dev, 0x05, 0xa0); + mvv_write(dev, 0x08, 0x25); + mvv_write(dev, 0x09, 0x00); + mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH); - mvv_write(0x10, 0x02); - mvv_write(0x1E, 0x0C); - mvv_write(0x1F, 0x03); - mvv_write(0x26, 0x06); + mvv_write(dev, 0x10, 0x02); + mvv_write(dev, 0x1e, 0x0c); + mvv_write(dev, 0x1f, 0x03); + mvv_write(dev, 0x26, 0x06); - mvv_write(0x2B, 0x00); - mvv_write(0x2C, 0x20); - mvv_write(0x2D, 0x00); - mvv_write(0x2F, 0x70); - mvv_write(0x32, 0x00); - mvv_write(0x33, MVVMEMORYWIDTH); - mvv_write(0x34, 0x00); - mvv_write(0x35, 0x00); - mvv_write(0x3A, 0x80); - mvv_write(0x3B, 0x10); - mvv_write(0x20, 0x00); - mvv_write(0x21, 0x00); - mvv_write(0x30, 0x22); + mvv_write(dev, 0x2b, 0x00); + mvv_write(dev, 0x2c, 0x20); + mvv_write(dev, 0x2d, 0x00); + mvv_write(dev, 0x2f, 0x70); + mvv_write(dev, 0x32, 0x00); + mvv_write(dev, 0x33, MVVMEMORYWIDTH); + mvv_write(dev, 0x34, 0x00); + mvv_write(dev, 0x35, 0x00); + mvv_write(dev, 0x3a, 0x80); + mvv_write(dev, 0x3b, 0x10); + mvv_write(dev, 0x20, 0x00); + mvv_write(dev, 0x21, 0x00); + mvv_write(dev, 0x30, 0x22); return 0; } @@ -1038,53 +996,70 @@ static int enable; module_param(enable, int, 0); #endif -static int __init init_pms_cards(void) +static int __init pms_init(void) { - printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n"); + struct pms *dev = &pms_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "pms", sizeof(v4l2_dev->name)); + + v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.03\n"); #ifndef MODULE if (!enable) { - printk(KERN_INFO "PMS: not enabled, use pms.enable=1 to " - "probe\n"); + v4l2_err(v4l2_dev, + "PMS: not enabled, use pms.enable=1 to probe\n"); return -ENODEV; } #endif - data_port = io_port +1; + dev->decoder = PHILIPS2; + dev->io = io_port; + dev->data = io_port + 1; - if(init_mediavision()) - { - printk(KERN_INFO "Board not found.\n"); + if (init_mediavision(dev)) { + v4l2_err(v4l2_dev, "Board not found.\n"); return -ENODEV; } - memcpy(&pms_device, &pms_template, sizeof(pms_template)); - mutex_init(&pms_device.lock); - pms_device.height=240; - pms_device.width=320; - pms_swsense(75); - pms_resolution(320,240); - return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER, video_nr); + + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &pms_fops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + mutex_init(&dev->lock); + dev->height = 240; + dev->width = 320; + pms_swsense(dev, 75); + pms_resolution(dev, 320, 240); + pms_videosource(dev, 0); + pms_vcrinput(dev, 0); + if (video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 3); + release_region(0x9a01, 1); + iounmap(dev->mem); + return -EINVAL; + } + return 0; } -module_param(io_port, int, 0); -module_param(mem_base, int, 0); -module_param(video_nr, int, 0); -MODULE_LICENSE("GPL"); - - -static void __exit shutdown_mediavision(void) +static void __exit pms_exit(void) { - release_region(io_port,3); - release_region(0x9A01, 1); + struct pms *dev = &pms_card; + + video_unregister_device(&dev->vdev); + release_region(dev->io, 3); + release_region(0x9a01, 1); + iounmap(dev->mem); } -static void __exit cleanup_pms_module(void) -{ - shutdown_mediavision(); - video_unregister_device((struct video_device *)&pms_device); - iounmap(mem); -} - -module_init(init_pms_cards); -module_exit(cleanup_pms_module); - +module_init(pms_init); +module_exit(pms_exit); From feba2f817d87891c002739ecdb54eef56740b882 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 12:47:02 -0300 Subject: [PATCH 322/345] V4L/DVB (13509): pms: convert from V4L1 to V4L2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- drivers/media/video/pms.c | 492 ++++++++++++++++++++++-------------- 2 files changed, 297 insertions(+), 197 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 82ae85c975f5..9dc74c93bf24 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -600,7 +600,7 @@ source "drivers/media/video/bt8xx/Kconfig" config VIDEO_PMS tristate "Mediavision Pro Movie Studio Video For Linux" - depends on ISA && VIDEO_V4L1 + depends on ISA && VIDEO_V4L2 help Say Y if you have such a thing. diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 2919aa42c94e..73ec970ca5ca 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -14,8 +14,10 @@ * unless the userspace driver also doesn't work for you... * * Changes: - * 08/07/2003 Daniele Bellucci - * - pms_capture: report back -EFAULT + * 25-11-2009 Hans Verkuil + * - converted to version 2 of the V4L API. + * 08/07/2003 Daniele Bellucci + * - pms_capture: report back -EFAULT */ #include @@ -27,20 +29,21 @@ #include #include #include +#include +#include +#include #include -#include + +#include #include #include #include -#include - -#include MODULE_LICENSE("GPL"); #define MOTOROLA 1 -#define PHILIPS2 2 +#define PHILIPS2 2 /* SAA7191 */ #define PHILIPS1 3 #define MVVMEMORYWIDTH 0x40 /* 512 bytes */ @@ -54,9 +57,11 @@ struct i2c_info { struct pms { struct v4l2_device v4l2_dev; struct video_device vdev; - struct video_picture picture; int height; int width; + int depth; + int input; + s32 brightness, saturation, hue, contrast; unsigned long in_use; struct mutex lock; int i2c_count; @@ -64,6 +69,7 @@ struct pms { int decoder; int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ + v4l2_std_id std; int io; int data; void __iomem *mem; @@ -209,7 +215,19 @@ static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or) static void pms_videosource(struct pms *dev, short source) { - mvv_write(dev, 0x2E, source ? 0x31 : 0x30); + switch (dev->decoder) { + case MOTOROLA: + break; + case PHILIPS2: + pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0); + break; + case PHILIPS1: + break; + } + mvv_write(dev, 0x2E, 0x31); + /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30); + But could not make this work correctly. Only Composite input + worked for me. */ } static void pms_hue(struct pms *dev, short hue) @@ -227,14 +245,14 @@ static void pms_hue(struct pms *dev, short hue) } } -static void pms_colour(struct pms *dev, short colour) +static void pms_saturation(struct pms *dev, short sat) { switch (dev->decoder) { case MOTOROLA: - pms_i2c_write(dev, 0x8a, 0x00, colour); + pms_i2c_write(dev, 0x8a, 0x00, sat); break; case PHILIPS1: - pms_i2c_write(dev, 0x42, 0x12, colour); + pms_i2c_write(dev, 0x42, 0x12, sat); break; } } @@ -467,7 +485,7 @@ static void pms_swsense(struct pms *dev, short sense) static void pms_framerate(struct pms *dev, short frr) { - int fps = (dev->standard == 1) ? 30 : 25; + int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25; if (frr == 0) return; @@ -557,7 +575,7 @@ static void pms_resolution(struct pms *dev, short width, short height) mvv_write(dev, 0x18, fg_height); mvv_write(dev, 0x19, fg_height >> 8); - if (dev->standard == 1) { + if (dev->std & V4L2_STD_525_60) { mvv_write(dev, 0x1a, 0xfc); mvv_write(dev, 0x1b, 0x00); if (height > fg_height) @@ -581,7 +599,7 @@ static void pms_resolution(struct pms *dev, short width, short height) mvv_write(dev, 0x22, width + 8); mvv_write(dev, 0x23, (width + 8) >> 8); - if (dev->standard == 1) + if (dev->std & V4L2_STD_525_60) pms_horzdeci(dev, width, 640); else pms_horzdeci(dev, width + 8, 768); @@ -654,192 +672,252 @@ static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count) * Video4linux interfacing */ -static long pms_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static int pms_querycap(struct file *file, void *priv, + struct v4l2_capability *vcap) { struct pms *dev = video_drvdata(file); - switch (cmd) { - case VIDIOCGCAP: { - struct video_capability *b = arg; - - strcpy(b->name, "Mediavision PMS"); - b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; - b->channels = 4; - b->audios = 0; - b->maxwidth = 640; - b->maxheight = 480; - b->minwidth = 16; - b->minheight = 16; - return 0; - } - case VIDIOCGCHAN: { - struct video_channel *v = arg; - - if (v->channel < 0 || v->channel > 3) - return -EINVAL; - v->flags = 0; - v->tuners = 1; - /* Good question.. its composite or SVHS so.. */ - v->type = VIDEO_TYPE_CAMERA; - switch (v->channel) { - case 0: - strcpy(v->name, "Composite"); - break; - case 1: - strcpy(v->name, "SVideo"); - break; - case 2: - strcpy(v->name, "Composite(VCR)"); - break; - case 3: - strcpy(v->name, "SVideo(VCR)"); - break; - } - return 0; - } - case VIDIOCSCHAN: { - struct video_channel *v = arg; - - if (v->channel < 0 || v->channel > 3) - return -EINVAL; - mutex_lock(&dev->lock); - pms_videosource(dev, v->channel & 1); - pms_vcrinput(dev, v->channel >> 1); - mutex_unlock(&dev->lock); - return 0; - } - case VIDIOCGTUNER: { - struct video_tuner *v = arg; - - if (v->tuner) - return -EINVAL; - strcpy(v->name, "Format"); - v->rangelow = 0; - v->rangehigh = 0; - v->flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC | VIDEO_TUNER_SECAM; - switch (dev->standard) { - case 0: - v->mode = VIDEO_MODE_AUTO; - break; - case 1: - v->mode = VIDEO_MODE_NTSC; - break; - case 2: - v->mode = VIDEO_MODE_PAL; - break; - case 3: - v->mode = VIDEO_MODE_SECAM; - break; - } - return 0; - } - case VIDIOCSTUNER: { - struct video_tuner *v = arg; - - if (v->tuner) - return -EINVAL; - mutex_lock(&dev->lock); - switch (v->mode) { - case VIDEO_MODE_AUTO: - pms_framerate(dev, 25); - pms_secamcross(dev, 0); - pms_format(dev, 0); - break; - case VIDEO_MODE_NTSC: - pms_framerate(dev, 30); - pms_secamcross(dev, 0); - pms_format(dev, 1); - break; - case VIDEO_MODE_PAL: - pms_framerate(dev, 25); - pms_secamcross(dev, 0); - pms_format(dev, 2); - break; - case VIDEO_MODE_SECAM: - pms_framerate(dev, 25); - pms_secamcross(dev, 1); - pms_format(dev, 2); - break; - default: - mutex_unlock(&dev->lock); - return -EINVAL; - } - mutex_unlock(&dev->lock); - return 0; - } - case VIDIOCGPICT: { - struct video_picture *p = arg; - - *p = dev->picture; - return 0; - } - case VIDIOCSPICT: { - struct video_picture *p = arg; - - if (!((p->palette == VIDEO_PALETTE_RGB565 && p->depth == 16) || - (p->palette == VIDEO_PALETTE_RGB555 && p->depth == 15))) - return -EINVAL; - dev->picture = *p; - - /* - * Now load the card. - */ - - mutex_lock(&dev->lock); - pms_brightness(dev, p->brightness >> 8); - pms_hue(dev, p->hue >> 8); - pms_colour(dev, p->colour >> 8); - pms_contrast(dev, p->contrast >> 8); - mutex_unlock(&dev->lock); - return 0; - } - case VIDIOCSWIN: { - struct video_window *vw = arg; - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (vw->height < 16 || vw->height > 480) - return -EINVAL; - if (vw->width < 16 || vw->width > 640) - return -EINVAL; - dev->width = vw->width; - dev->height = vw->height; - mutex_lock(&dev->lock); - pms_resolution(dev, dev->width, dev->height); - /* Ok we figured out what to use from our wide choice */ - mutex_unlock(&dev->lock); - return 0; - } - case VIDIOCGWIN: { - struct video_window *vw = arg; - - memset(vw, 0, sizeof(*vw)); - vw->width = dev->width; - vw->height = dev->height; - return 0; - } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } + strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver)); + strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card)); + strlcpy(vcap->bus_info, "ISA", sizeof(vcap->bus_info)); + vcap->version = KERNEL_VERSION(0, 0, 3); + vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; return 0; } -static long pms_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin) { - return video_usercopy(file, cmd, arg, pms_do_ioctl); + static const char *inputs[4] = { + "Composite", + "S-Video", + "Composite (VCR)", + "S-Video (VCR)" + }; + + if (vin->index > 3) + return -EINVAL; + strlcpy(vin->name, inputs[vin->index], sizeof(vin->name)); + vin->type = V4L2_INPUT_TYPE_CAMERA; + vin->audioset = 0; + vin->tuner = 0; + vin->std = V4L2_STD_ALL; + vin->status = 0; + return 0; +} + +static int pms_g_input(struct file *file, void *fh, unsigned int *inp) +{ + struct pms *dev = video_drvdata(file); + + *inp = dev->input; + return 0; +} + +static int pms_s_input(struct file *file, void *fh, unsigned int inp) +{ + struct pms *dev = video_drvdata(file); + + if (inp > 3) + return -EINVAL; + + mutex_lock(&dev->lock); + dev->input = inp; + pms_videosource(dev, inp & 1); + pms_vcrinput(dev, inp >> 1); + mutex_unlock(&dev->lock); + return 0; +} + +static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std) +{ + struct pms *dev = video_drvdata(file); + + *std = dev->std; + return 0; +} + +static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std) +{ + struct pms *dev = video_drvdata(file); + int ret = 0; + + dev->std = *std; + mutex_lock(&dev->lock); + if (dev->std & V4L2_STD_NTSC) { + pms_framerate(dev, 30); + pms_secamcross(dev, 0); + pms_format(dev, 1); + } else if (dev->std & V4L2_STD_PAL) { + pms_framerate(dev, 25); + pms_secamcross(dev, 0); + pms_format(dev, 2); + } else if (dev->std & V4L2_STD_SECAM) { + pms_framerate(dev, 25); + pms_secamcross(dev, 1); + pms_format(dev, 2); + } else { + ret = -EINVAL; + } + /* + switch (v->mode) { + case VIDEO_MODE_AUTO: + pms_framerate(dev, 25); + pms_secamcross(dev, 0); + pms_format(dev, 0); + break; + }*/ + mutex_unlock(&dev->lock); + return 0; +} + +static int pms_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 139); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 70); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 64); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0); + } + return -EINVAL; +} + +static int pms_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct pms *dev = video_drvdata(file); + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = dev->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = dev->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = dev->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = dev->hue; + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int pms_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct pms *dev = video_drvdata(file); + int ret = 0; + + mutex_lock(&dev->lock); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + dev->brightness = ctrl->value; + pms_brightness(dev, dev->brightness); + break; + case V4L2_CID_CONTRAST: + dev->contrast = ctrl->value; + pms_contrast(dev, dev->contrast); + break; + case V4L2_CID_SATURATION: + dev->saturation = ctrl->value; + pms_saturation(dev, dev->saturation); + break; + case V4L2_CID_HUE: + dev->hue = ctrl->value; + pms_hue(dev, dev->hue); + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&dev->lock); + return ret; +} + +static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct pms *dev = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + pix->width = dev->width; + pix->height = dev->height; + pix->pixelformat = dev->width == 15 ? + V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = 2 * dev->width; + pix->sizeimage = 2 * dev->width * dev->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SRGB; + return 0; +} + +static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + if (pix->height < 16 || pix->height > 480) + return -EINVAL; + if (pix->width < 16 || pix->width > 640) + return -EINVAL; + if (pix->pixelformat != V4L2_PIX_FMT_RGB555 && + pix->pixelformat != V4L2_PIX_FMT_RGB565) + return -EINVAL; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = 2 * pix->width; + pix->sizeimage = 2 * pix->width * pix->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SRGB; + return 0; +} + +static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct pms *dev = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + int ret = pms_try_fmt_vid_cap(file, fh, fmt); + + if (ret) + return ret; + mutex_lock(&dev->lock); + dev->width = pix->width; + dev->height = pix->height; + dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16; + pms_resolution(dev, dev->width, dev->height); + /* Ok we figured out what to use from our wide choice */ + mutex_unlock(&dev->lock); + return 0; +} + +static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) +{ + static struct v4l2_fmtdesc formats[] = { + { 0, 0, 0, + "RGB 5:5:5", V4L2_PIX_FMT_RGB555, + { 0, 0, 0, 0 } + }, + { 0, 0, 0, + "RGB 5:6:5", V4L2_PIX_FMT_RGB565, + { 0, 0, 0, 0 } + }, + }; + enum v4l2_buf_type type = fmt->type; + + if (fmt->index > 1) + return -EINVAL; + + *fmt = formats[fmt->index]; + fmt->type = type; + return 0; } static ssize_t pms_read(struct file *file, char __user *buf, @@ -849,7 +927,7 @@ static ssize_t pms_read(struct file *file, char __user *buf, int len; mutex_lock(&dev->lock); - len = pms_capture(dev, buf, (dev->picture.depth == 16) ? 0 : 1, count); + len = pms_capture(dev, buf, (dev->depth == 15), count); mutex_unlock(&dev->lock); return len; } @@ -873,10 +951,25 @@ static const struct v4l2_file_operations pms_fops = { .owner = THIS_MODULE, .open = pms_exclusive_open, .release = pms_exclusive_release, - .ioctl = pms_ioctl, + .ioctl = video_ioctl2, .read = pms_read, }; +static const struct v4l2_ioctl_ops pms_ioctl_ops = { + .vidioc_querycap = pms_querycap, + .vidioc_g_input = pms_g_input, + .vidioc_s_input = pms_s_input, + .vidioc_enum_input = pms_enum_input, + .vidioc_g_std = pms_g_std, + .vidioc_s_std = pms_s_std, + .vidioc_queryctrl = pms_queryctrl, + .vidioc_g_ctrl = pms_g_ctrl, + .vidioc_s_ctrl = pms_s_ctrl, + .vidioc_enum_fmt_vid_cap = pms_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = pms_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = pms_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = pms_try_fmt_vid_cap, +}; /* * Probe for and initialise the Mediavision PMS @@ -1032,11 +1125,18 @@ static int __init pms_init(void) strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); dev->vdev.v4l2_dev = v4l2_dev; dev->vdev.fops = &pms_fops; + dev->vdev.ioctl_ops = &pms_ioctl_ops; dev->vdev.release = video_device_release_empty; video_set_drvdata(&dev->vdev, dev); mutex_init(&dev->lock); + dev->std = V4L2_STD_NTSC_M; dev->height = 240; dev->width = 320; + dev->depth = 15; + dev->brightness = 139; + dev->contrast = 70; + dev->hue = 0; + dev->saturation = 64; pms_swsense(dev, 75); pms_resolution(dev, 320, 240); pms_videosource(dev, 0); From 533ce0464f290c74ee76dc952a9e630df38c5a7d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 16:12:01 -0300 Subject: [PATCH 323/345] V4L/DVB (13518): spec: regenerate videodev2.h.xml After excluding .h.xml from the whitespace to tab conversion I had to regenerate this xml file. The only changes here are whitespace changes. If we change videodev2.h in the future, then videodev2.h.xml will only show that same change and no more unrelated whitespace changes. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/videodev2.h.xml | 1096 ++++++++++----------- 1 file changed, 548 insertions(+), 548 deletions(-) diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index 228277bf9f10..033ecd2a14f9 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml @@ -99,148 +99,148 @@ /* Four-character-code (FOURCC) */ #define v4l2_fourcc(a, b, c, d)\ - ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24)) + ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24)) /* * E N U M S */ enum v4l2_field { - V4L2_FIELD_ANY = 0, /* driver can choose from none, - top, bottom, interlaced - depending on whatever it thinks - is approximate ... */ - V4L2_FIELD_NONE = 1, /* this device has no fields ... */ - V4L2_FIELD_TOP = 2, /* top field only */ - V4L2_FIELD_BOTTOM = 3, /* bottom field only */ - V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ - V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one - buffer, top-bottom order */ - V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ - V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into - separate buffers */ - V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field - first and the top field is - transmitted first */ - V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field - first and the bottom field is - transmitted first */ + V4L2_FIELD_ANY = 0, /* driver can choose from none, + top, bottom, interlaced + depending on whatever it thinks + is approximate ... */ + V4L2_FIELD_NONE = 1, /* this device has no fields ... */ + V4L2_FIELD_TOP = 2, /* top field only */ + V4L2_FIELD_BOTTOM = 3, /* bottom field only */ + V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ + V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one + buffer, top-bottom order */ + V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ + V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into + separate buffers */ + V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field + first and the top field is + transmitted first */ + V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field + first and the bottom field is + transmitted first */ }; #define V4L2_FIELD_HAS_TOP(field) \ - ((field) == V4L2_FIELD_TOP ||\ - (field) == V4L2_FIELD_INTERLACED ||\ - (field) == V4L2_FIELD_INTERLACED_TB ||\ - (field) == V4L2_FIELD_INTERLACED_BT ||\ - (field) == V4L2_FIELD_SEQ_TB ||\ - (field) == V4L2_FIELD_SEQ_BT) + ((field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) #define V4L2_FIELD_HAS_BOTTOM(field) \ - ((field) == V4L2_FIELD_BOTTOM ||\ - (field) == V4L2_FIELD_INTERLACED ||\ - (field) == V4L2_FIELD_INTERLACED_TB ||\ - (field) == V4L2_FIELD_INTERLACED_BT ||\ - (field) == V4L2_FIELD_SEQ_TB ||\ - (field) == V4L2_FIELD_SEQ_BT) + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) #define V4L2_FIELD_HAS_BOTH(field) \ - ((field) == V4L2_FIELD_INTERLACED ||\ - (field) == V4L2_FIELD_INTERLACED_TB ||\ - (field) == V4L2_FIELD_INTERLACED_BT ||\ - (field) == V4L2_FIELD_SEQ_TB ||\ - (field) == V4L2_FIELD_SEQ_BT) + ((field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) enum v4l2_buf_type { - V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, - V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, - V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, - V4L2_BUF_TYPE_VBI_CAPTURE = 4, - V4L2_BUF_TYPE_VBI_OUTPUT = 5, - V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, - V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, + V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, + V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, + V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, + V4L2_BUF_TYPE_VBI_CAPTURE = 4, + V4L2_BUF_TYPE_VBI_OUTPUT = 5, + V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, + V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, #if 1 /*KEEP*/ - /* Experimental */ - V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, + /* Experimental */ + V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, #endif - V4L2_BUF_TYPE_PRIVATE = 0x80, + V4L2_BUF_TYPE_PRIVATE = 0x80, }; enum v4l2_ctrl_type { - V4L2_CTRL_TYPE_INTEGER = 1, - V4L2_CTRL_TYPE_BOOLEAN = 2, - V4L2_CTRL_TYPE_MENU = 3, - V4L2_CTRL_TYPE_BUTTON = 4, - V4L2_CTRL_TYPE_INTEGER64 = 5, - V4L2_CTRL_TYPE_CTRL_CLASS = 6, - V4L2_CTRL_TYPE_STRING = 7, + V4L2_CTRL_TYPE_INTEGER = 1, + V4L2_CTRL_TYPE_BOOLEAN = 2, + V4L2_CTRL_TYPE_MENU = 3, + V4L2_CTRL_TYPE_BUTTON = 4, + V4L2_CTRL_TYPE_INTEGER64 = 5, + V4L2_CTRL_TYPE_CTRL_CLASS = 6, + V4L2_CTRL_TYPE_STRING = 7, }; enum v4l2_tuner_type { - V4L2_TUNER_RADIO = 1, - V4L2_TUNER_ANALOG_TV = 2, - V4L2_TUNER_DIGITAL_TV = 3, + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, + V4L2_TUNER_DIGITAL_TV = 3, }; enum v4l2_memory { - V4L2_MEMORY_MMAP = 1, - V4L2_MEMORY_USERPTR = 2, - V4L2_MEMORY_OVERLAY = 3, + V4L2_MEMORY_MMAP = 1, + V4L2_MEMORY_USERPTR = 2, + V4L2_MEMORY_OVERLAY = 3, }; /* see also http://vektor.theorem.ca/graphics/ycbcr/ */ enum v4l2_colorspace { - /* ITU-R 601 -- broadcast NTSC/PAL */ - V4L2_COLORSPACE_SMPTE170M = 1, + /* ITU-R 601 -- broadcast NTSC/PAL */ + V4L2_COLORSPACE_SMPTE170M = 1, - /* 1125-Line (US) HDTV */ - V4L2_COLORSPACE_SMPTE240M = 2, + /* 1125-Line (US) HDTV */ + V4L2_COLORSPACE_SMPTE240M = 2, - /* HD and modern captures. */ - V4L2_COLORSPACE_REC709 = 3, + /* HD and modern captures. */ + V4L2_COLORSPACE_REC709 = 3, - /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ - V4L2_COLORSPACE_BT878 = 4, + /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ + V4L2_COLORSPACE_BT878 = 4, - /* These should be useful. Assume 601 extents. */ - V4L2_COLORSPACE_470_SYSTEM_M = 5, - V4L2_COLORSPACE_470_SYSTEM_BG = 6, + /* These should be useful. Assume 601 extents. */ + V4L2_COLORSPACE_470_SYSTEM_M = 5, + V4L2_COLORSPACE_470_SYSTEM_BG = 6, - /* I know there will be cameras that send this. So, this is - * unspecified chromaticities and full 0-255 on each of the - * Y'CbCr components - */ - V4L2_COLORSPACE_JPEG = 7, + /* I know there will be cameras that send this. So, this is + * unspecified chromaticities and full 0-255 on each of the + * Y'CbCr components + */ + V4L2_COLORSPACE_JPEG = 7, - /* For RGB colourspaces, this is probably a good start. */ - V4L2_COLORSPACE_SRGB = 8, + /* For RGB colourspaces, this is probably a good start. */ + V4L2_COLORSPACE_SRGB = 8, }; enum v4l2_priority { - V4L2_PRIORITY_UNSET = 0, /* not initialized */ - V4L2_PRIORITY_BACKGROUND = 1, - V4L2_PRIORITY_INTERACTIVE = 2, - V4L2_PRIORITY_RECORD = 3, - V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, + V4L2_PRIORITY_UNSET = 0, /* not initialized */ + V4L2_PRIORITY_BACKGROUND = 1, + V4L2_PRIORITY_INTERACTIVE = 2, + V4L2_PRIORITY_RECORD = 3, + V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, }; struct v4l2_rect { - __s32 left; - __s32 top; - __s32 width; - __s32 height; + __s32 left; + __s32 top; + __s32 width; + __s32 height; }; struct v4l2_fract { - __u32 numerator; - __u32 denominator; + __u32 numerator; + __u32 denominator; }; /* * D R I V E R C A P A B I L I T I E S */ struct v4l2_capability { - __u8 driver[16]; /* i.e.ie; "bttv" */ - __u8 card[32]; /* i.e.ie; "Hauppauge WinTV" */ - __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ - __u32 version; /* should use KERNEL_VERSION() */ - __u32 capabilities; /* Device capabilities */ - __u32 reserved[4]; + __u8 driver[16]; /* i.e.ie; "bttv" */ + __u8 card[32]; /* i.e.ie; "Hauppauge WinTV" */ + __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ + __u32 version; /* should use KERNEL_VERSION() */ + __u32 capabilities; /* Device capabilities */ + __u32 reserved[4]; }; /* Values for 'capabilities' field */ @@ -269,14 +269,14 @@ struct v4l2_capability { * V I D E O I M A G E F O R M A T */ struct v4l2_pix_format { - __u32 width; - __u32 height; - __u32 pixelformat; - enum v4l2_field field; - __u32 bytesperline; /* for padding, zero if unused */ - __u32 sizeimage; - enum v4l2_colorspace colorspace; - __u32 priv; /* private data, depends on pixelformat */ + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; + enum v4l2_colorspace colorspace; + __u32 priv; /* private data, depends on pixelformat */ }; /* Pixel format FOURCC depth Description */ @@ -331,12 +331,12 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ #define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ #define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10bit raw bayer */ - /* 10bit raw bayer DPCM compressed to 8 bits */ + /* 10bit raw bayer DPCM compressed to 8 bits */ #define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0') - /* - * 10bit raw bayer, expanded to 16 bits - * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... - */ + /* + * 10bit raw bayer, expanded to 16 bits + * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... + */ #define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16 BGBG.. GRGR.. */ /* compressed formats */ @@ -369,83 +369,83 @@ struct v4l2_pix_format { * F O R M A T E N U M E R A T I O N */ struct v4l2_fmtdesc { - __u32 index; /* Format number */ - enum v4l2_buf_type type; /* buffer type */ - __u32 flags; - __u8 description[32]; /* Description string */ - __u32 pixelformat; /* Format fourcc */ - __u32 reserved[4]; + __u32 index; /* Format number */ + enum v4l2_buf_type type; /* buffer type */ + __u32 flags; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; }; #define V4L2_FMT_FLAG_COMPRESSED 0x0001 #define V4L2_FMT_FLAG_EMULATED 0x0002 #if 1 /*KEEP*/ - /* Experimental Frame Size and frame rate enumeration */ + /* Experimental Frame Size and frame rate enumeration */ /* * F R A M E S I Z E E N U M E R A T I O N */ enum v4l2_frmsizetypes { - V4L2_FRMSIZE_TYPE_DISCRETE = 1, - V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, - V4L2_FRMSIZE_TYPE_STEPWISE = 3, + V4L2_FRMSIZE_TYPE_DISCRETE = 1, + V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, + V4L2_FRMSIZE_TYPE_STEPWISE = 3, }; struct v4l2_frmsize_discrete { - __u32 width; /* Frame width [pixel] */ - __u32 height; /* Frame height [pixel] */ + __u32 width; /* Frame width [pixel] */ + __u32 height; /* Frame height [pixel] */ }; struct v4l2_frmsize_stepwise { - __u32 min_width; /* Minimum frame width [pixel] */ - __u32 max_width; /* Maximum frame width [pixel] */ - __u32 step_width; /* Frame width step size [pixel] */ - __u32 min_height; /* Minimum frame height [pixel] */ - __u32 max_height; /* Maximum frame height [pixel] */ - __u32 step_height; /* Frame height step size [pixel] */ + __u32 min_width; /* Minimum frame width [pixel] */ + __u32 max_width; /* Maximum frame width [pixel] */ + __u32 step_width; /* Frame width step size [pixel] */ + __u32 min_height; /* Minimum frame height [pixel] */ + __u32 max_height; /* Maximum frame height [pixel] */ + __u32 step_height; /* Frame height step size [pixel] */ }; struct v4l2_frmsizeenum { - __u32 index; /* Frame size number */ - __u32 pixel_format; /* Pixel format */ - __u32 type; /* Frame size type the device supports. */ + __u32 index; /* Frame size number */ + __u32 pixel_format; /* Pixel format */ + __u32 type; /* Frame size type the device supports. */ - union { /* Frame size */ - struct v4l2_frmsize_discrete discrete; - struct v4l2_frmsize_stepwise stepwise; - }; + union { /* Frame size */ + struct v4l2_frmsize_discrete discrete; + struct v4l2_frmsize_stepwise stepwise; + }; - __u32 reserved[2]; /* Reserved space for future use */ + __u32 reserved[2]; /* Reserved space for future use */ }; /* * F R A M E R A T E E N U M E R A T I O N */ enum v4l2_frmivaltypes { - V4L2_FRMIVAL_TYPE_DISCRETE = 1, - V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, - V4L2_FRMIVAL_TYPE_STEPWISE = 3, + V4L2_FRMIVAL_TYPE_DISCRETE = 1, + V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, + V4L2_FRMIVAL_TYPE_STEPWISE = 3, }; struct v4l2_frmival_stepwise { - struct v4l2_fract min; /* Minimum frame interval [s] */ - struct v4l2_fract max; /* Maximum frame interval [s] */ - struct v4l2_fract step; /* Frame interval step size [s] */ + struct v4l2_fract min; /* Minimum frame interval [s] */ + struct v4l2_fract max; /* Maximum frame interval [s] */ + struct v4l2_fract step; /* Frame interval step size [s] */ }; struct v4l2_frmivalenum { - __u32 index; /* Frame format index */ - __u32 pixel_format; /* Pixel format */ - __u32 width; /* Frame width */ - __u32 height; /* Frame height */ - __u32 type; /* Frame interval type the device supports. */ + __u32 index; /* Frame format index */ + __u32 pixel_format; /* Pixel format */ + __u32 width; /* Frame width */ + __u32 height; /* Frame height */ + __u32 type; /* Frame interval type the device supports. */ - union { /* Frame interval */ - struct v4l2_fract discrete; - struct v4l2_frmival_stepwise stepwise; - }; + union { /* Frame interval */ + struct v4l2_fract discrete; + struct v4l2_frmival_stepwise stepwise; + }; - __u32 reserved[2]; /* Reserved space for future use */ + __u32 reserved[2]; /* Reserved space for future use */ }; #endif @@ -453,13 +453,13 @@ struct v4l2_frmivalenum { * T I M E C O D E */ struct v4l2_timecode { - __u32 type; - __u32 flags; - __u8 frames; - __u8 seconds; - __u8 minutes; - __u8 hours; - __u8 userbits[4]; + __u32 type; + __u32 flags; + __u8 frames; + __u8 seconds; + __u8 minutes; + __u8 hours; + __u8 userbits[4]; }; /* Type */ @@ -478,63 +478,63 @@ struct v4l2_timecode { /* The above is based on SMPTE timecodes */ struct v4l2_jpegcompression { - int quality; + int quality; - int APPn; /* Number of APP segment to be written, - * must be 0..15 */ - int APP_len; /* Length of data in JPEG APPn segment */ - char APP_data[60]; /* Data in the JPEG APPn segment. */ + int APPn; /* Number of APP segment to be written, + * must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ - int COM_len; /* Length of data in JPEG COM segment */ - char COM_data[60]; /* Data in JPEG COM segment */ + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ - __u32 jpeg_markers; /* Which markers should go into the JPEG - * output. Unless you exactly know what - * you do, leave them untouched. - * Inluding less markers will make the - * resulting code smaller, but there will - * be fewer aplications which can read it. - * The presence of the APP and COM marker - * is influenced by APP_len and COM_len - * ONLY, not by this property! */ + __u32 jpeg_markers; /* Which markers should go into the JPEG + * output. Unless you exactly know what + * you do, leave them untouched. + * Inluding less markers will make the + * resulting code smaller, but there will + * be fewer aplications which can read it. + * The presence of the APP and COM marker + * is influenced by APP_len and COM_len + * ONLY, not by this property! */ #define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ #define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * allways use APP0 */ }; /* * M E M O R Y - M A P P I N G B U F F E R S */ struct v4l2_requestbuffers { - __u32 count; - enum v4l2_buf_type type; - enum v4l2_memory memory; - __u32 reserved[2]; + __u32 count; + enum v4l2_buf_type type; + enum v4l2_memory memory; + __u32 reserved[2]; }; struct v4l2_buffer { - __u32 index; - enum v4l2_buf_type type; - __u32 bytesused; - __u32 flags; - enum v4l2_field field; - struct timeval timestamp; - struct v4l2_timecode timecode; - __u32 sequence; + __u32 index; + enum v4l2_buf_type type; + __u32 bytesused; + __u32 flags; + enum v4l2_field field; + struct timeval timestamp; + struct v4l2_timecode timecode; + __u32 sequence; - /* memory location */ - enum v4l2_memory memory; - union { - __u32 offset; - unsigned long userptr; - } m; - __u32 length; - __u32 input; - __u32 reserved; + /* memory location */ + enum v4l2_memory memory; + union { + __u32 offset; + unsigned long userptr; + } m; + __u32 length; + __u32 input; + __u32 reserved; }; /* Flags for 'flags' field */ @@ -551,12 +551,12 @@ struct v4l2_buffer { * O V E R L A Y P R E V I E W */ struct v4l2_framebuffer { - __u32 capability; - __u32 flags; + __u32 capability; + __u32 flags; /* FIXME: in theory we should pass something like PCI device + memory * region + offset instead of some physical address */ - void *base; - struct v4l2_pix_format fmt; + void *base; + struct v4l2_pix_format fmt; }; /* Flags for the 'capability' field. Read only */ #define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 @@ -577,30 +577,30 @@ struct v4l2_framebuffer { #define V4L2_FBUF_FLAG_SRC_CHROMAKEY 0x0040 struct v4l2_clip { - struct v4l2_rect c; - struct v4l2_clip __user *next; + struct v4l2_rect c; + struct v4l2_clip __user *next; }; struct v4l2_window { - struct v4l2_rect w; - enum v4l2_field field; - __u32 chromakey; - struct v4l2_clip __user *clips; - __u32 clipcount; - void __user *bitmap; - __u8 global_alpha; + struct v4l2_rect w; + enum v4l2_field field; + __u32 chromakey; + struct v4l2_clip __user *clips; + __u32 clipcount; + void __user *bitmap; + __u8 global_alpha; }; /* * C A P T U R E P A R A M E T E R S */ struct v4l2_captureparm { - __u32 capability; /* Supported modes */ - __u32 capturemode; /* Current mode */ - struct v4l2_fract timeperframe; /* Time per frame in .1us units */ - __u32 extendedmode; /* Driver-specific extensions */ - __u32 readbuffers; /* # of buffers for read */ - __u32 reserved[4]; + __u32 capability; /* Supported modes */ + __u32 capturemode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in .1us units */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 readbuffers; /* # of buffers for read */ + __u32 reserved[4]; }; /* Flags for 'capability' and 'capturemode' fields */ @@ -608,27 +608,27 @@ struct v4l2_captureparm { #define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ struct v4l2_outputparm { - __u32 capability; /* Supported modes */ - __u32 outputmode; /* Current mode */ - struct v4l2_fract timeperframe; /* Time per frame in seconds */ - __u32 extendedmode; /* Driver-specific extensions */ - __u32 writebuffers; /* # of buffers for write */ - __u32 reserved[4]; + __u32 capability; /* Supported modes */ + __u32 outputmode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in seconds */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 writebuffers; /* # of buffers for write */ + __u32 reserved[4]; }; /* * I N P U T I M A G E C R O P P I N G */ struct v4l2_cropcap { - enum v4l2_buf_type type; - struct v4l2_rect bounds; - struct v4l2_rect defrect; - struct v4l2_fract pixelaspect; + enum v4l2_buf_type type; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; }; struct v4l2_crop { - enum v4l2_buf_type type; - struct v4l2_rect c; + enum v4l2_buf_type type; + struct v4l2_rect c; }; /* @@ -687,64 +687,64 @@ typedef __u64 v4l2_std_id; /* some common needed stuff */ #define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\ - V4L2_STD_PAL_B1 |\ - V4L2_STD_PAL_G) + V4L2_STD_PAL_B1 |\ + V4L2_STD_PAL_G) #define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\ - V4L2_STD_PAL_D1 |\ - V4L2_STD_PAL_K) + V4L2_STD_PAL_D1 |\ + V4L2_STD_PAL_K) #define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ - V4L2_STD_PAL_DK |\ - V4L2_STD_PAL_H |\ - V4L2_STD_PAL_I) + V4L2_STD_PAL_DK |\ + V4L2_STD_PAL_H |\ + V4L2_STD_PAL_I) #define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ - V4L2_STD_NTSC_M_JP |\ - V4L2_STD_NTSC_M_KR) + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) #define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ - V4L2_STD_SECAM_K |\ - V4L2_STD_SECAM_K1) + V4L2_STD_SECAM_K |\ + V4L2_STD_SECAM_K1) #define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ - V4L2_STD_SECAM_G |\ - V4L2_STD_SECAM_H |\ - V4L2_STD_SECAM_DK |\ - V4L2_STD_SECAM_L |\ - V4L2_STD_SECAM_LC) + V4L2_STD_SECAM_G |\ + V4L2_STD_SECAM_H |\ + V4L2_STD_SECAM_DK |\ + V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) #define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ - V4L2_STD_PAL_60 |\ - V4L2_STD_NTSC |\ - V4L2_STD_NTSC_443) + V4L2_STD_PAL_60 |\ + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) #define V4L2_STD_625_50 (V4L2_STD_PAL |\ - V4L2_STD_PAL_N |\ - V4L2_STD_PAL_Nc |\ - V4L2_STD_SECAM) + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_SECAM) #define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ - V4L2_STD_ATSC_16_VSB) + V4L2_STD_ATSC_16_VSB) #define V4L2_STD_UNKNOWN 0 #define V4L2_STD_ALL (V4L2_STD_525_60 |\ - V4L2_STD_625_50) + V4L2_STD_625_50) struct v4l2_standard { - __u32 index; - v4l2_std_id id; - __u8 name[24]; - struct v4l2_fract frameperiod; /* Frames, not fields */ - __u32 framelines; - __u32 reserved[4]; + __u32 index; + v4l2_std_id id; + __u8 name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + __u32 framelines; + __u32 reserved[4]; }; /* * V I D E O I N P U T S */ struct v4l2_input { - __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]; + __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]; }; /* Values for the 'type' field */ @@ -779,13 +779,13 @@ struct v4l2_input { * V I D E O O U T P U T S */ struct v4l2_output { - __u32 index; /* Which output */ - __u8 name[32]; /* Label */ - __u32 type; /* Type of output */ - __u32 audioset; /* Associated audios (bitfield) */ - __u32 modulator; /* Associated modulator */ - v4l2_std_id std; - __u32 reserved[4]; + __u32 index; /* Which output */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of output */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 modulator; /* Associated modulator */ + v4l2_std_id std; + __u32 reserved[4]; }; /* Values for the 'type' field */ #define V4L2_OUTPUT_TYPE_MODULATOR 1 @@ -796,27 +796,27 @@ struct v4l2_output { * C O N T R O L S */ struct v4l2_control { - __u32 id; - __s32 value; + __u32 id; + __s32 value; }; struct v4l2_ext_control { - __u32 id; - __u32 size; - __u32 reserved2[1]; - union { - __s32 value; - __s64 value64; - char *string; - }; + __u32 id; + __u32 size; + __u32 reserved2[1]; + union { + __s32 value; + __s64 value64; + char *string; + }; } __attribute__ ((packed)); struct v4l2_ext_controls { - __u32 ctrl_class; - __u32 count; - __u32 error_idx; - __u32 reserved[2]; - struct v4l2_ext_control *controls; + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + struct v4l2_ext_control *controls; }; /* Values for ctrl_class field */ @@ -831,23 +831,23 @@ struct v4l2_ext_controls { /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ struct v4l2_queryctrl { - __u32 id; - enum v4l2_ctrl_type type; - __u8 name[32]; /* Whatever */ - __s32 minimum; /* Note signedness */ - __s32 maximum; - __s32 step; - __s32 default_value; - __u32 flags; - __u32 reserved[2]; + __u32 id; + enum v4l2_ctrl_type type; + __u8 name[32]; /* Whatever */ + __s32 minimum; /* Note signedness */ + __s32 maximum; + __s32 step; + __s32 default_value; + __u32 flags; + __u32 reserved[2]; }; /* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ struct v4l2_querymenu { - __u32 id; - __u32 index; - __u8 name[32]; /* Whatever */ - __u32 reserved; + __u32 id; + __u32 index; + __u8 name[32]; /* Whatever */ + __u32 reserved; }; /* Control flags */ @@ -898,9 +898,9 @@ struct v4l2_querymenu { #define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) enum v4l2_power_line_frequency { - V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, - V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, }; #define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) #define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) @@ -910,9 +910,9 @@ enum v4l2_power_line_frequency #define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30) #define V4L2_CID_COLORFX (V4L2_CID_BASE+31) enum v4l2_colorfx { - V4L2_COLORFX_NONE = 0, - V4L2_COLORFX_BW = 1, - V4L2_COLORFX_SEPIA = 2, + V4L2_COLORFX_NONE = 0, + V4L2_COLORFX_BW = 1, + V4L2_COLORFX_SEPIA = 2, }; #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) @@ -929,12 +929,12 @@ enum v4l2_colorfx { /* MPEG streams */ #define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE+0) enum v4l2_mpeg_stream_type { - V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ - V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ - V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ - V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible stream */ - V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ - V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ }; #define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_MPEG_BASE+1) #define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_MPEG_BASE+2) @@ -944,139 +944,139 @@ enum v4l2_mpeg_stream_type { #define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) #define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) enum v4l2_mpeg_stream_vbi_fmt { - V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ - V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ + V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ + V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ }; /* MPEG audio */ #define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) enum v4l2_mpeg_audio_sampling_freq { - V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, }; #define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_MPEG_BASE+101) enum v4l2_mpeg_audio_encoding { - V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, - V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, - V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, - V4L2_MPEG_AUDIO_ENCODING_AAC = 3, - V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, + V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, + V4L2_MPEG_AUDIO_ENCODING_AAC = 3, + V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, }; #define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) enum v4l2_mpeg_audio_l1_bitrate { - V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, - V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, - V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, - V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, - V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, - V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, - V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, - V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, - V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, - V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, - V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, - V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, - V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, - V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, + V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, + V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, + V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, + V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, + V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, + V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, + V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, + V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, + V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, + V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, + V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, + V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, + V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, }; #define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_MPEG_BASE+103) enum v4l2_mpeg_audio_l2_bitrate { - V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, - V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, - V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, - V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, - V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, - V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, - V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, - V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, - V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, - V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, - V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, - V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, - V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, - V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, + V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, + V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, + V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, + V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, + V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, + V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, + V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, + V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, + V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, + V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, + V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, + V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, + V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, }; #define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_MPEG_BASE+104) enum v4l2_mpeg_audio_l3_bitrate { - V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, - V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, - V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, - V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, - V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, - V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, - V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, - V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, - V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, - V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, - V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, - V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, - V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, - V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, + V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, }; #define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_MPEG_BASE+105) enum v4l2_mpeg_audio_mode { - V4L2_MPEG_AUDIO_MODE_STEREO = 0, - V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, - V4L2_MPEG_AUDIO_MODE_DUAL = 2, - V4L2_MPEG_AUDIO_MODE_MONO = 3, + V4L2_MPEG_AUDIO_MODE_STEREO = 0, + V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, + V4L2_MPEG_AUDIO_MODE_DUAL = 2, + V4L2_MPEG_AUDIO_MODE_MONO = 3, }; #define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_MPEG_BASE+106) enum v4l2_mpeg_audio_mode_extension { - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, }; #define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_MPEG_BASE+107) enum v4l2_mpeg_audio_emphasis { - V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, - V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, - V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, + V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, + V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, }; #define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_MPEG_BASE+108) enum v4l2_mpeg_audio_crc { - V4L2_MPEG_AUDIO_CRC_NONE = 0, - V4L2_MPEG_AUDIO_CRC_CRC16 = 1, + V4L2_MPEG_AUDIO_CRC_NONE = 0, + V4L2_MPEG_AUDIO_CRC_CRC16 = 1, }; #define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) #define V4L2_CID_MPEG_AUDIO_AAC_BITRATE (V4L2_CID_MPEG_BASE+110) #define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_MPEG_BASE+111) enum v4l2_mpeg_audio_ac3_bitrate { - V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, - V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, - V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, - V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, - V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, - V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, - V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, - V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, - V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, - V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, - V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, - V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, - V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, - V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, - V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, - V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, - V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, - V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, - V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, + V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, + V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, + V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, + V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, }; /* MPEG video */ #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) enum v4l2_mpeg_video_encoding { - V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, }; #define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) enum v4l2_mpeg_video_aspect { - V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, - V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, - V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, - V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, + V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, + V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, + V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, + V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, }; #define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_MPEG_BASE+202) #define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_MPEG_BASE+203) @@ -1084,8 +1084,8 @@ enum v4l2_mpeg_video_aspect { #define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_MPEG_BASE+205) #define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_MPEG_BASE+206) enum v4l2_mpeg_video_bitrate_mode { - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, }; #define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE+207) #define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE+208) @@ -1097,36 +1097,36 @@ enum v4l2_mpeg_video_bitrate_modev4l2_mpeg_cx2341x_video_spatial_filter_mode { - V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, - V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+1) #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+2) enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, - V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+3) enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type { - V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, - V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+4) enum v4l2_mpeg_cx2341x_video_temporal_filter_mode { - V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, - V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+5) #define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+6) enum v4l2_mpeg_cx2341x_video_median_filter_type { - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, - V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+7) #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+8) @@ -1140,10 +1140,10 @@ enum v4l2_mpeg_cx2341 #define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) enum v4l2_exposure_auto_type { - V4L2_EXPOSURE_AUTO = 0, - V4L2_EXPOSURE_MANUAL = 1, - V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, - V4L2_EXPOSURE_APERTURE_PRIORITY = 3 + V4L2_EXPOSURE_AUTO = 0, + V4L2_EXPOSURE_MANUAL = 1, + V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, + V4L2_EXPOSURE_APERTURE_PRIORITY = 3 }; #define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) #define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) @@ -1192,9 +1192,9 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_TUNE_PREEMPHASIS (V4L2_CID_FM_TX_CLASS_BASE + 112) enum v4l2_preemphasis { - V4L2_PREEMPHASIS_DISABLED = 0, - V4L2_PREEMPHASIS_50_uS = 1, - V4L2_PREEMPHASIS_75_uS = 2, + V4L2_PREEMPHASIS_DISABLED = 0, + V4L2_PREEMPHASIS_50_uS = 1, + V4L2_PREEMPHASIS_75_uS = 2, }; #define V4L2_CID_TUNE_POWER_LEVEL (V4L2_CID_FM_TX_CLASS_BASE + 113) #define V4L2_CID_TUNE_ANTENNA_CAPACITOR (V4L2_CID_FM_TX_CLASS_BASE + 114) @@ -1203,27 +1203,27 @@ enum v4l2_preemphasis { * T U N I N G */ struct v4l2_tuner { - __u32 index; - __u8 name[32]; - enum v4l2_tuner_type type; - __u32 capability; - __u32 rangelow; - __u32 rangehigh; - __u32 rxsubchans; - __u32 audmode; - __s32 signal; - __s32 afc; - __u32 reserved[4]; + __u32 index; + __u8 name[32]; + enum v4l2_tuner_type type; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 rxsubchans; + __u32 audmode; + __s32 signal; + __s32 afc; + __u32 reserved[4]; }; struct v4l2_modulator { - __u32 index; - __u8 name[32]; - __u32 capability; - __u32 rangelow; - __u32 rangehigh; - __u32 txsubchans; - __u32 reserved[4]; + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 txsubchans; + __u32 reserved[4]; }; /* Flags for the 'capability' field */ @@ -1252,18 +1252,18 @@ struct v4l2_modulator { #define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 struct v4l2_frequency { - __u32 tuner; - enum v4l2_tuner_type type; - __u32 frequency; - __u32 reserved[8]; + __u32 tuner; + enum v4l2_tuner_type type; + __u32 frequency; + __u32 reserved[8]; }; struct v4l2_hw_freq_seek { - __u32 tuner; - enum v4l2_tuner_type type; - __u32 seek_upward; - __u32 wrap_around; - __u32 reserved[8]; + __u32 tuner; + enum v4l2_tuner_type type; + __u32 seek_upward; + __u32 wrap_around; + __u32 reserved[8]; }; /* @@ -1271,9 +1271,9 @@ struct v4l2_hw_freq_seek { */ struct v4l2_rds_data { - __u8 lsb; - __u8 msb; - __u8 block; + __u8 lsb; + __u8 msb; + __u8 block; } __attribute__ ((packed)); #define V4L2_RDS_BLOCK_MSK 0x7 @@ -1291,11 +1291,11 @@ struct v4l2_rds_data { * A U D I O */ struct v4l2_audio { - __u32 index; - __u8 name[32]; - __u32 capability; - __u32 mode; - __u32 reserved[2]; + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; }; /* Flags for the 'capability' field */ @@ -1306,11 +1306,11 @@ struct v4l2_audio { #define V4L2_AUDMODE_AVL 0x00001 struct v4l2_audioout { - __u32 index; - __u8 name[32]; - __u32 capability; - __u32 mode; - __u32 reserved[2]; + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; }; /* @@ -1325,19 +1325,19 @@ struct v4l2_audioout { #define V4L2_ENC_IDX_FRAME_MASK (0xf) struct v4l2_enc_idx_entry { - __u64 offset; - __u64 pts; - __u32 length; - __u32 flags; - __u32 reserved[2]; + __u64 offset; + __u64 pts; + __u32 length; + __u32 flags; + __u32 reserved[2]; }; #define V4L2_ENC_IDX_ENTRIES (64) struct v4l2_enc_idx { - __u32 entries; - __u32 entries_cap; - __u32 reserved[4]; - struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; + __u32 entries; + __u32 entries_cap; + __u32 reserved[4]; + struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; }; @@ -1350,13 +1350,13 @@ struct v4l2_enc_idx { #define V4L2_ENC_CMD_STOP_AT_GOP_END (1 << 0) struct v4l2_encoder_cmd { - __u32 cmd; - __u32 flags; - union { - struct { - __u32 data[8]; - } raw; - }; + __u32 cmd; + __u32 flags; + union { + struct { + __u32 data[8]; + } raw; + }; }; #endif @@ -1370,14 +1370,14 @@ struct v4l2_encoder_cmd { /* Raw VBI */ struct v4l2_vbi_format { - __u32 sampling_rate; /* in 1 Hz */ - __u32 offset; - __u32 samples_per_line; - __u32 sample_format; /* V4L2_PIX_FMT_* */ - __s32 start[2]; - __u32 count[2]; - __u32 flags; /* V4L2_VBI_* */ - __u32 reserved[2]; /* must be zero */ + __u32 sampling_rate; /* in 1 Hz */ + __u32 offset; + __u32 samples_per_line; + __u32 sample_format; /* V4L2_PIX_FMT_* */ + __s32 start[2]; + __u32 count[2]; + __u32 flags; /* V4L2_VBI_* */ + __u32 reserved[2]; /* must be zero */ }; /* VBI flags */ @@ -1392,14 +1392,14 @@ struct v4l2_vbi_format { */ struct v4l2_sliced_vbi_format { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - __u32 io_size; - __u32 reserved[2]; /* must be zero */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 io_size; + __u32 reserved[2]; /* must be zero */ }; /* Teletext World System Teletext @@ -1416,22 +1416,22 @@ struct v4l2_sliced_vbi_format { #define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) struct v4l2_sliced_vbi_cap { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - enum v4l2_buf_type type; - __u32 reserved[3]; /* must be 0 */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + enum v4l2_buf_type type; + __u32 reserved[3]; /* must be 0 */ }; struct v4l2_sliced_vbi_data { - __u32 id; - __u32 field; /* 0: first field, 1: second field */ - __u32 line; /* 1-23 */ - __u32 reserved; /* must be 0 */ - __u8 data[48]; + __u32 id; + __u32 field; /* 0: first field, 1: second field */ + __u32 line; /* 1-23 */ + __u32 reserved; /* must be 0 */ + __u8 data[48]; }; /* @@ -1457,28 +1457,28 @@ struct v4l2_sliced_vbi_data { #define V4L2_MPEG_VBI_IVTV_VPS (7) struct v4l2_mpeg_vbi_itv0_line { - __u8 id; /* One of V4L2_MPEG_VBI_IVTV_* above */ - __u8 data[42]; /* Sliced VBI data for the line */ + __u8 id; /* One of V4L2_MPEG_VBI_IVTV_* above */ + __u8 data[42]; /* Sliced VBI data for the line */ } __attribute__ ((packed)); struct v4l2_mpeg_vbi_itv0 { - __le32 linemask[2]; /* Bitmasks of VBI service lines present */ - struct v4l2_mpeg_vbi_itv0_line line[35]; + __le32 linemask[2]; /* Bitmasks of VBI service lines present */ + struct v4l2_mpeg_vbi_itv0_line line[35]; } __attribute__ ((packed)); struct v4l2_mpeg_vbi_ITV0 { - struct v4l2_mpeg_vbi_itv0_line line[36]; + struct v4l2_mpeg_vbi_itv0_line line[36]; } __attribute__ ((packed)); #define V4L2_MPEG_VBI_IVTV_MAGIC0 "itv0" #define V4L2_MPEG_VBI_IVTV_MAGIC1 "ITV0" struct v4l2_mpeg_vbi_fmt_ivtv { - __u8 magic[4]; - union { - struct v4l2_mpeg_vbi_itv0 itv0; - struct v4l2_mpeg_vbi_ITV0 ITV0; - }; + __u8 magic[4]; + union { + struct v4l2_mpeg_vbi_itv0 itv0; + struct v4l2_mpeg_vbi_ITV0 ITV0; + }; } __attribute__ ((packed)); /* @@ -1488,26 +1488,26 @@ struct v4l2_mpeg_vbi_fmt_ivtv { /* Stream data format */ struct v4l2_format { - enum v4l2_buf_type type; - union { - struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ - struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ - struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ - struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ - __u8 raw_data[200]; /* user-defined */ - } fmt; + enum v4l2_buf_type type; + union { + struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ + struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ + struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ + struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ + __u8 raw_data[200]; /* user-defined */ + } fmt; }; /* Stream type-dependent parameters */ struct v4l2_streamparm { - enum v4l2_buf_type type; - union { - struct v4l2_captureparm capture; - struct v4l2_outputparm output; - __u8 raw_data[200]; /* user-defined */ - } parm; + enum v4l2_buf_type type; + union { + struct v4l2_captureparm capture; + struct v4l2_outputparm output; + __u8 raw_data[200]; /* user-defined */ + } parm; }; /* @@ -1525,25 +1525,25 @@ struct v4l2_streamparm { #define V4L2_CHIP_MATCH_AC97 3 /* Match against anciliary AC97 chip */ struct v4l2_dbg_match { - __u32 type; /* Match type */ - union { /* Match this chip, meaning determined by type */ - __u32 addr; - char name[32]; - }; + __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; + 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 <media/v4l2-chip-ident.h> */ - __u32 revision; /* chip revision, chip specific */ + struct v4l2_dbg_match match; + __u32 ident; /* chip identifier as specified in <media/v4l2-chip-ident.h> */ + __u32 revision; /* chip revision, chip specific */ } __attribute__ ((packed)); /* From 516e24d78feb4dded16df0053bd0e7c7f68fafa2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 18:39:31 -0300 Subject: [PATCH 324/345] V4L/DVB (13521): dib8000: fix compile warning Trivial fix for this bogus compile warning: v4l/dib8000.c:958: warning: 'ncoeff' may be used uninitialized in this function Note: ncoeff is never used uninitialized, but the compiler couldn't figure that out. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib8000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 44c2dc9b4f11..898400d331a3 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -954,7 +954,7 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear u8 guard, crate, constellation, timeI; u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled - const s16 *ncoeff, *ana_fe; + const s16 *ncoeff = NULL, *ana_fe; u16 tmcc_pow = 0; u16 coff_pow = 0x2800; u16 init_prbs = 0xfff; From 289a774bf53b366393e51b4f512b610bfb5fdd9d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 18:42:42 -0300 Subject: [PATCH 325/345] V4L/DVB (13522): valj5jf8007s/t: fix compile warnings Trivial fix for these bogus compile warnings: v4l/va1j5jf8007s.c: In function 'va1j5jf8007s_tune': v4l/va1j5jf8007s.c:394: warning: 'lock' may be used uninitialized in this function v4l/va1j5jf8007t.c: In function 'va1j5jf8007t_tune': v4l/va1j5jf8007t.c:273: warning: 'lock' may be used uninitialized in this function v4l/va1j5jf8007t.c:273: warning: 'retry' may be used uninitialized in this function These variables are never used uninitialized, but the compiler couldn't figure that out unfortunately. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/pt1/va1j5jf8007s.c | 2 +- drivers/media/dvb/pt1/va1j5jf8007t.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.c b/drivers/media/dvb/pt1/va1j5jf8007s.c index a20927e10d70..fc6594996e79 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007s.c +++ b/drivers/media/dvb/pt1/va1j5jf8007s.c @@ -391,7 +391,7 @@ va1j5jf8007s_tune(struct dvb_frontend *fe, { struct va1j5jf8007s_state *state; int ret; - int lock; + int lock = 0; state = fe->demodulator_priv; diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.c b/drivers/media/dvb/pt1/va1j5jf8007t.c index fe897343f4f8..3db4f3e34e8f 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007t.c +++ b/drivers/media/dvb/pt1/va1j5jf8007t.c @@ -270,7 +270,7 @@ va1j5jf8007t_tune(struct dvb_frontend *fe, { struct va1j5jf8007t_state *state; int ret; - int lock, retry; + int lock = 0, retry = 0; state = fe->demodulator_priv; From 491aa96a8c37260d2466735ecd3c662db8c0a7af Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 25 Nov 2009 18:48:54 -0300 Subject: [PATCH 326/345] V4L/DVB (13523): dvb-bt8xx: fix compile warning Fix this compile warning: v4l/dvb-bt8xx.c: In function 'cx24108_tuner_set_params': v4l/dvb-bt8xx.c:221: warning: array subscript is above array bounds Make sure that we never get past the last element in the array. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index b1857c19bbd2..78fc469f0f69 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -215,7 +215,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend freq = 2150000; /* satellite IF is 950..2150MHz */ /* decide which VCO to use for the input frequency */ - for(i = 1; (i < ARRAY_SIZE(osci)) && (osci[i] < freq); i++); + for(i = 1; (i < ARRAY_SIZE(osci) - 1) && (osci[i] < freq); i++); printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq); band=bandsel[i]; /* the gain values must be set by SetSymbolrate */ From 1ca31892e3af05ad3a72769e3c922cca3cde4f9d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 13:49:48 -0200 Subject: [PATCH 327/345] em28xx: em2800 chips support max width of 640 Due to hardware limitation, em2800 chips can't work at resolutions higher than 640x576, since the URB packet size is not enough. The effect is that the image looses packages and shows a distortion along the vertical axes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index bca5cbb7931c..166d4a6e6eaa 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -796,7 +796,7 @@ static inline unsigned int norm_maxw(struct em28xx *dev) if (dev->board.is_webcam) return dev->sensor_xres; - if (dev->board.max_range_640_480) + if (dev->board.max_range_640_480 || dev->board.is_em2800) return 640; return 720; From 0731160aca15df5882387e07d61671e6746c658f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 13:52:54 -0200 Subject: [PATCH 328/345] em28xx: don't load audio modules when AC97 is mis-detected With em2800 hardware, AC97 hardware can be detected even when it doesn't exist. If, after probing for AC97, the driver won't find a companion chip, simply prevents the load of the audio modules. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 33586004eb44..3f86d36dff2b 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -533,8 +533,15 @@ int em28xx_audio_setup(struct em28xx *dev) vid1 = em28xx_read_ac97(dev, AC97_VENDOR_ID1); if (vid1 < 0) { - /* Device likely doesn't support AC97 */ + /* + * Device likely doesn't support AC97 + * Note: (some) em2800 devices without eeprom reports 0x91 on + * CHIPCFG register, even not having an AC97 chip + */ em28xx_warn("AC97 chip type couldn't be determined\n"); + dev->audio_mode.ac97 = EM28XX_NO_AC97; + dev->has_alsa_audio = 0; + dev->audio_mode.has_audio = 0; goto init_audio; } From fb3de0398ab1bf270bc55f66945f82e61e50f6b6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 13:55:21 -0200 Subject: [PATCH 329/345] em28xx: don't reduce scale to half size for em2800 Since em2800 can't support 720x480 / 720x576, the driver used to reduce the scale to half the size on those chips. As the proper fix were applied, reducing the maximum horizontal resolution to 640, this hack can be removed. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index fbe536f092f9..7ad65370f274 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1060,12 +1060,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; width = width > (3 * maxw / 4) ? maxw : maxw / 2; - /* According to empiatech support the MaxPacketSize is too small - * to support framesizes larger than 640x480 @ 30 fps or 640x576 - * @ 25 fps. As this would cut of a part of the image we prefer - * 360x576 or 360x480 for now */ - if (width == maxw && height == maxh) - width /= 2; } else { /* width must even because of the YUYV format height must be even because of interlacing */ From 694a101e6acb865f5405a95c358eea43c813cf24 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Nov 2009 21:26:13 -0300 Subject: [PATCH 330/345] V4L/DVB (13528): em28xx: add support for em2800 VC211A card Adds support to VC211A em2800 card. As this board doesn't have eeprom, and uses a common set of i2c address, it has no way to add any autodetection for it. The patch were tested by me and by Raimundo on his board. Thanks to those tests, several bugs related to em2800 support were corrected. for producing the usbsnoop dump, used to get the gpio's and allowing me to remotelly access his machine and to the needed tests. Thanks-to: Raimundo Eduvirgnes de Oliveira Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/video/em28xx/em28xx-cards.c | 25 +++++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 27 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index f8ea8acdd894..0c166ff003a0 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -69,3 +69,4 @@ 71 -> Silvercrest Webcam 1.3mpix (em2820/em2840) 72 -> Gadmei UTV330+ (em2861) 73 -> Reddo DVB-C USB TV Box (em2870) + 74 -> Actionmaster/LinXcel/Digitus VC211A (em2800) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 00bceb865a7c..ed5acc3a2b5a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -225,6 +225,14 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = { { -1, -1, -1, -1}, }; +static struct em28xx_reg_seq vc211a_enable[] = { + {EM28XX_R08_GPIO, 0xff, 0x07, 10}, + {EM28XX_R08_GPIO, 0xff, 0x0f, 10}, + {EM28XX_R08_GPIO, 0xff, 0x0b, 10}, + { -1, -1, -1, -1}, +}; + + /* * Board definitions */ @@ -1009,6 +1017,23 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2800_BOARD_VC211A] = { + .name = "Actionmaster/LinXcel/Digitus VC211A", + .is_em2800 = 1, + .tuner_type = TUNER_ABSENT, /* Capture-only board */ + .decoder = EM28XX_SAA711X, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = vc211a_enable, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = vc211a_enable, + } }, + }, [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { .name = "Leadtek Winfast USB II", .is_em2800 = 1, diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 166d4a6e6eaa..441df644ddbe 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -110,6 +110,7 @@ #define EM2820_BOARD_SILVERCREST_WEBCAM 71 #define EM2861_BOARD_GADMEI_UTV330PLUS 72 #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 +#define EM2800_BOARD_VC211A 74 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 From 832b6a8917f050a9cbeeb69e080733128d562f59 Mon Sep 17 00:00:00 2001 From: Pete Eberlein Date: Mon, 16 Nov 2009 15:13:51 -0300 Subject: [PATCH 331/345] V4L/DVB (13456): s2250: Change module structure The s2250-board i2c module was converted to use v4l2-i2c-drv.h in preparation for its subdev conversion. This change prevented the s2250-loader from being initialized within the same module due to the module_init and module_exit function definitions in v4l2-i2c-drv.h. Therefore, s2250-loader is now its own module, and the header for exporting s2250-loader functions is no longer needed. The s2250 i2c module name was "2220-board" in some places, and was changed to "s2250". Signed-off-by: Pete Eberlein Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/go7007/Makefile | 4 +- drivers/staging/go7007/go7007-driver.c | 2 +- drivers/staging/go7007/go7007-usb.c | 2 +- drivers/staging/go7007/s2250-board.c | 55 +++++++------------------- drivers/staging/go7007/s2250-loader.c | 12 ++++-- 5 files changed, 26 insertions(+), 49 deletions(-) diff --git a/drivers/staging/go7007/Makefile b/drivers/staging/go7007/Makefile index 1301caa7495d..d37b7edc2793 100644 --- a/drivers/staging/go7007/Makefile +++ b/drivers/staging/go7007/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_VIDEO_GO7007) += go7007.o obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o -obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o +obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o s2250-loader.o obj-$(CONFIG_VIDEO_GO7007_SAA7113) += wis-saa7113.o obj-$(CONFIG_VIDEO_GO7007_OV7640) += wis-ov7640.o obj-$(CONFIG_VIDEO_GO7007_SAA7115) += wis-saa7115.o @@ -17,7 +17,7 @@ obj-$(CONFIG_VIDEO_GO7007_TW2804) += wis-tw2804.o go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ snd-go7007.o -s2250-objs += s2250-board.o s2250-loader.o +s2250-objs += s2250-board.o # Uncomment when the saa7134 patches get into upstream #ifneq ($(CONFIG_VIDEO_SAA7134),) diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c index 869430ec0319..c5dc3b64ac03 100644 --- a/drivers/staging/go7007/go7007-driver.c +++ b/drivers/staging/go7007/go7007-driver.c @@ -219,7 +219,7 @@ static int init_i2c_module(struct i2c_adapter *adapter, const char *type, modname = "wis-ov7640"; break; case I2C_DRIVERID_S2250: - modname = "s2250-board"; + modname = "s2250"; break; default: modname = NULL; diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c index f17e7b337a15..1e89dc04ec23 100644 --- a/drivers/staging/go7007/go7007-usb.c +++ b/drivers/staging/go7007/go7007-usb.c @@ -425,7 +425,7 @@ static struct go7007_usb_board board_sensoray_2250 = { .num_i2c_devs = 1, .i2c_devs = { { - .type = "s2250_board", + .type = "s2250", .id = I2C_DRIVERID_S2250, .addr = 0x43, }, diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c index f4a6541c3e60..a69f7682295e 100644 --- a/drivers/staging/go7007/s2250-board.c +++ b/drivers/staging/go7007/s2250-board.c @@ -20,10 +20,13 @@ #include #include #include +#include #include -#include "s2250-loader.h" +#include #include "go7007-priv.h" -#include "wis-i2c.h" + +MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver"); +MODULE_LICENSE("GPL v2"); #define TLV320_ADDRESS 0x34 #define VPX322_ADDR_ANALOGCONTROL1 0x02 @@ -575,7 +578,7 @@ static int s2250_probe(struct i2c_client *client, dec->audio = audio; i2c_set_clientdata(client, dec); - printk(KERN_DEBUG + printk(KERN_INFO "s2250: initializing video decoder on %s\n", adapter->name); @@ -649,45 +652,15 @@ static int s2250_remove(struct i2c_client *client) } static struct i2c_device_id s2250_id[] = { - { "s2250_board", 0 }, + { "s2250", 0 }, { } }; +MODULE_DEVICE_TABLE(i2c, s2250_id); -static struct i2c_driver s2250_driver = { - .driver = { - .name = "Sensoray 2250 board driver", - }, - .probe = s2250_probe, - .remove = s2250_remove, - .command = s2250_command, - .id_table = s2250_id, +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "s2250", + .probe = s2250_probe, + .remove = s2250_remove, + .command = s2250_command, + .id_table = s2250_id, }; - -static int __init s2250_init(void) -{ - int r; - - r = s2250loader_init(); - if (r < 0) - return r; - - r = i2c_add_driver(&s2250_driver); - if (r < 0) - s2250loader_cleanup(); - - return r; -} - -static void __exit s2250_cleanup(void) -{ - i2c_del_driver(&s2250_driver); - - s2250loader_cleanup(); -} - -module_init(s2250_init); -module_exit(s2250_cleanup); - -MODULE_AUTHOR(""); -MODULE_DESCRIPTION("Board driver for Sensoryray 2250"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c index d7bf82983274..c152ab9be2fb 100644 --- a/drivers/staging/go7007/s2250-loader.c +++ b/drivers/staging/go7007/s2250-loader.c @@ -162,7 +162,7 @@ static struct usb_driver s2250loader_driver = { .id_table = s2250loader_ids, }; -int s2250loader_init(void) +static int __init s2250loader_init(void) { int r; unsigned i = 0; @@ -179,11 +179,15 @@ int s2250loader_init(void) printk(KERN_INFO "s2250loader_init: driver registered\n"); return 0; } -EXPORT_SYMBOL(s2250loader_init); +module_init(s2250loader_init); -void s2250loader_cleanup(void) +static void __exit s2250loader_cleanup(void) { printk(KERN_INFO "s2250loader_cleanup\n"); usb_deregister(&s2250loader_driver); } -EXPORT_SYMBOL(s2250loader_cleanup); +module_exit(s2250loader_cleanup); + +MODULE_AUTHOR(""); +MODULE_DESCRIPTION("firmware loader for Sensoray 2250/2251"); +MODULE_LICENSE("GPL v2"); From 05d76f2da1e5ccb68a3610246501334e5bc42542 Mon Sep 17 00:00:00 2001 From: Pete Eberlein Date: Mon, 16 Nov 2009 15:15:07 -0300 Subject: [PATCH 332/345] V4L/DVB (13457): s2250: subdev conversion Convert the s2250 i2c driver to use v4l2 subdev interface. Signed-off-by: Pete Eberlein Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/go7007/s2250-board.c | 523 ++++++++++++++------------- 1 file changed, 269 insertions(+), 254 deletions(-) diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c index a69f7682295e..8cf7f2750b3f 100644 --- a/drivers/staging/go7007/s2250-board.c +++ b/drivers/staging/go7007/s2250-board.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "go7007-priv.h" MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver"); @@ -115,6 +116,7 @@ static u16 vid_regs_fp_pal[] = }; struct s2250 { + struct v4l2_subdev sd; v4l2_std_id std; int input; int brightness; @@ -126,6 +128,11 @@ struct s2250 { struct i2c_client *audio; }; +static inline struct s2250 *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct s2250, sd); +} + /* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ static int go7007_usb_vendor_request(struct go7007 *go, u16 request, u16 value, u16 index, void *transfer_buffer, int length, int in) @@ -309,253 +316,262 @@ static int write_regs_fp(struct i2c_client *client, u16 *regs) } -static int s2250_command(struct i2c_client *client, - unsigned int cmd, void *arg) +/* ------------------------------------------------------------------------- */ + +static int s2250_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output, + u32 config) { - struct s2250 *dec = i2c_get_clientdata(client); + struct s2250 *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int vidsys; - switch (cmd) { - case VIDIOC_S_INPUT: - { - int vidsys; - int *input = arg; + vidsys = (state->std == V4L2_STD_NTSC) ? 0x01 : 0x00; + if (input == 0) { + /* composite */ + write_reg_fp(client, 0x20, 0x020 | vidsys); + write_reg_fp(client, 0x21, 0x662); + write_reg_fp(client, 0x140, 0x060); + } else if (input == 1) { + /* S-Video */ + write_reg_fp(client, 0x20, 0x040 | vidsys); + write_reg_fp(client, 0x21, 0x666); + write_reg_fp(client, 0x140, 0x060); + } else { + return -EINVAL; + } + state->input = input; + return 0; +} - vidsys = (dec->std == V4L2_STD_NTSC) ? 0x01 : 0x00; - if (*input == 0) { - /* composite */ - write_reg_fp(client, 0x20, 0x020 | vidsys); - write_reg_fp(client, 0x21, 0x662); - write_reg_fp(client, 0x140, 0x060); - } else { - /* S-Video */ - write_reg_fp(client, 0x20, 0x040 | vidsys); - write_reg_fp(client, 0x21, 0x666); - write_reg_fp(client, 0x140, 0x060); - } - dec->input = *input; +static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) +{ + struct s2250 *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + u16 vidsource; + + vidsource = (state->input == 1) ? 0x040 : 0x020; + switch (norm) { + case V4L2_STD_NTSC: + write_regs_fp(client, vid_regs_fp); + write_reg_fp(client, 0x20, vidsource | 1); break; - } - case VIDIOC_S_STD: - { - v4l2_std_id *std = arg; - u16 vidsource; - - vidsource = (dec->input == 1) ? 0x040 : 0x020; - dec->std = *std; - switch (dec->std) { - case V4L2_STD_NTSC: - write_regs_fp(client, vid_regs_fp); - write_reg_fp(client, 0x20, vidsource | 1); - break; - case V4L2_STD_PAL: - write_regs_fp(client, vid_regs_fp); - write_regs_fp(client, vid_regs_fp_pal); - write_reg_fp(client, 0x20, vidsource); - break; - default: - return -EINVAL; - } + case V4L2_STD_PAL: + write_regs_fp(client, vid_regs_fp); + write_regs_fp(client, vid_regs_fp_pal); + write_reg_fp(client, 0x20, vidsource); break; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - static const u32 user_ctrls[] = { - V4L2_CID_BRIGHTNESS, - V4L2_CID_CONTRAST, - V4L2_CID_SATURATION, - V4L2_CID_HUE, - 0 - }; - static const u32 *ctrl_classes[] = { - user_ctrls, - NULL - }; - - ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); - break; - case V4L2_CID_CONTRAST: - v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); - break; - case V4L2_CID_SATURATION: - v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); - break; - case V4L2_CID_HUE: - v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0); - break; - default: - ctrl->name[0] = '\0'; - return -EINVAL; - } - break; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - int value1; - u16 oldvalue; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if (ctrl->value > 100) - dec->brightness = 100; - else if (ctrl->value < 0) - dec->brightness = 0; - else - dec->brightness = ctrl->value; - value1 = (dec->brightness - 50) * 255 / 100; - read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue); - write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, - value1 | (oldvalue & ~0xff)); - read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue); - write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, - value1 | (oldvalue & ~0xff)); - write_reg_fp(client, 0x140, 0x60); - break; - case V4L2_CID_CONTRAST: - if (ctrl->value > 100) - dec->contrast = 100; - else if (ctrl->value < 0) - dec->contrast = 0; - else - dec->contrast = ctrl->value; - value1 = dec->contrast * 0x40 / 100; - if (value1 > 0x3f) - value1 = 0x3f; /* max */ - read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue); - write_reg_fp(client, VPX322_ADDR_CONTRAST0, - value1 | (oldvalue & ~0x3f)); - read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue); - write_reg_fp(client, VPX322_ADDR_CONTRAST1, - value1 | (oldvalue & ~0x3f)); - write_reg_fp(client, 0x140, 0x60); - break; - case V4L2_CID_SATURATION: - if (ctrl->value > 127) - dec->saturation = 127; - else if (ctrl->value < 0) - dec->saturation = 0; - else - dec->saturation = ctrl->value; - - value1 = dec->saturation * 4140 / 100; - if (value1 > 4094) - value1 = 4094; - write_reg_fp(client, VPX322_ADDR_SAT, value1); - break; - case V4L2_CID_HUE: - if (ctrl->value > 50) - dec->hue = 50; - else if (ctrl->value < -50) - dec->hue = -50; - else - dec->hue = ctrl->value; - /* clamp the hue range */ - value1 = dec->hue * 280 / 50; - write_reg_fp(client, VPX322_ADDR_HUE, value1); - break; - } - break; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = dec->brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = dec->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = dec->saturation; - break; - case V4L2_CID_HUE: - ctrl->value = dec->hue; - break; - } - break; - } - case VIDIOC_S_FMT: - { - struct v4l2_format *fmt = arg; - if (fmt->fmt.pix.height < 640) { - write_reg_fp(client, 0x12b, dec->reg12b_val | 0x400); - write_reg_fp(client, 0x140, 0x060); - } else { - write_reg_fp(client, 0x12b, dec->reg12b_val & ~0x400); - write_reg_fp(client, 0x140, 0x060); - } - return 0; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *audio = arg; - - memset(audio, 0, sizeof(*audio)); - audio->index = dec->audio_input; - /* fall through */ - } - case VIDIOC_ENUMAUDIO: - { - struct v4l2_audio *audio = arg; - - switch (audio->index) { - case 0: - strcpy(audio->name, "Line In"); - break; - case 1: - strcpy(audio->name, "Mic"); - break; - case 2: - strcpy(audio->name, "Mic Boost"); - break; - default: - audio->name[0] = '\0'; - return 0; - } - audio->capability = V4L2_AUDCAP_STEREO; - audio->mode = 0; - return 0; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *audio = arg; - - switch (audio->index) { - case 0: - write_reg(dec->audio, 0x08, 0x02); /* Line In */ - break; - case 1: - write_reg(dec->audio, 0x08, 0x04); /* Mic */ - break; - case 2: - write_reg(dec->audio, 0x08, 0x05); /* Mic Boost */ - break; - default: - return -EINVAL; - } - dec->audio_input = audio->index; - return 0; - } - default: - printk(KERN_INFO "s2250: unknown command 0x%x\n", cmd); - break; + return -EINVAL; + } + state->std = norm; + return 0; +} + +static int s2250_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *query) +{ + switch (query->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(query, 0, 100, 1, 50); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(query, 0, 100, 1, 50); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(query, 0, 100, 1, 50); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(query, -50, 50, 1, 0); + default: + return -EINVAL; } return 0; } +static int s2250_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct s2250 *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int value1; + u16 oldvalue; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value > 100) + state->brightness = 100; + else if (ctrl->value < 0) + state->brightness = 0; + else + state->brightness = ctrl->value; + value1 = (state->brightness - 50) * 255 / 100; + read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue); + write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, + value1 | (oldvalue & ~0xff)); + read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue); + write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, + value1 | (oldvalue & ~0xff)); + write_reg_fp(client, 0x140, 0x60); + break; + case V4L2_CID_CONTRAST: + if (ctrl->value > 100) + state->contrast = 100; + else if (ctrl->value < 0) + state->contrast = 0; + else + state->contrast = ctrl->value; + value1 = state->contrast * 0x40 / 100; + if (value1 > 0x3f) + value1 = 0x3f; /* max */ + read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue); + write_reg_fp(client, VPX322_ADDR_CONTRAST0, + value1 | (oldvalue & ~0x3f)); + read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue); + write_reg_fp(client, VPX322_ADDR_CONTRAST1, + value1 | (oldvalue & ~0x3f)); + write_reg_fp(client, 0x140, 0x60); + break; + case V4L2_CID_SATURATION: + if (ctrl->value > 100) + state->saturation = 100; + else if (ctrl->value < 0) + state->saturation = 0; + else + state->saturation = ctrl->value; + value1 = state->saturation * 4140 / 100; + if (value1 > 4094) + value1 = 4094; + write_reg_fp(client, VPX322_ADDR_SAT, value1); + break; + case V4L2_CID_HUE: + if (ctrl->value > 50) + state->hue = 50; + else if (ctrl->value < -50) + state->hue = -50; + else + state->hue = ctrl->value; + /* clamp the hue range */ + value1 = state->hue * 280 / 50; + write_reg_fp(client, VPX322_ADDR_HUE, value1); + break; + default: + return -EINVAL; + } + return 0; +} + +static int s2250_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct s2250 *state = to_state(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = state->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = state->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = state->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = state->hue; + break; + default: + return -EINVAL; + } + return 0; +} + +static int s2250_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct s2250 *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (fmt->fmt.pix.height < 640) { + write_reg_fp(client, 0x12b, state->reg12b_val | 0x400); + write_reg_fp(client, 0x140, 0x060); + } else { + write_reg_fp(client, 0x12b, state->reg12b_val & ~0x400); + write_reg_fp(client, 0x140, 0x060); + } + return 0; +} + +static int s2250_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output, + u32 config) +{ + struct s2250 *state = to_state(sd); + + switch (input) { + case 0: + write_reg(state->audio, 0x08, 0x02); /* Line In */ + break; + case 1: + write_reg(state->audio, 0x08, 0x04); /* Mic */ + break; + case 2: + write_reg(state->audio, 0x08, 0x05); /* Mic Boost */ + break; + default: + return -EINVAL; + } + state->audio_input = input; + return 0; +} + + +static int s2250_log_status(struct v4l2_subdev *sd) +{ + struct s2250 *state = to_state(sd); + + v4l2_info(sd, "Standard: %s\n", state->std == V4L2_STD_NTSC ? "NTSC" : + state->std == V4L2_STD_PAL ? "PAL" : + state->std == V4L2_STD_SECAM ? "SECAM" : + "unknown"); + v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" : + state->input == 1 ? "S-video" : + "error"); + v4l2_info(sd, "Brightness: %d\n", state->brightness); + v4l2_info(sd, "Contrast: %d\n", state->contrast); + v4l2_info(sd, "Saturation: %d\n", state->saturation); + v4l2_info(sd, "Hue: %d\n", state->hue); return 0; + v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" : + state->audio_input == 1 ? "Mic" : + state->audio_input == 2 ? "Mic Boost" : + "error"); + return 0; +} + +/* --------------------------------------------------------------------------*/ + +static const struct v4l2_subdev_core_ops s2250_core_ops = { + .log_status = s2250_log_status, + .g_ctrl = s2250_g_ctrl, + .s_ctrl = s2250_s_ctrl, + .queryctrl = s2250_queryctrl, + .s_std = s2250_s_std, +}; + +static const struct v4l2_subdev_audio_ops s2250_audio_ops = { + .s_routing = s2250_s_audio_routing, +}; + +static const struct v4l2_subdev_video_ops s2250_video_ops = { + .s_routing = s2250_s_video_routing, + .s_fmt = s2250_s_fmt, +}; + +static const struct v4l2_subdev_ops s2250_ops = { + .core = &s2250_core_ops, + .audio = &s2250_audio_ops, + .video = &s2250_video_ops, +}; + +/* --------------------------------------------------------------------------*/ + static int s2250_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_client *audio; struct i2c_adapter *adapter = client->adapter; - struct s2250 *dec; + struct s2250 *state; + struct v4l2_subdev *sd; u8 *data; struct go7007 *go = i2c_get_adapdata(adapter); struct go7007_usb *usb = go->hpi_context; @@ -564,30 +580,31 @@ static int s2250_probe(struct i2c_client *client, if (audio == NULL) return -ENOMEM; - dec = kmalloc(sizeof(struct s2250), GFP_KERNEL); - if (dec == NULL) { + state = kmalloc(sizeof(struct s2250), GFP_KERNEL); + if (state == NULL) { i2c_unregister_device(audio); return -ENOMEM; } - dec->std = V4L2_STD_NTSC; - dec->brightness = 50; - dec->contrast = 50; - dec->saturation = 50; - dec->hue = 0; - dec->audio = audio; - i2c_set_clientdata(client, dec); + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &s2250_ops); - printk(KERN_INFO - "s2250: initializing video decoder on %s\n", - adapter->name); + v4l2_info(sd, "initializing %s at address 0x%x on %s\n", + "Sensoray 2250/2251", client->addr, client->adapter->name); + + state->std = V4L2_STD_NTSC; + state->brightness = 50; + state->contrast = 50; + state->saturation = 50; + state->hue = 0; + state->audio = audio; /* initialize the audio */ if (write_regs(audio, aud_regs) < 0) { printk(KERN_ERR "s2250: error initializing audio\n"); i2c_unregister_device(audio); - kfree(dec); + kfree(state); return 0; } @@ -595,14 +612,14 @@ static int s2250_probe(struct i2c_client *client, printk(KERN_ERR "s2250: error initializing decoder\n"); i2c_unregister_device(audio); - kfree(dec); + kfree(state); return 0; } if (write_regs_fp(client, vid_regs_fp) < 0) { printk(KERN_ERR "s2250: error initializing decoder\n"); i2c_unregister_device(audio); - kfree(dec); + kfree(state); return 0; } /* set default channel */ @@ -612,7 +629,7 @@ static int s2250_probe(struct i2c_client *client, write_reg_fp(client, 0x140, 0x060); /* set default audio input */ - dec->audio_input = 0; + state->audio_input = 0; write_reg(client, 0x08, 0x02); /* Line In */ if (mutex_lock_interruptible(&usb->i2c_lock) == 0) { @@ -637,17 +654,16 @@ static int s2250_probe(struct i2c_client *client, mutex_unlock(&usb->i2c_lock); } - printk("s2250: initialized successfully\n"); + v4l2_info(sd, "initialized successfully\n"); return 0; } static int s2250_remove(struct i2c_client *client) { - struct s2250 *dec = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); - i2c_unregister_device(dec->audio); - kfree(dec); + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } @@ -661,6 +677,5 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "s2250", .probe = s2250_probe, .remove = s2250_remove, - .command = s2250_command, .id_table = s2250_id, }; From fa3c39bd17449581eedaa1a0b7c8b67ec20c796e Mon Sep 17 00:00:00 2001 From: Pete Eberlein Date: Mon, 16 Nov 2009 15:16:00 -0300 Subject: [PATCH 333/345] V4L/DVB (13458): go7007: subdev conversion Convert the go7007 driver to v4l2 subdev interface, using v4l2 i2c subdev functions instead of i2c functions directly. The v4l2 ioctl ops functions call subdev ops instead of i2c commands. Signed-off-by: Pete Eberlein Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/go7007/go7007-driver.c | 18 +++-- drivers/staging/go7007/go7007-v4l2.c | 100 +++++++++---------------- 2 files changed, 47 insertions(+), 71 deletions(-) diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c index c5dc3b64ac03..fb1345ffb858 100644 --- a/drivers/staging/go7007/go7007-driver.c +++ b/drivers/staging/go7007/go7007-driver.c @@ -193,7 +193,8 @@ int go7007_reset_encoder(struct go7007 *go) static int init_i2c_module(struct i2c_adapter *adapter, const char *type, int id, int addr) { - struct i2c_board_info info; + struct go7007 *go = i2c_get_adapdata(adapter); + struct v4l2_device *v4l2_dev = &go->v4l2_dev; char *modname; switch (id) { @@ -225,14 +226,10 @@ static int init_i2c_module(struct i2c_adapter *adapter, const char *type, modname = NULL; break; } - if (modname != NULL) - request_module(modname); - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = addr; - strlcpy(info.type, type, I2C_NAME_SIZE); - if (!i2c_new_device(adapter, &info)) + if (v4l2_i2c_new_subdev(v4l2_dev, adapter, modname, type, addr, NULL)) return 0; + if (modname != NULL) printk(KERN_INFO "go7007: probing for module %s failed\n", modname); @@ -262,6 +259,11 @@ int go7007_register_encoder(struct go7007 *go) if (ret < 0) return -1; + /* v4l2 init must happen before i2c subdevs */ + ret = go7007_v4l2_init(go); + if (ret < 0) + return ret; + if (!go->i2c_adapter_online && go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) { if (go7007_i2c_init(go) < 0) @@ -282,7 +284,7 @@ int go7007_register_encoder(struct go7007 *go) go->audio_enabled = 1; go7007_snd_init(go); } - return go7007_v4l2_init(go); + return 0; } EXPORT_SYMBOL(go7007_register_encoder); diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c index faa749dd0356..b18d8e2d4c5e 100644 --- a/drivers/staging/go7007/go7007-v4l2.c +++ b/drivers/staging/go7007/go7007-v4l2.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,9 @@ #define V4L2_MPEG_VIDEO_ENCODING_MPEG_4 3 #endif +#define call_all(dev, o, f, args...) \ + v4l2_device_call_until_err(dev, 0, o, f, ##args) + static void deactivate_buffer(struct go7007_buffer *gobuf) { int i; @@ -247,19 +251,23 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try) go->modet_map[i] = 0; if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) { - struct video_decoder_resolution res; + struct v4l2_format res; + + if (fmt != NULL) { + res = *fmt; + } else { + res.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + res.fmt.pix.width = width; + } - res.width = width; if (height > sensor_height / 2) { - res.height = height / 2; + res.fmt.pix.height = height / 2; go->encoder_v_halve = 0; } else { - res.height = height; + res.fmt.pix.height = height; go->encoder_v_halve = 1; } - if (go->i2c_adapter_online) - i2c_clients_command(&go->i2c_adapter, - DECODER_SET_RESOLUTION, &res); + call_all(&go->v4l2_dev, video, s_fmt, &res); } else { if (width <= sensor_width / 4) { go->encoder_h_halve = 1; @@ -385,7 +393,7 @@ static int clip_to_modet_map(struct go7007 *go, int region, } #endif -static int mpeg_queryctrl(struct v4l2_queryctrl *ctrl) +static int mpeg_query_ctrl(struct v4l2_queryctrl *ctrl) { static const u32 mpeg_ctrls[] = { V4L2_CID_MPEG_CLASS, @@ -973,51 +981,35 @@ static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *query) { struct go7007 *go = ((struct go7007_file *) priv)->go; + int id = query->id; - if (!go->i2c_adapter_online) - return -EIO; + if (0 == call_all(&go->v4l2_dev, core, queryctrl, query)) + return 0; - i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query); - - return (!query->name[0]) ? mpeg_queryctrl(query) : 0; + query->id = id; + return mpeg_query_ctrl(query); } static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct go7007 *go = ((struct go7007_file *) priv)->go; - struct v4l2_queryctrl query; - if (!go->i2c_adapter_online) - return -EIO; + if (0 == call_all(&go->v4l2_dev, core, g_ctrl, ctrl)) + return 0; - memset(&query, 0, sizeof(query)); - query.id = ctrl->id; - i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); - if (query.name[0] == 0) - return mpeg_g_ctrl(ctrl, go); - i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, ctrl); - - return 0; + return mpeg_g_ctrl(ctrl, go); } static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct go7007 *go = ((struct go7007_file *) priv)->go; - struct v4l2_queryctrl query; - if (!go->i2c_adapter_online) - return -EIO; + if (0 == call_all(&go->v4l2_dev, core, s_ctrl, ctrl)) + return 0; - memset(&query, 0, sizeof(query)); - query.id = ctrl->id; - i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); - if (query.name[0] == 0) - return mpeg_s_ctrl(ctrl, go); - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, ctrl); - - return 0; + return mpeg_s_ctrl(ctrl, go); } static int vidioc_g_parm(struct file *filp, void *priv, @@ -1135,8 +1127,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) if (go->streaming) return -EBUSY; - if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) && - *std != 0) + if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) && *std != 0) return -EINVAL; if (*std == 0) @@ -1146,9 +1137,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) go->input == go->board_info->num_inputs - 1) { if (!go->i2c_adapter_online) return -EIO; - i2c_clients_command(&go->i2c_adapter, - VIDIOC_S_STD, std); - if (!*std) /* hack to indicate EINVAL from tuner */ + if (call_all(&go->v4l2_dev, core, s_std, *std) < 0) return -EINVAL; } @@ -1164,9 +1153,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) } else return -EINVAL; - if (go->i2c_adapter_online) - i2c_clients_command(&go->i2c_adapter, - VIDIOC_S_STD, std); + call_all(&go->v4l2_dev, core, s_std, *std); set_capture_size(go, NULL, 0); return 0; @@ -1180,7 +1167,7 @@ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std) go->input == go->board_info->num_inputs - 1) { if (!go->i2c_adapter_online) return -EIO; - i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYSTD, std); + return call_all(&go->v4l2_dev, video, querystd, std); } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; else @@ -1238,14 +1225,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int input) return -EBUSY; go->input = input; - if (go->i2c_adapter_online) { - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT, - &go->board_info->inputs[input].video_input); - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO, - &go->board_info->inputs[input].audio_input); - } - return 0; + return call_all(&go->v4l2_dev, video, s_routing, input, 0, 0); } static int vidioc_g_tuner(struct file *file, void *priv, @@ -1260,10 +1241,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (!go->i2c_adapter_online) return -EIO; - i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, t); - - t->index = 0; - return 0; + return call_all(&go->v4l2_dev, tuner, g_tuner, t); } static int vidioc_s_tuner(struct file *file, void *priv, @@ -1287,9 +1265,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, break; } - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, t); - - return 0; + return call_all(&go->v4l2_dev, tuner, s_tuner, t); } static int vidioc_g_frequency(struct file *file, void *priv, @@ -1303,8 +1279,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, return -EIO; f->type = V4L2_TUNER_ANALOG_TV; - i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, f); - return 0; + + return call_all(&go->v4l2_dev, tuner, g_frequency, f); } static int vidioc_s_frequency(struct file *file, void *priv, @@ -1317,9 +1293,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (!go->i2c_adapter_online) return -EIO; - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, f); - - return 0; + return call_all(&go->v4l2_dev, tuner, s_frequency, f); } static int vidioc_cropcap(struct file *file, void *priv, From 4e89217b943cfb26f88f04920d44f2077931f0e7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 21:54:41 -0300 Subject: [PATCH 334/345] V4L/DVB (13531): ir-common: rename the debug routine to allow exporting it As newer IR common code will be added on other files, we need a global debug var inside the module. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-functions.c | 23 ++++++++++------------- include/media/ir-common.h | 4 ++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index fc2d8941459f..b111a0d9409b 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -34,11 +34,8 @@ static int repeat = 1; module_param(repeat, int, 0444); MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); -static int debug; /* debug level (0,1,2) */ -module_param(debug, int, 0644); - -#define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG fmt , ## arg) +int media_ir_debug; /* media_ir_debug level (0,1,2) */ +module_param_named(debug, media_ir_debug, int, 0644); /* -------------------------------------------------------------------------- */ @@ -49,7 +46,7 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) dev->name,ir->ir_key,ir->ir_raw,ir->keypressed); return; } - dprintk(1,"%s: key event code=%d down=%d\n", + IR_dprintk(1,"%s: key event code=%d down=%d\n", dev->name,ir->keycode,ir->keypressed); input_report_key(dev,ir->keycode,ir->keypressed); input_sync(dev); @@ -295,11 +292,11 @@ u32 ir_rc5_decode(unsigned int code) rc5 |= 1; break; case 3: - dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code); + IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code); return 0; } } - dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " + IR_dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " "instr=%x\n", rc5, org_code, RC5_START(rc5), RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); return rc5; @@ -331,20 +328,20 @@ void ir_rc5_timer_end(unsigned long data) /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ if (gap < 28000) { - dprintk(1, "ir-common: spurious timer_end\n"); + IR_dprintk(1, "ir-common: spurious timer_end\n"); return; } if (ir->last_bit < 20) { /* ignore spurious codes (caused by light/other remotes) */ - dprintk(1, "ir-common: short code: %x\n", ir->code); + IR_dprintk(1, "ir-common: short code: %x\n", ir->code); } else { ir->code = (ir->code << ir->shift_by) | 1; rc5 = ir_rc5_decode(ir->code); /* two start bits? */ if (RC5_START(rc5) != ir->start) { - dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5)); + IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5)); /* right address? */ } else if (RC5_ADDR(rc5) == ir->addr) { @@ -354,7 +351,7 @@ void ir_rc5_timer_end(unsigned long data) /* Good code, decide if repeat/repress */ if (toggle != RC5_TOGGLE(ir->last_rc5) || instr != RC5_INSTR(ir->last_rc5)) { - dprintk(1, "ir-common: instruction %x, toggle %x\n", instr, + IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", instr, toggle); ir_input_nokey(ir->dev, &ir->ir); ir_input_keydown(ir->dev, &ir->ir, instr, @@ -377,7 +374,7 @@ void ir_rc5_timer_keyup(unsigned long data) { struct card_ir *ir = (struct card_ir *)data; - dprintk(1, "ir-common: key released\n"); + IR_dprintk(1, "ir-common: key released\n"); ir_input_nokey(ir->dev, &ir->ir); } EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup); diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 5921776929e7..5964145d65e6 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -27,6 +27,10 @@ #include #include +extern int media_ir_debug; /* media_ir_debug level (0,1,2) */ +#define IR_dprintk(level, fmt, arg...) if (media_ir_debug >= level) \ + printk(KERN_DEBUG fmt , ## arg) + #define IR_TYPE_RC5 1 #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ #define IR_TYPE_OTHER 99 From ef53a1159dfcdc1fecf5adb5b8d26803f194c09b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 22:01:23 -0300 Subject: [PATCH 335/345] V4L/DVB (13532): ir-common: Add infrastructure to use a dynamic keycode table V4L drivers use an static keycode vector with 128 entries, where the scancode indexes the keycode. While this works, it limits the scancodes to have only 7 bits, not allowing for example full RC5 codes. Instead of implementing the same code on every V4L driver, provide a common infrastructure to handle the bigger tables, minimizing the changes inside each driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/Makefile | 2 +- drivers/media/common/ir-keytable.c | 156 +++++++++++++++++++++++++++++ include/media/ir-common.h | 12 ++- 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 drivers/media/common/ir-keytable.c diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index 351b98b9b302..169b337b7c9d 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -1,6 +1,6 @@ saa7146-objs := saa7146_i2c.o saa7146_core.o saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o -ir-common-objs := ir-functions.o ir-keymaps.o +ir-common-objs := ir-functions.o ir-keymaps.o ir-keytable.o obj-y += tuners/ obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/common/ir-keytable.c new file mode 100644 index 000000000000..2de7caeef437 --- /dev/null +++ b/drivers/media/common/ir-keytable.c @@ -0,0 +1,156 @@ +/* ir-register.c - handle IR scancode->keycode tables + * + * Copyright (C) 2009 by Mauro Carvalho Chehab + */ + +#include + +#include + +/** + * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table + * @dev: the struct input_dev device descriptor + * @scancode: the desired scancode + * @keycode: the keycode to be retorned. + * + * This routine is used to handle evdev EVIOCGKEY ioctl. + * If the key is not found, returns -EINVAL, otherwise, returns 0. + */ +static int ir_getkeycode(struct input_dev *dev, + int scancode, int *keycode) +{ + int i; + struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_scancode *keymap = rc_tab->scan; + + /* See if we can match the raw key code. */ + for (i = 0; i < rc_tab->size; i++) + if (keymap[i].scancode == scancode) { + *keycode = keymap[i].keycode; + return 0; + } + + /* + * If is there extra space, returns KEY_RESERVED, + * otherwise, input core won't let ir_setkeycode + * to work + */ + for (i = 0; i < rc_tab->size; i++) + if (keymap[i].keycode == KEY_RESERVED || + keymap[i].keycode == KEY_UNKNOWN) { + *keycode = KEY_RESERVED; + return 0; + } + + return -EINVAL; +} + +/** + * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table + * @dev: the struct input_dev device descriptor + * @scancode: the desired scancode + * @keycode: the keycode to be retorned. + * + * This routine is used to handle evdev EVIOCSKEY ioctl. + * There's one caveat here: how can we increase the size of the table? + * If the key is not found, returns -EINVAL, otherwise, returns 0. + */ +static int ir_setkeycode(struct input_dev *dev, + int scancode, int keycode) +{ + int i; + struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_scancode *keymap = rc_tab->scan; + + /* Search if it is replacing an existing keycode */ + for (i = 0; i < rc_tab->size; i++) + if (keymap[i].scancode == scancode) { + keymap[i].keycode = keycode; + return 0; + } + + /* Search if is there a clean entry. If so, use it */ + for (i = 0; i < rc_tab->size; i++) + if (keymap[i].keycode == KEY_RESERVED || + keymap[i].keycode == KEY_UNKNOWN) { + keymap[i].scancode = scancode; + keymap[i].keycode = keycode; + return 0; + } + + /* + * FIXME: Currently, it is not possible to increase the size of + * scancode table. For it to happen, one possibility + * would be to allocate a table with key_map_size + 1, + * copying data, appending the new key on it, and freeing + * the old one - or maybe just allocating some spare space + */ + + return -EINVAL; +} + +/** + * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode + * @rc_tab: the ir_scancode_table with the keymap to be used + * @scancode: the scancode that we're seeking + * + * This routine is used by the input routines when a key is pressed at the + * IR. The scancode is received and needs to be converted into a keycode. + * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the + * corresponding keycode from the table. + */ +u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) +{ + int i; + struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_scancode *keymap = rc_tab->scan; + + for (i = 0; i < rc_tab->size; i++) + if (keymap[i].scancode == scancode) { + IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", + dev->name, scancode, keymap[i].keycode); + + return keymap[i].keycode; + } + + printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n", + dev->name, scancode); + + return KEY_UNKNOWN; +} +EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); + +/** + * ir_set_keycode_table() - sets the IR keycode table and add the handlers + * for keymap table get/set + * @input_dev: the struct input_dev descriptor of the device + * @rc_tab: the struct ir_scancode_table table of scancode/keymap + * + * This routine is used to initialize the input infrastructure to work with + * an IR. It requires that the caller initializes the input_dev struct with + * some fields: name, + */ +int ir_set_keycode_table(struct input_dev *input_dev, + struct ir_scancode_table *rc_tab) +{ + struct ir_scancode *keymap = rc_tab->scan; + int i; + + if (rc_tab->scan == NULL || !rc_tab->size) + return -EINVAL; + + /* set the bits for the keys */ + IR_dprintk(1, "key map size: %d\n", rc_tab->size); + for (i = 0; i < rc_tab->size; i++) { + IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n", + i, keymap[i].keycode); + set_bit(keymap[i].keycode, input_dev->keybit); + } + + input_dev->getkeycode = ir_getkeycode; + input_dev->setkeycode = ir_setkeycode; + input_set_drvdata(input_dev, rc_tab); + + return 0; +} +EXPORT_SYMBOL_GPL(ir_set_keycode_table); diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 5964145d65e6..805f1e09770f 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -106,6 +106,8 @@ struct card_ir { struct tasklet_struct tlet; }; +/* Routines from ir-functions.c */ + void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, struct ir_scancode_table *ir_codes); void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir); @@ -120,7 +122,15 @@ u32 ir_rc5_decode(unsigned int code); void ir_rc5_timer_end(unsigned long data); void ir_rc5_timer_keyup(unsigned long data); -/* Keymaps to be used by other modules */ +/* Routines from ir-keytable.c */ + +u32 ir_g_keycode_from_table(struct input_dev *input_dev, + u32 scancode); + +int ir_set_keycode_table(struct input_dev *input_dev, + struct ir_scancode_table *rc_tab); + +/* scancode->keycode map tables from ir-keymaps.c */ extern struct ir_scancode_table ir_codes_empty_table; extern struct ir_scancode_table ir_codes_avermedia_table; From 8573b74af25c279de3e309beddcba984bee9ec15 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 22:40:22 -0300 Subject: [PATCH 336/345] V4L/DVB (13533): ir: use dynamic tables, instead of static ones Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-functions.c | 32 ++++----------------- drivers/media/common/ir-keytable.c | 2 -- drivers/media/dvb/dm1105/dm1105.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/video/bt8xx/bttv-input.c | 8 +++--- drivers/media/video/cx231xx/cx231xx-input.c | 3 +- drivers/media/video/cx23885/cx23885-input.c | 3 +- drivers/media/video/cx88/cx88-input.c | 14 ++++----- drivers/media/video/em28xx/em28xx-input.c | 3 +- drivers/media/video/ir-kbd-i2c.c | 2 +- drivers/media/video/saa7134/saa7134-input.c | 8 +++--- include/media/ir-common.h | 5 ++-- 12 files changed, 29 insertions(+), 55 deletions(-) diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index b111a0d9409b..29885c2893d2 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -42,8 +42,8 @@ module_param_named(debug, media_ir_debug, int, 0644); static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) { if (KEY_RESERVED == ir->keycode) { - printk(KERN_INFO "%s: unknown key: key=0x%02x raw=0x%02x down=%d\n", - dev->name,ir->ir_key,ir->ir_raw,ir->keypressed); + printk(KERN_INFO "%s: unknown key: key=0x%02x down=%d\n", + dev->name, ir->ir_key, ir->keypressed); return; } IR_dprintk(1,"%s: key event code=%d down=%d\n", @@ -57,28 +57,10 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, struct ir_scancode_table *ir_codes) { - int i; - ir->ir_type = ir_type; - memset(ir->ir_codes, 0, sizeof(ir->ir_codes)); + ir_set_keycode_table(dev, ir_codes); - /* - * FIXME: This is a temporary workaround to use the new IR tables - * with the old approach. Later patches will replace this to a - * proper method - */ - - if (ir_codes) - for (i = 0; i < ir_codes->size; i++) - if (ir_codes->scan[i].scancode < IR_KEYTAB_SIZE) - ir->ir_codes[ir_codes->scan[i].scancode] = ir_codes->scan[i].keycode; - - dev->keycode = ir->ir_codes; - dev->keycodesize = sizeof(IR_KEYTAB_TYPE); - dev->keycodemax = IR_KEYTAB_SIZE; - for (i = 0; i < IR_KEYTAB_SIZE; i++) - set_bit(ir->ir_codes[i], dev->keybit); clear_bit(0, dev->keybit); set_bit(EV_KEY, dev->evbit); @@ -97,9 +79,9 @@ void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) EXPORT_SYMBOL_GPL(ir_input_nokey); void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, - u32 ir_key, u32 ir_raw) + u32 ir_key) { - u32 keycode = IR_KEYCODE(ir->ir_codes, ir_key); + u32 keycode = ir_g_keycode_from_table(dev, ir_key); if (ir->keypressed && ir->keycode != keycode) { ir->keypressed = 0; @@ -107,7 +89,6 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, } if (!ir->keypressed) { ir->ir_key = ir_key; - ir->ir_raw = ir_raw; ir->keycode = keycode; ir->keypressed = 1; ir_input_key_event(dev,ir); @@ -354,8 +335,7 @@ void ir_rc5_timer_end(unsigned long data) IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", instr, toggle); ir_input_nokey(ir->dev, &ir->ir); - ir_input_keydown(ir->dev, &ir->ir, instr, - instr); + ir_input_keydown(ir->dev, &ir->ir, instr); } /* Set/reset key-up timer */ diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/common/ir-keytable.c index 2de7caeef437..65e352389b2d 100644 --- a/drivers/media/common/ir-keytable.c +++ b/drivers/media/common/ir-keytable.c @@ -118,7 +118,6 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) return KEY_UNKNOWN; } -EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); /** * ir_set_keycode_table() - sets the IR keycode table and add the handlers @@ -153,4 +152,3 @@ int ir_set_keycode_table(struct input_dev *input_dev, return 0; } -EXPORT_SYMBOL_GPL(ir_set_keycode_table); diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 2d099e271751..4c28632f94c4 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -510,7 +510,7 @@ static void dm1105_emit_key(struct work_struct *work) data = (ircom >> 8) & 0x7f; - ir_input_keydown(ir->input_dev, &ir->ir, data, data); + ir_input_keydown(ir->input_dev, &ir->ir, data); ir_input_nokey(ir->input_dev, &ir->ir); } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 88a0a5670ccf..adc4b954e5ad 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -178,7 +178,7 @@ static void msp430_ir_interrupt(unsigned long data) if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) { ir_input_nokey(dev, &budget_ci->ir.state); ir_input_keydown(dev, &budget_ci->ir.state, - budget_ci->ir.ir_key, raw); + budget_ci->ir.ir_key); budget_ci->ir.last_raw = raw; } diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index ebd51afe8761..62408ccf34c8 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -73,12 +73,12 @@ static void ir_handle_key(struct bttv *btv) if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev,&ir->ir,data,data); + ir_input_keydown(ir->dev, &ir->ir, data); } else { /* HACK: Probably, ir->mask_keydown is missing for this board */ if (btv->c.type == BTTV_BOARD_WINFAST2000) - ir_input_keydown(ir->dev, &ir->ir, data, data); + ir_input_keydown(ir->dev, &ir->ir, data); ir_input_nokey(ir->dev,&ir->ir); } @@ -104,7 +104,7 @@ static void ir_enltv_handle_key(struct bttv *btv) gpio, data, (gpio & ir->mask_keyup) ? " up" : "up/down"); - ir_input_keydown(ir->dev, &ir->ir, data, data); + ir_input_keydown(ir->dev, &ir->ir, data); if (keyup) ir_input_nokey(ir->dev, &ir->ir); } else { @@ -118,7 +118,7 @@ static void ir_enltv_handle_key(struct bttv *btv) if (keyup) ir_input_nokey(ir->dev, &ir->ir); else - ir_input_keydown(ir->dev, &ir->ir, data, data); + ir_input_keydown(ir->dev, &ir->ir, data); } ir->last_gpio = data | keyup; diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 48f22fa38e6c..58dd39bc6787 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -126,8 +126,7 @@ static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) if (do_sendkey) { dprintk("sending keypress\n"); - ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0], - poll_result.rc_data[0]); + ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0]); ir_input_nokey(ir->input, &ir->ir); } diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index f000ed787d4e..fea882d1fbcb 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -94,8 +94,7 @@ static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev) RC5_START(ir_input->last_rc5) == 0) { /* This keypress is differnet: not an auto repeat */ ir_input_nokey(ir_input->dev, &ir_input->ir); - ir_input_keydown(ir_input->dev, &ir_input->ir, - command, ir_input->code); + ir_input_keydown(ir_input->dev, &ir_input->ir, command); } ir_input->last_rc5 = rc5; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 47c03019357d..7b2066415d7e 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -118,13 +118,13 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) data = (data << 4) | ((gpio_key & 0xf0) >> 4); - ir_input_keydown(ir->input, &ir->ir, data, data); + ir_input_keydown(ir->input, &ir->ir, data); ir_input_nokey(ir->input, &ir->ir); } else if (ir->mask_keydown) { /* bit set on keydown */ if (gpio & ir->mask_keydown) { - ir_input_keydown(ir->input, &ir->ir, data, data); + ir_input_keydown(ir->input, &ir->ir, data); } else { ir_input_nokey(ir->input, &ir->ir); } @@ -132,14 +132,14 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } else if (ir->mask_keyup) { /* bit cleared on keydown */ if (0 == (gpio & ir->mask_keyup)) { - ir_input_keydown(ir->input, &ir->ir, data, data); + ir_input_keydown(ir->input, &ir->ir, data); } else { ir_input_nokey(ir->input, &ir->ir); } } else { /* can't distinguish keydown/up :-/ */ - ir_input_keydown(ir->input, &ir->ir, data, data); + ir_input_keydown(ir->input, &ir->ir, data); ir_input_nokey(ir->input, &ir->ir); } } @@ -487,7 +487,7 @@ void cx88_ir_irq(struct cx88_core *core) ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f); - ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff); + ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f); ir->release = jiffies + msecs_to_jiffies(120); break; case CX88_BOARD_HAUPPAUGE: @@ -524,7 +524,7 @@ void cx88_ir_irq(struct cx88_core *core) if ( dev != 0x1e && dev != 0x1f ) /* not a hauppauge remote */ break; - ir_input_keydown(ir->input, &ir->ir, code, ircode); + ir_input_keydown(ir->input, &ir->ir, code); ir->release = jiffies + msecs_to_jiffies(120); break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: @@ -532,7 +532,7 @@ void cx88_ir_irq(struct cx88_core *core) ir_dprintk("biphase decoded: %x\n", ircode); if ((ircode & 0xfffff000) != 0x3000) break; - ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f, ircode); + ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f); ir->release = jiffies + msecs_to_jiffies(120); break; } diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 7a0fe3816e3d..990ee04bbd5e 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -282,8 +282,7 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) if (do_sendkey) { dprintk("sending keypress\n"); - ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0], - poll_result.rc_data[0]); + ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0]); ir_input_nokey(ir->input, &ir->ir); } diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index aec36660987d..9c6d0ae58b1f 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -275,7 +275,7 @@ static void ir_key_poll(struct IR_i2c *ir) if (0 == rc) { ir_input_nokey(ir->input, &ir->ir); } else { - ir_input_keydown(ir->input, &ir->ir, ir_key, ir_raw); + ir_input_keydown(ir->input, &ir->ir, ir_key); } } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index f658f2513992..439f3d54d009 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -102,14 +102,14 @@ static int build_key(struct saa7134_dev *dev) if (data == ir->mask_keycode) ir_input_nokey(ir->dev, &ir->ir); else - ir_input_keydown(ir->dev, &ir->ir, data, data); + ir_input_keydown(ir->dev, &ir->ir, data); return 0; } if (ir->polling) { if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data, data); + ir_input_keydown(ir->dev, &ir->ir, data); } else { ir_input_nokey(ir->dev, &ir->ir); } @@ -117,7 +117,7 @@ static int build_key(struct saa7134_dev *dev) else { /* IRQ driven mode - handle key press and release in one go */ if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data, data); + ir_input_keydown(ir->dev, &ir->ir, data); ir_input_nokey(ir->dev, &ir->ir); } } @@ -938,7 +938,7 @@ static void nec_task(unsigned long data) dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", ir->code, ircode, not_code); - ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code); + ir_input_keydown(ir->dev, &ir->ir, ir->code); } else dprintk("Repeat last key\n"); diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 805f1e09770f..262347b61506 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -62,8 +62,7 @@ struct ir_input_state { IR_KEYTAB_TYPE ir_codes[IR_KEYTAB_SIZE]; /* key info */ - u32 ir_raw; /* raw data */ - u32 ir_key; /* ir key code */ + u32 ir_key; /* ir scancode */ u32 keycode; /* linux key code */ int keypressed; /* current state */ }; @@ -112,7 +111,7 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, struct ir_scancode_table *ir_codes); void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir); void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, - u32 ir_key, u32 ir_raw); + u32 ir_key); u32 ir_extract_bits(u32 data, u32 mask); int ir_dump_samples(u32 *samples, int count); int ir_decode_biphase(u32 *samples, int count, int low, int high); From 6d691237e61ed68a04b14e3c89364e481421d6e8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 22:51:56 -0300 Subject: [PATCH 337/345] V4L/DVB (13534): ir-common: Remove some unused fields/structs Now that the IR conversion to dynamic tables has finished, we can get rid of some fields and definitions that aren't used anymore. Signed-off-by: Mauro Carvalho Chehab --- include/media/ir-common.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 262347b61506..1a619a4ec5cc 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -35,9 +35,6 @@ extern int media_ir_debug; /* media_ir_debug level (0,1,2) */ #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ #define IR_TYPE_OTHER 99 -#define IR_KEYTAB_TYPE u32 -#define IR_KEYTAB_SIZE 128 /* enougth for rc5, probably need more some day */ - struct ir_scancode { u16 scancode; u32 keycode; @@ -48,9 +45,6 @@ struct ir_scancode_table { int size; }; -#define IR_KEYCODE(tab,code) (((unsigned)code < IR_KEYTAB_SIZE) \ - ? tab[code] : KEY_RESERVED) - #define RC5_START(x) (((x)>>12)&3) #define RC5_TOGGLE(x) (((x)>>11)&1) #define RC5_ADDR(x) (((x)>>6)&31) @@ -59,7 +53,6 @@ struct ir_scancode_table { struct ir_input_state { /* configuration */ int ir_type; - IR_KEYTAB_TYPE ir_codes[IR_KEYTAB_SIZE]; /* key info */ u32 ir_key; /* ir scancode */ From 35d1988c6e19db3d4240e2a60c71b3a13abf0781 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 23:25:13 -0300 Subject: [PATCH 338/345] V4L/DVB (13535): ir-common: Add a hauppauge new table with the complete RC5 code Now that V4L drivers can support more than 7 bits for scan code, let's add a modified version for the Hauppauge Grey IR containing the full IR scancode. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 71 +++++++++++++++++++++++++++++++ include/media/ir-common.h | 1 + 2 files changed, 72 insertions(+) diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index e353dffe696a..328c973a0838 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -1847,6 +1847,76 @@ struct ir_scancode_table ir_codes_hauppauge_new_table = { }; EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); +/* + * Hauppauge:the newer, gray remotes (seems there are multiple + * slightly different versions), shipped with cx88+ivtv cards. + * + * This table contains the complete RC5 code, instead of just the data part + */ +static struct ir_scancode ir_codes_rc5_hauppauge_new[] = { + /* Keys 0 to 9 */ + { 0x1e00, KEY_0 }, + { 0x1e01, KEY_1 }, + { 0x1e02, KEY_2 }, + { 0x1e03, KEY_3 }, + { 0x1e04, KEY_4 }, + { 0x1e05, KEY_5 }, + { 0x1e06, KEY_6 }, + { 0x1e07, KEY_7 }, + { 0x1e08, KEY_8 }, + { 0x1e09, KEY_9 }, + + { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ + { 0x1e0b, KEY_RED }, /* red button */ + { 0x1e0c, KEY_RADIO }, + { 0x1e0d, KEY_MENU }, + { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ + { 0x1e0f, KEY_MUTE }, + { 0x1e10, KEY_VOLUMEUP }, + { 0x1e11, KEY_VOLUMEDOWN }, + { 0x1e12, KEY_PREVIOUS }, /* previous channel */ + { 0x1e14, KEY_UP }, + { 0x1e15, KEY_DOWN }, + { 0x1e16, KEY_LEFT }, + { 0x1e17, KEY_RIGHT }, + { 0x1e18, KEY_VIDEO }, /* Videos */ + { 0x1e19, KEY_AUDIO }, /* Music */ + /* 0x1e1a: Pictures - presume this means + "Multimedia Home Platform" - + no "PICTURES" key in input.h + */ + { 0x1e1a, KEY_MHP }, + + { 0x1e1b, KEY_EPG }, /* Guide */ + { 0x1e1c, KEY_TV }, + { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ + { 0x1e1f, KEY_EXIT }, /* back/exit */ + { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ + { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ + { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x1e25, KEY_ENTER }, /* OK */ + { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ + { 0x1e29, KEY_BLUE }, /* blue key */ + { 0x1e2e, KEY_GREEN }, /* green button */ + { 0x1e30, KEY_PAUSE }, /* pause */ + { 0x1e32, KEY_REWIND }, /* backward << */ + { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ + { 0x1e35, KEY_PLAY }, + { 0x1e36, KEY_STOP }, + { 0x1e37, KEY_RECORD }, /* recording */ + { 0x1e38, KEY_YELLOW }, /* yellow key */ + { 0x1e3b, KEY_SELECT }, /* top right button */ + { 0x1e3c, KEY_ZOOM }, /* full */ + { 0x1e3d, KEY_POWER }, /* system power (green button) */ +}; + +struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { + .scan = ir_codes_rc5_hauppauge_new, + .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), +}; +EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); + static struct ir_scancode ir_codes_npgtech[] = { { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ { 0x2a, KEY_FRONT }, @@ -3243,3 +3313,4 @@ struct ir_scancode_table ir_codes_gadmei_rm008z_table = { .size = ARRAY_SIZE(ir_codes_gadmei_rm008z), }; EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); + diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 1a619a4ec5cc..cd21cb55d5d5 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -157,6 +157,7 @@ extern struct ir_scancode_table ir_codes_rc5_tv_table; extern struct ir_scancode_table ir_codes_winfast_table; extern struct ir_scancode_table ir_codes_pinnacle_color_table; extern struct ir_scancode_table ir_codes_hauppauge_new_table; +extern struct ir_scancode_table ir_codes_rc5_hauppauge_new_table; extern struct ir_scancode_table ir_codes_npgtech_table; extern struct ir_scancode_table ir_codes_norwood_table; extern struct ir_scancode_table ir_codes_proteus_2309_table; From 0278155c84af42d78785731263b69fb49f945ea7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Nov 2009 23:28:40 -0300 Subject: [PATCH 339/345] V4L/DVB (13536): em28xx: Use the full RC5 code on HVR-950 Remote Controller Modifies the IR table for HVR-950 to use the newer Hauppauge RC5 table, and adds the RC5 address to the functions that get the scancode for this device. It is easy to add support for all other RC5 IR's on em2880 boards, but the scancode table needs to be re-generated. So, keep using the old 7bits tables while we don't have all tables converted. Also, the 7bits tables are still used on other drivers, so this small patch needs to be ported to all drivers. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/em28xx/em28xx-input.c | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ed5acc3a2b5a..82da205047be 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -837,7 +837,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &ir_codes_hauppauge_new_table, + .ir_codes = &ir_codes_rc5_hauppauge_new_table, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 990ee04bbd5e..5550de9c669f 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -70,6 +70,7 @@ struct em28xx_IR { int polling; struct delayed_work work; unsigned int last_toggle:1; + unsigned int full_code:1; unsigned int last_readcount; unsigned int repeat_interval; @@ -246,9 +247,10 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) return; } - dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x\n", + dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x%02x\n", poll_result.toggle_bit, poll_result.read_count, - ir->last_readcount, poll_result.rc_data[0]); + ir->last_readcount, poll_result.rc_address, + poll_result.rc_data[0]); if (ir->dev->chip_id == CHIP_ID_EM2874) { /* The em2874 clears the readcount field every time the @@ -282,7 +284,15 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) if (do_sendkey) { dprintk("sending keypress\n"); - ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0]); + + if (ir->full_code) + ir_input_keydown(ir->input, &ir->ir, + poll_result.rc_address << 8 | + poll_result.rc_data[0]); + else + ir_input_keydown(ir->input, &ir->ir, + poll_result.rc_data[0]); + ir_input_nokey(ir->input, &ir->ir); } @@ -332,6 +342,8 @@ int em28xx_ir_init(struct em28xx *dev) switch (dev->chip_id) { case CHIP_ID_EM2860: case CHIP_ID_EM2883: + if (dev->model == EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950) + ir->full_code = 1; ir->get_key = default_polling_getkey; break; case CHIP_ID_EM2874: From 055cd55601f948675006ca90362fc2bfaae90a86 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Nov 2009 08:19:59 -0300 Subject: [PATCH 340/345] V4L/DVB (13537): ir: Prepare the code for dynamic keycode table allocation Currently, the IR table is initialized by calling ir_input_init(). However, this function doesn't return any error code, nor has a function to be called when de-initializing the IR's. Change the return argment to integer and make sure that each driver will handle the error code. Also adds a function to free any resources that may be allocating there: ir_input_free(). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-functions.c | 12 +++++++++++- drivers/media/dvb/dm1105/dm1105.c | 10 ++++++++-- drivers/media/dvb/ttpci/budget-ci.c | 14 +++++++++++--- drivers/media/video/bt8xx/bttv-input.c | 7 ++++++- drivers/media/video/cx231xx/cx231xx-input.c | 8 +++++++- drivers/media/video/cx23885/cx23885-input.c | 7 ++++++- drivers/media/video/cx88/cx88-input.c | 7 ++++++- drivers/media/video/em28xx/em28xx-input.c | 8 +++++++- drivers/media/video/ir-kbd-i2c.c | 7 ++++++- drivers/media/video/saa7134/saa7134-input.c | 7 ++++++- include/media/ir-common.h | 3 ++- 11 files changed, 76 insertions(+), 14 deletions(-) diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index 29885c2893d2..b31bd27da374 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -54,11 +54,13 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) /* -------------------------------------------------------------------------- */ -void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, +int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, struct ir_scancode_table *ir_codes) { ir->ir_type = ir_type; + /* FIXME: Add the proper code to dynamically allocate IR table */ + ir_set_keycode_table(dev, ir_codes); clear_bit(0, dev->keybit); @@ -66,9 +68,17 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, set_bit(EV_KEY, dev->evbit); if (repeat) set_bit(EV_REP, dev->evbit); + + return 0; } EXPORT_SYMBOL_GPL(ir_input_init); +void ir_input_free(struct input_dev *input_dev) +{ + /* FIXME: Add the proper code to free allocated resources */ +} +EXPORT_SYMBOL_GPL(ir_input_free); + void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) { if (ir->keypressed) { diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 4c28632f94c4..53e3f2a7d31a 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -589,7 +589,12 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), "pci-%s/ir0", pci_name(dm1105->pdev)); - ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes); + err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes); + if (err < 0) { + input_free_device(input_dev); + return err; + } + input_dev->name = "DVB on-card IR receiver"; input_dev->phys = dm1105->ir.input_phys; input_dev->id.bustype = BUS_PCI; @@ -608,6 +613,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) err = input_register_device(input_dev); if (err) { + ir_input_free(input_dev); input_free_device(input_dev); return err; } @@ -617,8 +623,8 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) { + ir_input_free(dm1105->ir.input_dev); input_unregister_device(dm1105->ir.input_dev); - } static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index adc4b954e5ad..7d193ebc0aea 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -224,8 +224,10 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1011: case 0x1012: /* The hauppauge keymap is a superset of these remotes */ - ir_input_init(input_dev, &budget_ci->ir.state, + error = ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5, &ir_codes_hauppauge_new_table); + if (error < 0) + goto out2; if (rc5_device < 0) budget_ci->ir.rc5_device = 0x1f; @@ -236,8 +238,10 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1017: case 0x101a: /* for the Technotrend 1500 bundled remote */ - ir_input_init(input_dev, &budget_ci->ir.state, + error = ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5, &ir_codes_tt_1500_table); + if (error < 0) + goto out2; if (rc5_device < 0) budget_ci->ir.rc5_device = IR_DEVICE_ANY; @@ -246,8 +250,10 @@ static int msp430_ir_init(struct budget_ci *budget_ci) break; default: /* unknown remote */ - ir_input_init(input_dev, &budget_ci->ir.state, + error = ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5, &ir_codes_budget_ci_old_table); + if (error < 0) + goto out2; if (rc5_device < 0) budget_ci->ir.rc5_device = IR_DEVICE_ANY; @@ -280,6 +286,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) return 0; out2: + ir_input_free(input_dev); input_free_device(input_dev); out1: return error; @@ -297,6 +304,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) del_timer_sync(&dev->timer); ir_input_nokey(dev, &budget_ci->ir.state); + ir_input_free(dev); input_unregister_device(dev); } diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 62408ccf34c8..84a957e52c4b 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -368,7 +368,10 @@ int bttv_input_init(struct bttv *btv) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(btv->c.pci)); - ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + if (err < 0) + goto err_out_free; + input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_PCI; @@ -400,6 +403,7 @@ int bttv_input_init(struct bttv *btv) bttv_ir_stop(btv); btv->remote = NULL; err_out_free: + ir_input_free(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -411,6 +415,7 @@ void bttv_input_fini(struct bttv *btv) return; bttv_ir_stop(btv); + ir_input_free(btv->remote->dev); input_unregister_device(btv->remote->dev); kfree(btv->remote); btv->remote = NULL; diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 58dd39bc6787..cd135f01b9c1 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -197,7 +197,11 @@ int cx231xx_ir_init(struct cx231xx *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->board.ir_codes); + err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, + dev->board.ir_codes); + if (err < 0) + goto err_out_free; + input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_USB; @@ -222,6 +226,7 @@ int cx231xx_ir_init(struct cx231xx *dev) cx231xx_ir_stop(ir); dev->ir = NULL; err_out_free: + ir_input_free(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -236,6 +241,7 @@ int cx231xx_ir_fini(struct cx231xx *dev) return 0; cx231xx_ir_stop(ir); + ir_input_free(ir->input); input_unregister_device(ir->input); kfree(ir); diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index fea882d1fbcb..469e083dd5f8 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -377,7 +377,10 @@ int cx23885_input_init(struct cx23885_dev *dev) cx23885_boards[dev->board].name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); - ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + ret = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + if (ret < 0) + goto err_out_free; + input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_PCI; @@ -404,6 +407,7 @@ int cx23885_input_init(struct cx23885_dev *dev) cx23885_input_ir_stop(dev); dev->ir_input = NULL; err_out_free: + ir_input_free(input_dev); input_free_device(input_dev); kfree(ir); return ret; @@ -416,6 +420,7 @@ void cx23885_input_fini(struct cx23885_dev *dev) if (dev->ir_input == NULL) return; + ir_input_free(dev->ir_input->dev); input_unregister_device(dev->ir_input->dev); kfree(dev->ir_input); dev->ir_input = NULL; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 7b2066415d7e..92b8cdf9fb81 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -360,7 +360,10 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); - ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + if (err < 0) + goto err_out_free; + input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_PCI; @@ -390,6 +393,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) cx88_ir_stop(core, ir); core->ir = NULL; err_out_free: + ir_input_free(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -404,6 +408,7 @@ int cx88_ir_fini(struct cx88_core *core) return 0; cx88_ir_stop(core, ir); + ir_input_free(ir->input); input_unregister_device(ir->input); kfree(ir); diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 5550de9c669f..d96ec7c09dca 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -367,7 +367,11 @@ 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->board.ir_codes); + err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, + dev->board.ir_codes); + if (err < 0) + goto err_out_free; + input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_USB; @@ -392,6 +396,7 @@ int em28xx_ir_init(struct em28xx *dev) em28xx_ir_stop(ir); dev->ir = NULL; err_out_free: + ir_input_free(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -406,6 +411,7 @@ int em28xx_ir_fini(struct em28xx *dev) return 0; em28xx_ir_stop(ir); + ir_input_free(ir->input); input_unregister_device(ir->input); kfree(ir); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 9c6d0ae58b1f..64360d26b32d 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -437,7 +437,10 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_name(&client->dev)); /* init + register input device */ - ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); + err = ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); + if (err < 0) + goto err_out_free; + input_dev->id.bustype = BUS_I2C; input_dev->name = ir->name; input_dev->phys = ir->phys; @@ -456,6 +459,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; err_out_free: + ir_input_free(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -469,6 +473,7 @@ static int ir_remove(struct i2c_client *client) cancel_delayed_work_sync(&ir->work); /* unregister device */ + ir_input_free(ir->input); input_unregister_device(ir->input); /* free memory */ diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 439f3d54d009..744918b1cd47 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -652,7 +652,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); - ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + if (err < 0) + goto err_out_free; + input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_PCI; @@ -683,6 +686,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa7134_ir_stop(dev); dev->remote = NULL; err_out_free: + ir_input_free(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -694,6 +698,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) return; saa7134_ir_stop(dev); + ir_input_free(dev->remote->dev); input_unregister_device(dev->remote->dev); kfree(dev->remote); dev->remote = NULL; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index cd21cb55d5d5..16b8f17bcfec 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -100,7 +100,7 @@ struct card_ir { /* Routines from ir-functions.c */ -void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, +int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, struct ir_scancode_table *ir_codes); void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir); void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, @@ -121,6 +121,7 @@ u32 ir_g_keycode_from_table(struct input_dev *input_dev, int ir_set_keycode_table(struct input_dev *input_dev, struct ir_scancode_table *rc_tab); +void ir_input_free(struct input_dev *input_dev); /* scancode->keycode map tables from ir-keymaps.c */ From f6fc50494027e913ff0159e43c593cd75f35ec7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Nov 2009 11:08:02 -0300 Subject: [PATCH 341/345] V4L/DVB (13538): ir-common: Use a dynamic keycode table Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-functions.c | 19 +++++--- drivers/media/common/ir-keytable.c | 75 +++++++++++++++++++++++++++++ include/media/ir-common.h | 6 +++ 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index b31bd27da374..e616f624ceaa 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -59,12 +59,20 @@ int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, { ir->ir_type = ir_type; - /* FIXME: Add the proper code to dynamically allocate IR table */ + ir->keytable.size = ir_roundup_tablesize(ir_codes->size); + ir->keytable.scan = kzalloc(ir->keytable.size * + sizeof(struct ir_scancode), GFP_KERNEL); + if (!ir->keytable.scan) + return -ENOMEM; - ir_set_keycode_table(dev, ir_codes); + IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", + ir->keytable.size, + ir->keytable.size * sizeof(ir->keytable.scan)); + + ir_copy_table(&ir->keytable, ir_codes); + ir_set_keycode_table(dev, &ir->keytable); clear_bit(0, dev->keybit); - set_bit(EV_KEY, dev->evbit); if (repeat) set_bit(EV_REP, dev->evbit); @@ -73,11 +81,6 @@ int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, } EXPORT_SYMBOL_GPL(ir_input_init); -void ir_input_free(struct input_dev *input_dev) -{ - /* FIXME: Add the proper code to free allocated resources */ -} -EXPORT_SYMBOL_GPL(ir_input_free); void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) { diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/common/ir-keytable.c index 65e352389b2d..6e3cc78c33b2 100644 --- a/drivers/media/common/ir-keytable.c +++ b/drivers/media/common/ir-keytable.c @@ -7,6 +7,68 @@ #include +#define IR_TAB_MIN_SIZE 32 + +/** + * ir_roundup_tablesize() - gets an optimum value for the table size + * @n_elems: minimum number of entries to store keycodes + * + * This routine is used to choose the keycode table size. + * + * In order to have some empty space for new keycodes, + * and knowing in advance that kmalloc allocates only power of two + * segments, it optimizes the allocated space to have some spare space + * for those new keycodes by using the maximum number of entries that + * will be effectively be allocated by kmalloc. + * In order to reduce the quantity of table resizes, it has a minimum + * table size of IR_TAB_MIN_SIZE. + */ +int ir_roundup_tablesize(int n_elems) +{ + size_t size; + + if (n_elems < IR_TAB_MIN_SIZE) + n_elems = IR_TAB_MIN_SIZE; + + /* + * As kmalloc only allocates sizes of power of two, get as + * much entries as possible for the allocated memory segment + */ + size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode)); + n_elems = size / sizeof(struct ir_scancode); + + return n_elems; +} + +/** + * ir_copy_table() - copies a keytable, discarding the unused entries + * @destin: destin table + * @origin: origin table + * + * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED + */ + +int ir_copy_table(struct ir_scancode_table *destin, + const struct ir_scancode_table *origin) +{ + int i, j = 0; + + for (i = 0; i < origin->size; i++) { + if (origin->scan[i].keycode != KEY_UNKNOWN && + origin->scan[i].keycode != KEY_RESERVED) { + memcpy(&destin->scan[j], &origin->scan[i], + sizeof(struct ir_scancode)); + j++; + } + } + destin->size = j; + + IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", j); + + return 0; +} + + /** * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table * @dev: the struct input_dev device descriptor @@ -152,3 +214,16 @@ int ir_set_keycode_table(struct input_dev *input_dev, return 0; } + +void ir_input_free(struct input_dev *dev) +{ + struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + + IR_dprintk(1, "Freed keycode table\n"); + + rc_tab->size = 0; + kfree(rc_tab->scan); + rc_tab->scan = NULL; +} +EXPORT_SYMBOL_GPL(ir_input_free); + diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 16b8f17bcfec..72df0467d2b9 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -54,6 +54,8 @@ struct ir_input_state { /* configuration */ int ir_type; + struct ir_scancode_table keytable; + /* key info */ u32 ir_key; /* ir scancode */ u32 keycode; /* linux key code */ @@ -121,6 +123,10 @@ u32 ir_g_keycode_from_table(struct input_dev *input_dev, int ir_set_keycode_table(struct input_dev *input_dev, struct ir_scancode_table *rc_tab); + +int ir_roundup_tablesize(int n_elems); +int ir_copy_table(struct ir_scancode_table *destin, + const struct ir_scancode_table *origin); void ir_input_free(struct input_dev *input_dev); /* scancode->keycode map tables from ir-keymaps.c */ From a53e21257171af42c9fa6aee417f7891744d6ebf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Dec 2009 15:44:30 -0300 Subject: [PATCH 342/345] V4L/DVB (13539): ir-common: add __func__ for debug messages Signed-off-by: Mauro Carvalho Chehab --- include/media/ir-common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 72df0467d2b9..452f6e86084d 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -29,7 +29,7 @@ extern int media_ir_debug; /* media_ir_debug level (0,1,2) */ #define IR_dprintk(level, fmt, arg...) if (media_ir_debug >= level) \ - printk(KERN_DEBUG fmt , ## arg) + printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) #define IR_TYPE_RC5 1 #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ From 7fee03e487e87a196deb5602ee3c7676511995c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Dec 2009 15:56:47 -0300 Subject: [PATCH 343/345] V4L/DVB (13540): ir-common: Cleanup get key evdev code The same loop to seek for a key were used on different places. Also, no spinlock were protecting it to avoid the risk of replacing a keycode while seeking for a new code. This cleanup does: - create an unique function to seek for a code; - adds an spinlock to protect the table lookup; - remove some unused code; - simplifies to code to make it easier to understand. Basically no change in behavior should be noticed after this patch. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keytable.c | 135 ++++++++++++++++------------- include/media/ir-common.h | 2 + 2 files changed, 76 insertions(+), 61 deletions(-) diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/common/ir-keytable.c index 6e3cc78c33b2..b06f023ca760 100644 --- a/drivers/media/common/ir-keytable.c +++ b/drivers/media/common/ir-keytable.c @@ -9,6 +9,38 @@ #define IR_TAB_MIN_SIZE 32 +/** + * ir_seek_table() - returns the element order on the table + * @rc_tab: the ir_scancode_table with the keymap to be used + * @scancode: the scancode that we're seeking + * + * This routine is used by the input routines when a key is pressed at the + * IR. The scancode is received and needs to be converted into a keycode. + * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the + * corresponding keycode from the table. + */ +static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode) +{ + int rc; + unsigned long flags; + struct ir_scancode *keymap = rc_tab->scan; + + spin_lock_irqsave(&rc_tab->lock, flags); + + /* FIXME: replace it by a binary search */ + + for (rc = 0; rc < rc_tab->size; rc++) + if (keymap[rc].scancode == scancode) + goto exit; + + /* Not found */ + rc = -EINVAL; + +exit: + spin_unlock_irqrestore(&rc_tab->lock, flags); + return rc; +} + /** * ir_roundup_tablesize() - gets an optimum value for the table size * @n_elems: minimum number of entries to store keycodes @@ -54,21 +86,20 @@ int ir_copy_table(struct ir_scancode_table *destin, int i, j = 0; for (i = 0; i < origin->size; i++) { - if (origin->scan[i].keycode != KEY_UNKNOWN && - origin->scan[i].keycode != KEY_RESERVED) { - memcpy(&destin->scan[j], &origin->scan[i], - sizeof(struct ir_scancode)); - j++; - } + if (origin->scan[i].keycode == KEY_UNKNOWN || + origin->scan[i].keycode == KEY_RESERVED) + continue; + + memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode)); + j++; } destin->size = j; - IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", j); + IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); return 0; } - /** * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table * @dev: the struct input_dev device descriptor @@ -81,28 +112,14 @@ int ir_copy_table(struct ir_scancode_table *destin, static int ir_getkeycode(struct input_dev *dev, int scancode, int *keycode) { - int i; + int elem; struct ir_scancode_table *rc_tab = input_get_drvdata(dev); - struct ir_scancode *keymap = rc_tab->scan; - /* See if we can match the raw key code. */ - for (i = 0; i < rc_tab->size; i++) - if (keymap[i].scancode == scancode) { - *keycode = keymap[i].keycode; - return 0; - } - - /* - * If is there extra space, returns KEY_RESERVED, - * otherwise, input core won't let ir_setkeycode - * to work - */ - for (i = 0; i < rc_tab->size; i++) - if (keymap[i].keycode == KEY_RESERVED || - keymap[i].keycode == KEY_UNKNOWN) { - *keycode = KEY_RESERVED; - return 0; - } + elem = ir_seek_table(rc_tab, scancode); + if (elem >= 0) { + *keycode = rc_tab->scan[elem].keycode; + return 0; + } return -EINVAL; } @@ -120,40 +137,33 @@ static int ir_getkeycode(struct input_dev *dev, static int ir_setkeycode(struct input_dev *dev, int scancode, int keycode) { - int i; + int rc = 0; struct ir_scancode_table *rc_tab = input_get_drvdata(dev); struct ir_scancode *keymap = rc_tab->scan; + unsigned long flags; /* Search if it is replacing an existing keycode */ - for (i = 0; i < rc_tab->size; i++) - if (keymap[i].scancode == scancode) { - keymap[i].keycode = keycode; - return 0; - } + rc = ir_seek_table(rc_tab, scancode); + if (rc <0) + return rc; - /* Search if is there a clean entry. If so, use it */ - for (i = 0; i < rc_tab->size; i++) - if (keymap[i].keycode == KEY_RESERVED || - keymap[i].keycode == KEY_UNKNOWN) { - keymap[i].scancode = scancode; - keymap[i].keycode = keycode; - return 0; - } + IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", + rc, scancode, keycode); - /* - * FIXME: Currently, it is not possible to increase the size of - * scancode table. For it to happen, one possibility - * would be to allocate a table with key_map_size + 1, - * copying data, appending the new key on it, and freeing - * the old one - or maybe just allocating some spare space - */ + clear_bit(keymap[rc].keycode, dev->keybit); - return -EINVAL; + spin_lock_irqsave(&rc_tab->lock, flags); + keymap[rc].keycode = keycode; + spin_unlock_irqrestore(&rc_tab->lock, flags); + + set_bit(keycode, dev->keybit); + + return 0; } /** * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode - * @rc_tab: the ir_scancode_table with the keymap to be used + * @input_dev: the struct input_dev descriptor of the device * @scancode: the scancode that we're seeking * * This routine is used by the input routines when a key is pressed at the @@ -163,22 +173,23 @@ static int ir_setkeycode(struct input_dev *dev, */ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) { - int i; struct ir_scancode_table *rc_tab = input_get_drvdata(dev); struct ir_scancode *keymap = rc_tab->scan; + int elem; - for (i = 0; i < rc_tab->size; i++) - if (keymap[i].scancode == scancode) { - IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", - dev->name, scancode, keymap[i].keycode); + elem = ir_seek_table(rc_tab, scancode); + if (elem >= 0) { + IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", + dev->name, scancode, keymap[elem].keycode); - return keymap[i].keycode; - } + return rc_tab->scan[elem].keycode; + } printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n", dev->name, scancode); - return KEY_UNKNOWN; + /* Reports userspace that an unknown keycode were got */ + return KEY_RESERVED; } /** @@ -188,8 +199,8 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) * @rc_tab: the struct ir_scancode_table table of scancode/keymap * * This routine is used to initialize the input infrastructure to work with - * an IR. It requires that the caller initializes the input_dev struct with - * some fields: name, + * an IR. + * It should be called before registering the IR device. */ int ir_set_keycode_table(struct input_dev *input_dev, struct ir_scancode_table *rc_tab) @@ -197,6 +208,8 @@ int ir_set_keycode_table(struct input_dev *input_dev, struct ir_scancode *keymap = rc_tab->scan; int i; + spin_lock_init(&rc_tab->lock); + if (rc_tab->scan == NULL || !rc_tab->size) return -EINVAL; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 452f6e86084d..e41a99ee353e 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -26,6 +26,7 @@ #include #include #include +#include extern int media_ir_debug; /* media_ir_debug level (0,1,2) */ #define IR_dprintk(level, fmt, arg...) if (media_ir_debug >= level) \ @@ -43,6 +44,7 @@ struct ir_scancode { struct ir_scancode_table { struct ir_scancode *scan; int size; + spinlock_t lock; }; #define RC5_START(x) (((x)>>12)&3) From 92fda216b439932bf7511e6381bbe1d42ba98875 Mon Sep 17 00:00:00 2001 From: David Wong Date: Thu, 3 Dec 2009 10:57:02 -0300 Subject: [PATCH 344/345] V4L/DVB (13541): atbm8830: replace 64-bit division and floating point usage Randy Dunlap wrote: > On Mon, 30 Nov 2009 10:07:21 -0800 Randy Dunlap wrote: > >> Stephen Rothwell wrote: >>> Hi all, >>> >>> Changes since 20091127: >>> >>> The v4l-dvb tree lost its conflict. >> >> on i386 (X86_32): >> >> a 'double' variable is used, causing: >> >> ERROR: "__floatunsidf" [drivers/media/common/tuners/max2165.ko] undefined! >> ERROR: "__adddf3" [drivers/media/common/tuners/max2165.ko] undefined! >> ERROR: "__fixunsdfsi" [drivers/media/common/tuners/max2165.ko] undefined! > > > linux-next-20091202: > > still have this one (above) and similar with > drivers/media/dvb/frontends/atbm8830.c: > > drivers/built-in.o: In function `atbm8830_init': > atbm8830.c:(.text+0x9012f9): undefined reference to `__udivdi3' > atbm8830.c:(.text+0x901384): undefined reference to `__floatunsidf' > atbm8830.c:(.text+0x901395): undefined reference to `__muldf3' > atbm8830.c:(.text+0x9013a5): undefined reference to `__floatunsidf' > atbm8830.c:(.text+0x9013b2): undefined reference to `__divdf3' > atbm8830.c:(.text+0x9013c3): undefined reference to `__muldf3' > atbm8830.c:(.text+0x9013cd): undefined reference to `__fixunsdfsi' > > --- > ~Randy > -- > To unsubscribe from this list: send the line "unsubscribe linux-media" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html This patch replace 64-bit division by do_div() macro and remove usage of floating point variable Signed-off-by: David T. L. Wong Acked-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/atbm8830.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c index d77684893d99..59881a5944eb 100644 --- a/drivers/media/dvb/frontends/atbm8830.c +++ b/drivers/media/dvb/frontends/atbm8830.c @@ -19,6 +19,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include "dvb_frontend.h" #include "atbm8830.h" @@ -102,8 +103,12 @@ static inline int atbm8830_reglatch_lock(struct atbm_state *priv, int lock) static int set_osc_freq(struct atbm_state *priv, u32 freq /*in kHz*/) { u32 val; + u64 t; - val = (u64)0x100000 * freq / 30400; + /* 0x100000 * freq / 30.4MHz */ + t = (u64)0x100000 * freq; + do_div(t, 30400); + val = t; atbm8830_write_reg(priv, REG_OSC_CLK, val); atbm8830_write_reg(priv, REG_OSC_CLK + 1, val >> 8); @@ -116,14 +121,18 @@ static int set_if_freq(struct atbm_state *priv, u32 freq /*in kHz*/) { u32 fs = priv->config->osc_clk_freq; - double t; + u64 t; u32 val; u8 dat; - t = 2 * 3.141593 * (freq - fs) / fs * (1 << 22); - val = t; - if (freq != 0) { + /* 2 * PI * (freq - fs) / fs * (2 ^ 22) */ + t = (u64) 2 * 31416 * (freq - fs); + t <<= 22; + do_div(t, fs); + do_div(t, 1000); + val = t; + atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 1); atbm8830_write_reg(priv, REG_IF_FREQ, val); atbm8830_write_reg(priv, REG_IF_FREQ+1, val >> 8); From e97f4677961f68e29bd906022ebf60a6df7f530a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 4 Dec 2009 17:17:47 -0300 Subject: [PATCH 345/345] V4L/DVB (13542): ir-keytable: Allow dynamic table change Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keytable.c | 213 +++++++++++++++++++++++++++-- 1 file changed, 200 insertions(+), 13 deletions(-) diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/common/ir-keytable.c index b06f023ca760..26ce5bc2fdd5 100644 --- a/drivers/media/common/ir-keytable.c +++ b/drivers/media/common/ir-keytable.c @@ -8,6 +8,7 @@ #include #define IR_TAB_MIN_SIZE 32 +#define IR_TAB_MAX_SIZE 1024 /** * ir_seek_table() - returns the element order on the table @@ -121,7 +122,154 @@ static int ir_getkeycode(struct input_dev *dev, return 0; } - return -EINVAL; + /* + * Scancode not found and table can't be expanded + */ + if (elem < 0 && rc_tab->size == IR_TAB_MAX_SIZE) + return -EINVAL; + + /* + * If is there extra space, returns KEY_RESERVED, + * otherwise, input core won't let ir_setkeycode to work + */ + *keycode = KEY_RESERVED; + return 0; +} + + +/** + * ir_is_resize_needed() - Check if the table needs rezise + * @table: keycode table that may need to resize + * @n_elems: minimum number of entries to store keycodes + * + * Considering that kmalloc uses power of two storage areas, this + * routine detects if the real alloced size will change. If not, it + * just returns without doing nothing. Otherwise, it will extend or + * reduce the table size to meet the new needs. + * + * It returns 0 if no resize is needed, 1 otherwise. + */ +static int ir_is_resize_needed(struct ir_scancode_table *table, int n_elems) +{ + int cur_size = ir_roundup_tablesize(table->size); + int new_size = ir_roundup_tablesize(n_elems); + + if (cur_size == new_size) + return 0; + + /* Resize is needed */ + return 1; +} + +/** + * ir_delete_key() - remove a keycode from the table + * @rc_tab: keycode table + * @elem: element to be removed + * + */ +static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem) +{ + unsigned long flags = 0; + int newsize = rc_tab->size - 1; + int resize = ir_is_resize_needed(rc_tab, newsize); + struct ir_scancode *oldkeymap = rc_tab->scan; + struct ir_scancode *newkeymap; + + if (resize) { + newkeymap = kzalloc(ir_roundup_tablesize(newsize) * + sizeof(*newkeymap), GFP_ATOMIC); + + /* There's no memory for resize. Keep the old table */ + if (!newkeymap) + resize = 0; + } + + if (!resize) { + newkeymap = oldkeymap; + + /* We'll modify the live table. Lock it */ + spin_lock_irqsave(&rc_tab->lock, flags); + } + + /* + * Copy the elements before the one that will be deleted + * if (!resize), both oldkeymap and newkeymap points + * to the same place, so, there's no need to copy + */ + if (resize && elem > 0) + memcpy(newkeymap, oldkeymap, + elem * sizeof(*newkeymap)); + + /* + * Copy the other elements overwriting the element to be removed + * This operation applies to both resize and non-resize case + */ + if (elem < newsize) + memcpy(&newkeymap[elem], &oldkeymap[elem + 1], + (newsize - elem) * sizeof(*newkeymap)); + + if (resize) { + /* + * As the copy happened to a temporary table, only here + * it needs to lock while replacing the table pointers + * to use the new table + */ + spin_lock_irqsave(&rc_tab->lock, flags); + rc_tab->size = newsize; + rc_tab->scan = newkeymap; + spin_unlock_irqrestore(&rc_tab->lock, flags); + + /* Frees the old keytable */ + kfree(oldkeymap); + } else { + rc_tab->size = newsize; + spin_unlock_irqrestore(&rc_tab->lock, flags); + } +} + +/** + * ir_insert_key() - insert a keycode at the table + * @rc_tab: keycode table + * @scancode: the desired scancode + * @keycode: the keycode to be retorned. + * + */ +static int ir_insert_key(struct ir_scancode_table *rc_tab, + int scancode, int keycode) +{ + unsigned long flags; + int elem = rc_tab->size; + int newsize = rc_tab->size + 1; + int resize = ir_is_resize_needed(rc_tab, newsize); + struct ir_scancode *oldkeymap = rc_tab->scan; + struct ir_scancode *newkeymap; + + if (resize) { + newkeymap = kzalloc(ir_roundup_tablesize(newsize) * + sizeof(*newkeymap), GFP_ATOMIC); + if (!newkeymap) + return -ENOMEM; + + memcpy(newkeymap, oldkeymap, + rc_tab->size * sizeof(*newkeymap)); + } else + newkeymap = oldkeymap; + + /* Stores the new code at the table */ + IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", + rc_tab->size, scancode, keycode); + + spin_lock_irqsave(&rc_tab->lock, flags); + rc_tab->size = newsize; + if (resize) { + rc_tab->scan = newkeymap; + kfree(oldkeymap); + } + newkeymap[elem].scancode = scancode; + newkeymap[elem].keycode = keycode; + spin_unlock_irqrestore(&rc_tab->lock, flags); + + return 0; } /** @@ -142,20 +290,59 @@ static int ir_setkeycode(struct input_dev *dev, struct ir_scancode *keymap = rc_tab->scan; unsigned long flags; - /* Search if it is replacing an existing keycode */ + /* + * Handle keycode table deletions + * + * If userspace is adding a KEY_UNKNOWN or KEY_RESERVED, + * deal as a trial to remove an existing scancode attribution + * if table become too big, reduce it to save space + */ + if (keycode == KEY_UNKNOWN || keycode == KEY_RESERVED) { + rc = ir_seek_table(rc_tab, scancode); + if (rc < 0) + return 0; + + IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", rc, scancode); + clear_bit(keymap[rc].keycode, dev->keybit); + ir_delete_key(rc_tab, rc); + + return 0; + } + + /* + * Handle keycode replacements + * + * If the scancode exists, just replace by the new value + */ rc = ir_seek_table(rc_tab, scancode); - if (rc <0) + if (rc >= 0) { + IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", + rc, scancode, keycode); + + clear_bit(keymap[rc].keycode, dev->keybit); + + spin_lock_irqsave(&rc_tab->lock, flags); + keymap[rc].keycode = keycode; + spin_unlock_irqrestore(&rc_tab->lock, flags); + + set_bit(keycode, dev->keybit); + + return 0; + } + + /* + * Handle new scancode inserts + * + * reallocate table if needed and insert a new keycode + */ + + /* Avoid growing the table indefinitely */ + if (rc_tab->size + 1 > IR_TAB_MAX_SIZE) + return -EINVAL; + + rc = ir_insert_key(rc_tab, scancode, keycode); + if (rc < 0) return rc; - - IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", - rc, scancode, keycode); - - clear_bit(keymap[rc].keycode, dev->keybit); - - spin_lock_irqsave(&rc_tab->lock, flags); - keymap[rc].keycode = keycode; - spin_unlock_irqrestore(&rc_tab->lock, flags); - set_bit(keycode, dev->keybit); return 0;