diff options
Diffstat (limited to 'linux')
187 files changed, 14948 insertions, 2422 deletions
diff --git a/linux/Documentation/video4linux/CARDLIST.cx23885 b/linux/Documentation/video4linux/CARDLIST.cx23885 index 91aa3c0f0..948e43610 100644 --- a/linux/Documentation/video4linux/CARDLIST.cx23885 +++ b/linux/Documentation/video4linux/CARDLIST.cx23885 @@ -16,3 +16,7 @@ 15 -> TeVii S470 [d470:9022] 16 -> DVBWorld DVB-S2 2005 [0001:2005] 17 -> NetUP Dual DVB-S2 CI [1b55:2a2c] + 18 -> Hauppauge WinTV-HVR1270 [0070:2211] + 19 -> Hauppauge WinTV-HVR1275 [0070:2215] + 20 -> Hauppauge WinTV-HVR1255 [0070:2251] + 21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295] diff --git a/linux/Documentation/video4linux/CARDLIST.cx88 b/linux/Documentation/video4linux/CARDLIST.cx88 index 71e9db0b2..80527b292 100644 --- a/linux/Documentation/video4linux/CARDLIST.cx88 +++ b/linux/Documentation/video4linux/CARDLIST.cx88 @@ -78,3 +78,4 @@ 77 -> TBS 8910 DVB-S [8910:8888] 78 -> Prof 6200 DVB-S [b022:3022] 79 -> Terratec Cinergy HT PCI MKII [153b:1177] + 80 -> Hauppauge WinTV-IR Only [0070:9290] diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index 8a15e2b83..112ff4f4f 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -124,10 +124,10 @@ 123 -> Beholder BeholdTV 407 [0000:4070] 124 -> Beholder BeholdTV 407 FM [0000:4071] 125 -> Beholder BeholdTV 409 [0000:4090] -126 -> Beholder BeholdTV 505 FM/RDS [0000:5051,0000:505B,5ace:5050] -127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090] +126 -> Beholder BeholdTV 505 FM [5ace:5050] +127 -> Beholder BeholdTV 507 FM / BeholdTV 509 FM [5ace:5070,5ace:5090] 128 -> Beholder BeholdTV Columbus TVFM [0000:5201] -129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093] +129 -> Beholder BeholdTV 607 FM [5ace:6070] 130 -> Beholder BeholdTV M6 [5ace:6190] 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 132 -> Genius TVGO AM11MCE @@ -156,3 +156,14 @@ 155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid [0070:6706,0070:6708] 156 -> Hauppauge WinTV-HVR1110r3 [0070:6707,0070:6709,0070:670a] 157 -> Avermedia AVerTV Studio 507UA [1461:a11b] +158 -> AVerMedia Cardbus TV/Radio (E501R) [1461:b7e9] +159 -> Beholder BeholdTV 505 RDS [0000:505B] +160 -> Beholder BeholdTV 507 RDS [0000:5071] +161 -> Beholder BeholdTV 507 RDS [0000:507B] +162 -> Beholder BeholdTV 607 FM [5ace:6071] +163 -> Beholder BeholdTV 609 FM [5ace:6090] +164 -> Beholder BeholdTV 609 FM [5ace:6091] +165 -> Beholder BeholdTV 607 RDS [5ace:6072] +166 -> Beholder BeholdTV 607 RDS [5ace:6073] +167 -> Beholder BeholdTV 609 RDS [5ace:6092] +168 -> Beholder BeholdTV 609 RDS [5ace:6093] diff --git a/linux/Documentation/video4linux/CARDLIST.tuner b/linux/Documentation/video4linux/CARDLIST.tuner index 691d2f37d..22c1c5597 100644 --- a/linux/Documentation/video4linux/CARDLIST.tuner +++ b/linux/Documentation/video4linux/CARDLIST.tuner @@ -76,3 +76,4 @@ tuner=75 - Philips TEA5761 FM Radio tuner=76 - Xceive 5000 tuner tuner=77 - TCL tuner MF02GIP-5N-E tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner +tuner=79 - Philips PAL/SECAM multi (FM1216 MK5) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index e418a8fb9..1bb103fe9 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -178,6 +178,7 @@ spca506 06e1:a190 ADS Instant VCD ov534 06f8:3002 Hercules Blog Webcam ov534 06f8:3003 Hercules Dualpix HD Weblog sonixj 06f8:3004 Hercules Classic Silver +sonixj 06f8:3008 Hercules Deluxe Optical Glass spca508 0733:0110 ViewQuest VQ110 spca508 0130:0130 Clone Digital Webcam 11043 spca501 0733:0401 Intel Create and Share @@ -266,6 +267,11 @@ sonixj 0c45:60ec SN9C105+MO4000 sonixj 0c45:60fb Surfer NoName sonixj 0c45:60fc LG-LIC300 sonixj 0c45:60fe Microdia Audio +sonixj 0c45:6100 PC Camera (SN9C128) +sonixj 0c45:610a PC Camera (SN9C128) +sonixj 0c45:610b PC Camera (SN9C128) +sonixj 0c45:610c PC Camera (SN9C128) +sonixj 0c45:610e PC Camera (SN9C128) sonixj 0c45:6128 Microdia/Sonix SNP325 sonixj 0c45:612a Avant Camera sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix diff --git a/linux/Documentation/video4linux/pxa_camera.txt b/linux/Documentation/video4linux/pxa_camera.txt index b1137f9a5..4f6d0ca01 100644 --- a/linux/Documentation/video4linux/pxa_camera.txt +++ b/linux/Documentation/video4linux/pxa_camera.txt @@ -26,6 +26,55 @@ Global video workflow Once the last buffer is filled in, the QCI interface stops. + c) Capture global finite state machine schema + + +----+ +---+ +----+ + | DQ | | Q | | DQ | + | v | v | v + +-----------+ +------------------------+ + | STOP | | Wait for capture start | + +-----------+ Q +------------------------+ ++-> | QCI: stop | ------------------> | QCI: run | <------------+ +| | DMA: stop | | DMA: stop | | +| +-----------+ +-----> +------------------------+ | +| / | | +| / +---+ +----+ | | +|capture list empty / | Q | | DQ | | QCI Irq EOF | +| / | v | v v | +| +--------------------+ +----------------------+ | +| | DMA hotlink missed | | Capture running | | +| +--------------------+ +----------------------+ | +| | QCI: run | +-----> | QCI: run | <-+ | +| | DMA: stop | / | DMA: run | | | +| +--------------------+ / +----------------------+ | Other | +| ^ /DMA still | | channels | +| | capture list / running | DMA Irq End | not | +| | not empty / | | finished | +| | / v | yet | +| +----------------------+ +----------------------+ | | +| | Videobuf released | | Channel completed | | | +| +----------------------+ +----------------------+ | | ++-- | QCI: run | | QCI: run | --+ | + | DMA: run | | DMA: run | | + +----------------------+ +----------------------+ | + ^ / | | + | no overrun / | overrun | + | / v | + +--------------------+ / +----------------------+ | + | Frame completed | / | Frame overran | | + +--------------------+ <-----+ +----------------------+ restart frame | + | QCI: run | | QCI: stop | --------------+ + | DMA: run | | DMA: stop | + +--------------------+ +----------------------+ + + Legend: - each box is a FSM state + - each arrow is the condition to transition to another state + - an arrow with a comment is a mandatory transition (no condition) + - arrow "Q" means : a buffer was enqueued + - arrow "DQ" means : a buffer was dequeued + - "QCI: stop" means the QCI interface is not enabled + - "DMA: stop" means all 3 DMA channels are stopped + - "DMA: run" means at least 1 DMA channel is still running DMA usage --------- diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index 854808b67..d54c1e4c6 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -89,6 +89,11 @@ from dev (driver name followed by the bus_id, to be precise). If you set it up before calling v4l2_device_register then it will be untouched. If dev is NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register. +You can use v4l2_device_set_name() to set the name based on a driver name and +a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1, +etc. If the name ends with a digit, then it will insert a dash: cx18-0, +cx18-1, etc. This function returns the instance number. + The first 'dev' argument is normally the struct device pointer of a pci_dev, usb_interface or platform_device. It is rare for dev to be NULL, but it happens with ISA devices or when one device creates multiple PCI devices, thus making diff --git a/linux/arch/arm/mach-pxa/pcm990-baseboard.c b/linux/arch/arm/mach-pxa/pcm990-baseboard.c index 7a95c80ab..9ce1ef2e5 100644 --- a/linux/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/linux/arch/arm/mach-pxa/pcm990-baseboard.c @@ -22,46 +22,21 @@ #include <linux/irq.h> #include <linux/platform_device.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) -#include <linux/ide.h> -#endif #include <linux/i2c.h> #include <linux/pwm_backlight.h> #include <media/soc_camera.h> #include <asm/gpio.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) -#include <asm/arch/i2c.h> -#include <asm/arch/camera.h> -#else #include <mach/i2c.h> #include <mach/camera.h> -#endif #include <asm/mach/map.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) -#include <asm/arch/pxa-regs.h> -#include <asm/arch/audio.h> -#include <asm/arch/mmc.h> -#include <asm/arch/ohci.h> -#include <asm/arch/pcm990_baseboard.h> -#include <asm/arch/pxafb.h> -#include <asm/arch/mfp-pxa27x.h> -#else -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) -#include <mach/pxa-regs.h> -#else #include <mach/pxa27x.h> -#endif #include <mach/audio.h> #include <mach/mmc.h> #include <mach/ohci.h> #include <mach/pcm990_baseboard.h> #include <mach/pxafb.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) -#include <mach/mfp-pxa27x.h> -#endif -#endif #include "devices.h" #include "generic.h" @@ -402,15 +377,15 @@ struct pxacamera_platform_data pcm990_pxacamera_platform_data = { #include <linux/i2c/pca953x.h> static struct pca953x_platform_data pca9536_data = { - .gpio_base = NR_BUILTIN_GPIO + 1, + .gpio_base = NR_BUILTIN_GPIO, }; -static int gpio_bus_switch; +static int gpio_bus_switch = -EINVAL; static int pcm990_camera_set_bus_param(struct soc_camera_link *link, - unsigned long flags) + unsigned long flags) { - if (gpio_bus_switch <= 0) { + if (gpio_bus_switch < 0) { if (flags == SOCAM_DATAWIDTH_10) return 0; else @@ -429,25 +404,34 @@ static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link) { int ret; - if (!gpio_bus_switch) { - ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera"); + if (gpio_bus_switch < 0) { + ret = gpio_request(NR_BUILTIN_GPIO, "camera"); if (!ret) { - gpio_bus_switch = NR_BUILTIN_GPIO + 1; + gpio_bus_switch = NR_BUILTIN_GPIO; gpio_direction_output(gpio_bus_switch, 0); - } else - gpio_bus_switch = -EINVAL; + } } - if (gpio_bus_switch > 0) + if (gpio_bus_switch >= 0) return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10; else return SOCAM_DATAWIDTH_10; } +static void pcm990_camera_free_bus(struct soc_camera_link *link) +{ + if (gpio_bus_switch < 0) + return; + + gpio_free(gpio_bus_switch); + gpio_bus_switch = -EINVAL; +} + static struct soc_camera_link iclink = { .bus_id = 0, /* Must match with the camera ID above */ .query_bus_param = pcm990_camera_query_bus_param, .set_bus_param = pcm990_camera_set_bus_param, + .free_bus = pcm990_camera_free_bus, }; /* Board I2C devices. */ diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c index 912458f66..39e46919d 100644 --- a/linux/arch/sh/boards/board-ap325rxa.c +++ b/linux/arch/sh/boards/board-ap325rxa.c @@ -349,6 +349,7 @@ static int ov7725_power(struct device *dev, int mode) static struct ov772x_camera_info ov7725_info = { .buswidth = SOCAM_DATAWIDTH_8, .flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP, + .edgectrl = OV772X_AUTO_EDGECTRL(0xf, 0), .link = { .power = ov7725_power, }, diff --git a/linux/drivers/media/common/tuners/tuner-types.c b/linux/drivers/media/common/tuners/tuner-types.c index d83df3604..43afd30b0 100644 --- a/linux/drivers/media/common/tuners/tuner-types.c +++ b/linux/drivers/media/common/tuners/tuner-types.c @@ -579,6 +579,31 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = { }, }; +/* ------------ TUNER_PHILIPS_FM1216MK5 - Philips PAL ------------ */ + +static struct tuner_range tuner_fm1216mk5_pal_ranges[] = { + { 16 * 158.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 441.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 864.00 , 0xce, 0x04, }, +}; + +static struct tuner_params tuner_fm1216mk5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_fm1216mk5_pal_ranges, + .count = ARRAY_SIZE(tuner_fm1216mk5_pal_ranges), + .cb_first_if_lower_freq = 1, + .has_tda9887 = 1, + .port1_active = 1, + .port2_active = 1, + .port2_invert_for_secam_lc = 1, + .port1_fm_high_sensitivity = 1, + .default_top_mid = -2, + .default_top_secam_mid = -2, + .default_top_secam_high = -2, + }, +}; + /* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */ static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = { @@ -1695,6 +1720,11 @@ struct tunertype tuners[] = { .initdata = tua603x_agc112, .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, }, + [TUNER_PHILIPS_FM1216MK5] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FM1216 MK5)", + .params = tuner_fm1216mk5_params, + .count = ARRAY_SIZE(tuner_fm1216mk5_params), + }, }; EXPORT_SYMBOL(tuners); diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c index bd010379b..cb5b577fa 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -34,7 +34,7 @@ MODULE_PARM_DESC(debug, "enable verbose debug messages"); static int no_poweroff; module_param(no_poweroff, int, 0644); -MODULE_PARM_DESC(debug, "0 (default) powers device off when not used.\n" +MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n" "1 keep device energized and with tuner ready all the times.\n" " Faster, but consumes more power and keeps the device hotter\n"); @@ -276,7 +276,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) fname = firmware_name; tuner_dbg("Reading firmware %s\n", fname); - rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev); + rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent); if (rc < 0) { if (rc == -ENOENT) tuner_err("Error: firmware %s not found.\n", diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 39c415df0..6626d19b3 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -3,6 +3,7 @@ * * Copyright (c) 2007 Xceive Corporation * Copyright (c) 2007 Steven Toth <stoth@linuxtv.org> + * Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.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 @@ -36,14 +37,20 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +static int no_poweroff; +module_param(no_poweroff, int, 0644); +MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n" + "\t\t1 keep device energized and with tuner ready all the times.\n" + "\t\tFaster, but consumes more power and keeps the device hotter"); + static DEFINE_MUTEX(xc5000_list_mutex); static LIST_HEAD(hybrid_tuner_instance_list); #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) -#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" -#define XC5000_DEFAULT_FIRMWARE_SIZE 12332 +#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" +#define XC5000_DEFAULT_FIRMWARE_SIZE 12401 struct xc5000_priv { struct tuner_i2c_props i2c_props; @@ -83,11 +90,11 @@ struct xc5000_priv { #define XREG_D_CODE 0x04 #define XREG_IF_OUT 0x05 #define XREG_SEEK_MODE 0x07 -#define XREG_POWER_DOWN 0x0A +#define XREG_POWER_DOWN 0x0A /* Obsolete */ #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */ #define XREG_SMOOTHEDCVBS 0x0E #define XREG_XTALFREQ 0x0F -#define XREG_FINERFFREQ 0x10 +#define XREG_FINERFREQ 0x10 #define XREG_DDIMODE 0x11 #define XREG_ADC_ENV 0x00 @@ -100,6 +107,7 @@ struct xc5000_priv { #define XREG_VERSION 0x07 #define XREG_PRODUCT_ID 0x08 #define XREG_BUSY 0x09 +#define XREG_BUILD 0x0D /* Basic firmware description. This will remain with @@ -191,27 +199,36 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { {"FM Radio-INPUT1", 0x0208, 0x9002} }; -static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); -static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); -static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len); -static void xc5000_TunerReset(struct dvb_frontend *fe); +static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); +static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); +static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); +static int xc5000_TunerReset(struct dvb_frontend *fe); static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) { - return xc5000_writeregs(priv, buf, len) - ? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS; + struct i2c_msg msg = { .addr = priv->i2c_props.addr, + .flags = 0, .buf = buf, .len = len }; + + if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { + printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len); + return XC_RESULT_I2C_WRITE_FAILURE; + } + return XC_RESULT_SUCCESS; } +/* This routine is never used because the only time we read data from the + i2c bus is when we read registers, and we want that to be an atomic i2c + transaction in case we are on a multi-master bus */ static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) { - return xc5000_readregs(priv, buf, len) - ? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS; -} + struct i2c_msg msg = { .addr = priv->i2c_props.addr, + .flags = I2C_M_RD, .buf = buf, .len = len }; -static int xc_reset(struct dvb_frontend *fe) -{ - xc5000_TunerReset(fe); - return XC_RESULT_SUCCESS; + if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { + printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", len); + return -EREMOTEIO; + } + return 0; } static void xc_wait(int wait_ms) @@ -219,7 +236,7 @@ static void xc_wait(int wait_ms) msleep(wait_ms); } -static void xc5000_TunerReset(struct dvb_frontend *fe) +static int xc5000_TunerReset(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; int ret; @@ -232,16 +249,21 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) priv->i2c_props.adap->algo_data, DVB_FRONTEND_COMPONENT_TUNER, XC5000_TUNER_RESET, 0); - if (ret) + if (ret) { printk(KERN_ERR "xc5000: reset failed\n"); - } else + return XC_RESULT_RESET_FAILURE; + } + } else { printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n"); + return XC_RESULT_RESET_FAILURE; + } + return XC_RESULT_SUCCESS; } static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) { u8 buf[4]; - int WatchDogTimer = 5; + int WatchDogTimer = 100; int result; buf[0] = (regAddr >> 8) & 0xFF; @@ -263,7 +285,7 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) /* busy flag cleared */ break; } else { - xc_wait(100); /* wait 5 ms */ + xc_wait(5); /* wait 5 ms */ WatchDogTimer--; } } @@ -276,25 +298,6 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) return result; } -static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData) -{ - u8 buf[2]; - int result; - - buf[0] = (regAddr >> 8) & 0xFF; - buf[1] = regAddr & 0xFF; - result = xc_send_i2c_data(priv, buf, 2); - if (result != XC_RESULT_SUCCESS) - return result; - - result = xc_read_i2c_data(priv, buf, 2); - if (result != XC_RESULT_SUCCESS) - return result; - - *i2cData = buf[0] * 256 + buf[1]; - return result; -} - static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) { struct xc5000_priv *priv = fe->tuner_priv; @@ -309,7 +312,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) len = i2c_sequence[index] * 256 + i2c_sequence[index+1]; if (len == 0x0000) { /* RESET command */ - result = xc_reset(fe); + result = xc5000_TunerReset(fe); index += 2; if (result != XC_RESULT_SUCCESS) return result; @@ -371,15 +374,6 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, return ret; } -static int xc_shutdown(struct xc5000_priv *priv) -{ - return XC_RESULT_SUCCESS; - /* Fixme: cannot bring tuner back alive once shutdown - * without reloading the driver modules. - * return xc_write_reg(priv, XREG_POWER_DOWN, 0); - */ -} - static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) { dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, @@ -408,22 +402,14 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) freq_code = (u16)(freq_hz / 15625); - return xc_write_reg(priv, XREG_RF_FREQ, freq_code); + /* Starting in firmware version 1.1.44, Xceive recommends using the + FINERFREQ for all normal tuning (the doc indicates reg 0x03 should + only be used for fast scanning for channel lock) */ + return xc_write_reg(priv, XREG_FINERFREQ, freq_code); } #if 0 /* We'll probably need these for analog support */ -static int xc_FineTune_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) -{ - u16 freq_code = (u16)(freq_hz / 15625); - - if ((freq_hz > xc5000_tuner_ops.info.frequency_max) || - (freq_hz < xc5000_tuner_ops.info.frequency_min)) - return XC_RESULT_OUT_OF_RANGE; - - return xc_write_reg(priv, XREG_FINERFFREQ, freq_code); -} - static int xc_set_Xtal_frequency(struct xc5000_priv *priv, u32 xtalFreqInKHz) { u16 xtalRatio = (32000 * 0x8000)/xtalFreqInKHz; @@ -443,7 +429,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz) static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope) { - return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope); + return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope); } static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) @@ -452,8 +438,8 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) u16 regData; u32 tmp; - result = xc_read_reg(priv, XREG_FREQ_ERROR, ®Data); - if (result) + result = xc5000_readreg(priv, XREG_FREQ_ERROR, ®Data); + if (result != XC_RESULT_SUCCESS) return result; tmp = (u32)regData; @@ -463,7 +449,7 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status) { - return xc_read_reg(priv, XREG_LOCK, lock_status); + return xc5000_readreg(priv, XREG_LOCK, lock_status); } static int xc_get_version(struct xc5000_priv *priv, @@ -473,8 +459,8 @@ static int xc_get_version(struct xc5000_priv *priv, u16 data; int result; - result = xc_read_reg(priv, XREG_VERSION, &data); - if (result) + result = xc5000_readreg(priv, XREG_VERSION, &data); + if (result != XC_RESULT_SUCCESS) return result; (*hw_majorversion) = (data >> 12) & 0x0F; @@ -485,13 +471,18 @@ static int xc_get_version(struct xc5000_priv *priv, return 0; } +static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev) +{ + return xc5000_readreg(priv, XREG_BUILD, buildrev); +} + static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) { u16 regData; int result; - result = xc_read_reg(priv, XREG_HSYNC_FREQ, ®Data); - if (result) + result = xc5000_readreg(priv, XREG_HSYNC_FREQ, ®Data); + if (result != XC_RESULT_SUCCESS) return result; (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100; @@ -500,12 +491,12 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines) { - return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines); + return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines); } static int xc_get_quality(struct xc5000_priv *priv, u16 *quality) { - return xc_read_reg(priv, XREG_QUALITY, quality); + return xc5000_readreg(priv, XREG_QUALITY, quality); } static u16 WaitForLock(struct xc5000_priv *priv) @@ -523,7 +514,9 @@ static u16 WaitForLock(struct xc5000_priv *priv) return lockState; } -static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) +#define XC_TUNE_ANALOG 0 +#define XC_TUNE_DIGITAL 1 +static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode) { int found = 0; @@ -532,8 +525,10 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) return 0; - if (WaitForLock(priv) == 1) - found = 1; + if (mode == XC_TUNE_ANALOG) { + if (WaitForLock(priv) == 1) + found = 1; + } return found; } @@ -555,32 +550,7 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) } *val = (bval[0] << 8) | bval[1]; - return 0; -} - -static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) -{ - struct i2c_msg msg = { .addr = priv->i2c_props.addr, - .flags = 0, .buf = buf, .len = len }; - - if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { - printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", - (int)len); - return -EREMOTEIO; - } - return 0; -} - -static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) -{ - struct i2c_msg msg = { .addr = priv->i2c_props.addr, - .flags = I2C_M_RD, .buf = buf, .len = len }; - - if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { - printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", (int)len); - return -EREMOTEIO; - } - return 0; + return XC_RESULT_SUCCESS; } static int xc5000_fwupload(struct dvb_frontend *fe) @@ -594,13 +564,13 @@ static int xc5000_fwupload(struct dvb_frontend *fe) XC5000_DEFAULT_FIRMWARE); ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, - &priv->i2c_props.adap->dev); + priv->i2c_props.adap->dev.parent); if (ret) { printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); ret = XC_RESULT_RESET_FAILURE; goto out; } else { - printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n", + printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n", fw->size); ret = XC_RESULT_SUCCESS; } @@ -609,8 +579,9 @@ static int xc5000_fwupload(struct dvb_frontend *fe) printk(KERN_ERR "xc5000: firmware incorrect size\n"); ret = XC_RESULT_RESET_FAILURE; } else { - printk(KERN_INFO "xc5000: firmware upload\n"); + printk(KERN_INFO "xc5000: firmware uploading...\n"); ret = xc_load_i2c_sequence(fe, fw->data); + printk(KERN_INFO "xc5000: firmware upload complete...\n"); } out: @@ -628,6 +599,7 @@ static void xc_debug_dump(struct xc5000_priv *priv) u16 quality; u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; + u16 fw_buildversion = 0; /* Wait for stats to stabilize. * Frame Lines needs two frame times after initial lock @@ -647,9 +619,10 @@ static void xc_debug_dump(struct xc5000_priv *priv) xc_get_version(priv, &hw_majorversion, &hw_minorversion, &fw_majorversion, &fw_minorversion); - dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n", + xc_get_buildversion(priv, &fw_buildversion); + dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n", hw_majorversion, hw_minorversion, - fw_majorversion, fw_minorversion); + fw_majorversion, fw_minorversion, fw_buildversion); xc_get_hsync_freq(priv, &hsync_freq_hz); dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz); @@ -667,27 +640,57 @@ 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); + dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); - switch (params->u.vsb.modulation) { - case VSB_8: - case VSB_16: - dprintk(1, "%s() VSB modulation\n", __func__); + if (fe->ops.info.type == FE_ATSC) { + dprintk(1, "%s() ATSC\n", __func__); + switch (params->u.vsb.modulation) { + case VSB_8: + case VSB_16: + dprintk(1, "%s() VSB modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_AIR; + priv->freq_hz = params->frequency - 1750000; + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + break; + case QAM_64: + case QAM_256: + case QAM_AUTO: + dprintk(1, "%s() QAM modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_CABLE; + priv->freq_hz = params->frequency - 1750000; + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + break; + default: + return -EINVAL; + } + } else if (fe->ops.info.type == FE_OFDM) { + dprintk(1, "%s() OFDM\n", __func__); + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + priv->freq_hz = params->frequency - 1750000; + break; + case BANDWIDTH_7_MHZ: + printk(KERN_ERR "xc5000 bandwidth 7MHz not supported\n"); + return -EINVAL; + case BANDWIDTH_8_MHZ: + priv->bandwidth = BANDWIDTH_8_MHZ; + priv->video_standard = DTV8; + priv->freq_hz = params->frequency - 2750000; + break; + default: + printk(KERN_ERR "xc5000 bandwidth not set!\n"); + return -EINVAL; + } priv->rf_mode = XC_RF_MODE_AIR; - priv->freq_hz = params->frequency - 1750000; - priv->bandwidth = BANDWIDTH_6_MHZ; - priv->video_standard = DTV6; - break; - case QAM_64: - case QAM_256: - case QAM_AUTO: - dprintk(1, "%s() QAM modulation\n", __func__); - priv->rf_mode = XC_RF_MODE_CABLE; - priv->freq_hz = params->frequency - 1750000; - priv->bandwidth = BANDWIDTH_6_MHZ; - priv->video_standard = DTV6; - break; - default: + } else { + printk(KERN_ERR "xc5000 modulation type not supported!\n"); return -EINVAL; } @@ -717,7 +720,7 @@ static int xc5000_set_params(struct dvb_frontend *fe, return -EIO; } - xc_tune_channel(priv, priv->freq_hz); + xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); if (debug) xc_debug_dump(priv); @@ -744,8 +747,6 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe) return ret; } -static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); - static int xc5000_set_analog_params(struct dvb_frontend *fe, struct analog_parameters *params) { @@ -826,7 +827,7 @@ tune_channel: return -EREMOTEIO; } - xc_tune_channel(priv, priv->freq_hz); + xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); if (debug) xc_debug_dump(priv); @@ -894,18 +895,18 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) static int xc5000_sleep(struct dvb_frontend *fe) { - struct xc5000_priv *priv = fe->tuner_priv; int ret; dprintk(1, "%s()\n", __func__); - /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized - * once shutdown without reloading the driver. Maybe I am not - * doing something right. - * - */ + /* Avoid firmware reload on slow devices */ + if (no_poweroff) + return 0; - ret = xc_shutdown(priv); + /* According to Xceive technical support, the "powerdown" register + was removed in newer versions of the firmware. The "supported" + way to sleep the tuner is to pull the reset pin low for 10ms */ + ret = xc5000_TunerReset(fe); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR "xc5000: %s() unable to shutdown tuner\n", @@ -1010,7 +1011,7 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, /* Check if firmware has been loaded. It is possible that another instance of the driver has loaded the firmware. */ - if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) + if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS) goto fail; switch (id) { diff --git a/linux/drivers/media/dvb/b2c2/flexcop-common.h b/linux/drivers/media/dvb/b2c2/flexcop-common.h index cee2956cb..9d66105d3 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-common.h +++ b/linux/drivers/media/dvb/b2c2/flexcop-common.h @@ -1,9 +1,7 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-common.h - common header file for device-specific source files also. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-common.h - common header file for device-specific source files + * see flexcop.c for copyright information */ #ifndef __FLEXCOP_COMMON_H__ #define __FLEXCOP_COMMON_H__ diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index f7afab594..3f485bf13 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -1,34 +1,27 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-fe-tuner.c - methods for attaching a frontend and controlling DiSEqC. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling + * see flexcop.c for copyright information */ #include <media/tuner.h> - #include "flexcop.h" - -#include "stv0299.h" -#include "mt352.h" -#include "nxt200x.h" -#include "bcm3510.h" -#include "stv0297.h" #include "mt312.h" -#include "lgdt330x.h" -#include "dvb-pll.h" -#include "tuner-simple.h" - +#include "stv0299.h" #include "s5h1420.h" #include "itd1000.h" - -#include "cx24123.h" #include "cx24113.h" - +#include "cx24123.h" #include "isl6421.h" +#include "mt352.h" +#include "bcm3510.h" +#include "nxt200x.h" +#include "dvb-pll.h" +#include "lgdt330x.h" +#include "tuner-simple.h" +#include "stv0297.h" /* lnb control */ - +#if defined(CONFIG_DVB_MT312_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct flexcop_device *fc = fe->dvb->priv; @@ -37,65 +30,62 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage v = fc->read_ibi_reg(fc, misc_204); switch (voltage) { - case SEC_VOLTAGE_OFF: - v.misc_204.ACPI1_sig = 1; - break; - case SEC_VOLTAGE_13: - v.misc_204.ACPI1_sig = 0; - v.misc_204.LNB_L_H_sig = 0; - break; - case SEC_VOLTAGE_18: - v.misc_204.ACPI1_sig = 0; - v.misc_204.LNB_L_H_sig = 1; - break; - default: - err("unknown SEC_VOLTAGE value"); - return -EINVAL; + case SEC_VOLTAGE_OFF: + v.misc_204.ACPI1_sig = 1; + break; + case SEC_VOLTAGE_13: + v.misc_204.ACPI1_sig = 0; + v.misc_204.LNB_L_H_sig = 0; + break; + case SEC_VOLTAGE_18: + v.misc_204.ACPI1_sig = 0; + v.misc_204.LNB_L_H_sig = 1; + break; + default: + err("unknown SEC_VOLTAGE value"); + return -EINVAL; } return fc->write_ibi_reg(fc, misc_204, v); } +#endif +#if defined(CONFIG_DVB_S5H1420_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) \ + || defined(CONFIG_DVB_MT312_MODULE) static int flexcop_sleep(struct dvb_frontend* fe) { struct flexcop_device *fc = fe->dvb->priv; -/* flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */ - if (fc->fe_sleep) return fc->fe_sleep(fe); - -/* v.misc_204.ACPI3_sig = 1; - fc->write_ibi_reg(fc,misc_204,v);*/ - return 0; } +#endif +/* SkyStar2 DVB-S rev 2.3 */ +#if defined(CONFIG_DVB_MT312_MODULE) static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) { - /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ +/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ struct flexcop_device *fc = fe->dvb->priv; flexcop_ibi_value v; u16 ax; v.raw = 0; - deb_tuner("tone = %u\n",tone); switch (tone) { - case SEC_TONE_ON: - ax = 0x01ff; - break; - case SEC_TONE_OFF: - ax = 0; - break; - default: - err("unknown SEC_TONE value"); - return -EINVAL; + case SEC_TONE_ON: + ax = 0x01ff; + break; + case SEC_TONE_OFF: + ax = 0; + break; + default: + err("unknown SEC_TONE value"); + return -EINVAL; } v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */ - v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax; v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax; - return fc->write_ibi_reg(fc,lnb_switch_freq_200,v); } @@ -110,17 +100,16 @@ static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data) static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data) { int i, par = 1, d; - for (i = 7; i >= 0; i--) { d = (data >> i) & 1; par ^= d; flexcop_diseqc_send_bit(fe, d); } - flexcop_diseqc_send_bit(fe, par); } -static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst) +static int flexcop_send_diseqc_msg(struct dvb_frontend *fe, + int len, u8 *msg, unsigned long burst) { int i; @@ -129,7 +118,6 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un for (i = 0; i < len; i++) flexcop_diseqc_send_byte(fe,msg[i]); - mdelay(16); if (burst != -1) { @@ -146,50 +134,110 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un return 0; } -static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) +static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *cmd) { return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0); } -static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +static int flexcop_diseqc_send_burst(struct dvb_frontend *fe, + fe_sec_mini_cmd_t minicmd) { return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd); } -/* dvb-s stv0299 */ -static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +static struct mt312_config skystar23_samsung_tbdu18132_config = { + .demod_address = 0x0e, +}; + +static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, + .len = sizeof(buf) }; + struct flexcop_device *fc = fe->dvb->priv; + div = (params->frequency + (125/2)) / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = (div >> 0) & 0xff; + buf[2] = 0x84 | ((div >> 10) & 0x60); + buf[3] = 0x80; + + if (params->frequency < 1550000) + buf[3] |= 0x02; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static void skystar2_rev23_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(mt312_attach, + &skystar23_samsung_tbdu18132_config, i2c); + if (fc->fe != NULL) { + struct dvb_frontend_ops *ops = &fc->fe->ops; + ops->tuner_ops.set_params \ + = skystar23_samsung_tbdu18132_tuner_set_params; + ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; + ops->diseqc_send_burst = flexcop_diseqc_send_burst; + ops->set_tone = flexcop_set_tone; + ops->set_voltage = flexcop_set_voltage; + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; + fc->dev_type = FC_SKY_REV23; + } +} +#endif + +/* SkyStar2 DVB-S rev 2.6 */ +#if defined(CONFIG_DVB_STV0299_MODULE) +static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe, + u32 srate, u32 ratio) { u8 aclk = 0; u8 bclk = 0; - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg (fe, 0x13, aclk); - stv0299_writereg (fe, 0x14, bclk); - stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + if (srate < 1500000) { + aclk = 0xb7; bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; bclk = 0x51; + } + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, ratio & 0xf0); return 0; } -static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) +static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { u8 buf[4]; u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct i2c_msg msg = { + .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; struct flexcop_device *fc = fe->dvb->priv; - div = params->frequency / 125; buf[0] = (div >> 8) & 0x7f; buf[1] = div & 0xff; - buf[2] = 0x84; /* 0xC4 */ + buf[2] = 0x84; /* 0xC4 */ buf[3] = 0x08; if (params->frequency < 1500000) @@ -203,48 +251,48 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv } static u8 samsung_tbmu24112_inittab[] = { - 0x01, 0x15, - 0x02, 0x30, - 0x03, 0x00, - 0x04, 0x7D, - 0x05, 0x35, - 0x06, 0x02, - 0x07, 0x00, - 0x08, 0xC3, - 0x0C, 0x00, - 0x0D, 0x81, - 0x0E, 0x23, - 0x0F, 0x12, - 0x10, 0x7E, - 0x11, 0x84, - 0x12, 0xB9, - 0x13, 0x88, - 0x14, 0x89, - 0x15, 0xC9, - 0x16, 0x00, - 0x17, 0x5C, - 0x18, 0x00, - 0x19, 0x00, - 0x1A, 0x00, - 0x1C, 0x00, - 0x1D, 0x00, - 0x1E, 0x00, - 0x1F, 0x3A, - 0x20, 0x2E, - 0x21, 0x80, - 0x22, 0xFF, - 0x23, 0xC1, - 0x28, 0x00, - 0x29, 0x1E, - 0x2A, 0x14, - 0x2B, 0x0F, - 0x2C, 0x09, - 0x2D, 0x05, - 0x31, 0x1F, - 0x32, 0x19, - 0x33, 0xFE, - 0x34, 0x93, - 0xff, 0xff, + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7D, + 0x05, 0x35, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0xC3, + 0x0C, 0x00, + 0x0D, 0x81, + 0x0E, 0x23, + 0x0F, 0x12, + 0x10, 0x7E, + 0x11, 0x84, + 0x12, 0xB9, + 0x13, 0x88, + 0x14, 0x89, + 0x15, 0xC9, + 0x16, 0x00, + 0x17, 0x5C, + 0x18, 0x00, + 0x19, 0x00, + 0x1A, 0x00, + 0x1C, 0x00, + 0x1D, 0x00, + 0x1E, 0x00, + 0x1F, 0x3A, + 0x20, 0x2E, + 0x21, 0x80, + 0x22, 0xFF, + 0x23, 0xC1, + 0x28, 0x00, + 0x29, 0x1E, + 0x2A, 0x14, + 0x2B, 0x0F, + 0x2C, 0x09, + 0x2D, 0x05, + 0x31, 0x1F, + 0x32, 0x19, + 0x33, 0xFE, + 0x34, 0x93, + 0xff, 0xff, }; static struct stv0299_config samsung_tbmu24112_config = { @@ -259,27 +307,136 @@ static struct stv0299_config samsung_tbmu24112_config = { .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, }; -/* dvb-t mt352 */ -static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) +static void skystar2_rev26_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) { - static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d }; - static u8 mt352_reset [] = { 0x50, 0x80 }; - static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; - static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 }; + fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); + if (fc->fe != NULL) { + struct dvb_frontend_ops *ops = &fc->fe->ops; + ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params; + ops->set_voltage = flexcop_set_voltage; + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; + } +} +#endif + +/* SkyStar2 DVB-S rev 2.7 */ +#if defined(CONFIG_DVB_S5H1420_MODULE) +static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { + .demod_address = 0x53, + .invert = 1, + .repeated_start_workaround = 1, + .serial_mpeg = 1, +}; + +static struct itd1000_config skystar2_rev2_7_itd1000_config = { + .i2c_address = 0x61, +}; + +static void skystar2_rev27_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + /* enable no_base_addr - no repeated start when reading */ + fc->fc_i2c_adap[0].no_base_addr = 1; + fc->fe = dvb_attach(s5h1420_attach, + &skystar2_rev2_7_s5h1420_config, i2c); + if (fc->fe != NULL) { + flexcop_ibi_value r108; + struct i2c_adapter *i2c_tuner \ + = s5h1420_get_tuner_i2c_adapter(fc->fe); + struct dvb_frontend_ops *ops = &fc->fe->ops; + + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; + + /* enable no_base_addr - no repeated start when reading */ + fc->fc_i2c_adap[2].no_base_addr = 1; + if (dvb_attach(isl6421_attach, fc->fe, + &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL) + err("ISL6421 could NOT be attached"); + else + info("ISL6421 successfully attached"); + + /* the ITD1000 requires a lower i2c clock - is it a problem ? */ + r108.raw = 0x00000506; + fc->write_ibi_reg(fc, tw_sm_c_108, r108); + if (i2c_tuner) { + if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, + &skystar2_rev2_7_itd1000_config) == NULL) + err("ITD1000 could NOT be attached"); + else + info("ITD1000 successfully attached"); + } + } else + fc->fc_i2c_adap[0].no_base_addr = 0; + /* for the next devices we need it again */ +} +#endif + +/* SkyStar2 rev 2.8 */ +#if defined(CONFIG_DVB_CX24123_MODULE) +static struct cx24123_config skystar2_rev2_8_cx24123_config = { + .demod_address = 0x55, + .dont_use_pll = 1, + .agc_callback = cx24113_agc_callback, +}; + +static const struct cx24113_config skystar2_rev2_8_cx24113_config = { + .i2c_addr = 0x54, + .xtal_khz = 10111, +}; + +static void skystar2_rev28_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(cx24123_attach, + &skystar2_rev2_8_cx24123_config, i2c); + if (fc->fe != NULL) { + struct i2c_adapter *i2c_tuner \ + = cx24123_get_tuner_i2c_adapter(fc->fe); + if (i2c_tuner != NULL) { + if (dvb_attach(cx24113_attach, fc->fe, + &skystar2_rev2_8_cx24113_config, + i2c_tuner) == NULL) + err("CX24113 could NOT be attached"); + else + info("CX24113 successfully attached"); + } + + fc->fc_i2c_adap[2].no_base_addr = 1; + if (dvb_attach(isl6421_attach, fc->fe, + &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL) + err("ISL6421 could NOT be attached"); + else + info("ISL6421 successfully attached"); + /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an + * IR-receiver (PIC16F818) - but the card has no input for that ??? */ + } +} +#endif + +/* AirStar DVB-T */ +#if defined(CONFIG_DVB_MT352_MODULE) +static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe) +{ + static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d }; + static u8 mt352_reset[] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 }; static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); udelay(2000); mt352_write(fe, mt352_reset, sizeof(mt352_reset)); mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - return 0; } -static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) +static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) { u32 div; unsigned char bs = 0; @@ -287,19 +444,20 @@ static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_fro if (buf_len < 5) return -EINVAL; - #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ +#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; - - if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09; - if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a; - if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08; + if (params->frequency >= 48000000 && params->frequency <= 154000000) \ + bs = 0x09; + if (params->frequency >= 161000000 && params->frequency <= 439000000) \ + bs = 0x0a; + if (params->frequency >= 447000000 && params->frequency <= 863000000) \ + bs = 0x08; pllbuf[0] = 0x61; pllbuf[1] = div >> 8; pllbuf[2] = div & 0xff; pllbuf[3] = 0xcc; pllbuf[4] = bs; - return 5; } @@ -308,70 +466,88 @@ static struct mt352_config samsung_tdtc9251dh0_config = { .demod_init = samsung_tdtc9251dh0_demod_init, }; -static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) +static void airstar_dvbt_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); + if (fc->fe != NULL) + fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; +} +#endif + +/* AirStar ATSC 1st generation */ +#if defined(CONFIG_DVB_BCM3510_MODULE) +static int flexcop_fe_request_firmware(struct dvb_frontend *fe, + const struct firmware **fw, char* name) { struct flexcop_device *fc = fe->dvb->priv; return request_firmware(fw, name, fc->dev); } -static struct lgdt330x_config air2pc_atsc_hd5000_config = { - .demod_address = 0x59, - .demod_chip = LGDT3303, - .serial_mpeg = 0x04, - .clock_polarity_flip = 1, -}; - -static struct nxt200x_config samsung_tbmv_config = { - .demod_address = 0x0a, -}; - static struct bcm3510_config air2pc_atsc_first_gen_config = { .demod_address = 0x0f, .request_firmware = flexcop_fe_request_firmware, }; -static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) +static void airstar_atsc1_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) { - u8 buf[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; - struct flexcop_device *fc = fe->dvb->priv; - - div = (params->frequency + (125/2)) / 125; - - buf[0] = (div >> 8) & 0x7f; - buf[1] = (div >> 0) & 0xff; - buf[2] = 0x84 | ((div >> 10) & 0x60); - buf[3] = 0x80; + fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); +} +#endif - if (params->frequency < 1550000) - buf[3] |= 0x02; +/* AirStar ATSC 2nd generation */ +#if defined(CONFIG_DVB_NXT200X_MODULE) +static struct nxt200x_config samsung_tbmv_config = { + .demod_address = 0x0a, +}; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1) - return -EIO; - return 0; +static void airstar_atsc2_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); + if (fc->fe != NULL) + dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, + DVB_PLL_SAMSUNG_TBMV); } +#endif -static struct mt312_config skystar23_samsung_tbdu18132_config = { - - .demod_address = 0x0e, +/* AirStar ATSC 3rd generation */ +#if defined(CONFIG_DVB_LGDT330X_MODULE) +static struct lgdt330x_config air2pc_atsc_hd5000_config = { + .demod_address = 0x59, + .demod_chip = LGDT3303, + .serial_mpeg = 0x04, + .clock_polarity_flip = 1, }; +static void airstar_atsc3_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); + if (fc->fe != NULL) { + dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, + TUNER_LG_TDVS_H06XF); + } +} +#endif + +/* CableStar2 DVB-C */ +#if defined(CONFIG_DVB_STV0297_MODULE) static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) + struct dvb_frontend_parameters *fep) { struct flexcop_device *fc = fe->dvb->priv; u8 buf[4]; u16 div; int ret; -/* 62.5 kHz * 10 */ +/* 62.5 kHz * 10 */ #define REF_FREQ 625 #define FREQ_OFFSET 36125 - div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10) / REF_FREQ; // 4 MHz = 4000 KHz + div = ((fep->frequency/1000 + FREQ_OFFSET) * 10) / REF_FREQ; +/* 4 MHz = 4000 KHz */ buf[0] = (u8)( div >> 8) & 0x7f; buf[1] = (u8) div & 0xff; @@ -384,11 +560,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */ buf[2] = 0x95; -// Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5 -// 47 - 153 0 * 0 0 0 0 0 1 0x01 -// 153 - 430 0 * 0 0 0 0 1 0 0x02 -// 430 - 822 0 * 0 0 1 0 0 0 0x08 -// 822 - 862 1 * 0 0 1 0 0 0 0x88 +/* Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5 + * 47 - 153 0 * 0 0 0 0 0 1 0x01 + * 153 - 430 0 * 0 0 0 0 1 0 0x02 + * 430 - 822 0 * 0 0 1 0 0 0 0x08 + * 822 - 862 1 * 0 0 1 0 0 0 0x88 */ if (fep->frequency <= 153000000) buf[3] = 0x01; else if (fep->frequency <= 430000000) buf[3] = 0x02; @@ -397,11 +573,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); - deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]); + deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n", fep->frequency, + buf[0], buf[1], buf[2], buf[3]); ret = fc->i2c_request(&fc->fc_i2c_adap[2], - FC_WRITE, 0x61, buf[0], &buf[1], 3); + FC_WRITE, 0x61, buf[0], &buf[1], 3); deb_tuner("tuner write returned: %d\n",ret); - return ret; } @@ -481,190 +657,75 @@ static u8 alps_tdee4_stv0297_inittab[] = { static struct stv0297_config alps_tdee4_stv0297_config = { .demod_address = 0x1c, .inittab = alps_tdee4_stv0297_inittab, -// .invert = 1, -// .pll_set = alps_tdee4_stv0297_pll_set, }; - -/* SkyStar2 rev2.7 (a/u) */ -static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { - .demod_address = 0x53, - .invert = 1, - .repeated_start_workaround = 1, - .serial_mpeg = 1, -}; - -static struct itd1000_config skystar2_rev2_7_itd1000_config = { - .i2c_address = 0x61, -}; - -/* SkyStar2 rev2.8 */ -static struct cx24123_config skystar2_rev2_8_cx24123_config = { - .demod_address = 0x55, - .dont_use_pll = 1, - .agc_callback = cx24113_agc_callback, -}; - -static const struct cx24113_config skystar2_rev2_8_cx24113_config = { - .i2c_addr = 0x54, - .xtal_khz = 10111, -}; - -/* try to figure out the frontend, each card/box can have on of the following list */ -int flexcop_frontend_init(struct flexcop_device *fc) +static void cablestar2_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) { - struct dvb_frontend_ops *ops; - struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap; - struct i2c_adapter *i2c_tuner; - - /* enable no_base_addr - no repeated start when reading */ - fc->fc_i2c_adap[0].no_base_addr = 1; - fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c); - if (fc->fe != NULL) { - flexcop_ibi_value r108; - i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe); - ops = &fc->fe->ops; - - fc->fe_sleep = ops->sleep; - ops->sleep = flexcop_sleep; - - fc->dev_type = FC_SKY_REV27; - - /* enable no_base_addr - no repeated start when reading */ - fc->fc_i2c_adap[2].no_base_addr = 1; - if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL) - err("ISL6421 could NOT be attached"); - else - info("ISL6421 successfully attached"); - - /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */ - r108.raw = 0x00000506; - fc->write_ibi_reg(fc, tw_sm_c_108, r108); - if (i2c_tuner) { - if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL) - err("ITD1000 could NOT be attached"); - else - info("ITD1000 successfully attached"); - } - goto fe_found; - } - fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */ - - /* try the sky v2.8 (cx24123, isl6421) */ - fc->fe = dvb_attach(cx24123_attach, - &skystar2_rev2_8_cx24123_config, i2c); - if (fc->fe != NULL) { - i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe); - if (i2c_tuner != NULL) { - if (dvb_attach(cx24113_attach, fc->fe, - &skystar2_rev2_8_cx24113_config, - i2c_tuner) == NULL) - err("CX24113 could NOT be attached"); - else - info("CX24113 successfully attached"); - } - - fc->dev_type = FC_SKY_REV28; - - fc->fc_i2c_adap[2].no_base_addr = 1; - if (dvb_attach(isl6421_attach, fc->fe, - &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL) - err("ISL6421 could NOT be attached"); - else - info("ISL6421 successfully attached"); - - /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an - * IR-receiver (PIC16F818) - but the card has no input for - * that ??? */ - - goto fe_found; - } - - /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ - fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); - if (fc->fe != NULL) { - ops = &fc->fe->ops; - - ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params; - - ops->set_voltage = flexcop_set_voltage; - - fc->fe_sleep = ops->sleep; - ops->sleep = flexcop_sleep; - - fc->dev_type = FC_SKY_REV26; - goto fe_found; - } - - /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */ - fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_AIR_DVBT; - fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; - goto fe_found; - } - - /* try the air atsc 2nd generation (nxt2002) */ - fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_AIR_ATSC2; - dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV); - goto fe_found; - } - - fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_AIR_ATSC3; - dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, - TUNER_LG_TDVS_H06XF); - goto fe_found; - } - - /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ - fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_AIR_ATSC1; - goto fe_found; - } - - /* try the cable dvb (stv0297) */ fc->fc_i2c_adap[0].no_base_addr = 1; fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_CABLE; - fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; - goto fe_found; - } - fc->fc_i2c_adap[0].no_base_addr = 0; - - /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ - fc->fe = dvb_attach(mt312_attach, - &skystar23_samsung_tbdu18132_config, i2c); - if (fc->fe != NULL) { - ops = &fc->fe->ops; - - ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params; - - ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; - ops->diseqc_send_burst = flexcop_diseqc_send_burst; - ops->set_tone = flexcop_set_tone; - ops->set_voltage = flexcop_set_voltage; - - fc->fe_sleep = ops->sleep; - ops->sleep = flexcop_sleep; + if (fc->fe != NULL) + fc->fe->ops.tuner_ops.set_params \ + = alps_tdee4_stv0297_tuner_set_params; + else + fc->fc_i2c_adap[0].no_base_addr = 0; +} +#endif + +static struct { + flexcop_device_type_t type; + void (*attach)(struct flexcop_device *, struct i2c_adapter *); +} flexcop_frontends[] = { +#if defined(CONFIG_DVB_S5H1420_MODULE) + { FC_SKY_REV27, skystar2_rev27_attach }, +#endif +#if defined(CONFIG_DVB_CX24123_MODULE) + { FC_SKY_REV28, skystar2_rev28_attach }, +#endif +#if defined(CONFIG_DVB_STV0299_MODULE) + { FC_SKY_REV26, skystar2_rev26_attach }, +#endif +#if defined(CONFIG_DVB_MT352_MODULE) + { FC_AIR_DVBT, airstar_dvbt_attach }, +#endif +#if defined(CONFIG_DVB_NXT200X_MODULE) + { FC_AIR_ATSC2, airstar_atsc2_attach }, +#endif +#if defined(CONFIG_DVB_LGDT330X_MODULE) + { FC_AIR_ATSC3, airstar_atsc3_attach }, +#endif +#if defined(CONFIG_DVB_BCM3510_MODULE) + { FC_AIR_ATSC1, airstar_atsc1_attach }, +#endif +#if defined(CONFIG_DVB_STV0297_MODULE) + { FC_CABLE, cablestar2_attach }, +#endif +#if defined(CONFIG_DVB_MT312_MODULE) + { FC_SKY_REV23, skystar2_rev23_attach }, +#endif +}; - fc->dev_type = FC_SKY_REV23; - goto fe_found; +/* try to figure out the frontend */ +int flexcop_frontend_init(struct flexcop_device *fc) +{ + int i; + for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) { + /* type needs to be set before, because of some workarounds + * done based on the probed card type */ + fc->dev_type = flexcop_frontends[i].type; + flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap); + if (fc->fe != NULL) + goto fe_found; } - + fc->dev_type = FC_UNK; err("no frontend driver found for this B2C2/FlexCop adapter"); return -ENODEV; fe_found: info("found '%s' .", fc->fe->ops.info.name); if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { + struct dvb_frontend_ops *ops = &fc->fe->ops; err("frontend registration failed!"); - ops = &fc->fe->ops; if (ops->release != NULL) ops->release(fc->fe); fc->fe = NULL; @@ -680,6 +741,5 @@ void flexcop_frontend_exit(struct flexcop_device *fc) dvb_unregister_frontend(fc->fe); dvb_frontend_detach(fc->fe); } - fc->init_state &= ~FC_STATE_FE_INIT; } diff --git a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c index 06a90f67e..df4d6e8d9 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -200,7 +200,7 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1); if (ret < 0) { - err("i2c master_xfer failed"); + deb_i2c("i2c master_xfer failed"); break; } } diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index da2890b22..d359f6841 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -554,6 +554,7 @@ restart: if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { /* got signal or quitting */ + fepriv->exit = 1; break; } diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 57c678892..5d9aacd0a 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1267,6 +1267,7 @@ static struct usb_device_id af9015_usb_table[] = { /* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1537,7 +1538,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 2, /* max 9 */ + .num_device_descs = 3, /* max 9 */ .devices = { { .name = "AverMedia AVerTV Volar GPS 805 (A805)", @@ -1550,6 +1551,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[22], NULL}, .warm_ids = {NULL}, }, + { + .name = "KWorld Digial MC-810", + .cold_ids = {&af9015_usb_table[23], NULL}, + .warm_ids = {NULL}, + }, } }, }; diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index 31fe6e10a..eda025714 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1346,9 +1346,9 @@ static int dib0700_xc5000_tuner_callback(void *priv, int component, if (command == XC5000_TUNER_RESET) { /* Reset the tuner */ dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); - msleep(330); /* from Windows USB trace */ + msleep(10); dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); - msleep(330); /* from Windows USB trace */ + msleep(10); } else { err("xc5000: unknown tuner callback command: %d\n", command); return -EINVAL; @@ -1497,6 +1497,10 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) }, { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) }, { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) }, +/* 50 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_Dlx) }, + { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_H) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1696,7 +1700,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 11, + .num_device_descs = 12, .devices = { { "DiBcom STK7070P reference design", { &dib0700_usb_id_table[15], NULL }, @@ -1730,8 +1734,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[30], NULL }, { NULL }, }, - { "Terratec Cinergy T USB XXS", - { &dib0700_usb_id_table[33], NULL }, + { "Terratec Cinergy T USB XXS/ T3", + { &dib0700_usb_id_table[33], + &dib0700_usb_id_table[52], NULL }, { NULL }, }, { "Elgato EyeTV DTT", @@ -1742,6 +1747,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[45], NULL }, { NULL }, }, + { "Elgato EyeTV Dtt Dlx PD378S", + { &dib0700_usb_id_table[50], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, @@ -1788,8 +1797,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[36], NULL }, { NULL }, }, - { "Terratec Cinergy DT USB XS Diversity", - { &dib0700_usb_id_table[43], NULL }, + { "Terratec Cinergy DT USB XS Diversity/ T5", + { &dib0700_usb_id_table[43], + &dib0700_usb_id_table[53], NULL}, { NULL }, }, { "Sony PlayTV", @@ -1816,7 +1826,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 7, + .num_device_descs = 8, .devices = { { "Terratec Cinergy HT USB XE", { &dib0700_usb_id_table[27], NULL }, @@ -1846,6 +1856,11 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[48], NULL }, { NULL }, }, + { "Leadtek WinFast DTV Dongle H", + { &dib0700_usb_id_table[51], NULL }, + { NULL }, + }, + }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c index d774879df..99b3b9a43 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -133,14 +133,17 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num for (i = 0; i < num; i++) { /* write/read request */ - if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { + if (i+1 < num && (msg[i].flags & I2C_M_RD) == 0 + && (msg[i+1].flags & I2C_M_RD)) { if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len, msg[i+1].buf,msg[i+1].len) < 0) break; i++; - } else + } else if ((msg[i].flags & I2C_M_RD) == 0) { if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) break; + } else + break; } mutex_unlock(&d->i2c_mutex); diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index ca0051272..7340ef4cd 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -105,6 +105,7 @@ #define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U_2 0xe39b #define USB_PID_KWORLD_395U_3 0xe395 +#define USB_PID_KWORLD_MC810 0xc810 #define USB_PID_KWORLD_PC160_2T 0xc160 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_WARM 0x17df @@ -180,6 +181,8 @@ #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 +#define USB_PID_TERRATEC_T3 0x10a0 +#define USB_PID_TERRATEC_T5 0x10a1 #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 @@ -224,6 +227,7 @@ #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 +#define USB_PID_WINFAST_DTV_DONGLE_H 0x60f6 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 #define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029 #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 @@ -253,5 +257,6 @@ #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 #define USB_PID_SONY_PLAYTV 0x0003 #define USB_PID_ELGATO_EYETV_DTT 0x0021 +#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 #endif diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index fd64daa06..8874221c1 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -224,7 +224,7 @@ struct dvb_usb_device_properties { int generic_bulk_ctrl_endpoint; int num_device_descs; - struct dvb_usb_device_description devices[11]; + struct dvb_usb_device_description devices[12]; }; /** diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk.c b/linux/drivers/media/dvb/dvb-usb/gp8psk.c index 3dd684386..003d97f8c 100644 --- a/linux/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.c @@ -223,7 +223,7 @@ static struct usb_device_id gp8psk_usb_table [] = { { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) }, - { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, +/* { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */ { 0 }, }; MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); @@ -254,7 +254,7 @@ static struct dvb_usb_device_properties gp8psk_properties = { .generic_bulk_ctrl_endpoint = 0x01, - .num_device_descs = 4, + .num_device_descs = 3, .devices = { { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", .cold_ids = { &gp8psk_usb_table[0], NULL }, @@ -268,10 +268,12 @@ static struct dvb_usb_device_properties gp8psk_properties = { .cold_ids = { NULL }, .warm_ids = { &gp8psk_usb_table[3], NULL }, }, +#if 0 { .name = "Genpix SkyWalker-CW3K DVB-S receiver", .cold_ids = { NULL }, .warm_ids = { &gp8psk_usb_table[4], NULL }, }, +#endif { NULL }, } }; diff --git a/linux/drivers/media/dvb/firewire/firedtv-1394.c b/linux/drivers/media/dvb/firewire/firedtv-1394.c index 4e207658c..2b6eeeab5 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-1394.c +++ b/linux/drivers/media/dvb/firewire/firedtv-1394.c @@ -225,7 +225,7 @@ fail_free: static int node_remove(struct device *dev) { - struct firedtv *fdtv = dev->driver_data; + struct firedtv *fdtv = dev_get_drvdata(dev); fdtv_dvb_unregister(fdtv); @@ -242,7 +242,7 @@ static int node_remove(struct device *dev) static int node_update(struct unit_directory *ud) { - struct firedtv *fdtv = ud->device.driver_data; + struct firedtv *fdtv = dev_get_drvdata(&ud->device); if (fdtv->isochannel >= 0) cmp_establish_pp_connection(fdtv, fdtv->subunit, diff --git a/linux/drivers/media/dvb/firewire/firedtv-dvb.c b/linux/drivers/media/dvb/firewire/firedtv-dvb.c index 9d308dd32..5742fde79 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-dvb.c +++ b/linux/drivers/media/dvb/firewire/firedtv-dvb.c @@ -268,7 +268,7 @@ struct firedtv *fdtv_alloc(struct device *dev, if (!fdtv) return NULL; - dev->driver_data = fdtv; + dev_set_drvdata(dev, fdtv); fdtv->device = dev; fdtv->isochannel = -1; fdtv->voltage = 0xff; diff --git a/linux/drivers/media/dvb/firewire/firedtv-rc.c b/linux/drivers/media/dvb/firewire/firedtv-rc.c index 46a6324d7..27bca2e28 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-rc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-rc.c @@ -18,7 +18,7 @@ #include "firedtv.h" /* fixed table with older keycodes, geared towards MythTV */ -const static u16 oldtable[] = { +static const u16 oldtable[] = { /* code from device: 0x4501...0x451f */ @@ -62,7 +62,7 @@ const static u16 oldtable[] = { }; /* user-modifiable table for a remote as sold in 2008 */ -const static u16 keytable[] = { +static const u16 keytable[] = { /* code from device: 0x0300...0x031f */ diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 23e4cffeb..be967ac09 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -35,6 +35,21 @@ config DVB_STB6100 A Silicon tuner from ST used in conjunction with the STB0899 demodulator. Say Y when you want to support this tuner. +config DVB_STV090x + tristate "STV0900/STV0903(A/B) based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators. + Say Y when you want to support these frontends. + +config DVB_STV6110x + tristate "STV6110/(A) based tuners" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A Silicon tuner that supports DVB-S and DVB-S2 modes + comment "DVB-S (satellite) frontends" depends on DVB_CORE @@ -506,6 +521,13 @@ config DVB_ISL6421 help An SEC control chip. +config DVB_ISL6423 + tristate "ISL6423 SEC controller" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A SEC controller chip from Intersil + config DVB_LGS8GL5 tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index bc2b00abd..832473c1e 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -71,4 +71,6 @@ obj-$(CONFIG_DVB_STB6000) += stb6000.o obj-$(CONFIG_DVB_S921) += s921.o obj-$(CONFIG_DVB_STV6110) += stv6110.o obj-$(CONFIG_DVB_STV0900) += stv0900.o - +obj-$(CONFIG_DVB_STV090x) += stv090x.o +obj-$(CONFIG_DVB_STV6110x) += stv6110x.o +obj-$(CONFIG_DVB_ISL6423) += isl6423.o diff --git a/linux/drivers/media/dvb/frontends/af9013.c b/linux/drivers/media/dvb/frontends/af9013.c index 937715a96..d12d99802 100644 --- a/linux/drivers/media/dvb/frontends/af9013.c +++ b/linux/drivers/media/dvb/frontends/af9013.c @@ -1456,7 +1456,7 @@ static int af9013_download_firmware(struct af9013_state *state) af9013_ops.info.name); /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &state->i2c->dev); + ret = request_firmware(&fw, fw_file, state->i2c->dev.parent); if (ret) { err("did not find the firmware file. (%s) " "Please see linux/Documentation/dvb/ for more details" \ diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c index b5ff0b6a8..fddd27bd1 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.c +++ b/linux/drivers/media/dvb/frontends/cx24116.c @@ -492,7 +492,7 @@ static int cx24116_firmware_ondemand(struct dvb_frontend *fe) printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE); ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, - &state->i2c->dev); + state->i2c->dev.parent); printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); if (ret) { diff --git a/linux/drivers/media/dvb/frontends/drx397xD.c b/linux/drivers/media/dvb/frontends/drx397xD.c index 0bdb933d0..95eff4a81 100644 --- a/linux/drivers/media/dvb/frontends/drx397xD.c +++ b/linux/drivers/media/dvb/frontends/drx397xD.c @@ -124,10 +124,10 @@ static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix) } memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); - if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) { + rc = request_firmware(&fw[ix].file, fw[ix].name, s->i2c->dev.parent); + if (rc != 0) { printk(KERN_ERR "%s: Firmware \"%s\" not available\n", mod_name, fw[ix].name); - rc = -ENOENT; goto exit_err; } diff --git a/linux/drivers/media/dvb/frontends/isl6423.c b/linux/drivers/media/dvb/frontends/isl6423.c new file mode 100644 index 000000000..dca5bebfe --- /dev/null +++ b/linux/drivers/media/dvb/frontends/isl6423.c @@ -0,0 +1,308 @@ +/* + Intersil ISL6423 SEC and LNB Power supply controller + + Copyright (C) Manu Abraham <abraham.manu@gmail.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 <linux/delay.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/slab.h> + +#include "dvb_frontend.h" +#include "isl6423.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "Set Verbosity level"); + +#define FE_ERROR 0 +#define FE_NOTICE 1 +#define FE_INFO 2 +#define FE_DEBUG 3 +#define FE_DEBUGREG 4 + +#define dprintk(__y, __z, format, arg...) do { \ + if (__z) { \ + if ((verbose > FE_ERROR) && (verbose > __y)) \ + printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_NOTICE) && (verbose > __y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_INFO) && (verbose > __y)) \ + printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_DEBUG) && (verbose > __y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ + } else { \ + if (verbose > __y) \ + printk(format, ##arg); \ + } \ +} while (0) + +struct isl6423_dev { + const struct isl6423_config *config; + struct i2c_adapter *i2c; + + u8 reg_3; + u8 reg_4; + + unsigned int verbose; +}; + +static int isl6423_write(struct isl6423_dev *isl6423, u8 reg) +{ + struct i2c_adapter *i2c = isl6423->i2c; + u8 addr = isl6423->config->addr; + int err = 0; + + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = ®, .len = 1 }; + + dprintk(FE_DEBUG, 1, "write reg %02X", reg); + err = i2c_transfer(i2c, &msg, 1); + if (err < 0) + goto exit; + return 0; + +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + +static int isl6423_set_modulation(struct dvb_frontend *fe) +{ + struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + const struct isl6423_config *config = isl6423->config; + int err = 0; + u8 reg_2 = 0; + + reg_2 = 0x01 << 5; + + if (config->mod_extern) + reg_2 |= (1 << 3); + else + reg_2 |= (1 << 4); + + err = isl6423_write(isl6423, reg_2); + if (err < 0) + goto exit; + return 0; + +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + +static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg) +{ + struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + u8 reg_3 = isl6423->reg_3; + u8 reg_4 = isl6423->reg_4; + int err = 0; + + if (arg) { + /* EN = 1, VSPEN = 1, VBOT = 1 */ + reg_4 |= (1 << 4); + reg_4 |= 0x1; + reg_3 |= (1 << 3); + } else { + /* EN = 1, VSPEN = 1, VBOT = 0 */ + reg_4 |= (1 << 4); + reg_4 &= ~0x1; + reg_3 |= (1 << 3); + } + err = isl6423_write(isl6423, reg_3); + if (err < 0) + goto exit; + + err = isl6423_write(isl6423, reg_4); + if (err < 0) + goto exit; + + isl6423->reg_3 = reg_3; + isl6423->reg_4 = reg_4; + + return 0; +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + + +static int isl6423_set_voltage(struct dvb_frontend *fe, + enum fe_sec_voltage voltage) +{ + struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + u8 reg_3 = isl6423->reg_3; + u8 reg_4 = isl6423->reg_4; + int err = 0; + + switch (voltage) { + case SEC_VOLTAGE_OFF: + /* EN = 0 */ + reg_4 &= ~(1 << 4); + break; + + case SEC_VOLTAGE_13: + /* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */ + reg_4 |= (1 << 4); + reg_4 &= ~0x3; + reg_3 |= (1 << 3); + break; + + case SEC_VOLTAGE_18: + /* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */ + reg_4 |= (1 << 4); + reg_4 |= 0x2; + reg_4 &= ~0x1; + reg_3 |= (1 << 3); + break; + + default: + break; + } + err = isl6423_write(isl6423, reg_3); + if (err < 0) + goto exit; + + err = isl6423_write(isl6423, reg_4); + if (err < 0) + goto exit; + + isl6423->reg_3 = reg_3; + isl6423->reg_4 = reg_4; + + return 0; +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + +static int isl6423_set_current(struct dvb_frontend *fe) +{ + struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + u8 reg_3 = isl6423->reg_3; + const struct isl6423_config *config = isl6423->config; + int err = 0; + + switch (config->current_max) { + case SEC_CURRENT_275m: + /* 275mA */ + /* ISELH = 0, ISELL = 0 */ + reg_3 &= ~0x3; + break; + + case SEC_CURRENT_515m: + /* 515mA */ + /* ISELH = 0, ISELL = 1 */ + reg_3 &= ~0x2; + reg_3 |= 0x1; + break; + + case SEC_CURRENT_635m: + /* 635mA */ + /* ISELH = 1, ISELL = 0 */ + reg_3 &= ~0x1; + reg_3 |= 0x2; + break; + + case SEC_CURRENT_800m: + /* 800mA */ + /* ISELH = 1, ISELL = 1 */ + reg_3 |= 0x3; + break; + } + + err = isl6423_write(isl6423, reg_3); + if (err < 0) + goto exit; + + switch (config->curlim) { + case SEC_CURRENT_LIM_ON: + /* DCL = 0 */ + reg_3 &= ~0x10; + break; + + case SEC_CURRENT_LIM_OFF: + /* DCL = 1 */ + reg_3 |= 0x10; + break; + } + + err = isl6423_write(isl6423, reg_3); + if (err < 0) + goto exit; + + isl6423->reg_3 = reg_3; + + return 0; +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + +static void isl6423_release(struct dvb_frontend *fe) +{ + isl6423_set_voltage(fe, SEC_VOLTAGE_OFF); + + kfree(fe->sec_priv); + fe->sec_priv = NULL; +} + +struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct isl6423_config *config) +{ + struct isl6423_dev *isl6423; + + isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL); + if (!isl6423) + return NULL; + + isl6423->config = config; + isl6423->i2c = i2c; + fe->sec_priv = isl6423; + + /* SR3H = 0, SR3M = 1, SR3L = 0 */ + isl6423->reg_3 = 0x02 << 5; + /* SR4H = 0, SR4M = 1, SR4L = 1 */ + isl6423->reg_4 = 0x03 << 5; + + if (isl6423_set_current(fe)) + goto exit; + + if (isl6423_set_modulation(fe)) + goto exit; + + fe->ops.release_sec = isl6423_release; + fe->ops.set_voltage = isl6423_set_voltage; + fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost; + isl6423->verbose = verbose; + + return fe; + +exit: + kfree(isl6423); + fe->sec_priv = NULL; + return NULL; +} +EXPORT_SYMBOL(isl6423_attach); + +MODULE_DESCRIPTION("ISL6423 SEC"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/isl6423.h b/linux/drivers/media/dvb/frontends/isl6423.h new file mode 100644 index 000000000..e1a37fba0 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/isl6423.h @@ -0,0 +1,63 @@ +/* + Intersil ISL6423 SEC and LNB Power supply controller + + Copyright (C) Manu Abraham <abraham.manu@gmail.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 __ISL_6423_H +#define __ISL_6423_H + +#include <linux/dvb/frontend.h> + +enum isl6423_current { + SEC_CURRENT_275m = 0, + SEC_CURRENT_515m, + SEC_CURRENT_635m, + SEC_CURRENT_800m, +}; + +enum isl6423_curlim { + SEC_CURRENT_LIM_ON = 1, + SEC_CURRENT_LIM_OFF +}; + +struct isl6423_config { + enum isl6423_current current_max; + enum isl6423_curlim curlim; + u8 addr; + u8 mod_extern; +}; + +#if defined(CONFIG_DVB_ISL6423) || (defined(CONFIG_DVB_ISL6423_MODULE) && defined(MODULE)) + + +extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct isl6423_config *config); + +#else +static inline struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct isl6423_config *config) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif /* CONFIG_DVB_ISL6423 */ + +#endif /* __ISL_6423_H */ diff --git a/linux/drivers/media/dvb/frontends/mt312.c b/linux/drivers/media/dvb/frontends/mt312.c index 5ac9b1592..a621f7279 100644 --- a/linux/drivers/media/dvb/frontends/mt312.c +++ b/linux/drivers/media/dvb/frontends/mt312.c @@ -77,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { - printk(KERN_ERR "%s: ret == %d\n", __func__, ret); + printk(KERN_DEBUG "%s: ret == %d\n", __func__, ret); return -EREMOTEIO; } diff --git a/linux/drivers/media/dvb/frontends/nxt200x.c b/linux/drivers/media/dvb/frontends/nxt200x.c index 846350bc4..748f95b22 100644 --- a/linux/drivers/media/dvb/frontends/nxt200x.c +++ b/linux/drivers/media/dvb/frontends/nxt200x.c @@ -880,7 +880,8 @@ static int nxt2002_init(struct dvb_frontend* fe) /* request the firmware, this will block until someone uploads it */ printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); - ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, &state->i2c->dev); + ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, + state->i2c->dev.parent); printk("nxt2002: Waiting for firmware upload(2)...\n"); if (ret) { printk("nxt2002: No firmware uploaded (timeout or file not found?)\n"); @@ -944,7 +945,8 @@ static int nxt2004_init(struct dvb_frontend* fe) /* request the firmware, this will block until someone uploads it */ printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE); - ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, &state->i2c->dev); + ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, + state->i2c->dev.parent); printk("nxt2004: Waiting for firmware upload(2)...\n"); if (ret) { printk("nxt2004: No firmware uploaded (timeout or file not found?)\n"); diff --git a/linux/drivers/media/dvb/frontends/or51132.c b/linux/drivers/media/dvb/frontends/or51132.c index 5ed32544d..8133ea3cd 100644 --- a/linux/drivers/media/dvb/frontends/or51132.c +++ b/linux/drivers/media/dvb/frontends/or51132.c @@ -340,7 +340,7 @@ static int or51132_set_parameters(struct dvb_frontend* fe, } printk("or51132: Waiting for firmware upload(%s)...\n", fwname); - ret = request_firmware(&fw, fwname, &state->i2c->dev); + ret = request_firmware(&fw, fwname, state->i2c->dev.parent); if (ret) { printk(KERN_WARNING "or51132: No firmware up" "loaded(timeout or file not found?)\n"); diff --git a/linux/drivers/media/dvb/frontends/stv0900_priv.h b/linux/drivers/media/dvb/frontends/stv0900_priv.h index 762d5af62..67dc8ec63 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_priv.h +++ b/linux/drivers/media/dvb/frontends/stv0900_priv.h @@ -60,8 +60,6 @@ } \ } while (0) -#define dmd_choose(a, b) (demod = STV0900_DEMOD_2 ? b : a)) - static int stvdebug; #define dprintk(args...) \ diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c new file mode 100644 index 000000000..62078400f --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -0,0 +1,5124 @@ +/* + STV0900/0903 Multistandard Broadcast Frontend driver + Copyright (C) Manu Abraham <abraham.manu@gmail.com> + + Copyright (C) ST Microelectronics + + 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 <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/mutex.h> + +#include <linux/dvb/frontend.h> +#include "dvb_frontend.h" + +#include "stv6110x.h" /* for demodulator internal modes */ + +#include "stv090x_reg.h" +#include "stv090x.h" +#include "stv090x_priv.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); + +struct mutex demod_lock; + +/* DVBS1 and DSS C/N Lookup table */ +static const struct stv090x_tab stv090x_s1cn_tab[] = { + { 0, 8917 }, /* 0.0dB */ + { 5, 8801 }, /* 0.5dB */ + { 10, 8667 }, /* 1.0dB */ + { 15, 8522 }, /* 1.5dB */ + { 20, 8355 }, /* 2.0dB */ + { 25, 8175 }, /* 2.5dB */ + { 30, 7979 }, /* 3.0dB */ + { 35, 7763 }, /* 3.5dB */ + { 40, 7530 }, /* 4.0dB */ + { 45, 7282 }, /* 4.5dB */ + { 50, 7026 }, /* 5.0dB */ + { 55, 6781 }, /* 5.5dB */ + { 60, 6514 }, /* 6.0dB */ + { 65, 6241 }, /* 6.5dB */ + { 70, 5965 }, /* 7.0dB */ + { 75, 5690 }, /* 7.5dB */ + { 80, 5424 }, /* 8.0dB */ + { 85, 5161 }, /* 8.5dB */ + { 90, 4902 }, /* 9.0dB */ + { 95, 4654 }, /* 9.5dB */ + { 100, 4417 }, /* 10.0dB */ + { 105, 4186 }, /* 10.5dB */ + { 110, 3968 }, /* 11.0dB */ + { 115, 3757 }, /* 11.5dB */ + { 120, 3558 }, /* 12.0dB */ + { 125, 3366 }, /* 12.5dB */ + { 130, 3185 }, /* 13.0dB */ + { 135, 3012 }, /* 13.5dB */ + { 140, 2850 }, /* 14.0dB */ + { 145, 2698 }, /* 14.5dB */ + { 150, 2550 }, /* 15.0dB */ + { 160, 2283 }, /* 16.0dB */ + { 170, 2042 }, /* 17.0dB */ + { 180, 1827 }, /* 18.0dB */ + { 190, 1636 }, /* 19.0dB */ + { 200, 1466 }, /* 20.0dB */ + { 210, 1315 }, /* 21.0dB */ + { 220, 1181 }, /* 22.0dB */ + { 230, 1064 }, /* 23.0dB */ + { 240, 960 }, /* 24.0dB */ + { 250, 869 }, /* 25.0dB */ + { 260, 792 }, /* 26.0dB */ + { 270, 724 }, /* 27.0dB */ + { 280, 665 }, /* 28.0dB */ + { 290, 616 }, /* 29.0dB */ + { 300, 573 }, /* 30.0dB */ + { 310, 537 }, /* 31.0dB */ + { 320, 507 }, /* 32.0dB */ + { 330, 483 }, /* 33.0dB */ + { 400, 398 }, /* 40.0dB */ + { 450, 381 }, /* 45.0dB */ + { 500, 377 } /* 50.0dB */ +}; + +/* DVBS2 C/N Lookup table */ +static const struct stv090x_tab stv090x_s2cn_tab[] = { + { -30, 13348 }, /* -3.0dB */ + { -20, 12640 }, /* -2d.0B */ + { -10, 11883 }, /* -1.0dB */ + { 0, 11101 }, /* -0.0dB */ + { 5, 10718 }, /* 0.5dB */ + { 10, 10339 }, /* 1.0dB */ + { 15, 9947 }, /* 1.5dB */ + { 20, 9552 }, /* 2.0dB */ + { 25, 9183 }, /* 2.5dB */ + { 30, 8799 }, /* 3.0dB */ + { 35, 8422 }, /* 3.5dB */ + { 40, 8062 }, /* 4.0dB */ + { 45, 7707 }, /* 4.5dB */ + { 50, 7353 }, /* 5.0dB */ + { 55, 7025 }, /* 5.5dB */ + { 60, 6684 }, /* 6.0dB */ + { 65, 6331 }, /* 6.5dB */ + { 70, 6036 }, /* 7.0dB */ + { 75, 5727 }, /* 7.5dB */ + { 80, 5437 }, /* 8.0dB */ + { 85, 5164 }, /* 8.5dB */ + { 90, 4902 }, /* 9.0dB */ + { 95, 4653 }, /* 9.5dB */ + { 100, 4408 }, /* 10.0dB */ + { 105, 4187 }, /* 10.5dB */ + { 110, 3961 }, /* 11.0dB */ + { 115, 3751 }, /* 11.5dB */ + { 120, 3558 }, /* 12.0dB */ + { 125, 3368 }, /* 12.5dB */ + { 130, 3191 }, /* 13.0dB */ + { 135, 3017 }, /* 13.5dB */ + { 140, 2862 }, /* 14.0dB */ + { 145, 2710 }, /* 14.5dB */ + { 150, 2565 }, /* 15.0dB */ + { 160, 2300 }, /* 16.0dB */ + { 170, 2058 }, /* 17.0dB */ + { 180, 1849 }, /* 18.0dB */ + { 190, 1663 }, /* 19.0dB */ + { 200, 1495 }, /* 20.0dB */ + { 210, 1349 }, /* 21.0dB */ + { 220, 1222 }, /* 22.0dB */ + { 230, 1110 }, /* 23.0dB */ + { 240, 1011 }, /* 24.0dB */ + { 250, 925 }, /* 25.0dB */ + { 260, 853 }, /* 26.0dB */ + { 270, 789 }, /* 27.0dB */ + { 280, 734 }, /* 28.0dB */ + { 290, 690 }, /* 29.0dB */ + { 300, 650 }, /* 30.0dB */ + { 310, 619 }, /* 31.0dB */ + { 320, 593 }, /* 32.0dB */ + { 330, 571 }, /* 33.0dB */ + { 400, 498 }, /* 40.0dB */ + { 450, 484 }, /* 45.0dB */ + { 500, 481 } /* 50.0dB */ +}; + +/* RF level C/N lookup table */ +static const struct stv090x_tab stv090x_rf_tab[] = { + { -5, 0xcaa1 }, /* -5dBm */ + { -10, 0xc229 }, /* -10dBm */ + { -15, 0xbb08 }, /* -15dBm */ + { -20, 0xb4bc }, /* -20dBm */ + { -25, 0xad5a }, /* -25dBm */ + { -30, 0xa298 }, /* -30dBm */ + { -35, 0x98a8 }, /* -35dBm */ + { -40, 0x8389 }, /* -40dBm */ + { -45, 0x59be }, /* -45dBm */ + { -50, 0x3a14 }, /* -50dBm */ + { -55, 0x2d11 }, /* -55dBm */ + { -60, 0x210d }, /* -60dBm */ + { -65, 0xa14f }, /* -65dBm */ + { -70, 0x07aa } /* -70dBm */ +}; + +#if 0 +static struct stv090x_reg stv090x_defval[] = { + + { STV090x_MID, 0x20 }, /* MID */ + { STV090x_DACR1, 0x00 }, /* DACR1 */ + { STV090x_DACR2, 0x00 }, /* DACR2 */ + { STV090x_OUTCFG, 0x00 }, /* OUTCFG */ + { STV090x_MODECFG, 0xff }, /* MODECFG */ + { STV090x_IRQSTATUS3, 0x00 }, /* IRQSTATUS3 */ + { STV090x_IRQSTATUS2, 0x00 }, /* IRQSTATUS2 */ + { STV090x_IRQSTATUS1, 0x00 }, /* IRQSTATUS1 */ + { STV090x_IRQSTATUS0, 0x00 }, /* IRQSTATUS0 */ + { STV090x_IRQMASK3, 0x3f }, /* IRQMASK3 */ + { STV090x_IRQMASK2, 0xff }, /* IRQMASK2 */ + { STV090x_IRQMASK1, 0xff }, /* IRQMASK1 */ + { STV090x_IRQMASK0, 0xff }, /* IRQMASK0 */ + { STV090x_I2CCFG, 0x08 }, /* I2CCFG */ + { STV090x_P1_I2CRPT, 0x44 }, /* P1_I2CRPT */ + { STV090x_P2_I2CRPT, 0x44 }, /* P2_I2CRPT */ + { STV090x_CLKI2CFG, 0x82 }, /* CLKI2CFG */ + { STV090x_GPIO1CFG, 0x82 }, /* GPIO1CFG */ + { STV090x_GPIO2CFG, 0x82 }, /* GPIO2CFG */ + { STV090x_GPIO3CFG, 0x82 }, /* GPIO3CFG */ + { STV090x_GPIO4CFG, 0x82 }, /* GPIO4CFG */ + { STV090x_GPIO5CFG, 0x82 }, /* GPIO5CFG */ + { STV090x_GPIO6CFG, 0x82 }, /* GPIO6CFG */ + { STV090x_GPIO7CFG, 0x82 }, /* GPIO7CFG */ + { STV090x_GPIO8CFG, 0x82 }, /* GPIO8CFG */ + { STV090x_GPIO9CFG, 0x82 }, /* GPIO9CFG */ + { STV090x_GPIO10CFG, 0x82 }, /* GPIO10CFG */ + { STV090x_GPIO11CFG, 0x82 }, /* GPIO11CFG */ + { STV090x_GPIO12CFG, 0x82 }, /* GPIO12CFG */ + { STV090x_GPIO13CFG, 0x82 }, /* GPIO13CFG */ + { STV090x_CS0CFG, 0x82 }, /* CS0CFG */ + { STV090x_CS1CFG, 0x82 }, /* CS1CFG */ + { STV090x_STDBYCFG, 0x82 }, /* STDBYCFG */ + { STV090x_DIRCLKCFG, 0x82 }, /* DIRCLKCFG */ + { STV090x_AGCRF1CFG, 0x11 }, /* AGCRF1CFG */ + { STV090x_SDAT1CFG, 0xb0 }, /* SDAT1CFG */ + { STV090x_SCLT1CFG, 0xb2 }, /* SCLT1CFG */ + { STV090x_DISEQCO1CFG, 0x14 }, /* DISEQCO1CFG */ + { STV090x_AGCRF2CFG, 0x13 }, /* AGCRF2CFG */ + { STV090x_SDAT2CFG, 0xb4 }, /* SDAT2CFG */ + { STV090x_SCLT2CFG, 0xb6 }, /* SCLT2CFG */ + { STV090x_DISEQCO2CFG, 0x16 }, /* DISEQCO2CFG */ + { STV090x_CLKOUT27CFG, 0x7e }, /* ERROR1CFG */ + { STV090x_DPN1CFG, 0xc0 }, /* DPN1CFG */ + { STV090x_STROUT1CFG, 0xc2 }, /* STROUT1CFG */ + { STV090x_CLKOUT1CFG, 0xc6 }, /* CLKOUT1CFG */ + { STV090x_DATA71CFG, 0xc8 }, /* DATA71CFG */ + { STV090x_ERROR2CFG, 0xce }, /* ERROR2CFG */ + { STV090x_DPN2CFG, 0xca }, /* DPN2CFG */ + { STV090x_STROUT2CFG, 0xcc }, /* STROUT2CFG */ + { STV090x_CLKOUT2CFG, 0xd0 }, /* CLKOUT2CFG */ + { STV090x_DATA72CFG, 0xd2 }, /* DATA72CFG */ + { STV090x_ERROR3CFG, 0xd8 }, /* ERROR3CFG */ + { STV090x_DPN3CFG, 0xd4 }, /* DPN3CFG */ + { STV090x_STROUT3CFG, 0xd6 }, /* STROUT3CFG */ + { STV090x_CLKOUT3CFG, 0xda }, /* CLKOUT3CFG */ + { STV090x_DATA73CFG, 0xdc }, /* DATA73CFG */ + { STV090x_FSKTFC2, 0x8c }, /* FSKTFC2 */ + { STV090x_FSKTFC1, 0x75 }, /* FSKTFC1 */ + { STV090x_FSKTFC0, 0xc2 }, /* FSKTFC0 */ + { STV090x_FSKTDELTAF1, 0x02 }, /* FSKTDELTAF1 */ + { STV090x_FSKTDELTAF0, 0x0c }, /* FSKTDELTAF0 */ + { STV090x_FSKTCTRL, 0x04 }, /* FSKTCTRL */ + { STV090x_FSKRFC2, 0x10 }, /* FSKRFC2 */ + { STV090x_FSKRFC1, 0x75 }, /* FSKRFC1 */ + { STV090x_FSKRFC0, 0xc2 }, /* FSKRFC0 */ + { STV090x_FSKRK1, 0x3a }, /* FSKRK1 */ + { STV090x_FSKRK2, 0x74 }, /* FSKRK2 */ + { STV090x_FSKRAGCR, 0x28 }, /* FSKRAGCR */ + { STV090x_FSKRAGC, 0xff }, /* FSKRAGC */ + { STV090x_FSKRALPHA, 0x17 }, /* FSKRALPHA */ + { STV090x_FSKRPLTH1, 0x80 }, /* FSKRPLTH1 */ + { STV090x_FSKRPLTH0, 0x00 }, /* FSKRPLTH0 */ + { STV090x_FSKRDF1, 0x80 }, /* FSKRDF1 */ + { STV090x_FSKRDF0, 0x00 }, /* FSKRDF0 */ + { STV090x_FSKRSTEPP, 0x30 }, /* FSKRSTEPP */ + { STV090x_FSKRSTEPM, 0x70 }, /* FSKRSTEPM */ + { STV090x_FSKRDET1, 0x00 }, /* FSKRDET1 */ + { STV090x_FSKRDET0, 0x00 }, /* FSKRDET0 */ + { STV090x_FSKRDTH1, 0x11 }, /* FSKRDTH1 */ + { STV090x_FSKRDTH0, 0x89 }, /* FSKRDTH0 */ + { STV090x_FSKRLOSS, 0x06 }, /* FSKRLOSS */ + { STV090x_P2_DISTXCTL, 0x22 }, /* P2_DISTXCTL */ + { STV090x_P2_DISRXCTL, 0x80 }, /* P2_DISRXCTL */ + { STV090x_P2_DISRX_ST0, 0x04 }, /* P2_DISRX_ST0 */ + { STV090x_P2_DISRX_ST1, 0x00 }, /* P2_DISRX_ST1 */ + { STV090x_P2_DISRXDATA, 0x00 }, /* P2_DISRXDATA */ + { STV090x_P2_DISTXDATA, 0x00 }, /* P2_DISTXDATA */ + { STV090x_P2_DISTXSTATUS, 0x20 }, /* P2_DISTXSTATUS */ + { STV090x_P2_F22TX, 0xc0 }, /* P2_F22TX */ + { STV090x_P2_F22RX, 0xc0 }, /* P2_F22RX */ + { STV090x_P2_ACRPRESC, 0x01 }, /* P2_ACRPRESC */ + { STV090x_P2_ACRDIV, 0x14 }, /* P2_ACRDIV */ + { STV090x_P1_DISTXCTL, 0x22 }, /* P1_DISTXCTL */ + { STV090x_P1_DISRXCTL, 0x80 }, /* P1_DISRXCTL */ + { STV090x_P1_DISRX_ST0, 0x14 }, /* P1_DISRX_ST0 */ + { STV090x_P1_DISRX_ST1, 0x80 }, /* P1_DISRX_ST1 */ + { STV090x_P1_DISRXDATA, 0x00 }, /* P1_DISRXDATA */ + { STV090x_P1_DISTXDATA, 0x00 }, /* P1_DISTXDATA */ + { STV090x_P1_DISTXSTATUS, 0x20 }, /* P1_DISTXSTATUS */ + { STV090x_P1_F22TX, 0xc0 }, /* P1_F22TX */ + { STV090x_P1_F22RX, 0xc0 }, /* P1_F22RX */ + { STV090x_P1_ACRPRESC, 0x01 }, /* P1_ACRPRESC */ + { STV090x_P1_ACRDIV, 0x14 }, /* P1_ACRDIV */ + { STV090x_NCOARSE, 0x13 }, /* NCOARSE */ + { STV090x_SYNTCTRL, 0x22 }, /* SYNTCTRL (default CLKI) */ + { STV090x_FILTCTRL, 0x01 }, /* FILTCTRL */ + { STV090x_PLLSTAT, 0xc0 }, /* PLLSTAT */ + { STV090x_STOPCLK1, 0x00 }, /* STOPCLK1 */ + { STV090x_STOPCLK2, 0x00 }, /* STOPCLK2 */ + { STV090x_TSTTNR0, 0x04 }, /* TSTTNR0 */ + { STV090x_TSTTNR1, 0x27 }, /* TSTTNR1 */ + { STV090x_TSTTNR2, 0x21 }, /* TSTTNR2 */ + { STV090x_TSTTNR3, 0x27 }, /* TSTTNR3 */ + { STV090x_TSTTNR4, 0x21 }, /* TSTTNR4 */ + { STV090x_P2_IQCONST, 0x00 }, /* P2_IQCONST */ + { STV090x_P2_NOSCFG, 0x1c }, /* P2_NOSCFG */ + { STV090x_P2_ISYMB, 0x27 }, /* P2_ISYMB */ + { STV090x_P2_QSYMB, 0x2a }, /* P2_QSYMB */ + { STV090x_P2_AGC1CFG, 0x54 }, /* P2_AGC1CFG */ + { STV090x_P2_AGC1CN, 0xd9 }, /* P2_AGC1CN */ + { STV090x_P2_AGC1REF, 0x58 }, /* P2_AGC1REF */ + { STV090x_P2_IDCCOMP, 0x00 }, /* P2_IDCCOMP */ + { STV090x_P2_QDCCOMP, 0xfd }, /* P2_QDCCOMP */ + { STV090x_P2_POWERI, 0x0e }, /* P2_POWERI */ + { STV090x_P2_POWERQ, 0x0c }, /* P2_POWERQ */ + { STV090x_P2_AGC1AMM, 0x19 }, /* P2_AGC1AMM */ + { STV090x_P2_AGC1QUAD, 0xf9 }, /* P2_AGC1QUAD */ + { STV090x_P2_AGCIQIN1, 0x00 }, /* P2_AGCIQIN1 */ + { STV090x_P2_AGCIQIN0, 0x00 }, /* P2_AGCIQIN0 */ + { STV090x_P2_DEMOD, 0x08 }, /* P2_DEMOD */ + { STV090x_P2_DMDMODCOD, 0x10 }, /* P2_DMDMODCOD */ + { STV090x_P2_DSTATUS, 0x10 }, /* P2_DSTATUS */ + { STV090x_P2_DSTATUS2, 0x88 }, /* P2_DSTATUS2 */ + { STV090x_P2_DMDCFGMD, 0xf9 }, /* P2_DMDCFGMD */ + { STV090x_P2_DMDCFG2, 0x3b }, /* P2_DMDCFG2 */ + { STV090x_P2_DMDISTATE, 0x5c }, /* P2_DMDISTATE */ + { STV090x_P2_DMDTOM, 0x20 }, /* P2_DMDT0M */ + { STV090x_P2_DMDSTATE, 0x1c }, /* P2_DMDSTATE */ + { STV090x_P2_DMDFLYW, 0x00 }, /* P2_DMDFLYW */ + { STV090x_P2_DSTATUS3, 0x00 }, /* P2_DSTATUS3 */ + { STV090x_P2_DMDCFG3, 0x68 }, /* P2_DMDCFG3 */ + { STV090x_P2_DMDCFG4, 0x10 }, /* P2_DMDCFG4 */ + { STV090x_P2_CORRELMANT, 0x70 }, /* P2_CORRELMANT */ + { STV090x_P2_CORRELABS, 0x88 }, /* P2_CORRELABS */ + { STV090x_P2_CORRELEXP, 0xaa }, /* P2_CORRELEXP */ + { STV090x_P2_PLHMODCOD, 0x42 }, /* P2_PLHMODCOD */ + { STV090x_P2_AGCK32, 0x00 }, /* P2_AGCK32 */ + { STV090x_P2_AGC2O, 0x5b }, /* P2_AGC2O */ + { STV090x_P2_AGC2REF, 0x38 }, /* P2_AGC2REF */ + { STV090x_P2_AGC1ADJ, 0x58 }, /* P2_AGC1ADJ */ + { STV090x_P2_AGC2I1, 0x00 }, /* P2_AGC2I1 */ + { STV090x_P2_AGC2I0, 0x60 }, /* P2_AGC2I0 */ + { STV090x_P2_CARCFG, 0xe4 }, /* P2_CARCFG */ + { STV090x_P2_ACLC, 0x1a }, /* P2_ACLC */ + { STV090x_P2_BCLC, 0x09 }, /* P2_BCLC */ + { STV090x_P2_CARFREQ, 0x38 }, /* P2_CARFREQ */ + { STV090x_P2_CARHDR, 0x20 }, /* P2_CARHDR */ + { STV090x_P2_LDT, 0xd0 }, /* P2_LDT */ + { STV090x_P2_LDT2, 0xb0 }, /* P2_LDT2 */ + { STV090x_P2_CFRICFG, 0xf8 }, /* P2_CFRICFG */ + { STV090x_P2_CFRUP1, 0x3f }, /* P2_CFRUP1 */ + { STV090x_P2_CFRUP0, 0xff }, /* P2_CFRUP0 */ + { STV090x_P2_CFRLOW1, 0xc0 }, /* P2_CFRLOW1 */ + { STV090x_P2_CFRLOW0, 0x01 }, /* P2_CFRLOW0 */ + { STV090x_P2_CFRINIT1, 0xfc }, /* P2_CFRINIT1 */ + { STV090x_P2_CFRINIT0, 0xff }, /* P2_CFRINIT0 */ + { STV090x_P2_CFRINC1, 0x03 }, /* P2_CFRINC1 */ + { STV090x_P2_CFRINC0, 0x00 }, /* P2_CFRINC0 */ + { STV090x_P2_CFR2, 0xfc }, /* P2_CFR2 */ + { STV090x_P2_CFR1, 0xff }, /* P2_CFR1 */ + { STV090x_P2_CFR0, 0x00 }, /* P2_CFR0 */ + { STV090x_P2_LDI, 0x80 }, /* P2_LDI */ + { STV090x_P2_TMGCFG, 0xd2 }, /* P2_TMGCFG */ + { STV090x_P2_RTC, 0x88 }, /* P2_RTC */ + { STV090x_P2_RTCS2, 0x66 }, /* P2_RTCS2 */ + { STV090x_P2_TMGTHRISE, 0x20 }, /* P2_TMGTHRISE */ + { STV090x_P2_TMGTHFALL, 0x00 }, /* P2_TMGTHFALL */ + { STV090x_P2_SFRUPRATIO, 0xf0 }, /* P2_SFRUPRATIO */ + { STV090x_P2_SFRLOWRATIO, 0x70 }, /* P2_SFRLOWRATIO */ + { STV090x_P2_KREFTMG, 0x31 }, /* P2_KREFTMG */ + { STV090x_P2_SFRSTEP, 0x58 }, /* P2_SFRSTEP */ + { STV090x_P2_TMGCFG2, 0x01 }, /* P2_TMGCFG2 */ + { STV090x_P2_SFRINIT1, 0x03 }, /* P2_SFRINIT1 */ + { STV090x_P2_SFRINIT0, 0x01 }, /* P2_SFRINIT0 */ + { STV090x_P2_SFRUP1, 0x83 }, /* P2_SFRUP1 */ + { STV090x_P2_SFRUP0, 0xc0 }, /* P2_SFRUP0 */ + { STV090x_P2_SFRLOW1, 0x82 }, /* P2_SFRLOW1 */ + { STV090x_P2_SFRLOW0, 0xa0 }, /* P2_SFRLOW0 */ + { STV090x_P2_SFR3, 0x03 }, /* P2_SFR3 */ + { STV090x_P2_SFR2, 0x01 }, /* P2_SFR2 */ + { STV090x_P2_SFR1, 0x00 }, /* P2_SFR1 */ + { STV090x_P2_SFR0, 0x00 }, /* P2_SFR0 */ + { STV090x_P2_TMGREG2, 0x00 }, /* P2_TMGREG2 */ + { STV090x_P2_TMGREG1, 0x00 }, /* P2_TMGREG1 */ + { STV090x_P2_TMGREG0, 0x00 }, /* P2_TMGREG0 */ + { STV090x_P2_TMGLOCK1, 0x00 }, /* P2_TMGLOCK1 */ + { STV090x_P2_TMGLOCK0, 0x00 }, /* P2_TMGLOCK0 */ + { STV090x_P2_TMGOBS, 0x10 }, /* P2_TMGOBS */ + { STV090x_P2_EQUALCFG, 0x41 }, /* P2_EQUALCFG */ + { STV090x_P2_EQUAI1, 0xf0 }, /* P2_EQUAI1 */ + { STV090x_P2_EQUAQ1, 0x00 }, /* P2_EQUAQ1 */ + { STV090x_P2_EQUAI2, 0xf0 }, /* P2_EQUAI2 */ + { STV090x_P2_EQUAQ2, 0x00 }, /* P2_EQUAQ2 */ + { STV090x_P2_EQUAI3, 0xf0 }, /* P2_EQUAI3 */ + { STV090x_P2_EQUAQ3, 0x00 }, /* P2_EQUAQ3 */ + { STV090x_P2_EQUAI4, 0xf0 }, /* P2_EQUAI4 */ + { STV090x_P2_EQUAQ4, 0x00 }, /* P2_EQUAQ4 */ + { STV090x_P2_EQUAI5, 0xf0 }, /* P2_EQUAI5 */ + { STV090x_P2_EQUAQ5, 0x00 }, /* P2_EQUAQ5 */ + { STV090x_P2_EQUAI6, 0xf0 }, /* P2_EQUAI6 */ + { STV090x_P2_EQUAQ6, 0x00 }, /* P2_EQUAQ6 */ + { STV090x_P2_EQUAI7, 0xf0 }, /* P2_EQUAI7 */ + { STV090x_P2_EQUAQ7, 0x00 }, /* P2_EQUAQ7 */ + { STV090x_P2_EQUAI8, 0xf0 }, /* P2_EQUAI8 */ + { STV090x_P2_EQUAQ8, 0x00 }, /* P2_EQUAQ8 */ + { STV090x_P2_NNOSDATAT1, 0x01 }, /* P2_NNOSDATAT1 */ + { STV090x_P2_NNOSDATAT0, 0x65 }, /* P2_NNOSDATAT0 */ + { STV090x_P2_NNOSDATA1, 0x00 }, /* P2_NNOSDATA1 */ + { STV090x_P2_NNOSDATA0, 0x0d }, /* P2_NNOSDATA0 */ + { STV090x_P2_NNOSPLHT1, 0x4d }, /* P2_NNOSPLHT1 */ + { STV090x_P2_NNOSPLHT0, 0x6a }, /* P2_NNOSPLHT0 */ + { STV090x_P2_NNOSPLH1, 0x57 }, /* P2_NNOSPLH1 */ + { STV090x_P2_NNOSPLH0, 0x52 }, /* P2_NNOSPLH0 */ + { STV090x_P2_NOSDATAT1, 0x01 }, /* P2_NOSDATAT1 */ + { STV090x_P2_NOSDATAT0, 0x39 }, /* P2_NOSDATAT0 */ + { STV090x_P2_NOSDATA1, 0x00 }, /* P2_NOSDATA1 */ + { STV090x_P2_NOSDATA0, 0x0a }, /* P2_NOSDATA0 */ + { STV090x_P2_NOSPLHT1, 0x43 }, /* P2_NOSPLHT1 */ + { STV090x_P2_NOSPLHT0, 0xbd }, /* P2_NOSPLHT0 */ + { STV090x_P2_NNOSPLH1, 0x42 }, /* P2_NOSPLH1 */ + { STV090x_P2_NNOSPLH0, 0xdb }, /* P2_NOSPLH0 */ + { STV090x_P2_CAR2CFG, 0x26 }, /* P2_CAR2CFG */ + { STV090x_P2_ACLC2, 0x28 }, /* P2_ACLC2 */ + { STV090x_P2_BCLC2, 0x25 }, /* P2_BCLC2 */ +#if 0 + { STV090x_P2_CFR22, 0x00 }, /* P2_CFR22 */ + { STV090x_P2_CFR21, 0x00 }, /* P2_CFR21 */ + { STV090x_P2_CFR20, 0x00 }, /* P2_CFR20 */ +#endif + { STV090x_P2_ACLC2S2Q, 0x6a }, /* P2_ACLC2S2Q */ + { STV090x_P2_ACLC2S28, 0x58 }, /* P2_ACLC2S28 */ + { STV090x_P2_ACLC2S216A, 0x68 }, /* P2_ACLC2S216A */ + { STV090x_P2_ACLC2S232A, 0x68 }, /* P2_ACLC2S232A */ + + { STV090x_P2_BCLC2S2Q, 0x86 }, /* P2_BCLC2S2Q */ + { STV090x_P2_BCLC2S28, 0x86 }, /* P2_BCLC2S28 */ + { STV090x_P2_BCLC2S216A, 0xa5 }, /* P2_BCLC2S216A */ + { STV090x_P2_BCLC2S232A, 0xa5 }, /* P2_BCLC2S232A */ + + { STV090x_P2_PLROOT2, 0x00 }, /* P2_PLROOT2 */ + { STV090x_P2_FECM, 0x10 }, /* P2_FECM */ + { STV090x_P2_PLROOT1, 0x00 }, /* P2_PLROOT1 */ + { STV090x_P2_PLROOT0, 0x01 }, /* P2_PLROOT0 */ + { STV090x_P2_MODCODLST0, 0xff }, /* P2_MODCODLST0 */ + { STV090x_P2_MODCODLST1, 0xff }, /* P2_MODCODLST1 */ + { STV090x_P2_MODCODLST2, 0xff }, /* P2_MODCODLST2 */ + { STV090x_P2_MODCODLST3, 0xff }, /* P2_MODCODLST3 */ + { STV090x_P2_MODCODLST4, 0xff }, /* P2_MODCODLST4 */ + { STV090x_P2_MODCODLST5, 0xff }, /* P2_MODCODLST5 */ + { STV090x_P2_MODCODLST6, 0xff }, /* P2_MODCODLST6 */ + { STV090x_P2_MODCODLST7, 0xcc }, /* P2_MODCODLST7 */ + { STV090x_P2_MODCODLST8, 0xcc }, /* P2_MODCODLST8 */ + { STV090x_P2_MODCODLST9, 0xcc }, /* P2_MODCODLST9 */ + { STV090x_P2_MODCODLSTA, 0xcc }, /* P2_MODCODLSTA */ + { STV090x_P2_MODCODLSTB, 0xcc }, /* P2_MODCODLSTB */ + { STV090x_P2_MODCODLSTC, 0xcc }, /* P2_MODCODLSTC */ + { STV090x_P2_MODCODLSTD, 0xcc }, /* P2_MODCODLSTD */ + { STV090x_P2_MODCODLSTE, 0xcc }, /* P2_MODCODLSTE */ + { STV090x_P2_MODCODLSTF, 0xcf }, /* P2_MODCODLSTF */ + { STV090x_P2_DMDRESCFG, 0x29 }, /* P2_DMDRESCFG */ + { STV090x_P2_DMDRESADR, 0x11 }, /* P2_DMDRESADR */ + { STV090x_P2_DMDRESDATA7, 0x47 }, /* P2_DMDRESDATA7 */ + { STV090x_P2_DMDRESDATA6, 0x82 }, /* P2_DMDRESDATA6 */ + { STV090x_P2_DMDRESDATA5, 0x00 }, /* P2_DMDRESDATA5 */ + { STV090x_P2_DMDRESDATA4, 0x00 }, /* P2_DMDRESDATA4 */ + { STV090x_P2_DMDRESDATA3, 0x92 }, /* P2_DMDRESDATA3 */ + { STV090x_P2_DMDRESDATA2, 0x4c }, /* P2_DMDRESDATA2 */ + { STV090x_P2_DMDRESDATA1, 0x00 }, /* P2_DMDRESDATA1 */ + { STV090x_P2_DMDRESDATA0, 0x07 }, /* P2_DMDRESDATA0 */ + { STV090x_P2_FFEI1, 0x00 }, /* P2_FFEI1 */ + { STV090x_P2_FFEQ1, 0x00 }, /* P2_FFEQ1 */ + { STV090x_P2_FFEI2, 0x00 }, /* P2_FFEI2 */ + { STV090x_P2_FFEQ2, 0x00 }, /* P2_FFEQ2 */ + { STV090x_P2_FFEI3, 0x00 }, /* P2_FFEI3 */ + { STV090x_P2_FFEQ3, 0x00 }, /* P2_FFEQ3 */ + { STV090x_P2_FFEI4, 0x00 }, /* P2_FFEI4 */ + { STV090x_P2_FFEQ4, 0x00 }, /* P2_FFEQ4 */ + { STV090x_P2_FFECFG, 0x31 }, /* P2_FFECFG */ +#if 0 + { STV090x_P2_TNRCFG, 0xef }, /* P2_TNRCFG */ + { STV090x_P2_TNRCFG2, 0x02 }, /* P2_TNRCFG2 */ + { STV090x_P2_TNRXTAL, 0x1b }, /* P2_TNRXTAL */ + { STV090x_P2_TNRSTEPS, 0x87 }, /* P2_TNRSTEPS */ + { STV090x_P2_TNRGAIN, 0x09 }, /* P2_TNRGAIN */ + { STV090x_P2_TNRRF1, 0x47 }, /* P2_TNRRF1 */ + { STV090x_P2_TNRRF0, 0x82 }, /* P2_TNRRF0 */ + { STV090x_P2_TNRBW, 0x24 }, /* P2_TNRBW */ + { STV090x_P2_TNRADJ, 0x1f }, /* P2_TNRADJ */ + { STV090x_P2_TNRCTL2, 0x37 }, /* P2_TNRCTL2 */ + { STV090x_P2_TNRCFG3, 0x02 }, /* P2_TNRCFG3 */ + { STV090x_P2_TNRLAUNCH, 0x00 }, /* P2_TNRLAUNCH */ + { STV090x_P2_TNRLD, 0x00 }, /* P2_TNRLD */ + { STV090x_P2_TNROBSL, 0x50 }, /* P2_TNROBSL */ + { STV090x_P2_TNRRESTE, 0x00 }, /* P2_TNRRESTE */ +#endif + { STV090x_P2_SMAPCOEF7, 0x06 }, /* P2_SMAPCOEF7 */ + { STV090x_P2_SMAPCOEF6, 0x00 }, /* P2_SMAPCOEF6 */ + { STV090x_P2_SMAPCOEF5, 0x04 }, /* P2_SMAPCOEF5 */ + { STV090x_P2_DMDPLHSTAT, 0x00 }, /* P2_DMDPLHSTAT */ + { STV090x_P2_LOCKTIME3, 0xff }, /* P2_LOCKTIME3 */ + { STV090x_P2_LOCKTIME2, 0xf0 }, /* P2_LOCKTIME2 */ + { STV090x_P2_LOCKTIME1, 0x5a }, /* P2_LOCKTIME1 */ + { STV090x_P2_LOCKTIME0, 0x86 }, /* P2_LOCKTIME0 */ + { STV090x_P2_VITSCALE, 0x00 }, /* P2_VITSCALE */ + { STV090x_P2_FECM, 0x10 }, /* P2_FECM */ + { STV090x_P2_VTH12, 0xd0 }, /* P2_VTH12 */ + { STV090x_P2_VTH23, 0x7d }, /* P2_VTH23 */ + { STV090x_P2_VTH34, 0x53 }, /* P2_VTH34 */ + { STV090x_P2_VTH56, 0x2f }, /* P2_VTH56 */ + { STV090x_P2_VTH67, 0x24 }, /* P2_VTH67 */ + { STV090x_P2_VTH78, 0x1f }, /* P2_VTH78 */ + { STV090x_P2_VITCURPUN, 0x0d }, /* P2_VITCURPUN */ + { STV090x_P2_VERROR, 0xff }, /* P2_VERROR */ + { STV090x_P2_PRVIT, 0x3f }, /* P2_PRVIT */ + { STV090x_P2_VAVSRVIT, 0x00 }, /* P2_VAVSRVIT */ + { STV090x_P2_VSTATUSVIT, 0xa7 }, /* P2_VSTATUSVIT */ + { STV090x_P2_VTHINUSE, 0x01 }, /* P2_VTHINUSE */ + { STV090x_P2_KDIV12, 0x27 }, /* P2_KDIV12 */ + { STV090x_P2_KDIV23, 0x32 }, /* P2_KDIV23 */ + { STV090x_P2_KDIV34, 0x32 }, /* P2_KDIV34 */ + { STV090x_P2_KDIV56, 0x32 }, /* P2_KDIV56 */ + { STV090x_P2_KDIV67, 0x32 }, /* P2_KDIV67 */ + { STV090x_P2_KDIV78, 0x50 }, /* P2_KDIV78 */ + { STV090x_P2_PDELCTRL1, 0x00 }, /* P2_PDELCTRL1 */ + { STV090x_P2_PDELCTRL2, 0x20 }, /* P2_PDELCTRL2 */ + { STV090x_P2_HYSTTHRESH, 0x41 }, /* P2_HYSTTHRESH */ + { STV090x_P2_ISIENTRY, 0x00 }, /* P2_ISIENTRY */ + { STV090x_P2_ISIBITENA, 0x00 }, /* P2_ISIBITENA */ + { STV090x_P2_MATSTR1, 0xf0 }, /* P2_MATSTR1 */ + { STV090x_P2_MATSTR0, 0x00 }, /* P2_MATSTR0 */ + { STV090x_P2_UPLSTR1, 0x05 }, /* P2_UPLSTR1 */ + { STV090x_P2_UPLSTR0, 0xe0 }, /* P2_UPLSTR0 */ + { STV090x_P2_DFLSTR1, 0x7d }, /* P2_DFLSTR1 */ + { STV090x_P2_DFLSTR0, 0x80 }, /* P2_DFLSTR0 */ + { STV090x_P2_SYNCSTR, 0x47 }, /* P2_SYNCSTR */ + { STV090x_P2_SYNCDSTR1, 0x00 }, /* P2_SYNCDSTR1 */ + { STV090x_P2_SYNCDSTR0, 0x00 }, /* P2_SYNCDSTR0 */ + { STV090x_P2_PDELSTATUS1, 0x94 }, /* P2_PDELSTATUS1 */ + { STV090x_P2_PDELSTATUS2, 0x90 }, /* P2_PDELSTATUS2 */ + { STV090x_P2_BBFCRCKO1, 0x00 }, /* P2_BBFCRCKO1 */ + { STV090x_P2_BBFCRCKO0, 0x00 }, /* P2_BBFCRCKO0 */ + { STV090x_P2_UPCRCKO1, 0x00 }, /* P2_UPCRCKO1 */ + { STV090x_P2_UPCRCKO0, 0x00 }, /* P2_UPCRCKO0 */ + { STV090x_P2_TSSTATEM, 0xb0 }, /* P2_TSSTATEM */ + { STV090x_P2_TSCFGH, 0x40 }, /* P2_TSCFGH */ + { STV090x_P2_TSCFGM, 0x00 }, /* P2_TSCFGM */ + { STV090x_P2_TSCFGL, 0x20 }, /* P2_TSCFGL */ + { STV090x_P2_TSINSDELH, 0x00 }, /* P2_TSINSDELH */ + { STV090x_P2_TSSPEED, 0xff }, /* P2_TSSPEED */ + { STV090x_P2_TSSTATUS, 0x52 }, /* P2_TSSTATUS */ + { STV090x_P2_TSSTATUS2, 0xea }, /* P2_TSSTATUS2 */ + { STV090x_P2_TSBITRATE1, 0x00 }, /* P2_TSBITRATE1 */ + { STV090x_P2_TSBITRATE0, 0x00 }, /* P2_TSBITRATE0 */ + { STV090x_P2_ERRCTRL1, 0x35 }, /* P2_ERRCTRL1 */ + { STV090x_P2_ERRCNT12, 0x80 }, /* P2_ERRCNT12 */ + { STV090x_P2_ERRCNT11, 0x00 }, /* P2_ERRCNT11 */ + { STV090x_P2_ERRCNT10, 0x00 }, /* P2_ERRCNT10 */ + { STV090x_P2_ERRCTRL2, 0xc1 }, /* P2_ERRCTRL2 */ + { STV090x_P2_ERRCNT22, 0x00 }, /* P2_ERRCNT22 */ + { STV090x_P2_ERRCNT21, 0x00 }, /* P2_ERRCNT21 */ + { STV090x_P2_ERRCNT20, 0x00 }, /* P2_ERRCNT20 */ + { STV090x_P2_FECSPY, 0xa8 }, /* P2_FECSPY */ + { STV090x_P2_FSPYCFG, 0x2c }, /* P2_FSPYCFG */ + { STV090x_P2_FSPYDATA, 0x3a }, /* P2_FSPYDATA */ + { STV090x_P2_FSPYOUT, 0x07 }, /* P2_FSPYOUT */ + { STV090x_P2_FSTATUS, 0x00 }, /* P2_FSTATUS */ + { STV090x_P2_FBERCPT4, 0x00 }, /* P2_FBERCPT4 */ + { STV090x_P2_FBERCPT3, 0x00 }, /* P2_FBERCPT3 */ + { STV090x_P2_FBERCPT2, 0x00 }, /* P2_FBERCPT2 */ + { STV090x_P2_FBERCPT1, 0x00 }, /* P2_FBERCPT1 */ + { STV090x_P2_FBERCPT0, 0x00 }, /* P2_FBERCPT0 */ + { STV090x_P2_FBERERR2, 0x00 }, /* P2_FBERERR2 */ + { STV090x_P2_FBERERR1, 0x00 }, /* P2_FBERERR1 */ + { STV090x_P2_FBERERR0, 0x00 }, /* P2_FBERERR0 */ + { STV090x_P2_FSPYBER, 0x10 }, /* P2_FSPYBER */ + { STV090x_P1_IQCONST, 0x00 }, /* P1_IQCONST */ + { STV090x_P1_NOSCFG, 0x1c }, /* P1_NOSCFG */ + { STV090x_P1_ISYMB, 0x29 }, /* P1_ISYMB */ + { STV090x_P1_QSYMB, 0x29 }, /* P1_QSYMB */ + { STV090x_P1_AGC1CFG, 0x54 }, /* P1_AGC1CFG */ + { STV090x_P1_AGC1CN, 0x99 }, /* P1_AGC1CN */ + { STV090x_P1_AGC1REF, 0x58 }, /* P1_AGC1REF */ + { STV090x_P1_IDCCOMP, 0x03 }, /* P1_IDCCOMP */ + { STV090x_P1_QDCCOMP, 0xfe }, /* P1_QDCCOMP */ + { STV090x_P1_POWERI, 0x91 }, /* P1_POWERI */ + { STV090x_P1_POWERQ, 0x86 }, /* P1_POWERQ */ + { STV090x_P1_AGC1AMM, 0x08 }, /* P1_AGC1AMM */ + { STV090x_P1_AGC1QUAD, 0x02 }, /* P1_AGC1QUAD */ + { STV090x_P1_AGCIQIN1, 0x68 }, /* P1_AGCIQIN1 */ + { STV090x_P1_AGCIQIN0, 0x20 }, /* P1_AGCIQIN0 */ + { STV090x_P1_DEMOD, 0x08 }, /* P1_DEMOD */ + { STV090x_P1_DMDMODCOD, 0x10 }, /* P1_DMDMODCOD */ + { STV090x_P1_DSTATUS, 0x10 }, /* P1_DSTATUS */ + { STV090x_P1_DSTATUS2, 0x80 }, /* P1_DSTATUS2 */ + { STV090x_P1_DMDCFGMD, 0xf9 }, /* P1_DMDCFGMD */ + { STV090x_P1_DMDCFG2, 0x3b }, /* P1_DMDCFG2 */ + { STV090x_P1_DMDISTATE, 0x5c }, /* P1_DMDISTATE */ + { STV090x_P1_DMDTOM, 0x20 }, /* P1_DMDT0M */ + { STV090x_P1_DMDSTATE, 0x1c }, /* P1_DMDSTATE */ + { STV090x_P1_DMDFLYW, 0x00 }, /* P1_DMDFLYW */ + { STV090x_P1_DSTATUS3, 0x00 }, /* P1_DSTATUS3 */ + { STV090x_P1_DMDCFG3, 0x68 }, /* P1_DMDCFG3 */ + { STV090x_P1_DMDCFG4, 0x10 }, /* P1_DMDCFG4 */ + { STV090x_P1_CORRELMANT, 0x70 }, /* P1_CORRELMANT */ + { STV090x_P1_CORRELABS, 0x88 }, /* P1_CORRELABS */ + { STV090x_P1_CORRELEXP, 0xaa }, /* P1_CORRELEXP */ + { STV090x_P1_PLHMODCOD, 0x42 }, /* P1_PLHMODCOD */ + { STV090x_P1_AGCK32, 0x00 }, /* P1_AGCK32 */ + { STV090x_P1_AGC2O, 0x5b }, /* P1_AGC2O */ + { STV090x_P1_AGC2REF, 0x38 }, /* P1_AGC2REF */ + { STV090x_P1_AGC1ADJ, 0x58 }, /* P1_AGC1ADJ */ + { STV090x_P1_AGC2I1, 0x00 }, /* P1_AGC2I1 */ + { STV090x_P1_AGC2I0, 0x60 }, /* P1_AGC2I0 */ + { STV090x_P1_CARCFG, 0xe4 }, /* P1_CARCFG */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P1_ACLC, 0x1a }, /* P1_ACLC */ + { STV090x_P1_BCLC, 0x09 }, /* P1_BCLC */ + { STV090x_P1_CARFREQ, 0x38 }, /* P1_CARFREQ */ + { STV090x_P1_CARHDR, 0x20 }, /* P1_CARHDR */ + { STV090x_P1_LDT, 0xd0 }, /* P1_LDT */ + { STV090x_P1_LDT2, 0xb0 }, /* P1_LDT2 */ + { STV090x_P1_CFRICFG, 0xf8 }, /* P1_CFRICFG */ + { STV090x_P1_CFRUP1, 0x3f }, /* P1_CFRUP1 */ + { STV090x_P1_CFRUP0, 0xff }, /* P1_CFRUP0 */ + { STV090x_P1_CFRLOW1, 0xc0 }, /* P1_CFRLOW1 */ + { STV090x_P1_CFRLOW0, 0x01 }, /* P1_CFRLOW0 */ + { STV090x_P1_CFRINIT1, 0x03 }, /* P1_CFRINIT1 */ + { STV090x_P1_CFRINIT0, 0x00 }, /* P1_CFRINIT0 */ + { STV090x_P1_CFRINC1, 0x03 }, /* P1_CFRINC1 */ + { STV090x_P1_CFRINC0, 0x00 }, /* P1_CFRINC0 */ + { STV090x_P1_CFR2, 0x03 }, /* P1_CFR2 */ + { STV090x_P1_CFR1, 0x00 }, /* P1_CFR1 */ + { STV090x_P1_CFR0, 0x00 }, /* P1_CFR0 */ + { STV090x_P1_LDI, 0x80 }, /* P1_LDI */ + { STV090x_P1_TMGCFG, 0xd3 }, /* P1_TMGCFG */ + { STV090x_P1_RTC, 0x88 }, /* P1_RTC */ + { STV090x_P1_RTCS2, 0x66 }, /* P1_RTCS2 */ + { STV090x_P1_TMGTHRISE, 0x20 }, /* P1_TMGTHRISE */ + { STV090x_P1_TMGTHFALL, 0x00 }, /* P1_TMGTHFALL */ + { STV090x_P1_SFRUPRATIO, 0xf0 }, /* P1_SFRUPRATIO */ + { STV090x_P1_SFRLOWRATIO, 0x70 }, /* P1_SFRLOWRATIO */ + { STV090x_P1_KREFTMG, 0x31 }, /* P1_KREFTMG */ + { STV090x_P1_SFRSTEP, 0x58 }, /* P1_SFRSTEP */ + { STV090x_P1_TMGCFG2, 0x01 }, /* P1_TMGCFG2 */ + { STV090x_P1_SFRINIT1, 0x03 }, /* P1_SFRINIT1 */ + { STV090x_P1_SFRINIT0, 0x01 }, /* P1_SFRINIT0 */ + { STV090x_P1_SFRUP1, 0x83 }, /* P1_SFRUP1 */ + { STV090x_P1_SFRUP0, 0xc0 }, /* P1_SFRUP0 */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P1_SFRLOW1, 0x82 }, /* P1_SFRLOW1 */ + { STV090x_P1_SFRLOW0, 0xa0 }, /* P1_SFRLOW0 */ + { STV090x_P1_SFR3, 0x03 }, /* P1_SFR3 */ + { STV090x_P1_SFR2, 0x01 }, /* P1_SFR2 */ + { STV090x_P1_SFR1, 0x00 }, /* P1_SFR1 */ + { STV090x_P1_SFR0, 0x00 }, /* P1_SFR0 */ + { STV090x_P1_TMGREG2, 0x00 }, /* P1_TMGREG2 */ + { STV090x_P1_TMGREG1, 0x00 }, /* P1_TMGREG1 */ + { STV090x_P1_TMGREG0, 0x00 }, /* P1_TMGREG0 */ + { STV090x_P1_TMGLOCK1, 0x00 }, /* P1_TMGLOCK1 */ + { STV090x_P1_TMGLOCK0, 0x00 }, /* P1_TMGLOCK0 */ + { STV090x_P1_TMGOBS, 0x10 }, /* P1_TMGOBS */ + { STV090x_P1_EQUALCFG, 0x41 }, /* P1_EQUALCFG */ + { STV090x_P1_EQUAI1, 0xf1 }, /* P1_EQUAI1 */ + { STV090x_P1_EQUAQ1, 0x00 }, /* P1_EQUAQ1 */ + { STV090x_P1_EQUAI2, 0xf1 }, /* P1_EQUAI2 */ + { STV090x_P1_EQUAQ2, 0x00 }, /* P1_EQUAQ2 */ + { STV090x_P1_EQUAI3, 0xf1 }, /* P1_EQUAI3 */ + { STV090x_P1_EQUAQ3, 0x00 }, /* P1_EQUAQ3 */ + { STV090x_P1_EQUAI4, 0xf1 }, /* P1_EQUAI4 */ + { STV090x_P1_EQUAQ4, 0x00 }, /* P1_EQUAQ4 */ + { STV090x_P1_EQUAI5, 0xf1 }, /* P1_EQUAI5 */ + { STV090x_P1_EQUAQ5, 0x00 }, /* P1_EQUAQ5 */ + { STV090x_P1_EQUAI6, 0xf1 }, /* P1_EQUAI6 */ + { STV090x_P1_EQUAQ6, 0x00 }, /* P1_EQUAQ6 */ + { STV090x_P1_EQUAI7, 0xf1 }, /* P1_EQUAI7 */ + { STV090x_P1_EQUAQ7, 0x00 }, /* P1_EQUAQ7 */ + { STV090x_P1_EQUAI8, 0xf1 }, /* P1_EQUAI8 */ + { STV090x_P1_EQUAQ8, 0x00 }, /* P1_EQUAQ8 */ + { STV090x_P1_NNOSDATAT1, 0x01 }, /* P1_NNOSDATAT1 */ + { STV090x_P1_NNOSDATAT0, 0xab }, /* P1_NNOSDATAT0 */ + { STV090x_P1_NNOSDATA1, 0x00 }, /* P1_NNOSDATA1 */ + { STV090x_P1_NNOSDATA0, 0x12 }, /* P1_NNOSDATA0 */ + { STV090x_P1_NNOSPLHT1, 0x4d }, /* P1_NNOSPLHT1 */ + { STV090x_P1_NNOSPLHT0, 0x7b }, /* P1_NNOSPLHT0 */ + { STV090x_P1_NNOSPLH1, 0x57 }, /* P1_NNOSPLH1 */ + { STV090x_P1_NNOSPLH0, 0x52 }, /* P1_NNOSPLH0 */ + { STV090x_P1_NOSDATAT1, 0x01 }, /* P1_NOSDATAT1 */ + { STV090x_P1_NOSDATAT0, 0x76 }, /* P1_NOSDATAT0 */ + { STV090x_P1_NOSDATA1, 0x00 }, /* P1_NOSDATA1 */ + { STV090x_P1_NOSDATA0, 0x0e }, /* P1_NOSDATA0 */ + { STV090x_P1_NOSPLHT1, 0x43 }, /* P1_NOSPLHT1 */ + { STV090x_P1_NOSPLHT0, 0xcc }, /* P1_NOSPLHT0 */ + { STV090x_P1_NNOSPLH1, 0x42 }, /* P1_NOSPLH1 */ + { STV090x_P1_NNOSPLH0, 0xdb }, /* P1_NOSPLH0 */ + { STV090x_P1_CAR2CFG, 0x26 }, /* P1_CAR2CFG */ + { STV090x_P1_ACLC2, 0x28 }, /* P1_ACLC2 */ + { STV090x_P1_BCLC2, 0x25 }, /* P1_BCLC2 */ +#if 0 + { STV090x_P1_CFR22, 0x00 }, /* P2_CFR22 */ + { STV090x_P1_CFR21, 0x00 }, /* P2_CFR21 */ + { STV090x_P1_CFR20, 0x00 }, /* P2_CFR20 */ +#endif + { STV090x_P1_ACLC2S2Q, 0x6a }, /* P1_ACLC2S2Q */ + { STV090x_P1_ACLC2S28, 0x58 }, /* P1_ACLC2S28 */ + { STV090x_P1_ACLC2S216A, 0x68 }, /* P2_ACLC2S216A */ + { STV090x_P1_ACLC2S232A, 0x68 }, /* P2_ACLC2S232A */ + { STV090x_P1_BCLC2S2Q, 0x86 }, /* P1_BCLC2S2Q */ + { STV090x_P1_BCLC2S28, 0x86 }, /* P1_BCLC2S28 */ + { STV090x_P1_BCLC2S216A, 0xa5 }, /* P2_BCLC2S216A */ + { STV090x_P1_BCLC2S232A, 0xa5 }, /* P2_BCLC2S232A */ + + { STV090x_P1_PLROOT2, 0x00 }, /* P1_PLROOT2 */ + { STV090x_P1_PLROOT1, 0x00 }, /* P1_PLROOT1 */ + { STV090x_P1_PLROOT0, 0x01 }, /* P1_PLROOT0 */ + { STV090x_P1_MODCODLST0, 0xff }, /* P1_MODCODLST0 */ + { STV090x_P1_MODCODLST1, 0xff }, /* P1_MODCODLST1 */ + { STV090x_P1_MODCODLST2, 0xff }, /* P1_MODCODLST2 */ + { STV090x_P1_MODCODLST3, 0xff }, /* P1_MODCODLST3 */ + { STV090x_P1_MODCODLST4, 0xff }, /* P1_MODCODLST4 */ + { STV090x_P1_MODCODLST5, 0xff }, /* P1_MODCODLST5 */ + { STV090x_P1_MODCODLST6, 0xff }, /* P1_MODCODLST6 */ + { STV090x_P1_MODCODLST7, 0xcc }, /* P1_MODCODLST7 */ + { STV090x_P1_MODCODLST8, 0xcc }, /* P1_MODCODLST8 */ + { STV090x_P1_MODCODLST9, 0xcc }, /* P1_MODCODLST9 */ + { STV090x_P1_MODCODLSTA, 0xcc }, /* P1_MODCODLSTA */ + { STV090x_P1_MODCODLSTB, 0xcc }, /* P1_MODCODLSTB */ + { STV090x_P1_MODCODLSTC, 0xcc }, /* P1_MODCODLSTC */ + { STV090x_P1_MODCODLSTD, 0xcc }, /* P1_MODCODLSTD */ + { STV090x_P1_MODCODLSTE, 0xcc }, /* P1_MODCODLSTE */ + { STV090x_P1_MODCODLSTF, 0xcf }, /* P1_MODCODLSTF */ + { STV090x_P1_DMDRESCFG, 0x29 }, /* P1_DMDRESCFG */ + { STV090x_P1_DMDRESADR, 0x11 }, /* P1_DMDRESADR */ + { STV090x_P1_DMDRESDATA7, 0x4e }, /* P1_DMDRESDATA7 */ + { STV090x_P1_DMDRESDATA6, 0x7f }, /* P1_DMDRESDATA6 */ + { STV090x_P1_DMDRESDATA5, 0x00 }, /* P1_DMDRESDATA5 */ + { STV090x_P1_DMDRESDATA4, 0x04 }, /* P1_DMDRESDATA4 */ + { STV090x_P1_DMDRESDATA3, 0x92 }, /* P1_DMDRESDATA3 */ + { STV090x_P1_DMDRESDATA2, 0xcc }, /* P1_DMDRESDATA2 */ + { STV090x_P1_DMDRESDATA1, 0x0a }, /* P1_DMDRESDATA1 */ + { STV090x_P1_DMDRESDATA0, 0x07 }, /* P1_DMDRESDATA0 */ + { STV090x_P1_FFEI1, 0x00 }, /* P1_FFEI1 */ + { STV090x_P1_FFEQ1, 0x00 }, /* P1_FFEQ1 */ + { STV090x_P1_FFEI2, 0x00 }, /* P1_FFEI2 */ + { STV090x_P1_FFEQ2, 0x00 }, /* P1_FFEQ2 */ + { STV090x_P1_FFEI3, 0x00 }, /* P1_FFEI3 */ + { STV090x_P1_FFEQ3, 0x00 }, /* P1_FFEQ3 */ + { STV090x_P1_FFEI4, 0x00 }, /* P1_FFEI4 */ + { STV090x_P1_FFEQ4, 0x00 }, /* P1_FFEQ4 */ + { STV090x_P1_FFECFG, 0x31 }, /* P1_FFECFG */ +#if 0 + { STV090x_P1_TNRCFG, 0xec }, /* P1_TNRCFG */ + { STV090x_P1_TNRCFG2, 0x82 }, /* P1_TNRCFG2 */ + { STV090x_P1_TNRXTAL, 0x1b }, /* P1_TNRXTAL */ + { STV090x_P1_TNRSTEPS, 0x87 }, /* P1_TNRSTEPS */ + { STV090x_P1_TNRGAIN, 0x09 }, /* P1_TNRGAIN */ + { STV090x_P1_TNRRF1, 0x4e }, /* P1_TNRRF1 */ + { STV090x_P1_TNRRF0, 0x7f }, /* P1_TNRRF0 */ + { STV090x_P1_TNRBW, 0x64 }, /* P1_TNRBW */ + { STV090x_P1_TNRADJ, 0x1f }, /* P1_TNRADJ */ + { STV090x_P1_TNRCTL2, 0x37 }, /* P1_TNRCTL2 */ + { STV090x_P1_TNRCFG3, 0x02 }, /* P1_TNRCFG3 */ + { STV090x_P1_TNRLAUNCH, 0x00 }, /* P1_TNRLAUNCH */ + { STV090x_P1_TNRLD, 0x00 }, /* P1_TNRLD */ + { STV090x_P1_TNROBSL, 0x50 }, /* P1_TNROBSL */ + { STV090x_P1_TNRRESTE, 0x40 }, /* P1_TNRRESTE */ +#endif + { STV090x_P1_SMAPCOEF7, 0x06 }, /* P1_SMAPCOEF7 */ + { STV090x_P1_SMAPCOEF6, 0x00 }, /* P1_SMAPCOEF6 */ + { STV090x_P1_SMAPCOEF5, 0x04 }, /* P1_SMAPCOEF5 */ + { STV090x_P1_DMDPLHSTAT, 0x00 }, /* P1_DMDPLHSTAT */ + { STV090x_P1_LOCKTIME3, 0xff }, /* P1_LOCKTIME3 */ + { STV090x_P1_LOCKTIME2, 0xf0 }, /* P1_LOCKTIME2 */ + { STV090x_P1_LOCKTIME1, 0x73 }, /* P1_LOCKTIME1 */ + { STV090x_P1_LOCKTIME0, 0x27 }, /* P1_LOCKTIME0 */ + { STV090x_P1_VITSCALE, 0x00 }, /* P1_VITSCALE */ + { STV090x_P1_FECM, 0x10 }, /* P1_FECM */ + { STV090x_P1_VTH12, 0xd0 }, /* P1_VTH12 */ + { STV090x_P1_VTH23, 0x7d }, /* P1_VTH23 */ + { STV090x_P1_VTH34, 0x53 }, /* P1_VTH34 */ + { STV090x_P1_VTH56, 0x2f }, /* P1_VTH56 */ + { STV090x_P1_VTH67, 0x24 }, /* P1_VTH67 */ + { STV090x_P1_VTH78, 0x1f }, /* P1_VTH78 */ + { STV090x_P1_VITCURPUN, 0x0d }, /* P1_VITCURPUN */ + { STV090x_P1_VERROR, 0xff }, /* P1_VERROR */ + { STV090x_P1_PRVIT, 0x3f }, /* P1_PRVIT */ + { STV090x_P1_VAVSRVIT, 0x00 }, /* P1_VAVSRVIT */ + { STV090x_P1_VSTATUSVIT, 0xa5 }, /* P1_VSTATUSVIT */ + { STV090x_P1_VTHINUSE, 0x01 }, /* P1_VTHINUSE */ + { STV090x_P1_KDIV12, 0x27 }, /* P1_KDIV12 */ + { STV090x_P1_KDIV23, 0x32 }, /* P1_KDIV23 */ + { STV090x_P1_KDIV34, 0x32 }, /* P1_KDIV34 */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P1_KDIV56, 0x32 }, /* P1_KDIV56 */ + { STV090x_P1_KDIV67, 0x32 }, /* P1_KDIV67 */ + { STV090x_P1_KDIV78, 0x50 }, /* P1_KDIV78 */ + { STV090x_P1_PDELCTRL1, 0x00 }, /* P1_PDELCTRL1 */ + { STV090x_P1_PDELCTRL2, 0x00 }, /* P1_PDELCTRL2 */ + { STV090x_P1_HYSTTHRESH, 0x41 }, /* P1_HYSTTHRESH */ + { STV090x_P1_ISIENTRY, 0x00 }, /* P1_ISIENTRY */ + { STV090x_P1_ISIBITENA, 0x00 }, /* P1_ISIBITENA */ + { STV090x_P1_MATSTR1, 0xf0 }, /* P1_MATSTR1 */ + { STV090x_P1_MATSTR0, 0x00 }, /* P1_MATSTR0 */ + { STV090x_P1_UPLSTR1, 0x05 }, /* P1_UPLSTR1 */ + { STV090x_P1_UPLSTR0, 0xe0 }, /* P1_UPLSTR0 */ + { STV090x_P1_DFLSTR1, 0x7d }, /* P1_DFLSTR1 */ + { STV090x_P1_DFLSTR0, 0x80 }, /* P1_DFLSTR0 */ + { STV090x_P1_SYNCSTR, 0x47 }, /* P1_SYNCSTR */ + { STV090x_P1_SYNCDSTR1, 0x00 }, /* P1_SYNCDSTR1 */ + { STV090x_P1_SYNCDSTR0, 0x00 }, /* P1_SYNCDSTR0 */ + { STV090x_P1_PDELSTATUS1, 0x94 }, /* P1_PDELSTATUS1 */ + { STV090x_P1_PDELSTATUS2, 0x10 }, /* P1_PDELSTATUS2 */ + { STV090x_P1_BBFCRCKO1, 0x00 }, /* P1_BBFCRCKO1 */ + { STV090x_P1_BBFCRCKO0, 0x00 }, /* P1_BBFCRCKO0 */ + { STV090x_P1_UPCRCKO1, 0x00 }, /* P1_UPCRCKO1 */ + { STV090x_P1_UPCRCKO0, 0x00 }, /* P1_UPCRCKO0 */ + { STV090x_P1_TSSTATEM, 0xb0 }, /* P1_TSSTATEM */ + { STV090x_P1_TSCFGH, 0x40 }, /* P1_TSCFGH */ + { STV090x_P1_TSCFGM, 0x00 }, /* P1_TSCFGM */ + { STV090x_P1_TSCFGL, 0x20 }, /* P1_TSCFGL */ + { STV090x_P1_TSINSDELH, 0x00 }, /* P1_TSINSDELH */ + { STV090x_P1_TSSPEED, 0xff }, /* P1_TSSPEED */ + { STV090x_P1_TSSTATUS, 0x52 }, /* P1_TSSTATUS */ + { STV090x_P1_TSSTATUS2, 0x6a }, /* P1_TSSTATUS2 */ + { STV090x_P1_TSBITRATE1, 0x00 }, /* P1_TSBITRATE1 */ + { STV090x_P1_TSBITRATE0, 0x00 }, /* P1_TSBITRATE0 */ + { STV090x_P1_ERRCTRL1, 0x35 }, /* P1_ERRCTRL1 */ + { STV090x_P1_ERRCNT12, 0x80 }, /* P1_ERRCNT12 */ + { STV090x_P1_ERRCNT11, 0x00 }, /* P1_ERRCNT11 */ + { STV090x_P1_ERRCNT10, 0x00 }, /* P1_ERRCNT10 */ + { STV090x_P1_ERRCTRL2, 0xc1 }, /* P1_ERRCTRL2 */ + { STV090x_P1_ERRCNT22, 0x00 }, /* P1_ERRCNT22 */ + { STV090x_P1_ERRCNT21, 0x00 }, /* P1_ERRCNT21 */ + { STV090x_P1_ERRCNT20, 0x00 }, /* P1_ERRCNT20 */ + { STV090x_P1_FECSPY, 0xa8 }, /* P1_FECSPY */ + { STV090x_P1_FSPYCFG, 0x2c }, /* P1_FSPYCFG */ + { STV090x_P1_FSPYDATA, 0x3a }, /* P1_FSPYDATA */ + { STV090x_P1_FSPYOUT, 0x07 }, /* P1_FSPYOUT */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P1_FSTATUS, 0x00 }, /* P1_FSTATUS */ + { STV090x_P1_FBERCPT4, 0x00 }, /* P1_FBERCPT4 */ + { STV090x_P1_FBERCPT3, 0x00 }, /* P1_FBERCPT3 */ + { STV090x_P1_FBERCPT2, 0x00 }, /* P1_FBERCPT2 */ + { STV090x_P1_FBERCPT1, 0x00 }, /* P1_FBERCPT1 */ + { STV090x_P1_FBERCPT0, 0x00 }, /* P1_FBERCPT0 */ + { STV090x_P1_FBERERR2, 0x00 }, /* P1_FBERERR2 */ + { STV090x_P1_FBERERR1, 0x00 }, /* P1_FBERERR1 */ + { STV090x_P1_FBERERR0, 0x00 }, /* P1_FBERERR0 */ + { STV090x_P1_FSPYBER, 0x10 }, /* P1_FSPYBER */ + { STV090x_RCCFGH, 0x20 }, /* RCCFGH */ + { STV090x_TSGENERAL, 0x14 }, /* TSGENERAL */ + { STV090x_TSGENERAL1X, 0x00 }, /* TSGENERAL1X */ + { STV090x_NBITER_NF4, 0x37 }, /* NBITER_NF4 */ + { STV090x_AGCRF2CFG, 0x13 }, + + { STV090x_NBITER_NF5, 0x29 }, /* NBITER_NF5 */ + { STV090x_NBITER_NF6, 0x37 }, /* NBITER_NF6 */ + { STV090x_NBITER_NF7, 0x33 }, /* NBITER_NF7 */ + { STV090x_NBITER_NF8, 0x31 }, /* NBITER_NF8 */ + { STV090x_NBITER_NF9, 0x2f }, /* NBITER_NF9 */ + { STV090x_NBITER_NF10, 0x39 }, /* NBITER_NF10 */ + { STV090x_NBITER_NF11, 0x3a }, /* NBITER_NF11 */ + { STV090x_NBITER_NF12, 0x29 }, /* NBITER_NF12 */ + { STV090x_NBITER_NF13, 0x37 }, /* NBITER_NF13 */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_NBITER_NF14, 0x33 }, /* NBITER_NF14 */ + { STV090x_NBITER_NF15, 0x2f }, /* NBITER_NF15 */ + { STV090x_NBITER_NF16, 0x39 }, /* NBITER_NF16 */ + { STV090x_NBITER_NF17, 0x3a }, /* NBITER_NF17 */ + { STV090x_NBITERNOERR, 0x04 }, /* NBITERNOERR */ + { STV090x_GAINLLR_NF4, 0x21 }, /* GAINLLR_NF4 */ + { STV090x_GAINLLR_NF5, 0x21 }, /* GAINLLR_NF5 */ + { STV090x_GAINLLR_NF6, 0x20 }, /* GAINLLR_NF6 */ + { STV090x_GAINLLR_NF7, 0x1f }, /* GAINLLR_NF7 */ + { STV090x_GAINLLR_NF8, 0x1e }, /* GAINLLR_NF8 */ + { STV090x_GAINLLR_NF9, 0x1e }, /* GAINLLR_NF9 */ + { STV090x_GAINLLR_NF10, 0x1d }, /* GAINLLR_NF10 */ + { STV090x_GAINLLR_NF11, 0x1b }, /* GAINLLR_NF11 */ + { STV090x_GAINLLR_NF12, 0x20 }, /* GAINLLR_NF12 */ + { STV090x_GAINLLR_NF13, 0x20 }, /* GAINLLR_NF13 */ + { STV090x_GAINLLR_NF14, 0x20 }, /* GAINLLR_NF14 */ + { STV090x_GAINLLR_NF15, 0x20 }, /* GAINLLR_NF15 */ + { STV090x_GAINLLR_NF16, 0x20 }, /* GAINLLR_NF16 */ + { STV090x_GAINLLR_NF17, 0x21 }, /* GAINLLR_NF17 */ + { STV090x_CFGEXT, 0x01 }, /* CFGEXT */ + { STV090x_GENCFG, 0x1d }, /* GENCFG */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_LDPCERR1, 0x00 }, /* LDPCERR1 */ + { STV090x_LDPCERR0, 0x00 }, /* LDPCERR0 */ + { STV090x_BCHERR, 0x00 }, /* BCHERR */ + { STV090x_TSTRES0, 0x00 }, /* TSTRES0 */ + { STV090x_P2_TSTDISRX, 0x00 }, /* P2_TSTDISRX */ + { STV090x_P1_TSTDISRX, 0x00 }, /* P1_TSTDISRX */ +}; +#endif + +static struct stv090x_reg stv0900_initval[] = { + + { STV090x_OUTCFG, 0x00 }, + { STV090x_MODECFG, 0xff }, + { STV090x_AGCRF1CFG, 0x11 }, + { STV090x_AGCRF2CFG, 0x13 }, + { STV090x_TSGENERAL1X, 0x14 }, + { STV090x_TSTTNR2, 0x21 }, + { STV090x_TSTTNR4, 0x21 }, + { STV090x_P2_DISTXCTL, 0x22 }, + { STV090x_P2_F22TX, 0xc0 }, + { STV090x_P2_F22RX, 0xc0 }, + { STV090x_P2_DISRXCTL, 0x00 }, +#if 0 + { STV090x_P2_TNRSTEPS, 0x87 }, + { STV090x_P2_TNRGAIN, 0x09 }, +#endif + { STV090x_P2_DMDCFGMD, 0xF9 }, + { STV090x_P2_DEMOD, 0x08 }, + { STV090x_P2_DMDCFG3, 0xc4 }, + { STV090x_P2_CARFREQ, 0xed }, +#if 0 + { STV090x_P2_TNRCFG2, 0x02 }, + { STV090x_P2_TNRCFG3, 0x02 }, +#endif + { STV090x_P2_LDT, 0xd0 }, + { STV090x_P2_LDT2, 0xb8 }, + { STV090x_P2_TMGCFG, 0xd2 }, + { STV090x_P2_TMGTHRISE, 0x20 }, + { STV090x_P1_TMGCFG, 0xd2 }, + + { STV090x_P2_TMGTHFALL, 0x00 }, + { STV090x_P2_FECSPY, 0x88 }, + { STV090x_P2_FSPYDATA, 0x3a }, + { STV090x_P2_FBERCPT4, 0x00 }, + { STV090x_P2_FSPYBER, 0x10 }, + { STV090x_P2_ERRCTRL1, 0x35 }, + { STV090x_P2_ERRCTRL2, 0xc1 }, + { STV090x_P2_CFRICFG, 0xf8 }, + { STV090x_P2_NOSCFG, 0x1c }, + { STV090x_P2_DMDTOM, 0x20 }, + { STV090x_P2_CORRELMANT, 0x70 }, + { STV090x_P2_CORRELABS, 0x88 }, + { STV090x_P2_AGC2O, 0x5b }, + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P2_CARCFG, 0xe4 }, + { STV090x_P2_ACLC, 0x1A }, + { STV090x_P2_BCLC, 0x09 }, + { STV090x_P2_CARHDR, 0x08 }, + { STV090x_P2_KREFTMG, 0xc1 }, + { STV090x_P2_SFRUPRATIO, 0xf0 }, + { STV090x_P2_SFRLOWRATIO, 0x70 }, + { STV090x_P2_SFRSTEP, 0x58 }, + { STV090x_P2_TMGCFG2, 0x01 }, + { STV090x_P2_CAR2CFG, 0x26 }, + { STV090x_P2_BCLC2S2Q, 0x86 }, + { STV090x_P2_BCLC2S28, 0x86 }, + { STV090x_P2_SMAPCOEF7, 0x77 }, + { STV090x_P2_SMAPCOEF6, 0x85 }, + { STV090x_P2_SMAPCOEF5, 0x77 }, + { STV090x_P2_TSCFGL, 0x20 }, + { STV090x_P2_DMDCFG2, 0x3b }, + { STV090x_P2_MODCODLST0, 0xff }, + { STV090x_P2_MODCODLST1, 0xff }, + { STV090x_P2_MODCODLST2, 0xff }, + { STV090x_P2_MODCODLST3, 0xff }, + { STV090x_P2_MODCODLST4, 0xff }, + { STV090x_P2_MODCODLST5, 0xff }, + { STV090x_P2_MODCODLST6, 0xff }, + { STV090x_P2_MODCODLST7, 0xcc }, + { STV090x_P2_MODCODLST8, 0xcc }, + { STV090x_P2_MODCODLST9, 0xcc }, + { STV090x_P2_MODCODLSTA, 0xcc }, + { STV090x_P2_MODCODLSTB, 0xcc }, + { STV090x_P2_MODCODLSTC, 0xcc }, + { STV090x_P2_MODCODLSTD, 0xcc }, + { STV090x_P2_MODCODLSTE, 0xcc }, + { STV090x_P2_MODCODLSTF, 0xcf }, + { STV090x_P1_DISTXCTL, 0x22 }, + { STV090x_P1_F22TX, 0xc0 }, + { STV090x_P1_F22RX, 0xc0 }, + { STV090x_P1_DISRXCTL, 0x00 }, +#if 0 + { STV090x_P1_TNRSTEPS, 0x87 }, + { STV090x_P1_TNRGAIN, 0x09 }, +#endif + { STV090x_P1_DMDCFGMD, 0xf9 }, + { STV090x_P1_DEMOD, 0x08 }, + { STV090x_P1_DMDCFG3, 0xc4 }, + { STV090x_P1_DMDTOM, 0x20 }, + { STV090x_P1_CARFREQ, 0xed }, +#if 0 + { STV090x_P1_TNRCFG2, 0x82 }, + { STV090x_P1_TNRCFG3, 0x02 }, +#endif + { STV090x_P1_LDT, 0xd0 }, + { STV090x_P1_LDT2, 0xb8 }, + { STV090x_P1_TMGCFG, 0xd2 }, + { STV090x_P1_TMGTHRISE, 0x20 }, + { STV090x_P1_TMGTHFALL, 0x00 }, + { STV090x_P1_SFRUPRATIO, 0xf0 }, + { STV090x_P1_SFRLOWRATIO, 0x70 }, + { STV090x_P1_TSCFGL, 0x20 }, + { STV090x_P1_FECSPY, 0x88 }, + { STV090x_P1_FSPYDATA, 0x3a }, + { STV090x_P1_FBERCPT4, 0x00 }, + { STV090x_P1_FSPYBER, 0x10 }, + { STV090x_P1_ERRCTRL1, 0x35 }, + { STV090x_P1_ERRCTRL2, 0xc1 }, + { STV090x_P1_CFRICFG, 0xf8 }, + { STV090x_P1_NOSCFG, 0x1c }, + { STV090x_P1_CORRELMANT, 0x70 }, + { STV090x_P1_CORRELABS, 0x88 }, + { STV090x_P1_AGC2O, 0x5b }, + { STV090x_P1_AGC2REF, 0x38 }, + { STV090x_P1_CARCFG, 0xe4 }, + { STV090x_P1_ACLC, 0x1A }, + { STV090x_P1_BCLC, 0x09 }, + { STV090x_P1_CARHDR, 0x08 }, + { STV090x_P1_KREFTMG, 0xc1 }, + { STV090x_P1_SFRSTEP, 0x58 }, + { STV090x_P1_TMGCFG2, 0x01 }, + { STV090x_P1_CAR2CFG, 0x26 }, + { STV090x_P1_BCLC2S2Q, 0x86 }, + { STV090x_P1_BCLC2S28, 0x86 }, + { STV090x_P1_SMAPCOEF7, 0x77 }, + { STV090x_P1_SMAPCOEF6, 0x85 }, + { STV090x_P1_SMAPCOEF5, 0x77 }, + { STV090x_P1_DMDCFG2, 0x3b }, + { STV090x_P1_MODCODLST0, 0xff }, + { STV090x_P1_MODCODLST1, 0xff }, + { STV090x_P1_MODCODLST2, 0xff }, + { STV090x_P1_MODCODLST3, 0xff }, + { STV090x_P1_MODCODLST4, 0xff }, + { STV090x_P1_MODCODLST5, 0xff }, + { STV090x_P1_MODCODLST6, 0xff }, + { STV090x_P1_MODCODLST7, 0xcc }, + { STV090x_P1_MODCODLST8, 0xcc }, + { STV090x_P1_MODCODLST9, 0xcc }, + { STV090x_P1_MODCODLSTA, 0xcc }, + { STV090x_P1_MODCODLSTB, 0xcc }, + { STV090x_P1_MODCODLSTC, 0xcc }, + { STV090x_P1_MODCODLSTD, 0xcc }, + { STV090x_P1_MODCODLSTE, 0xcc }, + { STV090x_P1_MODCODLSTF, 0xcf }, + { STV090x_GENCFG, 0x1d }, + { STV090x_NBITER_NF4, 0x37 }, + { STV090x_NBITER_NF5, 0x29 }, + { STV090x_NBITER_NF6, 0x37 }, + { STV090x_NBITER_NF7, 0x33 }, + { STV090x_NBITER_NF8, 0x31 }, + { STV090x_NBITER_NF9, 0x2f }, + { STV090x_NBITER_NF10, 0x39 }, + { STV090x_NBITER_NF11, 0x3a }, + { STV090x_NBITER_NF12, 0x29 }, + { STV090x_NBITER_NF13, 0x37 }, + { STV090x_NBITER_NF14, 0x33 }, + { STV090x_NBITER_NF15, 0x2f }, + { STV090x_NBITER_NF16, 0x39 }, + { STV090x_NBITER_NF17, 0x3a }, + { STV090x_NBITERNOERR, 0x04 }, + { STV090x_GAINLLR_NF4, 0x0C }, + { STV090x_GAINLLR_NF5, 0x0F }, + { STV090x_GAINLLR_NF6, 0x11 }, + { STV090x_GAINLLR_NF7, 0x14 }, + { STV090x_GAINLLR_NF8, 0x17 }, + { STV090x_GAINLLR_NF9, 0x19 }, + { STV090x_GAINLLR_NF10, 0x20 }, + { STV090x_GAINLLR_NF11, 0x21 }, + { STV090x_GAINLLR_NF12, 0x0D }, + { STV090x_GAINLLR_NF13, 0x0F }, + { STV090x_GAINLLR_NF14, 0x13 }, + { STV090x_GAINLLR_NF15, 0x1A }, + { STV090x_GAINLLR_NF16, 0x1F }, + { STV090x_GAINLLR_NF17, 0x21 }, + { STV090x_RCCFGH, 0x20 }, + { STV090x_P1_FECM, 0x01 }, /* disable DSS modes */ + { STV090x_P2_FECM, 0x01 }, /* disable DSS modes */ + { STV090x_P1_PRVIT, 0x2F }, /* disable PR 6/7 */ + { STV090x_P2_PRVIT, 0x2F }, /* disable PR 6/7 */ +}; + +static struct stv090x_reg stv0903_initval[] = { + { STV090x_OUTCFG, 0x00 }, + { STV090x_AGCRF1CFG, 0x11 }, + { STV090x_STOPCLK1, 0x48 }, + { STV090x_STOPCLK2, 0x14 }, + { STV090x_TSTTNR1, 0x27 }, + { STV090x_TSTTNR2, 0x21 }, + { STV090x_P1_DISTXCTL, 0x22 }, + { STV090x_P1_F22TX, 0xc0 }, + { STV090x_P1_F22RX, 0xc0 }, + { STV090x_P1_DISRXCTL, 0x00 }, +#if 0 + { STV090x_TNRSTEPS, 0x87 }, + { STV090x_TNRGAIN, 0x09 }, +#endif + { STV090x_P1_DMDCFGMD, 0xF9 }, + { STV090x_P1_DEMOD, 0x08 }, + { STV090x_P1_DMDCFG3, 0xc4 }, + { STV090x_P1_CARFREQ, 0xed }, + { STV090x_P1_TNRCFG2, 0x82 }, +#if 0 + { STV090x_P1_TNRCFG3, 0x03 }, +#endif + { STV090x_P1_LDT, 0xd0 }, + { STV090x_P1_LDT2, 0xb8 }, + { STV090x_P1_TMGCFG, 0xd2 }, + { STV090x_P1_TMGTHRISE, 0x20 }, + { STV090x_P1_TMGTHFALL, 0x00 }, + { STV090x_P1_SFRUPRATIO, 0xf0 }, + { STV090x_P1_SFRLOWRATIO, 0x70 }, + { STV090x_P1_TSCFGL, 0x20 }, + { STV090x_P1_FECSPY, 0x88 }, + { STV090x_P1_FSPYDATA, 0x3a }, + { STV090x_P1_FBERCPT4, 0x00 }, + { STV090x_P1_FSPYBER, 0x10 }, + { STV090x_P1_ERRCTRL1, 0x35 }, + { STV090x_P1_ERRCTRL2, 0xc1 }, + { STV090x_P1_CFRICFG, 0xf8 }, + { STV090x_P1_NOSCFG, 0x1c }, + { STV090x_P1_DMDTOM, 0x20 }, + { STV090x_P1_CORRELMANT, 0x70 }, + { STV090x_P1_CORRELABS, 0x88 }, + { STV090x_P1_AGC2O, 0x5b }, + { STV090x_P1_AGC2REF, 0x38 }, + { STV090x_P1_CARCFG, 0xe4 }, + { STV090x_P1_ACLC, 0x1A }, + { STV090x_P1_BCLC, 0x09 }, + { STV090x_P1_CARHDR, 0x08 }, + { STV090x_P1_KREFTMG, 0xc1 }, + { STV090x_P1_SFRSTEP, 0x58 }, + { STV090x_P1_TMGCFG2, 0x01 }, + { STV090x_P1_CAR2CFG, 0x26 }, + { STV090x_P1_BCLC2S2Q, 0x86 }, + { STV090x_P1_BCLC2S28, 0x86 }, + { STV090x_P1_SMAPCOEF7, 0x77 }, + { STV090x_P1_SMAPCOEF6, 0x85 }, + { STV090x_P1_SMAPCOEF5, 0x77 }, + { STV090x_P1_DMDCFG2, 0x3b }, + { STV090x_P1_MODCODLST0, 0xff }, + { STV090x_P1_MODCODLST1, 0xff }, + { STV090x_P1_MODCODLST2, 0xff }, + { STV090x_P1_MODCODLST3, 0xff }, + { STV090x_P1_MODCODLST4, 0xff }, + { STV090x_P1_MODCODLST5, 0xff }, + { STV090x_P1_MODCODLST6, 0xff }, + { STV090x_P1_MODCODLST7, 0xcc }, + { STV090x_P1_MODCODLST8, 0xcc }, + { STV090x_P1_MODCODLST9, 0xcc }, + { STV090x_P1_MODCODLSTA, 0xcc }, + { STV090x_P1_MODCODLSTB, 0xcc }, + { STV090x_P1_MODCODLSTC, 0xcc }, + { STV090x_P1_MODCODLSTD, 0xcc }, + { STV090x_P1_MODCODLSTE, 0xcc }, + { STV090x_P1_MODCODLSTF, 0xcf }, + { STV090x_GENCFG, 0x1c }, + { STV090x_NBITER_NF4, 0x37 }, + { STV090x_NBITER_NF5, 0x29 }, + { STV090x_NBITER_NF6, 0x37 }, + { STV090x_NBITER_NF7, 0x33 }, + { STV090x_NBITER_NF8, 0x31 }, + { STV090x_NBITER_NF9, 0x2f }, + { STV090x_NBITER_NF10, 0x39 }, + { STV090x_NBITER_NF11, 0x3a }, + { STV090x_NBITER_NF12, 0x29 }, + { STV090x_NBITER_NF13, 0x37 }, + { STV090x_NBITER_NF14, 0x33 }, + { STV090x_NBITER_NF15, 0x2f }, + { STV090x_NBITER_NF16, 0x39 }, + { STV090x_NBITER_NF17, 0x3a }, + { STV090x_NBITERNOERR, 0x04 }, + { STV090x_GAINLLR_NF4, 0x0C }, + { STV090x_GAINLLR_NF5, 0x0F }, + { STV090x_GAINLLR_NF6, 0x11 }, + { STV090x_GAINLLR_NF7, 0x14 }, + { STV090x_GAINLLR_NF8, 0x17 }, + { STV090x_GAINLLR_NF9, 0x19 }, + { STV090x_GAINLLR_NF10, 0x20 }, + { STV090x_GAINLLR_NF11, 0x21 }, + { STV090x_GAINLLR_NF12, 0x0D }, + { STV090x_GAINLLR_NF13, 0x0F }, + { STV090x_GAINLLR_NF14, 0x13 }, + { STV090x_GAINLLR_NF15, 0x1A }, + { STV090x_GAINLLR_NF16, 0x1F }, + { STV090x_GAINLLR_NF17, 0x21 }, + { STV090x_RCCFGH, 0x20 }, + { STV090x_P1_FECM, 0x01 }, /*disable the DSS mode */ + { STV090x_P1_PRVIT, 0x2f } /*disable puncture rate 6/7*/ +}; + +static struct stv090x_reg stv0900_cut20_val[] = { + + { STV090x_P2_DMDCFG3, 0xe8 }, + { STV090x_P2_DMDCFG4, 0x10 }, + { STV090x_P2_CARFREQ, 0x38 }, + { STV090x_P2_CARHDR, 0x20 }, + { STV090x_P2_KREFTMG, 0x5a }, + { STV090x_P2_SMAPCOEF7, 0x06 }, + { STV090x_P2_SMAPCOEF6, 0x00 }, + { STV090x_P2_SMAPCOEF5, 0x04 }, + { STV090x_P2_NOSCFG, 0x0c }, + { STV090x_P1_DMDCFG3, 0xe8 }, + { STV090x_P1_DMDCFG4, 0x10 }, + { STV090x_P1_CARFREQ, 0x38 }, + { STV090x_P1_CARHDR, 0x20 }, + { STV090x_P1_KREFTMG, 0x5a }, + { STV090x_P1_SMAPCOEF7, 0x06 }, + { STV090x_P1_SMAPCOEF6, 0x00 }, + { STV090x_P1_SMAPCOEF5, 0x04 }, + { STV090x_P1_NOSCFG, 0x0c }, + { STV090x_GAINLLR_NF4, 0x21 }, + { STV090x_GAINLLR_NF5, 0x21 }, + { STV090x_GAINLLR_NF6, 0x20 }, + { STV090x_GAINLLR_NF7, 0x1F }, + { STV090x_GAINLLR_NF8, 0x1E }, + { STV090x_GAINLLR_NF9, 0x1E }, + { STV090x_GAINLLR_NF10, 0x1D }, + { STV090x_GAINLLR_NF11, 0x1B }, + { STV090x_GAINLLR_NF12, 0x20 }, + { STV090x_GAINLLR_NF13, 0x20 }, + { STV090x_GAINLLR_NF14, 0x20 }, + { STV090x_GAINLLR_NF15, 0x20 }, + { STV090x_GAINLLR_NF16, 0x20 }, + { STV090x_GAINLLR_NF17, 0x21 }, +}; + +static struct stv090x_reg stv0903_cut20_val[] = { + { STV090x_P1_DMDCFG3, 0xe8 }, + { STV090x_P1_DMDCFG4, 0x10 }, + { STV090x_P1_CARFREQ, 0x38 }, + { STV090x_P1_CARHDR, 0x20 }, + { STV090x_P1_KREFTMG, 0x5a }, + { STV090x_P1_SMAPCOEF7, 0x06 }, + { STV090x_P1_SMAPCOEF6, 0x00 }, + { STV090x_P1_SMAPCOEF5, 0x04 }, + { STV090x_P1_NOSCFG, 0x0c }, + { STV090x_GAINLLR_NF4, 0x21 }, + { STV090x_GAINLLR_NF5, 0x21 }, + { STV090x_GAINLLR_NF6, 0x20 }, + { STV090x_GAINLLR_NF7, 0x1F }, + { STV090x_GAINLLR_NF8, 0x1E }, + { STV090x_GAINLLR_NF9, 0x1E }, + { STV090x_GAINLLR_NF10, 0x1D }, + { STV090x_GAINLLR_NF11, 0x1B }, + { STV090x_GAINLLR_NF12, 0x20 }, + { STV090x_GAINLLR_NF13, 0x20 }, + { STV090x_GAINLLR_NF14, 0x20 }, + { STV090x_GAINLLR_NF15, 0x20 }, + { STV090x_GAINLLR_NF16, 0x20 }, + { STV090x_GAINLLR_NF17, 0x21 } +}; + +/* Cut 2.0 Long Frame Tracking CR loop */ +static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_12, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x1e }, + { STV090x_QPSK_35, 0x2f, 0x3f, 0x2e, 0x2f, 0x3d, 0x0f, 0x0e, 0x2e, 0x3d, 0x0e }, + { STV090x_QPSK_23, 0x2f, 0x3f, 0x2e, 0x2f, 0x0e, 0x0f, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_34, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_45, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_56, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_89, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_910, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_8PSK_35, 0x3c, 0x3e, 0x1c, 0x2e, 0x0c, 0x1e, 0x2b, 0x2d, 0x1b, 0x1d }, + { STV090x_8PSK_23, 0x1d, 0x3e, 0x3c, 0x2e, 0x2c, 0x1e, 0x0c, 0x2d, 0x2b, 0x1d }, + { STV090x_8PSK_34, 0x0e, 0x3e, 0x3d, 0x2e, 0x0d, 0x1e, 0x2c, 0x2d, 0x0c, 0x1d }, + { STV090x_8PSK_56, 0x2e, 0x3e, 0x1e, 0x2e, 0x2d, 0x1e, 0x3c, 0x2d, 0x2c, 0x1d }, + { STV090x_8PSK_89, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x0d, 0x2d, 0x3c, 0x1d }, + { STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d } +}; + +/* Cut 3.0 Long Frame Tracking CR loop */ +static struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_12, 0x3c, 0x2c, 0x0c, 0x2c, 0x1b, 0x2c, 0x1b, 0x1c, 0x0b, 0x3b }, + { STV090x_QPSK_35, 0x0d, 0x0d, 0x0c, 0x0d, 0x1b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, + { STV090x_QPSK_23, 0x1d, 0x0d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, + { STV090x_QPSK_34, 0x1d, 0x1d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, + { STV090x_QPSK_45, 0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, + { STV090x_QPSK_56, 0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, + { STV090x_QPSK_89, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, + { STV090x_QPSK_910, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, + { STV090x_8PSK_35, 0x39, 0x29, 0x39, 0x19, 0x19, 0x19, 0x19, 0x19, 0x09, 0x19 }, + { STV090x_8PSK_23, 0x2a, 0x39, 0x1a, 0x0a, 0x39, 0x0a, 0x29, 0x39, 0x29, 0x0a }, + { STV090x_8PSK_34, 0x2b, 0x3a, 0x1b, 0x1b, 0x3a, 0x1b, 0x1a, 0x0b, 0x1a, 0x3a }, + { STV090x_8PSK_56, 0x0c, 0x1b, 0x3b, 0x3b, 0x1b, 0x3b, 0x3a, 0x3b, 0x3a, 0x1b }, + { STV090x_8PSK_89, 0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b }, + { STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b } +}; + +/* Cut 2.0 Long Frame Tracking CR Loop */ +static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_16APSK_23, 0x0c, 0x0c, 0x0c, 0x0c, 0x1d, 0x0c, 0x3c, 0x0c, 0x2c, 0x0c }, + { STV090x_16APSK_34, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x2d, 0x0c, 0x1d, 0x0c }, + { STV090x_16APSK_45, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c }, + { STV090x_16APSK_56, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c }, + { STV090x_16APSK_89, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c }, + { STV090x_16APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c }, + { STV090x_32APSK_34, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, + { STV090x_32APSK_45, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, + { STV090x_32APSK_56, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, + { STV090x_32APSK_89, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, + { STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c } +}; + +/* Cut 3.0 Long Frame Tracking CR Loop */ +static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut30[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_16APSK_23, 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x0a, 0x3a, 0x0a, 0x2a, 0x0a }, + { STV090x_16APSK_34, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x3b, 0x0a, 0x1b, 0x0a }, + { STV090x_16APSK_45, 0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a }, + { STV090x_16APSK_56, 0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a }, + { STV090x_16APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a }, + { STV090x_16APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a }, + { STV090x_32APSK_34, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, + { STV090x_32APSK_45, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, + { STV090x_32APSK_56, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, + { STV090x_32APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, + { STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } +}; + +static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_14, 0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x2d, 0x1f, 0x3d, 0x3e }, + { STV090x_QPSK_13, 0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x3d, 0x0f, 0x3d, 0x2e }, + { STV090x_QPSK_25, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e } +}; + +static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut30[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_14, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b }, + { STV090x_QPSK_13, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b }, + { STV090x_QPSK_25, 0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b } +}; + +/* Cut 2.0 Short Frame Tracking CR Loop */ +static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut20[] = { + /* MODCOD 2M 5M 10M 20M 30M */ + { STV090x_QPSK, 0x2f, 0x2e, 0x0e, 0x0e, 0x3d }, + { STV090x_8PSK, 0x3e, 0x0e, 0x2d, 0x0d, 0x3c }, + { STV090x_16APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d }, + { STV090x_32APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d } +}; + +/* Cut 3.0 Short Frame Tracking CR Loop */ +static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut30[] = { + /* MODCOD 2M 5M 10M 20M 30M */ + { STV090x_QPSK, 0x2C, 0x2B, 0x0B, 0x0B, 0x3A }, + { STV090x_8PSK, 0x3B, 0x0B, 0x2A, 0x0A, 0x39 }, + { STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }, + { STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A } +}; + +static inline s32 comp2(s32 __x, s32 __width) +{ + if (__width == 32) + return __x; + else + return (__x >= (1 << (__width - 1))) ? (__x - (1 << __width)) : __x; +} + +static int stv090x_read_reg(struct stv090x_state *state, unsigned int reg) +{ + const struct stv090x_config *config = state->config; + int ret; + + u8 b0[] = { reg >> 8, reg & 0xff }; + u8 buf; + + struct i2c_msg msg[] = { + { .addr = config->address, .flags = 0, .buf = b0, .len = 2 }, + { .addr = config->address, .flags = I2C_M_RD, .buf = &buf, .len = 1 } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + if (ret != 2) { + if (ret != -ERESTARTSYS) + dprintk(FE_ERROR, 1, + "Read error, Reg=[0x%02x], Status=%d", + reg, ret); + + return ret < 0 ? ret : -EREMOTEIO; + } + if (unlikely(*state->verbose >= FE_DEBUGREG)) + dprintk(FE_ERROR, 1, "Reg=[0x%02x], data=%02x", + reg, buf); + + return (unsigned int) buf; +} + +static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 *data, u32 count) +{ + const struct stv090x_config *config = state->config; + int ret; + u8 buf[2 + count]; + struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + memcpy(&buf[2], data, count); + + if (unlikely(*state->verbose >= FE_DEBUGREG)) { + int i; + + printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg); + for (i = 0; i < count; i++) + printk(" %02x", data[i]); + printk("\n"); + } + + ret = i2c_transfer(state->i2c, &i2c_msg, 1); + if (ret != 1) { + if (ret != -ERESTARTSYS) + dprintk(FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d", + reg, data[0], count, ret); + return ret < 0 ? ret : -EREMOTEIO; + } + + return 0; +} + +static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data) +{ + return stv090x_write_regs(state, reg, &data, 1); +} + +static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + + reg = STV090x_READ_DEMOD(state, I2CRPT); + if (enable) { + dprintk(FE_DEBUG, 1, "Enable Gate"); + STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) + goto err; + + } else { + dprintk(FE_DEBUG, 1, "Disable Gate"); + STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0); + if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0) + goto err; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static void stv090x_get_lock_tmg(struct stv090x_state *state) +{ + switch (state->algo) { + case STV090x_BLIND_SEARCH: + dprintk(FE_DEBUG, 1, "Blind Search"); + if (state->srate <= 1500000) { /*10Msps< SR <=15Msps*/ + state->DemodTimeout = 1500; + state->FecTimeout = 400; + } else if (state->srate <= 5000000) { /*10Msps< SR <=15Msps*/ + state->DemodTimeout = 1000; + state->FecTimeout = 300; + } else { /*SR >20Msps*/ + state->DemodTimeout = 700; + state->FecTimeout = 100; + } + break; + + case STV090x_COLD_SEARCH: + case STV090x_WARM_SEARCH: + default: + dprintk(FE_DEBUG, 1, "Normal Search"); + if (state->srate <= 1000000) { /*SR <=1Msps*/ + state->DemodTimeout = 4500; + state->FecTimeout = 1700; + } else if (state->srate <= 2000000) { /*1Msps < SR <= 2Msps */ + state->DemodTimeout = 2500; + state->FecTimeout = 1100; + } else if (state->srate <= 5000000) { /*2Msps < SR <= 5Msps */ + state->DemodTimeout = 1000; + state->FecTimeout = 550; + } else if (state->srate <= 10000000) { /*5Msps < SR <= 10Msps */ + state->DemodTimeout = 700; + state->FecTimeout = 250; + } else if (state->srate <= 20000000) { /*10Msps < SR <= 20Msps */ + state->DemodTimeout = 400; + state->FecTimeout = 130; + } else { /*SR >20Msps*/ + state->DemodTimeout = 300; + state->FecTimeout = 100; + } + break; + } + + if (state->algo == STV090x_WARM_SEARCH) + state->DemodTimeout /= 2; +} + +static int stv090x_set_srate(struct stv090x_state *state, u32 srate) +{ + u32 sym; + + if (srate > 60000000) { + sym = (srate << 4); /* SR * 2^16 / master_clk */ + sym /= (state->mclk >> 12); + } else if (srate > 6000000) { + sym = (srate << 6); + sym /= (state->mclk >> 10); + } else { + sym = (srate << 9); + sym /= (state->mclk >> 7); + } + + if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */ + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate) +{ + u32 sym; + + srate = 105 * (srate / 100); + if (srate > 60000000) { + sym = (srate << 4); /* SR * 2^16 / master_clk */ + sym /= (state->mclk >> 12); + } else if (srate > 6000000) { + sym = (srate << 6); + sym /= (state->mclk >> 10); + } else { + sym = (srate << 9); + sym /= (state->mclk >> 7); + } + + if (sym < 0x7fff) { + if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */ + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */ + goto err; + } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate) +{ + u32 sym; + + srate = 95 * (srate / 100); + if (srate > 60000000) { + sym = (srate << 4); /* SR * 2^16 / master_clk */ + sym /= (state->mclk >> 12); + } else if (srate > 6000000) { + sym = (srate << 6); + sym /= (state->mclk >> 10); + } else { + sym = (srate << 9); + sym /= (state->mclk >> 7); + } + + if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0xff)) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */ + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff) +{ + u32 ro; + + switch (rolloff) { + case STV090x_RO_20: + ro = 20; + break; + case STV090x_RO_25: + ro = 25; + break; + case STV090x_RO_35: + default: + ro = 35; + break; + } + + return srate + (srate * ro) / 100; +} + +static int stv090x_set_vit_thacq(struct stv090x_state *state) +{ + if (STV090x_WRITE_DEMOD(state, VTH12, 0x96) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH23, 0x64) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH34, 0x36) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH56, 0x23) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH67, 0x1e) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH78, 0x19) < 0) + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_vit_thtracq(struct stv090x_state *state) +{ + if (STV090x_WRITE_DEMOD(state, VTH12, 0xd0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH23, 0x7d) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH34, 0x53) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH56, 0x2f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH67, 0x24) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH78, 0x1f) < 0) + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_viterbi(struct stv090x_state *state) +{ + switch (state->search_mode) { + case STV090x_SEARCH_AUTO: + if (STV090x_WRITE_DEMOD(state, FECM, 0x10) < 0) /* DVB-S and DVB-S2 */ + goto err; + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x3f) < 0) /* all puncture rate */ + goto err; + break; + case STV090x_SEARCH_DVBS1: + if (STV090x_WRITE_DEMOD(state, FECM, 0x00) < 0) /* disable DSS */ + goto err; + switch (state->fec) { + case STV090x_PR12: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0) + goto err; + break; + + case STV090x_PR23: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0) + goto err; + break; + + case STV090x_PR34: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x04) < 0) + goto err; + break; + + case STV090x_PR56: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x08) < 0) + goto err; + break; + + case STV090x_PR78: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x20) < 0) + goto err; + break; + + default: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x2f) < 0) /* all */ + goto err; + break; + } + break; + case STV090x_SEARCH_DSS: + if (STV090x_WRITE_DEMOD(state, FECM, 0x80) < 0) + goto err; + switch (state->fec) { + case STV090x_PR12: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0) + goto err; + break; + + case STV090x_PR23: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0) + goto err; + break; + + case STV090x_PR67: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x10) < 0) + goto err; + break; + + default: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x13) < 0) /* 1/2, 2/3, 6/7 */ + goto err; + break; + } + break; + default: + break; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_stop_modcod(struct stv090x_state *state) +{ + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xff) < 0) + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_activate_modcod(struct stv090x_state *state) +{ + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_activate_modcod_single(struct stv090x_state *state) +{ + + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xf0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0x0f) < 0) + goto err; + + return 0; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable) +{ + u32 reg; + + switch (state->demod) { + case STV090x_DEMODULATOR_0: + mutex_lock(&demod_lock); + reg = stv090x_read_reg(state, STV090x_STOPCLK2); + STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable); + if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) + goto err; + mutex_unlock(&demod_lock); + break; + + case STV090x_DEMODULATOR_1: + mutex_lock(&demod_lock); + reg = stv090x_read_reg(state, STV090x_STOPCLK2); + STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable); + if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) + goto err; + mutex_unlock(&demod_lock); + break; + + default: + dprintk(FE_ERROR, 1, "Wrong demodulator!"); + break; + } + return 0; +err: + mutex_unlock(&demod_lock); + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_dvbs_track_crl(struct stv090x_state *state) +{ + if (state->dev_ver >= 0x30) { + /* Set ACLC BCLC optimised value vs SR */ + if (state->srate >= 15000000) { + if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x1a) < 0) + goto err; + } else if ((state->srate >= 7000000) && (15000000 > state->srate)) { + if (STV090x_WRITE_DEMOD(state, ACLC, 0x0c) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x1b) < 0) + goto err; + } else if (state->srate < 7000000) { + if (STV090x_WRITE_DEMOD(state, ACLC, 0x2c) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x1c) < 0) + goto err; + } + + } else { + /* Cut 2.0 */ + if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) + goto err; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_delivery_search(struct stv090x_state *state) +{ + u32 reg; + + switch (state->search_mode) { + case STV090x_SEARCH_DVBS1: + case STV090x_SEARCH_DSS: + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + /* Activate Viterbi decoder in legacy search, + * do not use FRESVIT1, might impact VITERBI2 + */ + if (stv090x_vitclk_ctl(state, 0) < 0) + goto err; + + if (stv090x_dvbs_track_crl(state) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */ + goto err; + + if (stv090x_set_vit_thacq(state) < 0) + goto err; + if (stv090x_set_viterbi(state) < 0) + goto err; + break; + + case STV090x_SEARCH_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_vitclk_ctl(state, 1) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) /* stop DVB-S CR loop */ + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) + goto err; + + if (state->dev_ver <= 0x20) { + /* enable S2 carrier loop */ + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) + goto err; + } else { + /* > Cut 3: Stop carrier 3 */ + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0) + goto err; + } + + if (state->demod_mode != STV090x_SINGLE) { + /* Cut 2: enable link during search */ + if (stv090x_activate_modcod(state) < 0) + goto err; + } else { + /* Single demodulator + * Authorize SHORT and LONG frames, + * QPSK, 8PSK, 16APSK and 32APSK + */ + if (stv090x_activate_modcod_single(state) < 0) + goto err; + } + + break; + + case STV090x_SEARCH_AUTO: + default: + /* enable DVB-S2 and DVB-S2 in Auto MODE */ + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + 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_vitclk_ctl(state, 0) < 0) + goto err; + + if (stv090x_dvbs_track_crl(state) < 0) + goto err; + + if (state->dev_ver <= 0x20) { + /* enable S2 carrier loop */ + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) + goto err; + } else { + /* > Cut 3: Stop carrier 3 */ + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0) + goto err; + } + + if (state->demod_mode != STV090x_SINGLE) { + /* Cut 2: enable link during search */ + if (stv090x_activate_modcod(state) < 0) + goto err; + } else { + /* Single demodulator + * Authorize SHORT and LONG frames, + * QPSK, 8PSK, 16APSK and 32APSK + */ + if (stv090x_activate_modcod_single(state) < 0) + 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_viterbi(state) < 0) + goto err; + break; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_start_search(struct stv090x_state *state) +{ + u32 reg, freq_abs; + s16 freq; + + /* Reset demodulator */ + reg = STV090x_READ_DEMOD(state, DMDISTATE); + STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); + if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) + goto err; + + if (state->dev_ver <= 0x20) { + if (state->srate <= 5000000) { + if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRUP1, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0) + goto err; + + /*enlarge the timing bandwith for Low SR*/ + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) + goto err; + } else { + /* If the symbol rate is >5 Msps + Set The carrier search up and low to auto mode */ + if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) + goto err; + /*reduce the timing bandwith for high SR*/ + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) + goto err; + } + } else { + /* >= Cut 3 */ + if (state->srate <= 5000000) { + /* enlarge the timing bandwith for Low SR */ + STV090x_WRITE_DEMOD(state, RTCS2, 0x68); + } else { + /* reduce timing bandwith for high SR */ + STV090x_WRITE_DEMOD(state, RTCS2, 0x44); + } + + /* Set CFR min and max to manual mode */ + STV090x_WRITE_DEMOD(state, CARCFG, 0x46); + + if (state->algo == STV090x_WARM_SEARCH) { + /* WARM Start + * CFR min = -1MHz, + * CFR max = +1MHz + */ + freq_abs = 1000 << 16; + freq_abs /= (state->mclk / 1000); + freq = (s16) freq_abs; + } else { + /* COLD Start + * CFR min =- (SearchRange / 2 + 600KHz) + * CFR max = +(SearchRange / 2 + 600KHz) + * (600KHz for the tuner step size) + */ + freq_abs = (state->search_range / 2000) + 600; + freq_abs = freq_abs << 16; + freq_abs /= (state->mclk / 1000); + freq = (s16) freq_abs; + } + + if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRUP1, LSB(freq)) < 0) + goto err; + + freq *= -1; + + if (STV090x_WRITE_DEMOD(state, CFRLOW1, MSB(freq)) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRLOW0, LSB(freq)) < 0) + goto err; + + } + + if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0) + goto err; + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) + goto err; + + if ((state->search_mode == STV090x_DVBS1) || + (state->search_mode == STV090x_DSS) || + (state->search_mode == STV090x_SEARCH_AUTO)) { + + if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) + goto err; + } + } + + if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xe0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xc0) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + 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; + reg = STV090x_READ_DEMOD(state, DMDCFG2); + STV090x_SETFIELD_Px(reg, S1S2_SEQUENTIAL_FIELD, 0x0); + if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0) + goto err; + + if (state->dev_ver >= 0x20) { + /*Frequency offset detector setting*/ + if (state->srate < 2000000) { + if (state->dev_ver <= 0x20) { + /* Cut 2 */ + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0) + goto err; + } else { + /* Cut 2 */ + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0) + goto err; + } + + if (state->srate < 10000000) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0) + goto err; + } + } else { + if (state->srate < 10000000) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) + goto err; + } + } + + switch (state->algo) { + case STV090x_WARM_SEARCH: + /* The symbol rate and the exact + * carrier Frequency are known + */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) + goto err; + break; + + case STV090x_COLD_SEARCH: + /* The symbol rate is known */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) + goto err; + break; + + default: + break; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_agc2_min_level(struct stv090x_state *state) +{ + u32 agc2_min = 0, agc2 = 0, freq_init, freq_step, reg; + s32 i, j, steps, dir; + + 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); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) /* SR = 65 Msps Max */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) /* SR= 400 ksps Min */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */ + goto err; + 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 = 1; + + dir = 1; + freq_step = (1000000 * 256) / (state->mclk / 256); + freq_init = 0; + + for (i = 0; i < steps; i++) { + if (dir > 0) + freq_init = freq_init + (freq_step * i); + else + freq_init = freq_init - (freq_step * i); + + dir = -1; + + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */ + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_init >> 8) & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_init & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */ + goto err; + msleep(10); + for (j = 0; j < 10; j++) { + agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8; + agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + } + agc2 /= 10; + agc2_min = 0xffff; + if (agc2 < 0xffff) + agc2_min = agc2; + } + + return agc2_min; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk) +{ + u8 r3, r2, r1, r0; + s32 srate, int_1, int_2, tmp_1, tmp_2; + + r3 = STV090x_READ_DEMOD(state, SFR3); + r2 = STV090x_READ_DEMOD(state, SFR2); + r1 = STV090x_READ_DEMOD(state, SFR1); + r0 = STV090x_READ_DEMOD(state, SFR0); + + srate = ((r3 << 24) | (r2 << 16) | (r1 << 8) | r0); + + int_1 = clk >> 16; + int_2 = srate >> 16; + + tmp_1 = clk % 0x10000; + tmp_2 = srate % 0x10000; + + srate = (int_1 * int_2) + + ((int_1 * tmp_2) >> 16) + + ((int_2 * tmp_1) >> 16); + + return srate; +} + +static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) +{ + struct dvb_frontend *fe = &state->frontend; + + 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; + + reg = STV090x_READ_DEMOD(state, DMDISTATE); + STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 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); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x60) < 0) + goto err; + + if (state->dev_ver >= 0x30) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) + goto err; + + } else if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) + goto err; + } + + if (state->srate <= 2000000) + car_step = 1000; + else if (state->srate <= 5000000) + car_step = 2000; + else if (state->srate <= 12000000) + car_step = 3000; + else + car_step = 5000; + + steps = -1 + ((state->search_range / 1000) / car_step); + steps /= 2; + steps = (2 * steps) + 1; + if (steps < 0) + steps = 1; + else if (steps > 10) { + steps = 11; + car_step = (state->search_range / 1000) / 10; + } + cur_step = 0; + dir = 1; + freq = state->frequency; + + 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) + goto err; + msleep(50); + for (i = 0; i < 10; i++) { + 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 /= 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)) + tmg_lock = 1; + else if (cur_step < steps) { + if (dir > 0) + freq += cur_step * car_step; + else + freq -= cur_step * car_step; + + /* Setup tuner */ + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_set_frequency) { + if (state->config->tuner_set_frequency(fe, state->frequency) < 0) + goto err; + } + + if (state->config->tuner_set_bandwidth) { + if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) + goto err; + } + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + msleep(50); + + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_get_status) { + if (state->config->tuner_get_status(fe, ®) < 0) + goto err; + } + + if (reg) + dprintk(FE_DEBUG, 1, "Tuner phase locked"); + else + dprintk(FE_DEBUG, 1, "Tuner unlocked"); + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + } + } + if (!tmg_lock) + srate_coarse = 0; + else + srate_coarse = stv090x_get_srate(state, state->mclk); + + return srate_coarse; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static u32 stv090x_srate_srch_fine(struct stv090x_state *state) +{ + u32 srate_coarse, freq_coarse, sym, reg; + + srate_coarse = stv090x_get_srate(state, state->mclk); + freq_coarse = STV090x_READ_DEMOD(state, CFR2) << 8; + freq_coarse |= STV090x_READ_DEMOD(state, CFR1); + sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ + + if (sym < state->srate) + srate_coarse = 0; + else { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */ + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + if (state->dev_ver >= 0x30) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0) + goto err; + } else if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) + goto err; + } + + if (srate_coarse > 3000000) { + sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ + sym = (sym / 1000) * 65536; + sym /= (state->mclk / 1000); + if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) + goto err; + sym = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */ + sym = (sym / 1000) * 65536; + sym /= (state->mclk / 1000); + if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) + goto err; + sym = (srate_coarse / 1000) * 65536; + sym /= (state->mclk / 1000); + if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) + goto err; + } else { + sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ + sym = (sym / 100) * 65536; + sym /= (state->mclk / 100); + if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) + goto err; + sym = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */ + sym = (sym / 100) * 65536; + sym /= (state->mclk / 100); + if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) + goto err; + sym = (srate_coarse / 100) * 65536; + sym /= (state->mclk / 100); + if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_coarse >> 8) & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_coarse & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) /* trigger acquisition */ + goto err; + } + + return srate_coarse; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout) +{ + s32 timer = 0, lock = 0; + u32 reg; + u8 stat; + + while ((timer < timeout) && (!lock)) { + reg = STV090x_READ_DEMOD(state, DMDSTATE); + stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); + + switch (stat) { + case 0: /* searching */ + case 1: /* first PLH detected */ + default: + dprintk(FE_DEBUG, 1, "Demodulator searching .."); + lock = 0; + break; + case 2: /* DVB-S2 mode */ + case 3: /* DVB-S1/legacy mode */ + reg = STV090x_READ_DEMOD(state, DSTATUS); + lock = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); + break; + } + + if (!lock) + msleep(10); + else + dprintk(FE_DEBUG, 1, "Demodulator acquired LOCK"); + + timer += 10; + } + return lock; +} + +static int stv090x_blind_search(struct stv090x_state *state) +{ + u32 agc2, reg, srate_coarse; + s32 timeout_dmd = 500, cpt_fail, agc2_ovflw, i; + u8 k_ref, k_max, k_min; + int coarse_fail, lock; + + k_max = 120; + k_min = 30; + + agc2 = stv090x_get_agc2_min_level(state); + + if (agc2 > STV090x_SEARCH_AGC2_TH(state->dev_ver)) { + lock = 0; + } else { + + if (state->dev_ver <= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) + goto err; + } else { + /* > Cut 3 */ + if (STV090x_WRITE_DEMOD(state, CARCFG, 0x06) < 0) + goto err; + } + + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) + goto err; + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) /* set viterbi hysteresis */ + goto err; + } + + k_ref = k_max; + do { + if (STV090x_WRITE_DEMOD(state, KREFTMG, k_ref) < 0) + goto err; + if (stv090x_srate_srch_coarse(state) != 0) { + srate_coarse = stv090x_srate_srch_fine(state); + if (srate_coarse != 0) { + stv090x_get_lock_tmg(state); + lock = stv090x_get_dmdlock(state, timeout_dmd); + } else { + lock = 0; + } + } else { + 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); + if (agc2 >= 0xff00) + agc2_ovflw++; + reg = STV090x_READ_DEMOD(state, DSTATUS2); + if ((STV090x_GETFIELD_Px(reg, CFR_OVERFLOW_FIELD) == 0x01) && + (STV090x_GETFIELD_Px(reg, DEMOD_DELOCK_FIELD) == 0x01)) + + cpt_fail++; + } + if ((cpt_fail > 7) || (agc2_ovflw > 7)) + coarse_fail = 1; + + lock = 0; + } + k_ref -= 30; + } while ((k_ref >= k_min) && (!lock) && (!coarse_fail)); + } + + return lock; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_chk_tmg(struct stv090x_state *state) +{ + u32 reg; + s32 tmg_cpt = 0, i; + u8 freq, tmg_thh, tmg_thl; + int tmg_lock; + + freq = STV090x_READ_DEMOD(state, CARFREQ); + tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE); + tmg_thl = STV090x_READ_DEMOD(state, TMGTHFALL); + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); /* stop carrier offset search */ + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, RTC, 0x80) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x40) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x00) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) /* set car ofset to 0 */ + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x65) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* trigger acquisition */ + goto err; + msleep(10); + + for (i = 0; i < 10; i++) { + reg = STV090x_READ_DEMOD(state, DSTATUS); + if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2) + tmg_cpt++; + msleep(1); + } + if (tmg_cpt >= 3) + tmg_lock = 1; + + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) /* DVB-S1 timing */ + goto err; + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) /* DVB-S2 timing */ + goto err; + + if (STV090x_WRITE_DEMOD(state, CARFREQ, freq) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, tmg_thh) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, tmg_thl) < 0) + goto err; + + return tmg_lock; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) +{ + struct dvb_frontend *fe = &state->frontend; + + u32 reg; + s32 car_step, steps, cur_step, dir, freq, timeout_lock; + int lock = 0; + + if (state->srate >= 10000000) + timeout_lock = timeout_dmd / 3; + else + timeout_lock = timeout_dmd / 2; + + lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */ + if (!lock) { + if (state->srate >= 10000000) { + if (stv090x_chk_tmg(state)) { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) + goto err; + lock = stv090x_get_dmdlock(state, timeout_dmd); + } else { + lock = 0; + } + } else { + if (state->srate <= 4000000) + car_step = 1000; + else if (state->srate <= 7000000) + car_step = 2000; + else if (state->srate <= 10000000) + car_step = 3000; + else + car_step = 5000; + + steps = (state->search_range / 1000) / car_step; + steps /= 2; + steps = 2 * (steps + 1); + if (steps < 0) + steps = 2; + else if (steps > 12) + steps = 12; + + cur_step = 1; + dir = 1; + + if (!lock) { + freq = state->frequency; + state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate; + while ((cur_step <= steps) && (!lock)) { + if (dir > 0) + freq += cur_step * car_step; + else + freq -= cur_step * car_step; + + /* Setup tuner */ + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_set_frequency) { + if (state->config->tuner_set_frequency(fe, state->frequency) < 0) + goto err; + } + + if (state->config->tuner_set_bandwidth) { + if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) + goto err; + } + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + msleep(50); + + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_get_status) { + if (state->config->tuner_get_status(fe, ®) < 0) + goto err; + } + + if (reg) + dprintk(FE_DEBUG, 1, "Tuner phase locked"); + else + dprintk(FE_DEBUG, 1, "Tuner unlocked"); + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + 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) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) + goto err; + lock = stv090x_get_dmdlock(state, (timeout_dmd / 3)); + + dir *= -1; + cur_step++; + } + } + } + } + + return lock; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s32 *timeout_sw, s32 *steps) +{ + s32 timeout, inc, steps_max, srate, car_max; + + srate = state->srate; + car_max = state->search_range / 1000; + car_max += car_max / 10; + car_max = 65536 * (car_max / 2); + car_max /= (state->mclk / 1000); + + if (car_max > 0x4000) + car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */ + + inc = srate; + inc /= state->mclk / 1000; + inc *= 256; + inc *= 256; + inc /= 1000; + + switch (state->search_mode) { + case STV090x_SEARCH_DVBS1: + case STV090x_SEARCH_DSS: + inc *= 3; /* freq step = 3% of srate */ + timeout = 20; + break; + + case STV090x_SEARCH_DVBS2: + inc *= 4; + timeout = 25; + break; + + case STV090x_SEARCH_AUTO: + default: + inc *= 3; + timeout = 25; + break; + } + inc /= 100; + if ((inc > car_max) || (inc < 0)) + inc = car_max / 2; /* increment <= 1/8 Mclk */ + + timeout *= 27500; /* 27.5 Msps reference */ + if (srate > 0) + timeout /= (srate / 1000); + + if ((timeout > 100) || (timeout < 0)) + timeout = 100; + + steps_max = (car_max / inc) + 1; /* min steps = 3 */ + if ((steps_max > 100) || (steps_max < 0)) { + steps_max = 100; /* max steps <= 100 */ + inc = car_max / steps_max; + } + *freq_inc = inc; + *timeout_sw = timeout; + *steps = steps_max; + + return 0; +} + +static int stv090x_chk_signal(struct stv090x_state *state) +{ + s32 offst_car, agc2, car_max; + int no_signal; + + offst_car = STV090x_READ_DEMOD(state, CFR2) << 8; + offst_car |= STV090x_READ_DEMOD(state, CFR1); + offst_car = comp2(offst_car, 16); + + agc2 = STV090x_READ_DEMOD(state, AGC2I1) << 8; + agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + car_max = state->search_range / 1000; + + car_max += (car_max / 10); /* 10% margin */ + car_max = (65536 * car_max / 2); + car_max /= state->mclk / 1000; + + if (car_max > 0x4000) + car_max = 0x4000; + + if ((agc2 > 0x2000) || (offst_car > 2 * car_max) || (offst_car < -2 * car_max)) { + no_signal = 1; + dprintk(FE_DEBUG, 1, "No Signal"); + } else { + no_signal = 0; + dprintk(FE_DEBUG, 1, "Found Signal"); + } + + return no_signal; +} + +static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max) +{ + int no_signal, lock = 0; + s32 cpt_step = 0, offst_freq, car_max; + u32 reg; + + car_max = state->search_range / 1000; + car_max += (car_max / 10); + car_max = (65536 * car_max / 2); + car_max /= (state->mclk / 1000); + if (car_max > 0x4000) + car_max = 0x4000; + + if (zigzag) + offst_freq = 0; + else + offst_freq = -car_max + inc; + + do { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, ((offst_freq / 256) & 0xff)) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, offst_freq & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x1); /* stop DVB-S2 packet delin */ + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + + if (zigzag) { + if (offst_freq >= 0) + offst_freq = -offst_freq - 2 * inc; + else + offst_freq = -offst_freq; + } else { + offst_freq += 2 * inc; + } + + cpt_step++; + + lock = stv090x_get_dmdlock(state, timeout); + no_signal = stv090x_chk_signal(state); + + } while ((!lock) && + (!no_signal) && + ((offst_freq - inc) < car_max) && + ((offst_freq + inc) > -car_max) && + (cpt_step < steps_max)); + + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + + return lock; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_sw_algo(struct stv090x_state *state) +{ + int no_signal, zigzag, lock = 0; + u32 reg; + + s32 dvbs2_fly_wheel; + s32 inc, timeout_step, trials, steps_max; + + /* get params */ + stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max); + + switch (state->search_mode) { + case STV090x_SEARCH_DVBS1: + case STV090x_SEARCH_DSS: + /* accelerate the frequency detector */ + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0) + goto err; + } + + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0) + goto err; + zigzag = 0; + break; + + case STV090x_SEARCH_DVBS2: + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) + goto err; + } + + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0) + goto err; + zigzag = 1; + break; + + case STV090x_SEARCH_AUTO: + default: + /* accelerate the frequency detector */ + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) + goto err; + } + + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0) + goto err; + zigzag = 0; + break; + } + + trials = 0; + do { + lock = stv090x_search_car_loop(state, inc, timeout_step, zigzag, steps_max); + no_signal = stv090x_chk_signal(state); + trials++; + + /*run the SW search 2 times maximum*/ + if (lock || no_signal || (trials == 2)) { + /*Check if the demod is not losing lock in DVBS2*/ + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) + goto err; + } + + reg = STV090x_READ_DEMOD(state, DMDSTATE); + if ((lock) && (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == STV090x_DVBS2)) { + /*Check if the demod is not losing lock in DVBS2*/ + msleep(timeout_step); + reg = STV090x_READ_DEMOD(state, DMDFLYW); + dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD); + if (dvbs2_fly_wheel < 0xd) { /*if correct frames is decrementing */ + msleep(timeout_step); + reg = STV090x_READ_DEMOD(state, DMDFLYW); + dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD); + } + if (dvbs2_fly_wheel < 0xd) { + /*FALSE lock, The demod is loosing lock */ + lock = 0; + if (trials < 2) { + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) + goto err; + } + + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0) + goto err; + } + } + } + } + } while ((!lock) && (trials < 2) && (!no_signal)); + + return lock; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state) +{ + u32 reg; + enum stv090x_delsys delsys; + + reg = STV090x_READ_DEMOD(state, DMDSTATE); + if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 2) + delsys = STV090x_DVBS2; + else if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) { + reg = STV090x_READ_DEMOD(state, FECM); + if (STV090x_GETFIELD_Px(reg, DSS_DVB_FIELD) == 1) + delsys = STV090x_DSS; + else + delsys = STV090x_DVBS1; + } else { + delsys = STV090x_ERROR; + } + + return delsys; +} + +/* in Hz */ +static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk) +{ + s32 derot, int_1, int_2, tmp_1, tmp_2; + + derot = STV090x_READ_DEMOD(state, CFR2) << 16; + derot |= STV090x_READ_DEMOD(state, CFR1) << 8; + derot |= STV090x_READ_DEMOD(state, CFR0); + + derot = comp2(derot, 24); + int_1 = state->mclk >> 12; + int_2 = derot >> 12; + + /* carrier_frequency = MasterClock * Reg / 2^24 */ + tmp_1 = state->mclk % 0x1000; + tmp_2 = derot % 0x1000; + + derot = (int_1 * int_2) + + ((int_1 * tmp_2) >> 12) + + ((int_1 * tmp_1) >> 12); + + return derot; +} + +static int stv090x_get_viterbi(struct stv090x_state *state) +{ + u32 reg, rate; + + reg = STV090x_READ_DEMOD(state, VITCURPUN); + rate = STV090x_GETFIELD_Px(reg, VIT_CURPUN_FIELD); + + switch (rate) { + case 13: + state->fec = STV090x_PR12; + break; + + case 18: + state->fec = STV090x_PR23; + break; + + case 21: + state->fec = STV090x_PR34; + break; + + case 24: + state->fec = STV090x_PR56; + break; + + case 25: + state->fec = STV090x_PR67; + break; + + case 26: + state->fec = STV090x_PR78; + break; + + default: + state->fec = STV090x_PRERR; + break; + } + + return 0; +} + +static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *state) +{ + struct dvb_frontend *fe = &state->frontend; + + u8 tmg; + u32 reg; + s32 i = 0, offst_freq; + + msleep(5); + + if (state->algo == STV090x_BLIND_SEARCH) { + tmg = STV090x_READ_DEMOD(state, TMGREG2); + STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c); + while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) { + tmg = STV090x_READ_DEMOD(state, TMGREG2); + msleep(5); + i += 5; + } + } + state->delsys = stv090x_get_std(state); + + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_get_frequency) { + if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) + goto err; + } + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + offst_freq = stv090x_get_car_freq(state, state->mclk) / 1000; + state->frequency += offst_freq; + + if (stv090x_get_viterbi(state) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, DMDMODCOD); + state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD); + state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01; + state->frame_len = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) >> 1; + reg = STV090x_READ_DEMOD(state, TMGOBS); + state->rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD); + reg = STV090x_READ_DEMOD(state, FECM); + state->inversion = STV090x_GETFIELD_Px(reg, IQINV_FIELD); + + if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) { + + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_get_frequency) { + if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) + goto err; + } + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) + return STV090x_RANGEOK; + else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000)) + return STV090x_RANGEOK; + else + return STV090x_OUTOFRANGE; /* Out of Range */ + } else { + if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) + return STV090x_RANGEOK; + else + return STV090x_OUTOFRANGE; + } + + return STV090x_OUTOFRANGE; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate) +{ + s32 offst_tmg; + + offst_tmg = STV090x_READ_DEMOD(state, TMGREG2) << 16; + offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) << 8; + offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0); + + offst_tmg = comp2(offst_tmg, 24); /* 2's complement */ + if (!offst_tmg) + offst_tmg = 1; + + offst_tmg = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg); + offst_tmg /= 320; + + return offst_tmg; +} + +static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_modcod modcod, s32 pilots) +{ + u8 aclc = 0x29; + s32 i; + struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low; + + if (state->dev_ver == 0x20) { + car_loop = stv090x_s2_crl_cut20; + car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut20; + car_loop_apsk_low = stv090x_s2_apsk_crl_cut20; + } else { + /* >= Cut 3 */ + car_loop = stv090x_s2_crl_cut30; + car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut30; + car_loop_apsk_low = stv090x_s2_apsk_crl_cut30; + } + + if (modcod < STV090x_QPSK_12) { + i = 0; + while ((i < 3) && (modcod != car_loop_qpsk_low[i].modcod)) + i++; + + if (i >= 3) + i = 2; + + } else { + i = 0; + while ((i < 14) && (modcod != car_loop[i].modcod)) + i++; + + if (i >= 14) { + i = 0; + while ((i < 11) && (modcod != car_loop_apsk_low[i].modcod)) + i++; + + if (i >= 11) + i = 10; + } + } + + if (modcod <= STV090x_QPSK_25) { + if (pilots) { + if (state->srate <= 3000000) + aclc = car_loop_qpsk_low[i].crl_pilots_on_2; + else if (state->srate <= 7000000) + aclc = car_loop_qpsk_low[i].crl_pilots_on_5; + else if (state->srate <= 15000000) + aclc = car_loop_qpsk_low[i].crl_pilots_on_10; + else if (state->srate <= 25000000) + aclc = car_loop_qpsk_low[i].crl_pilots_on_20; + else + aclc = car_loop_qpsk_low[i].crl_pilots_on_30; + } else { + if (state->srate <= 3000000) + aclc = car_loop_qpsk_low[i].crl_pilots_off_2; + else if (state->srate <= 7000000) + aclc = car_loop_qpsk_low[i].crl_pilots_off_5; + else if (state->srate <= 15000000) + aclc = car_loop_qpsk_low[i].crl_pilots_off_10; + else if (state->srate <= 25000000) + aclc = car_loop_qpsk_low[i].crl_pilots_off_20; + else + aclc = car_loop_qpsk_low[i].crl_pilots_off_30; + } + + } else if (modcod <= STV090x_8PSK_910) { + if (pilots) { + if (state->srate <= 3000000) + aclc = car_loop[i].crl_pilots_on_2; + else if (state->srate <= 7000000) + aclc = car_loop[i].crl_pilots_on_5; + else if (state->srate <= 15000000) + aclc = car_loop[i].crl_pilots_on_10; + else if (state->srate <= 25000000) + aclc = car_loop[i].crl_pilots_on_20; + else + aclc = car_loop[i].crl_pilots_on_30; + } else { + if (state->srate <= 3000000) + aclc = car_loop[i].crl_pilots_off_2; + else if (state->srate <= 7000000) + aclc = car_loop[i].crl_pilots_off_5; + else if (state->srate <= 15000000) + aclc = car_loop[i].crl_pilots_off_10; + else if (state->srate <= 25000000) + aclc = car_loop[i].crl_pilots_off_20; + else + aclc = car_loop[i].crl_pilots_off_30; + } + } else { /* 16APSK and 32APSK */ + if (state->srate <= 3000000) + aclc = car_loop_apsk_low[i].crl_pilots_on_2; + else if (state->srate <= 7000000) + aclc = car_loop_apsk_low[i].crl_pilots_on_5; + else if (state->srate <= 15000000) + aclc = car_loop_apsk_low[i].crl_pilots_on_10; + else if (state->srate <= 25000000) + aclc = car_loop_apsk_low[i].crl_pilots_on_20; + else + aclc = car_loop_apsk_low[i].crl_pilots_on_30; + } + + return aclc; +} + +static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) +{ + struct stv090x_short_frame_crloop *short_crl; + s32 index = 0; + u8 aclc = 0x0b; + + switch (state->modulation) { + case STV090x_QPSK: + default: + index = 0; + break; + case STV090x_8PSK: + index = 1; + break; + case STV090x_16APSK: + index = 2; + break; + case STV090x_32APSK: + index = 3; + break; + } + + if (state->dev_ver >= 0x30) + short_crl = stv090x_s2_short_crl_cut20; + else if (state->dev_ver >= 0x20) + short_crl = stv090x_s2_short_crl_cut30; + + if (state->srate <= 3000000) + aclc = short_crl[index].crl_2; + else if (state->srate <= 7000000) + aclc = short_crl[index].crl_5; + else if (state->srate <= 15000000) + aclc = short_crl[index].crl_10; + else if (state->srate <= 25000000) + aclc = short_crl[index].crl_20; + else + aclc = short_crl[index].crl_30; + + return aclc; +} + +static int stv090x_optimize_track(struct stv090x_state *state) +{ + struct dvb_frontend *fe = &state->frontend; + + enum stv090x_rolloff rolloff; + enum stv090x_modcod modcod; + + s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0; + u32 reg; + + srate = stv090x_get_srate(state, state->mclk); + srate += stv090x_get_tmgoffst(state, srate); + + switch (state->delsys) { + case STV090x_DVBS1: + case STV090x_DSS: + if (state->algo == 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); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + } + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff); + STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x01); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + + if (state->dev_ver >= 0x30) { + if (stv090x_get_viterbi(state) < 0) + goto err; + + if (state->fec == STV090x_PR12) { + if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x98) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x18) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0) + goto err; + } + } + + if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0) + goto err; + break; + + case STV090x_DVBS2: + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0) < 0) + goto err; + if (state->frame_len == STV090x_LONG_FRAME) { + reg = STV090x_READ_DEMOD(state, DMDMODCOD); + modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD); + pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01; + aclc = stv090x_optimize_carloop(state, modcod, pilots); + if (modcod <= STV090x_QPSK_910) { + STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc); + } else if (modcod <= STV090x_8PSK_910) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0) + goto err; + } + if ((state->demod_mode == STV090x_SINGLE) && (modcod > STV090x_8PSK_910)) { + if (modcod <= STV090x_16APSK_910) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0) + goto err; + } + } + } else { + /*Carrier loop setting for short frame*/ + aclc = stv090x_optimize_carloop_short(state); + if (state->modulation == STV090x_QPSK) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc) < 0) + goto err; + } else if (state->modulation == STV090x_8PSK) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0) + goto err; + } else if (state->modulation == STV090x_16APSK) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0) + goto err; + } else if (state->modulation == STV090x_32APSK) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0) + goto err; + } + } + + STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */ + break; + + case STV090x_UNKNOWN: + default: + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + 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; + break; + } + + f_1 = STV090x_READ_DEMOD(state, CFR2); + f_0 = STV090x_READ_DEMOD(state, CFR1); + reg = STV090x_READ_DEMOD(state, TMGOBS); + rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD); + + if (state->algo == STV090x_BLIND_SEARCH) { + STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00); + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) + goto err; + + if (stv090x_set_srate(state, srate) < 0) + goto err; +#if 0 + if (stv090x_set_max_srate(state, state->mclk, srate) < 0) + goto err; + if (stv090x_set_min_srate(state, state->mclk, srate) < 0) + goto err; +#endif + blind_tune = 1; + } + + if (state->dev_ver >= 0x20) { + if ((state->search_mode == STV090x_SEARCH_DVBS1) || + (state->search_mode == STV090x_SEARCH_DSS) || + (state->search_mode == STV090x_SEARCH_AUTO)) { + + if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x0a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x00) < 0) + goto err; + } + } + + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) + goto err; + + /* AUTO tracking MODE */ + if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x80) < 0) + goto err; + /* AUTO tracking MODE */ + if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0) + goto err; + + if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) { + /* update initial carrier freq with the found freq offset */ + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) + goto err; + state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000; + + if ((state->dev_ver >= 0x20) || (blind_tune == 1)) { + + if (state->algo != STV090x_WARM_SEARCH) { + + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_set_bandwidth) { + if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) + goto err; + } + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + } + } + if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) + msleep(50); /* blind search: wait 50ms for SR stabilization */ + else + msleep(5); + + stv090x_get_lock_tmg(state); + + if (!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) + goto err; + + i = 0; + + while ((!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) && (i <= 2)) { + + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) + goto err; + i++; + } + } + + } + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) + goto err; + } + + if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS)) + stv090x_set_vit_thtracq(state); + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_feclock(struct stv090x_state *state, s32 timeout) +{ + s32 timer = 0, lock = 0, stat; + u32 reg; + + while ((timer < timeout) && (!lock)) { + reg = STV090x_READ_DEMOD(state, DMDSTATE); + stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); + + switch (stat) { + case 0: /* searching */ + case 1: /* first PLH detected */ + default: + lock = 0; + break; + + case 2: /* DVB-S2 mode */ + reg = STV090x_READ_DEMOD(state, PDELSTATUS1); + lock = STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD); + break; + + case 3: /* DVB-S1/legacy mode */ + reg = STV090x_READ_DEMOD(state, VSTATUSVIT); + lock = STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD); + break; + } + if (!lock) { + msleep(10); + timer += 10; + } + } + return lock; +} + +static int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 timeout_fec) +{ + u32 reg; + s32 timer = 0; + int lock; + + lock = stv090x_get_dmdlock(state, timeout_dmd); + if (lock) + lock = stv090x_get_feclock(state, timeout_fec); + + if (lock) { + lock = 0; + + while ((timer < timeout_fec) && (!lock)) { + reg = STV090x_READ_DEMOD(state, TSSTATUS); + lock = STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD); + msleep(1); + timer++; + } + } + + return lock; +} + +static int stv090x_set_s2rolloff(struct stv090x_state *state) +{ + u32 reg; + + if (state->dev_ver <= 0x20) { + /* rolloff to auto mode if DVBS2 */ + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + } else { + /* DVB-S2 rolloff to auto mode if DVBS2 */ + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +#if 0 +static enum stv090x_signal_state stv090x_acq_fixs1(struct stv090x_state *state) +{ + s32 srate, f_1, f_2; + enum stv090x_signal_state signal_state = STV090x_NODATA; + u32 reg; + int lock; + + reg = STV090x_READ_DEMOD(state, DMDSTATE); + if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) { /* DVB-S mode */ + srate = stv090x_get_srate(state, state->mclk); + srate += stv090x_get_tmgoffst(state, state->srate); + + if (state->algo == STV090x_BLIND_SEARCH) { + if (stv090x_set_srate(state, state->srate) < 0) + goto err; + } + + stv090x_get_lock_tmg(state); + + f_1 = STV090x_READ_DEMOD(state, CFR2); + f_2 = STV090x_READ_DEMOD(state, CFR1); + + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, STV090x_IQ_SWAP); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0) /* stop demod */ + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_2) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* warm start trigger */ + goto err; + + if (stv090x_get_lock(state, state->DemodTimeout, state->FecTimeout)) { + lock = 1; + stv090x_get_sig_params(state); + stv090x_optimize_track(state); + } else { + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, STV090x_IQ_NORMAL); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_2) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* warm start trigger */ + goto err; + if (stv090x_get_lock(state, state->DemodTimeout, state->FecTimeout)) { + lock = 1; + signal_state = stv090x_get_sig_params(state); + stv090x_optimize_track(state); + } + } + } else { + lock = 0; + } + + return signal_state; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} +#endif + +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; + int lock = 0, low_sr = 0, no_signal = 0; + + reg = STV090x_READ_DEMOD(state, TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */ + goto err; + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) /* cut 2.0 */ + goto err; + } + + stv090x_get_lock_tmg(state); + + if (state->algo == STV090x_BLIND_SEARCH) { + state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */ + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) /* wider srate scan */ + goto err; + if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0) + goto err; + if (stv090x_set_srate(state, 1000000) < 0) /* inital srate = 1Msps */ + goto err; + } else { + /* known srate */ + if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0) + goto err; + + if (state->srate < 2000000) { + /* SR < 2MSPS */ + if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x63) < 0) + goto err; + } else { + /* SR >= 2Msps */ + if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0) + goto err; + } + + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) + goto err; + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0) + goto err; + if (state->algo == STV090x_COLD_SEARCH) + state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10; + else if (state->algo == STV090x_WARM_SEARCH) + state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000; + } + + /* if cold start or warm (Symbolrate is known) + * use a Narrow symbol rate scan range + */ + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) /* narrow srate scan */ + goto err; + + if (stv090x_set_srate(state, state->srate) < 0) + goto err; + + if (stv090x_set_max_srate(state, state->mclk, state->srate) < 0) + goto err; + if (stv090x_set_min_srate(state, state->mclk, state->srate) < 0) + goto err; + + if (state->srate >= 10000000) + low_sr = 0; + else + low_sr = 1; + } + + /* Setup tuner */ + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_set_bbgain) { + if (state->config->tuner_set_bbgain(fe, 10) < 0) /* 10dB */ + goto err; + } + + if (state->config->tuner_set_frequency) { + if (state->config->tuner_set_frequency(fe, state->frequency) < 0) + goto err; + } + + if (state->config->tuner_set_bandwidth) { + if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) + goto err; + } + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + msleep(50); + + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_get_status) { + if (state->config->tuner_get_status(fe, ®) < 0) + goto err; + } + + if (reg) + dprintk(FE_DEBUG, 1, "Tuner phase locked"); + else + dprintk(FE_DEBUG, 1, "Tuner unlocked"); + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + msleep(10); + agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1), + STV090x_READ_DEMOD(state, AGCIQIN0)); + + if (agc1_power == 0) { + /* If AGC1 integrator value is 0 + * then read POWERI, POWERQ + */ + for (i = 0; i < 5; i++) { + power_iq += (STV090x_READ_DEMOD(state, POWERI) + + STV090x_READ_DEMOD(state, POWERQ)) >> 1; + } + power_iq /= 5; + } + + if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) { + dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq); + lock = 0; + + } else { + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); + + if (state->dev_ver <= 0x20) { + /* rolloff to auto mode if DVBS2 */ + STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1); + } else { + /* DVB-S2 rolloff to auto mode if DVBS2 */ + STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 1); + } + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + + if (stv090x_delivery_search(state) < 0) + goto err; + + if (state->algo != STV090x_BLIND_SEARCH) { + if (stv090x_start_search(state) < 0) + goto err; + } + } + + /* need to check for AGC1 state */ + + + + if (state->algo == STV090x_BLIND_SEARCH) + lock = stv090x_blind_search(state); + + else if (state->algo == STV090x_COLD_SEARCH) + lock = stv090x_get_coldlock(state, timeout_dmd); + + else if (state->algo == STV090x_WARM_SEARCH) + lock = stv090x_get_dmdlock(state, timeout_dmd); + + if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) { + if (!low_sr) { + if (stv090x_chk_tmg(state)) + lock = stv090x_sw_algo(state); + } + } + + if (lock) + signal_state = stv090x_get_sig_params(state); + + if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */ + stv090x_optimize_track(state); + + if (state->dev_ver >= 0x20) { + /* >= Cut 2.0 :release TS reset after + * demod lock and optimized Tracking + */ + reg = STV090x_READ_DEMOD(state, TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + + msleep(3); + + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + } + + if (stv090x_get_lock(state, timeout_fec, timeout_fec)) { + lock = 1; + if (state->delsys == STV090x_DVBS2) { + stv090x_set_s2rolloff(state); + + reg = STV090x_READ_DEMOD(state, PDELCTRL2); + STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 1); + if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0) + goto err; + /* Reset DVBS2 packet delinator error counter */ + reg = STV090x_READ_DEMOD(state, PDELCTRL2); + STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 0); + if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */ + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0) + goto err; + } + /* Reset the Total packet counter */ + if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0) + goto err; + /* Reset the packet Error counter2 */ + if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) + goto err; + } else { + lock = 0; + signal_state = STV090x_NODATA; + no_signal = stv090x_chk_signal(state); + } + } + return signal_state; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +{ + struct stv090x_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *props = &fe->dtv_property_cache; + + state->delsys = props->delivery_system; + state->frequency = p->frequency; + state->srate = p->u.qpsk.symbol_rate; + state->search_mode = STV090x_SEARCH_AUTO; + state->algo = STV090x_COLD_SEARCH; + state->fec = STV090x_PRERR; + state->search_range = 2000000; + + if (stv090x_algo(state) == STV090x_RANGEOK) { + dprintk(FE_DEBUG, 1, "Search success!"); + return DVBFE_ALGO_SEARCH_SUCCESS; + } else { + dprintk(FE_DEBUG, 1, "Search failed!"); + return DVBFE_ALGO_SEARCH_FAILED; + } + + 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; + u32 reg; + u8 search_state; + + reg = STV090x_READ_DEMOD(state, DMDSTATE); + search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); + + switch (search_state) { + case 0: /* searching */ + case 1: /* first PLH detected */ + default: + dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)"); + *status = 0; + break; + + case 2: /* DVB-S2 mode */ + 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; + } + } + break; + + case 3: /* DVB-S1/legacy mode */ + dprintk(FE_DEBUG, 1, "Delivery system: DVB-S"); + reg = STV090x_READ_DEMOD(state, DSTATUS); + if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) { + reg = STV090x_READ_DEMOD(state, VSTATUSVIT); + if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_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; + } + + return 0; +} + +static int stv090x_read_per(struct dvb_frontend *fe, u32 *per) +{ + struct stv090x_state *state = fe->demodulator_priv; + + s32 count_4, count_3, count_2, count_1, count_0, count; + u32 reg, h, m, l; + enum fe_status status; + + stv090x_read_status(fe, &status); + if (!(status & FE_HAS_LOCK)) { + *per = 1 << 23; /* Max PER */ + } else { + /* Counter 2 */ + reg = STV090x_READ_DEMOD(state, ERRCNT22); + h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD); + + reg = STV090x_READ_DEMOD(state, ERRCNT21); + m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD); + + reg = STV090x_READ_DEMOD(state, ERRCNT20); + l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD); + + *per = ((h << 16) | (m << 8) | l); + + count_4 = STV090x_READ_DEMOD(state, FBERCPT4); + count_3 = STV090x_READ_DEMOD(state, FBERCPT3); + count_2 = STV090x_READ_DEMOD(state, FBERCPT2); + count_1 = STV090x_READ_DEMOD(state, FBERCPT1); + count_0 = STV090x_READ_DEMOD(state, FBERCPT0); + + if ((!count_4) && (!count_3)) { + count = (count_2 & 0xff) << 16; + count |= (count_1 & 0xff) << 8; + count |= count_0 & 0xff; + } else { + count = 1 << 24; + } + if (count == 0) + *per = 1; + } + if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +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 { + while ((max - min) > 1) { + med = (max + min) / 2; + if (val >= tab[min].read && val < tab[med].read) + max = med; + else + min = med; + } + res = ((val - tab[min].read) * + (tab[max].real - tab[min].real) / + (tab[max].read - tab[min].read)) + + tab[min].real; + } + + return res; +} + +static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + s32 agc; + + reg = STV090x_READ_DEMOD(state, AGCIQIN1); + agc = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); + + *strength = stv090x_table_lookup(stv090x_rf_tab, ARRAY_SIZE(stv090x_rf_tab) - 1, agc); + if (agc > stv090x_rf_tab[0].read) + *strength = 5; + else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read) + *strength = -100; + + return 0; +} + +static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg_0, reg_1, reg, i; + s32 val_0, val_1, val = 0; + u8 lock_f; + + switch (state->delsys) { + case STV090x_DVBS2: + reg = STV090x_READ_DEMOD(state, DSTATUS); + lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); + if (lock_f) { + msleep(5); + for (i = 0; i < 16; i++) { + 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 += 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; + } + break; + + case STV090x_DVBS1: + case STV090x_DSS: + reg = STV090x_READ_DEMOD(state, DSTATUS); + lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); + if (lock_f) { + msleep(5); + for (i = 0; i < 16; i++) { + 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 += 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; + } + break; + default: + break; + } + + return 0; +} + +static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + + reg = STV090x_READ_DEMOD(state, DISTXCTL); + switch (tone) { + case SEC_TONE_ON: + STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + break; + + case SEC_TONE_OFF: + STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + break; + default: + return -EINVAL; + } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + + +static enum dvbfe_algo stv090x_frontend_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_CUSTOM; +} + +static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg, idle = 0, fifo_full = 1; + int i; + + reg = STV090x_READ_DEMOD(state, DISTXCTL); + + STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 2); + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + for (i = 0; i < cmd->msg_len; i++) { + + while (fifo_full) { + reg = STV090x_READ_DEMOD(state, DISTXSTATUS); + fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD); + } + + if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0) + goto err; + } + reg = STV090x_READ_DEMOD(state, DISTXCTL); + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + i = 0; + + while ((!idle) && (i < 10)) { + reg = STV090x_READ_DEMOD(state, DISTXSTATUS); + idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD); + msleep(10); + i++; + } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg, idle = 0, fifo_full = 1; + u8 mode, value; + int i; + + reg = STV090x_READ_DEMOD(state, DISTXCTL); + + if (burst == SEC_MINI_A) { + mode = 3; + value = 0x00; + } else { + mode = 2; + value = 0xFF; + } + + STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode); + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + while (fifo_full) { + reg = STV090x_READ_DEMOD(state, DISTXSTATUS); + fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD); + } + + if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, DISTXCTL); + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + i = 0; + + while ((!idle) && (i < 10)) { + reg = STV090x_READ_DEMOD(state, DISTXSTATUS); + idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD); + msleep(10); + i++; + } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg = 0, i = 0, rx_end = 0; + + while ((rx_end != 1) && (i < 10)) { + msleep(10); + i++; + reg = STV090x_READ_DEMOD(state, DISRX_ST0); + rx_end = STV090x_GETFIELD_Px(reg, RX_END_FIELD); + } + + if (rx_end) { + reply->msg_len = STV090x_GETFIELD_Px(reg, FIFO_BYTENBR_FIELD); + for (i = 0; i < reply->msg_len; i++) + reply->msg[i] = STV090x_READ_DEMOD(state, DISRXDATA); + } + + return 0; +} + +static int stv090x_sleep(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + + dprintk(FE_DEBUG, 1, "Set %s to sleep", + state->device == STV0900 ? "STV0900" : "STV0903"); + + reg = stv090x_read_reg(state, STV090x_SYNTCTRL); + STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) + goto err; + + reg = stv090x_read_reg(state, STV090x_TSTTNR1); + STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0); + if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_wakeup(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + + dprintk(FE_DEBUG, 1, "Wake %s from standby", + state->device == STV0900 ? "STV0900" : "STV0903"); + + reg = stv090x_read_reg(state, STV090x_SYNTCTRL); + STV090x_SETFIELD(reg, STANDBY_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) + goto err; + + reg = stv090x_read_reg(state, STV090x_TSTTNR1); + STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1); + if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static void stv090x_release(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + + kfree(state); +} + +static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode) +{ + u32 reg = 0; + + switch (ldpc_mode) { + case STV090x_DUAL: + default: + if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) { + /* set LDPC to dual mode */ + if (stv090x_write_reg(state, STV090x_GENCFG, 0x1d) < 0) + goto err; + + state->demod_mode = STV090x_DUAL; + + reg = stv090x_read_reg(state, STV090x_TSTRES0); + STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1); + if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) + goto err; + STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0); + if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0) + goto err; + } + break; + + case STV090x_SINGLE: + if (stv090x_stop_modcod(state) < 0) + goto err; + if (stv090x_activate_modcod_single(state) < 0) + goto err; + + if (state->demod == STV090x_DEMODULATOR_1) { + if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */ + goto err; + } else { + if (stv090x_write_reg(state, STV090x_GENCFG, 0x04) < 0) /* path 1 */ + goto err; + } + + reg = stv090x_read_reg(state, STV090x_TSTRES0); + STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1); + if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) + goto err; + STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0); + if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x01); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + break; + } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +/* return (Hz), clk in Hz*/ +static u32 stv090x_get_mclk(struct stv090x_state *state) +{ + const struct stv090x_config *config = state->config; + u32 div, reg; + u8 ratio; + + div = stv090x_read_reg(state, STV090x_NCOARSE); + reg = stv090x_read_reg(state, STV090x_SYNTCTRL); + ratio = STV090x_GETFIELD(reg, SELX1RATIO_FIELD) ? 4 : 6; + + return (div + 1) * config->xtal / ratio; /* kHz */ +} + +static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk) +{ + const struct stv090x_config *config = state->config; + u32 reg, div, clk_sel; + + reg = stv090x_read_reg(state, STV090x_SYNTCTRL); + clk_sel = ((STV090x_GETFIELD(reg, SELX1RATIO_FIELD) == 1) ? 4 : 6); + + div = ((clk_sel * mclk) / config->xtal) - 1; + + reg = stv090x_read_reg(state, STV090x_NCOARSE); + STV090x_SETFIELD(reg, M_DIV_FIELD, div); + if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0) + goto err; + + state->mclk = stv090x_get_mclk(state); + + /*Set the DiseqC frequency to 22KHz */ + div = state->mclk / 704000; + if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_tspath(struct stv090x_state *state) +{ + u32 reg; + + if (state->dev_ver >= 0x20) { + switch (state->config->ts1_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + switch (state->config->ts2_mode) { + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + stv090x_write_reg(state, STV090x_TSGENERAL, 0x00); + break; + + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x06) < 0) /* Mux'd stream mode */ + goto err; + reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); + if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) + goto err; + reg = stv090x_read_reg(state, STV090x_P2_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); + if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0) + goto err; + break; + } + break; + + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + switch (state->config->ts2_mode) { + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) + goto err; + break; + + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0a) < 0) + goto err; + break; + } + break; + } + } else { + switch (state->config->ts1_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + switch (state->config->ts2_mode) { + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10); + break; + + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16); + reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); + if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) + goto err; + reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 0); + if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0) + goto err; + break; + } + break; + + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + switch (state->config->ts2_mode) { + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14); + break; + + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12); + break; + } + break; + } + } + + switch (state->config->ts1_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_DVBCI: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_SERIAL_PUNCTURED: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_SERIAL_CONTINUOUS: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + default: + break; + } + + switch (state->config->ts2_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_DVBCI: + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_SERIAL_PUNCTURED: + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_SERIAL_CONTINUOUS: + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) + goto err; + break; + + default: + break; + } + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) + goto err; + + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_init(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + const struct stv090x_config *config = state->config; + u32 reg; + + if (stv090x_wakeup(fe) < 0) { + dprintk(FE_ERROR, 1, "Error waking device"); + goto err; + } + + if (stv090x_ldpc_mode(state, state->demod_mode) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, TNRCFG2); + STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion); + if (STV090x_WRITE_DEMOD(state, TNRCFG2, reg) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (config->tuner_set_mode) { + if (config->tuner_set_mode(fe, TUNER_WAKE) < 0) + goto err; + } + + if (config->tuner_init) { + if (config->tuner_init(fe) < 0) + goto err; + } + + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + if (stv090x_set_tspath(state) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_setup(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + const struct stv090x_config *config = state->config; + const struct stv090x_reg *stv090x_initval = NULL; + const struct stv090x_reg *stv090x_cut20_val = NULL; + unsigned long t1_size = 0, t2_size = 0; + u32 reg = 0; + + int i; + + if (state->device == STV0900) { + dprintk(FE_DEBUG, 1, "Initializing STV0900"); + stv090x_initval = stv0900_initval; + t1_size = ARRAY_SIZE(stv0900_initval); + stv090x_cut20_val = stv0900_cut20_val; + t2_size = ARRAY_SIZE(stv0900_cut20_val); + } else if (state->device == STV0903) { + dprintk(FE_DEBUG, 1, "Initializing STV0903"); + stv090x_initval = stv0903_initval; + t1_size = ARRAY_SIZE(stv0903_initval); + stv090x_cut20_val = stv0903_cut20_val; + t2_size = ARRAY_SIZE(stv0903_cut20_val); + } +#if 0 + /* write defval to image map */ + for (i = 0; i < (ARRAY_SIZE(stv090x_defval)); i++) { + dprintk(FE_DEBUG, 1, "Setting up defaults"); + if (stv090x_write_reg(state, stv090x_defval[i].addr, stv090x_defval[i].data) < 0) + goto err; + } + /* check register fields */ + + reg = STV090x_READ_DEMOD(state, TNRCFG); + STV090x_SETFIELD_Px(reg, TUN_TYPE, 6); + STV090x_WRITE_DEMOD(state, TNRCFG, reg); +#endif + + /* STV090x init */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Stop Demod */ + goto err; + + msleep(5); + + if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */ + goto err; + + STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level); + if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) /* repeater OFF */ + goto err; + + if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */ + goto err; + msleep(5); + if (stv090x_write_reg(state, STV090x_I2CCFG, 0x08) < 0) /* 1/41 oversampling */ + goto err; + if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) /* enable PLL */ + goto err; + msleep(5); + + /* write initval */ + dprintk(FE_DEBUG, 1, "Setting up initial values"); + for (i = 0; i < t1_size; i++) { + if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0) + goto err; + } + + state->dev_ver = stv090x_read_reg(state, STV090x_MID); + if (state->dev_ver >= 0x20) { + if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) + goto err; + + /* write cut20_val*/ + dprintk(FE_DEBUG, 1, "Setting up Cut 2.0 initial values"); + for (i = 0; i < t2_size; i++) { + if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0) + goto err; + } + + } else if (state->dev_ver < 0x20) { + dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!", + state->dev_ver); + + goto err; + } else if (state->dev_ver > 0x30) { + /* we shouldn't bail out from here */ + dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!", + state->dev_ver); + } + + if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) + goto err; + + stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ + msleep(5); + if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) + goto err; + stv090x_get_mclk(state); + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static struct dvb_frontend_ops stv090x_ops = { + + .info = { + .name = "STV090x Multistandard", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 0, + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | + FE_CAN_2G_MODULATION + }, + + .release = stv090x_release, + .init = stv090x_init, + + .sleep = stv090x_sleep, + .get_frontend_algo = stv090x_frontend_algo, + + .i2c_gate_ctrl = stv090x_i2c_gate_ctrl, + + .diseqc_send_master_cmd = stv090x_send_diseqc_msg, + .diseqc_send_burst = stv090x_send_diseqc_burst, + .diseqc_recv_slave_reply = stv090x_recv_slave_reply, + .set_tone = stv090x_set_tone, + + .search = stv090x_search, + .read_status = stv090x_read_status, + .read_ber = stv090x_read_per, + .read_signal_strength = stv090x_read_signal_strength, + .read_snr = stv090x_read_cnr +}; + + +struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, + struct i2c_adapter *i2c, + enum stv090x_demodulator demod) +{ + struct stv090x_state *state = NULL; + + state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->verbose = &verbose; + state->config = config; + state->i2c = i2c; + state->frontend.ops = stv090x_ops; + state->frontend.demodulator_priv = state; + state->demod = demod; + state->demod_mode = config->demod_mode; /* Single or Dual mode */ + state->device = config->device; + state->rolloff = STV090x_RO_35; /* default */ + + if (state->demod == STV090x_DEMODULATOR_0) + mutex_init(&demod_lock); + + if (stv090x_sleep(&state->frontend) < 0) { + dprintk(FE_ERROR, 1, "Error putting device to sleep"); + goto error; + } + + if (stv090x_setup(&state->frontend) < 0) { + dprintk(FE_ERROR, 1, "Error setting up device"); + goto error; + } + if (stv090x_wakeup(&state->frontend) < 0) { + dprintk(FE_ERROR, 1, "Error waking device"); + goto error; + } + + dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n", + state->device == STV0900 ? "STV0900" : "STV0903", + demod, + state->dev_ver); + + return &state->frontend; + +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(stv090x_attach); +MODULE_PARM_DESC(verbose, "Set Verbosity level"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/stv090x.h b/linux/drivers/media/dvb/frontends/stv090x.h new file mode 100644 index 000000000..e968c98bb --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv090x.h @@ -0,0 +1,106 @@ +/* + STV0900/0903 Multistandard Broadcast Frontend driver + Copyright (C) Manu Abraham <abraham.manu@gmail.com> + + Copyright (C) ST Microelectronics + + 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 __STV090x_H +#define __STV090x_H + +enum stv090x_demodulator { + STV090x_DEMODULATOR_0 = 1, + STV090x_DEMODULATOR_1 +}; + +enum stv090x_device { + STV0903 = 0, + STV0900, +}; + +enum stv090x_mode { + STV090x_DUAL = 0, + STV090x_SINGLE +}; + +enum stv090x_tsmode { + STV090x_TSMODE_SERIAL_PUNCTURED = 1, + STV090x_TSMODE_SERIAL_CONTINUOUS, + STV090x_TSMODE_PARALLEL_PUNCTURED, + STV090x_TSMODE_DVBCI +}; + +enum stv090x_clkmode { + STV090x_CLK_INT = 0, /* Clk i/p = CLKI */ + STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */ +}; + +enum stv090x_i2crpt { + STV090x_RPTLEVEL_256 = 0, + STV090x_RPTLEVEL_128 = 1, + STV090x_RPTLEVEL_64 = 2, + STV090x_RPTLEVEL_32 = 3, + STV090x_RPTLEVEL_16 = 4, + STV090x_RPTLEVEL_8 = 5, + STV090x_RPTLEVEL_4 = 6, + STV090x_RPTLEVEL_2 = 7, +}; + +struct stv090x_config { + enum stv090x_device device; + enum stv090x_mode demod_mode; + enum stv090x_clkmode clk_mode; + + u32 xtal; /* default: 8000000 */ + u8 address; /* default: 0x68 */ + + u32 ref_clk; /* default: 16000000 FIXME to tuner config */ + + u8 ts1_mode; + u8 ts2_mode; + + enum stv090x_i2crpt repeater_level; + + int (*tuner_init) (struct dvb_frontend *fe); + int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); + int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); + int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); + int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth); + int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth); + int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain); + int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain); + int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk); + int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status); +}; + +#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE)) + +extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, + struct i2c_adapter *i2c, + enum stv090x_demodulator demod); +#else + +static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, + struct i2c_adapter *i2c, + enum stv090x_demodulator demod) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_STV090x */ + +#endif /* __STV090x_H */ diff --git a/linux/drivers/media/dvb/frontends/stv090x_priv.h b/linux/drivers/media/dvb/frontends/stv090x_priv.h new file mode 100644 index 000000000..5a4a01740 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv090x_priv.h @@ -0,0 +1,269 @@ +/* + STV0900/0903 Multistandard Broadcast Frontend driver + Copyright (C) Manu Abraham <abraham.manu@gmail.com> + + Copyright (C) ST Microelectronics + + 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 __STV090x_PRIV_H +#define __STV090x_PRIV_H + +#include "dvb_frontend.h" + +#define FE_ERROR 0 +#define FE_NOTICE 1 +#define FE_INFO 2 +#define FE_DEBUG 3 +#define FE_DEBUGREG 4 + +#define dprintk(__y, __z, format, arg...) do { \ + if (__z) { \ + if ((verbose > FE_ERROR) && (verbose > __y)) \ + printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_NOTICE) && (verbose > __y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_INFO) && (verbose > __y)) \ + printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_DEBUG) && (verbose > __y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ + } else { \ + if (verbose > __y) \ + printk(format, ##arg); \ + } \ +} while (0) + +#define STV090x_READ_DEMOD(__state, __reg) (( \ + (__state)->demod == STV090x_DEMODULATOR_1) ? \ + stv090x_read_reg(__state, STV090x_P2_##__reg) : \ + stv090x_read_reg(__state, STV090x_P1_##__reg)) + +#define STV090x_WRITE_DEMOD(__state, __reg, __data) (( \ + (__state)->demod == STV090x_DEMODULATOR_1) ? \ + stv090x_write_reg(__state, STV090x_P2_##__reg, __data) :\ + stv090x_write_reg(__state, STV090x_P1_##__reg, __data)) + +#define STV090x_ADDR_OFFST(__state, __x) (( \ + (__state->demod) == STV090x_DEMODULATOR_1) ? \ + STV090x_P1_##__x : \ + STV090x_P2_##__x) + + +#define STV090x_SETFIELD(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_##bitf) - 1) <<\ + STV090x_OFFST_##bitf))) | \ + (val << STV090x_OFFST_##bitf)) + +#define STV090x_GETFIELD(val, bitf) ((val >> STV090x_OFFST_##bitf) & ((1 << STV090x_WIDTH_##bitf) - 1)) + + +#define STV090x_SETFIELD_Px(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_Px_##bitf) - 1) <<\ + STV090x_OFFST_Px_##bitf))) | \ + (val << STV090x_OFFST_Px_##bitf)) + +#define STV090x_GETFIELD_Px(val, bitf) ((val >> STV090x_OFFST_Px_##bitf) & ((1 << STV090x_WIDTH_Px_##bitf) - 1)) + +#define MAKEWORD16(__a, __b) (((__a) << 8) | (__b)) + +#define MSB(__x) ((__x >> 8) & 0xff) +#define LSB(__x) (__x & 0xff) + + +#define STV090x_IQPOWER_THRESHOLD 30 +#define STV090x_SEARCH_AGC2_TH_CUT20 700 +#define STV090x_SEARCH_AGC2_TH_CUT30 1200 + +#define STV090x_SEARCH_AGC2_TH(__ver) \ + ((__ver <= 0x20) ? \ + STV090x_SEARCH_AGC2_TH_CUT20 : \ + STV090x_SEARCH_AGC2_TH_CUT30) + +enum stv090x_signal_state { + STV090x_NOCARRIER, + STV090x_NODATA, + STV090x_DATAOK, + STV090x_RANGEOK, + STV090x_OUTOFRANGE +}; + +enum stv090x_fec { + STV090x_PR12 = 0, + STV090x_PR23, + STV090x_PR34, + STV090x_PR45, + STV090x_PR56, + STV090x_PR67, + STV090x_PR78, + STV090x_PR89, + STV090x_PR910, + STV090x_PRERR +}; + +enum stv090x_modulation { + STV090x_QPSK, + STV090x_8PSK, + STV090x_16APSK, + STV090x_32APSK, + STV090x_UNKNOWN +}; + +enum stv090x_frame { + STV090x_LONG_FRAME, + STV090x_SHORT_FRAME +}; + +enum stv090x_pilot { + STV090x_PILOTS_OFF, + STV090x_PILOTS_ON +}; + +enum stv090x_rolloff { + STV090x_RO_35, + STV090x_RO_25, + STV090x_RO_20 +}; + +enum stv090x_inversion { + STV090x_IQ_AUTO, + STV090x_IQ_NORMAL, + STV090x_IQ_SWAP +}; + +enum stv090x_modcod { + STV090x_DUMMY_PLF = 0, + STV090x_QPSK_14, + STV090x_QPSK_13, + STV090x_QPSK_25, + STV090x_QPSK_12, + STV090x_QPSK_35, + STV090x_QPSK_23, + STV090x_QPSK_34, + STV090x_QPSK_45, + STV090x_QPSK_56, + STV090x_QPSK_89, + STV090x_QPSK_910, + STV090x_8PSK_35, + STV090x_8PSK_23, + STV090x_8PSK_34, + STV090x_8PSK_56, + STV090x_8PSK_89, + STV090x_8PSK_910, + STV090x_16APSK_23, + STV090x_16APSK_34, + STV090x_16APSK_45, + STV090x_16APSK_56, + STV090x_16APSK_89, + STV090x_16APSK_910, + STV090x_32APSK_34, + STV090x_32APSK_45, + STV090x_32APSK_56, + STV090x_32APSK_89, + STV090x_32APSK_910, + STV090x_MODCODE_UNKNOWN +}; + +enum stv090x_search { + STV090x_SEARCH_DSS = 0, + STV090x_SEARCH_DVBS1, + STV090x_SEARCH_DVBS2, + STV090x_SEARCH_AUTO +}; + +enum stv090x_algo { + STV090x_BLIND_SEARCH, + STV090x_COLD_SEARCH, + STV090x_WARM_SEARCH +}; + +enum stv090x_delsys { + STV090x_ERROR = 0, + STV090x_DVBS1 = 1, + STV090x_DVBS2, + STV090x_DSS +}; + +struct stv090x_long_frame_crloop { + enum stv090x_modcod modcod; + + u8 crl_pilots_on_2; + u8 crl_pilots_off_2; + u8 crl_pilots_on_5; + u8 crl_pilots_off_5; + u8 crl_pilots_on_10; + u8 crl_pilots_off_10; + u8 crl_pilots_on_20; + u8 crl_pilots_off_20; + u8 crl_pilots_on_30; + u8 crl_pilots_off_30; +}; + +struct stv090x_short_frame_crloop { + enum stv090x_modulation modulation; + + u8 crl_2; /* SR < 3M */ + u8 crl_5; /* 3 < SR <= 7M */ + u8 crl_10; /* 7 < SR <= 15M */ + u8 crl_20; /* 10 < SR <= 25M */ + u8 crl_30; /* 10 < SR <= 45M */ +}; + +struct stv090x_reg { + u16 addr; + u8 data; +}; + +struct stv090x_tab { + s32 real; + s32 read; +}; + +struct stv090x_state { + enum stv090x_device device; + enum stv090x_demodulator demod; + enum stv090x_mode demod_mode; + u32 dev_ver; + + struct i2c_adapter *i2c; + const struct stv090x_config *config; + struct dvb_frontend frontend; + + u32 *verbose; /* Cached module verbosity */ + + enum stv090x_delsys delsys; + enum stv090x_fec fec; + enum stv090x_modulation modulation; + enum stv090x_modcod modcod; + enum stv090x_search search_mode; + enum stv090x_frame frame_len; + enum stv090x_pilot pilots; + enum stv090x_rolloff rolloff; + enum stv090x_inversion inversion; + enum stv090x_algo algo; + + u32 frequency; + u32 srate; + + s32 mclk; /* Masterclock Divider factor */ + s32 tuner_bw; + + u32 tuner_refclk; + + s32 search_range; + + s32 DemodTimeout; + s32 FecTimeout; +}; + +#endif /* __STV090x_PRIV_H */ diff --git a/linux/drivers/media/dvb/frontends/stv090x_reg.h b/linux/drivers/media/dvb/frontends/stv090x_reg.h new file mode 100644 index 000000000..57b6abbbd --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv090x_reg.h @@ -0,0 +1,2373 @@ +/* + STV0900/0903 Multistandard Broadcast Frontend driver + Copyright (C) Manu Abraham <abraham.manu@gmail.com> + + Copyright (C) ST Microelectronics + + 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 __STV090x_REG_H +#define __STV090x_REG_H + +#define STV090x_MID 0xf100 +#define STV090x_OFFST_MCHIP_IDENT_FIELD 4 +#define STV090x_WIDTH_MCHIP_IDENT_FIELD 4 +#define STV090x_OFFST_MRELEASE_FIELD 0 +#define STV090x_WIDTH_MRELEASE_FIELD 4 + +#define STV090x_DACR1 0xf113 +#define STV090x_OFFST_DACR1_MODE_FIELD 5 +#define STV090x_WIDTH_DACR1_MODE_FIELD 3 +#define STV090x_OFFST_DACR1_VALUE_FIELD 0 +#define STV090x_WIDTH_DACR1_VALUE_FIELD 4 + +#define STV090x_DACR2 0xf114 +#define STV090x_OFFST_DACR2_VALUE_FIELD 0 +#define STV090x_WIDTH_DACR2_VALUE_FIELD 8 + +#define STV090x_OUTCFG 0xf11c +#define STV090x_OFFST_OUTSERRS1_HZ_FIELD 6 +#define STV090x_WIDTH_OUTSERRS1_HZ_FIELD 1 +#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_OFFST_OUTPARRS3_HZ_FIELD 3 +#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD 1 + +#define STV090x_MODECFG 0xf11d + +#define STV090x_IRQSTATUS3 0xf120 +#define STV090x_OFFST_SPLL_LOCK_FIELD 5 +#define STV090x_WIDTH_SPLL_LOCK_FIELD 1 +#define STV090x_OFFST_SSTREAM_LCK_3_FIELD 4 +#define STV090x_WIDTH_SSTREAM_LCK_3_FIELD 1 +#define STV090x_OFFST_SSTREAM_LCK_2_FIELD 3 +#define STV090x_WIDTH_SSTREAM_LCK_2_FIELD 1 +#define STV090x_OFFST_SSTREAM_LCK_1_FIELD 2 +#define STV090x_WIDTH_SSTREAM_LCK_1_FIELD 1 +#define STV090x_OFFST_SDVBS1_PRF_2_FIELD 1 +#define STV090x_WIDTH_SDVBS1_PRF_2_FIELD 1 +#define STV090x_OFFST_SDVBS1_PRF_1_FIELD 0 +#define STV090x_WIDTH_SDVBS1_PRF_1_FIELD 1 + +#define STV090x_IRQSTATUS2 0xf121 +#define STV090x_OFFST_SSPY_ENDSIM_3_FIELD 7 +#define STV090x_WIDTH_SSPY_ENDSIM_3_FIELD 1 +#define STV090x_OFFST_SSPY_ENDSIM_2_FIELD 6 +#define STV090x_WIDTH_SSPY_ENDSIM_2_FIELD 1 +#define STV090x_OFFST_SSPY_ENDSIM_1_FIELD 5 +#define STV090x_WIDTH_SSPY_ENDSIM_1_FIELD 1 +#define STV090x_OFFST_SPKTDEL_ERROR_2_FIELD 4 +#define STV090x_WIDTH_SPKTDEL_ERROR_2_FIELD 1 +#define STV090x_OFFST_SPKTDEL_LOCKB_2_FIELD 3 +#define STV090x_WIDTH_SPKTDEL_LOCKB_2_FIELD 1 +#define STV090x_OFFST_SPKTDEL_LOCK_2_FIELD 2 +#define STV090x_WIDTH_SPKTDEL_LOCK_2_FIELD 1 +#define STV090x_OFFST_SPKTDEL_ERROR_1_FIELD 1 +#define STV090x_WIDTH_SPKTDEL_ERROR_1_FIELD 1 +#define STV090x_OFFST_SPKTDEL_LOCKB_1_FIELD 0 +#define STV090x_WIDTH_SPKTDEL_LOCKB_1_FIELD 1 + +#define STV090x_IRQSTATUS1 0xf122 +#define STV090x_OFFST_SPKTDEL_LOCK_1_FIELD 7 +#define STV090x_WIDTH_SPKTDEL_LOCK_1_FIELD 1 +#define STV090x_OFFST_SDEMOD_LOCKB_2_FIELD 2 +#define STV090x_WIDTH_SDEMOD_LOCKB_2_FIELD 1 +#define STV090x_OFFST_SDEMOD_LOCK_2_FIELD 1 +#define STV090x_WIDTH_SDEMOD_LOCK_2_FIELD 1 +#define STV090x_OFFST_SDEMOD_IRQ_2_FIELD 0 +#define STV090x_WIDTH_SDEMOD_IRQ_2_FIELD 1 + +#define STV090x_IRQSTATUS0 0xf123 +#define STV090x_OFFST_SDEMOD_LOCKB_1_FIELD 7 +#define STV090x_WIDTH_SDEMOD_LOCKB_1_FIELD 1 +#define STV090x_OFFST_SDEMOD_LOCK_1_FIELD 6 +#define STV090x_WIDTH_SDEMOD_LOCK_1_FIELD 1 +#define STV090x_OFFST_SDEMOD_IRQ_1_FIELD 5 +#define STV090x_WIDTH_SDEMOD_IRQ_1_FIELD 1 +#define STV090x_OFFST_SBCH_ERRFLAG_FIELD 4 +#define STV090x_WIDTH_SBCH_ERRFLAG_FIELD 1 +#define STV090x_OFFST_SDISEQC2RX_IRQ_FIELD 3 +#define STV090x_WIDTH_SDISEQC2RX_IRQ_FIELD 1 +#define STV090x_OFFST_SDISEQC2TX_IRQ_FIELD 2 +#define STV090x_WIDTH_SDISEQC2TX_IRQ_FIELD 1 +#define STV090x_OFFST_SDISEQC1RX_IRQ_FIELD 1 +#define STV090x_WIDTH_SDISEQC1RX_IRQ_FIELD 1 +#define STV090x_OFFST_SDISEQC1TX_IRQ_FIELD 0 +#define STV090x_WIDTH_SDISEQC1TX_IRQ_FIELD 1 + +#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_1_FIELD 2 +#define STV090x_WIDTH_MSTREAM_LCK_1_FIELD 3 +#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_1_FIELD 5 +#define STV090x_WIDTH_MSPY_ENDSIM_1_FIELD 3 +#define STV090x_OFFST_MPKTDEL_ERROR_2_FIELD 4 +#define STV090x_WIDTH_MPKTDEL_ERROR_2_FIELD 1 +#define STV090x_OFFST_MPKTDEL_LOCKB_2_FIELD 3 +#define STV090x_WIDTH_MPKTDEL_LOCKB_2_FIELD 1 +#define STV090x_OFFST_MPKTDEL_LOCK_2_FIELD 2 +#define STV090x_WIDTH_MPKTDEL_LOCK_2_FIELD 1 +#define STV090x_OFFST_MPKTDEL_ERROR_1_FIELD 1 +#define STV090x_WIDTH_MPKTDEL_ERROR_1_FIELD 1 +#define STV090x_OFFST_MPKTDEL_LOCKB_1_FIELD 0 +#define STV090x_WIDTH_MPKTDEL_LOCKB_1_FIELD 1 + +#define STV090x_IRQMASK1 0xf126 +#define STV090x_OFFST_MPKTDEL_LOCK_1_FIELD 7 +#define STV090x_WIDTH_MPKTDEL_LOCK_1_FIELD 1 +#define STV090x_OFFST_MEXTPINB2_FIELD 6 +#define STV090x_WIDTH_MEXTPINB2_FIELD 1 +#define STV090x_OFFST_MEXTPIN2_FIELD 5 +#define STV090x_WIDTH_MEXTPIN2_FIELD 1 +#define STV090x_OFFST_MEXTPINB1_FIELD 4 +#define STV090x_WIDTH_MEXTPINB1_FIELD 1 +#define STV090x_OFFST_MEXTPIN1_FIELD 3 +#define STV090x_WIDTH_MEXTPIN1_FIELD 1 +#define STV090x_OFFST_MDEMOD_LOCKB_2_FIELD 2 +#define STV090x_WIDTH_MDEMOD_LOCKB_2_FIELD 1 +#define STV090x_OFFST_MDEMOD_LOCK_2_FIELD 1 +#define STV090x_WIDTH_MDEMOD_LOCK_2_FIELD 1 +#define STV090x_OFFST_MDEMOD_IRQ_2_FIELD 0 +#define STV090x_WIDTH_MDEMOD_IRQ_2_FIELD 1 + +#define STV090x_IRQMASK0 0xf127 +#define STV090x_OFFST_MDEMOD_LOCKB_1_FIELD 7 +#define STV090x_WIDTH_MDEMOD_LOCKB_1_FIELD 1 +#define STV090x_OFFST_MDEMOD_LOCK_1_FIELD 6 +#define STV090x_WIDTH_MDEMOD_LOCK_1_FIELD 1 +#define STV090x_OFFST_MDEMOD_IRQ_1_FIELD 5 +#define STV090x_WIDTH_MDEMOD_IRQ_1_FIELD 1 +#define STV090x_OFFST_MBCH_ERRFLAG_FIELD 4 +#define STV090x_WIDTH_MBCH_ERRFLAG_FIELD 1 +#define STV090x_OFFST_MDISEQC2RX_IRQ_FIELD 3 +#define STV090x_WIDTH_MDISEQC2RX_IRQ_FIELD 1 +#define STV090x_OFFST_MDISEQC2TX_IRQ_FIELD 2 +#define STV090x_WIDTH_MDISEQC2TX_IRQ_FIELD 1 +#define STV090x_OFFST_MDISEQC1RX_IRQ_FIELD 1 +#define STV090x_WIDTH_MDISEQC1RX_IRQ_FIELD 1 +#define STV090x_OFFST_MDISEQC1TX_IRQ_FIELD 0 +#define STV090x_WIDTH_MDISEQC1TX_IRQ_FIELD 1 + +#define STV090x_I2CCFG 0xf129 +#define STV090x_OFFST_12C_FASTMODE_FIELD 3 +#define STV090x_WIDTH_12C_FASTMODE_FIELD 1 +#define STV090x_OFFST_12CADDR_INC_FIELD 0 +#define STV090x_WIDTH_12CADDR_INC_FIELD 2 + +#define STV090x_Px_I2CRPT(__x) (0xf12a + (__x - 1) * 0x1) +#define STV090x_P1_I2CRPT STV090x_Px_I2CRPT(1) +#define STV090x_P2_I2CRPT STV090x_Px_I2CRPT(2) +#define STV090x_OFFST_Px_I2CT_ON_FIELD 7 +#define STV090x_WIDTH_Px_I2CT_ON_FIELD 1 +#define STV090x_OFFST_Px_ENARPT_LEVEL_FIELD 4 +#define STV090x_WIDTH_Px_ENARPT_LEVEL_FIELD 3 +#define STV090x_OFFST_Px_SCLT_DELAY_FIELD 3 +#define STV090x_WIDTH_Px_SCLT_DELAY_FIELD 1 +#define STV090x_OFFST_Px_STOP_ENABLE_FIELD 2 +#define STV090x_WIDTH_Px_STOP_ENABLE_FIELD 1 +#define STV090x_OFFST_Px_STOP_SDAT2SDA_FIELD 1 +#define STV090x_WIDTH_Px_STOP_SDAT2SDA_FIELD 1 + +#define STV090x_CLKI2CFG 0xf140 +#define STV090x_OFFST_CLKI2_OPD_FIELD 7 +#define STV090x_WIDTH_CLKI2_OPD_FIELD 1 +#define STV090x_OFFST_CLKI2_CONFIG_FIELD 1 +#define STV090x_WIDTH_CLKI2_CONFIG_FIELD 6 +#define STV090x_OFFST_CLKI2_XOR_FIELD 0 +#define STV090x_WIDTH_CLKI2_XOR_FIELD 1 + +#define STV090x_GPIOxCFG(__x) (0xf141 + (__x - 1)) +#define STV090x_GPIO1CFG STV090x_GPIOxCFG(1) +#define STV090x_GPIO2CFG STV090x_GPIOxCFG(2) +#define STV090x_GPIO3CFG STV090x_GPIOxCFG(3) +#define STV090x_GPIO4CFG STV090x_GPIOxCFG(4) +#define STV090x_GPIO5CFG STV090x_GPIOxCFG(5) +#define STV090x_GPIO6CFG STV090x_GPIOxCFG(6) +#define STV090x_GPIO7CFG STV090x_GPIOxCFG(7) +#define STV090x_GPIO8CFG STV090x_GPIOxCFG(8) +#define STV090x_GPIO9CFG STV090x_GPIOxCFG(9) +#define STV090x_GPIO10CFG STV090x_GPIOxCFG(10) +#define STV090x_GPIO11CFG STV090x_GPIOxCFG(11) +#define STV090x_GPIO12CFG STV090x_GPIOxCFG(12) +#define STV090x_GPIO13CFG STV090x_GPIOxCFG(13) +#define STV090x_OFFST_GPIOx_OPD_FIELD 7 +#define STV090x_WIDTH_GPIOx_OPD_FIELD 1 +#define STV090x_OFFST_GPIOx_CONFIG_FIELD 1 +#define STV090x_WIDTH_GPIOx_CONFIG_FIELD 6 +#define STV090x_OFFST_GPIOx_XOR_FIELD 0 +#define STV090x_WIDTH_GPIOx_XOR_FIELD 1 + +#define STV090x_CSxCFG(__x) (0xf14e + __x * 0x1) +#define STV090x_CS0CFG STV090x_CSxCFG(0) +#define STV090x_CS1CFG STV090x_CSxCFG(1) +#define STV090x_OFFST_CSX_OPD_FIELD 7 +#define STV090x_WIDTH_CSX_OPD_FIELD 1 +#define STV090x_OFFST_CSX_CONFIG_FIELD 1 +#define STV090x_WIDTH_CSX_CONFIG_FIELD 6 +#define STV090x_OFFST_CSX_XOR_FIELD 0 +#define STV090x_WIDTH_CSX_XOR_FIELD 1 + + +#define STV090x_STDBYCFG 0xf150 +#define STV090x_OFFST_STDBY_OPD_FIELD 7 +#define STV090x_WIDTH_STDBY_OPD_FIELD 1 +#define STV090x_OFFST_STDBY_CONFIG_FIELD 1 +#define STV090x_WIDTH_STDBY_CONFIG_FIELD 6 +#define STV090x_OFFST_STDBY_XOR_FIELD 0 +#define STV090x_WIDTH_STDBY_XOR_FIELD 1 + +#define STV090x_DIRCLKCFG 0xf151 +#define STV090x_OFFST_DIRCLK_OPD_FIELD 7 +#define STV090x_WIDTH_DIRCLK_OPD_FIELD 1 +#define STV090x_OFFST_DIRCLK_CONFIG_FIELD 1 +#define STV090x_WIDTH_DIRCLK_CONFIG_FIELD 6 +#define STV090x_OFFST_DIRCLK_XOR_FIELD 0 +#define STV090x_WIDTH_DIRCLK_XOR_FIELD 1 + + +#define STV090x_AGCRFxCFG(__x) (0xf152 + (__x - 1) * 0x4) +#define STV090x_AGCRF1CFG STV090x_AGCRFxCFG(1) +#define STV090x_AGCRF2CFG STV090x_AGCRFxCFG(2) +#define STV090x_OFFST_AGCRFx_OPD_FIELD 7 +#define STV090x_WIDTH_AGCRFx_OPD_FIELD 1 +#define STV090x_OFFST_AGCRFx_CONFIG_FIELD 1 +#define STV090x_WIDTH_AGCRFx_CONFIG_FIELD 6 +#define STV090x_OFFST_AGCRFx_XOR_FIELD 0 +#define STV090x_WIDTH_AGCRFx_XOR_FIELD 1 + +#define STV090x_SDATxCFG(__x) (0xf153 + (__x - 1) * 0x4) +#define STV090x_SDAT1CFG STV090x_SDATxCFG(1) +#define STV090x_SDAT2CFG STV090x_SDATxCFG(2) +#define STV090x_OFFST_SDATx_OPD_FIELD 7 +#define STV090x_WIDTH_SDATx_OPD_FIELD 1 +#define STV090x_OFFST_SDATx_CONFIG_FIELD 1 +#define STV090x_WIDTH_SDATx_CONFIG_FIELD 6 +#define STV090x_OFFST_SDATx_XOR_FIELD 0 +#define STV090x_WIDTH_SDATx_XOR_FIELD 1 + +#define STV090x_SCLTxCFG(__x) (0xf154 + (__x - 1) * 0x4) +#define STV090x_SCLT1CFG STV090x_SCLTxCFG(1) +#define STV090x_SCLT2CFG STV090x_SCLTxCFG(2) +#define STV090x_OFFST_SCLTx_OPD_FIELD 7 +#define STV090x_WIDTH_SCLTx_OPD_FIELD 1 +#define STV090x_OFFST_SCLTx_CONFIG_FIELD 1 +#define STV090x_WIDTH_SCLTx_CONFIG_FIELD 6 +#define STV090x_OFFST_SCLTx_XOR_FIELD 0 +#define STV090x_WIDTH_SCLTx_XOR_FIELD 1 + +#define STV090x_DISEQCOxCFG(__x) (0xf155 + (__x - 1) * 0x4) +#define STV090x_DISEQCO1CFG STV090x_DISEQCOxCFG(1) +#define STV090x_DISEQCO2CFG STV090x_DISEQCOxCFG(2) +#define STV090x_OFFST_DISEQCOx_OPD_FIELD 7 +#define STV090x_WIDTH_DISEQCOx_OPD_FIELD 1 +#define STV090x_OFFST_DISEQCOx_CONFIG_FIELD 1 +#define STV090x_WIDTH_DISEQCOx_CONFIG_FIELD 6 +#define STV090x_OFFST_DISEQCOx_XOR_FIELD 0 +#define STV090x_WIDTH_DISEQCOx_XOR_FIELD 1 + +#define STV090x_CLKOUT27CFG 0xf15a +#define STV090x_OFFST_CLKOUT27_OPD_FIELD 7 +#define STV090x_WIDTH_CLKOUT27_OPD_FIELD 1 +#define STV090x_OFFST_CLKOUT27_CONFIG_FIELD 1 +#define STV090x_WIDTH_CLKOUT27_CONFIG_FIELD 6 +#define STV090x_OFFST_CLKOUT27_XOR_FIELD 0 +#define STV090x_WIDTH_CLKOUT27_XOR_FIELD 1 + +#define STV090x_ERRORxCFG(__x) (0xf15b + (__x - 1) * 0x5) +#define STV090x_ERROR1CFG STV090x_ERRORxCFG(1) +#define STV090x_ERROR2CFG STV090x_ERRORxCFG(2) +#define STV090x_ERROR3CFG STV090x_ERRORxCFG(3) +#define STV090x_OFFST_ERRORx_OPD_FIELD 7 +#define STV090x_WIDTH_ERRORx_OPD_FIELD 1 +#define STV090x_OFFST_ERRORx_CONFIG_FIELD 1 +#define STV090x_WIDTH_ERRORx_CONFIG_FIELD 6 +#define STV090x_OFFST_ERRORx_XOR_FIELD 0 +#define STV090x_WIDTH_ERRORx_XOR_FIELD 1 + +#define STV090x_DPNxCFG(__x) (0xf15c + (__x - 1) * 0x5) +#define STV090x_DPN1CFG STV090x_DPNxCFG(1) +#define STV090x_DPN2CFG STV090x_DPNxCFG(2) +#define STV090x_DPN3CFG STV090x_DPNxCFG(3) +#define STV090x_OFFST_DPNx_OPD_FIELD 7 +#define STV090x_WIDTH_DPNx_OPD_FIELD 1 +#define STV090x_OFFST_DPNx_CONFIG_FIELD 1 +#define STV090x_WIDTH_DPNx_CONFIG_FIELD 6 +#define STV090x_OFFST_DPNx_XOR_FIELD 0 +#define STV090x_WIDTH_DPNx_XOR_FIELD 1 + +#define STV090x_STROUTxCFG(__x) (0xf15d + (__x - 1) * 0x5) +#define STV090x_STROUT1CFG STV090x_STROUTxCFG(1) +#define STV090x_STROUT2CFG STV090x_STROUTxCFG(2) +#define STV090x_STROUT3CFG STV090x_STROUTxCFG(3) +#define STV090x_OFFST_STROUTx_OPD_FIELD 7 +#define STV090x_WIDTH_STROUTx_OPD_FIELD 1 +#define STV090x_OFFST_STROUTx_CONFIG_FIELD 1 +#define STV090x_WIDTH_STROUTx_CONFIG_FIELD 6 +#define STV090x_OFFST_STROUTx_XOR_FIELD 0 +#define STV090x_WIDTH_STROUTx_XOR_FIELD 1 + +#define STV090x_CLKOUTxCFG(__x) (0xf15e + (__x - 1) * 0x5) +#define STV090x_CLKOUT1CFG STV090x_CLKOUTxCFG(1) +#define STV090x_CLKOUT2CFG STV090x_CLKOUTxCFG(2) +#define STV090x_CLKOUT3CFG STV090x_CLKOUTxCFG(3) +#define STV090x_OFFST_CLKOUTx_OPD_FIELD 7 +#define STV090x_WIDTH_CLKOUTx_OPD_FIELD 1 +#define STV090x_OFFST_CLKOUTx_CONFIG_FIELD 1 +#define STV090x_WIDTH_CLKOUTx_CONFIG_FIELD 6 +#define STV090x_OFFST_CLKOUTx_XOR_FIELD 0 +#define STV090x_WIDTH_CLKOUTx_XOR_FIELD 1 + +#define STV090x_DATAxCFG(__x) (0xf15f + (__x - 71) * 0x5) +#define STV090x_DATA71CFG STV090x_DATAxCFG(71) +#define STV090x_DATA72CFG STV090x_DATAxCFG(72) +#define STV090x_DATA73CFG STV090x_DATAxCFG(73) +#define STV090x_OFFST_DATAx_OPD_FIELD 7 +#define STV090x_WIDTH_DATAx_OPD_FIELD 1 +#define STV090x_OFFST_DATAx_CONFIG_FIELD 1 +#define STV090x_WIDTH_DATAx_CONFIG_FIELD 6 +#define STV090x_OFFST_DATAx_XOR_FIELD 0 +#define STV090x_WIDTH_DATAx_XOR_FIELD 1 + +#define STV090x_NCOARSE 0xf1b3 +#define STV090x_OFFST_M_DIV_FIELD 0 +#define STV090x_WIDTH_M_DIV_FIELD 8 + +#define STV090x_SYNTCTRL 0xf1b6 +#define STV090x_OFFST_STANDBY_FIELD 7 +#define STV090x_WIDTH_STANDBY_FIELD 1 +#define STV090x_OFFST_BYPASSPLLCORE_FIELD 6 +#define STV090x_WIDTH_BYPASSPLLCORE_FIELD 1 +#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_OFFST_BYPASSPLLFSK_FIELD 2 +#define STV090x_WIDTH_BYPASSPLLFSK_FIELD 1 +#define STV090x_OFFST_SELOSCI_FIELD 1 +#define STV090x_WIDTH_SELOSCI_FIELD 1 +#define STV090x_OFFST_BYPASSPLLADC_FIELD 0 +#define STV090x_WIDTH_BYPASSPLLADC_FIELD 1 + +#define STV090x_FILTCTRL 0xf1b7 +#define STV090x_OFFST_INV_CLK135_FIELD 7 +#define STV090x_WIDTH_INV_CLK135_FIELD 1 +#define STV090x_OFFST_SEL_FSKCKDIV_FIELD 2 +#define STV090x_WIDTH_SEL_FSKCKDIV_FIELD 1 +#define STV090x_OFFST_INV_CLKFSK_FIELD 1 +#define STV090x_WIDTH_INV_CLKFSK_FIELD 1 +#define STV090x_OFFST_BYPASS_APPLI_FIELD 0 +#define STV090x_WIDTH_BYPASS_APPLI_FIELD 1 + +#define STV090x_PLLSTAT 0xf1b8 +#define STV090x_OFFST_PLLLOCK_FIELD 0 +#define STV090x_WIDTH_PLLLOCK_FIELD 1 + +#define STV090x_STOPCLK1 0xf1c2 +#define STV090x_OFFST_STOP_CLKPKDT2_FIELD 6 +#define STV090x_WIDTH_STOP_CLKPKDT2_FIELD 1 +#define STV090x_OFFST_STOP_CLKPKDT1_FIELD 5 +#define STV090x_WIDTH_STOP_CLKPKDT1_FIELD 1 +#define STV090x_OFFST_STOP_CLKFEC_FIELD 4 +#define STV090x_WIDTH_STOP_CLKFEC_FIELD 1 +#define STV090x_OFFST_STOP_CLKADCI2_FIELD 3 +#define STV090x_WIDTH_STOP_CLKADCI2_FIELD 1 +#define STV090x_OFFST_INV_CLKADCI2_FIELD 2 +#define STV090x_WIDTH_INV_CLKADCI2_FIELD 1 +#define STV090x_OFFST_STOP_CLKADCI1_FIELD 1 +#define STV090x_WIDTH_STOP_CLKADCI1_FIELD 1 +#define STV090x_OFFST_INV_CLKADCI1_FIELD 0 +#define STV090x_WIDTH_INV_CLKADCI1_FIELD 1 + +#define STV090x_STOPCLK2 0xf1c3 +#define STV090x_OFFST_STOP_CLKSAMP2_FIELD 4 +#define STV090x_WIDTH_STOP_CLKSAMP2_FIELD 1 +#define STV090x_OFFST_STOP_CLKSAMP1_FIELD 3 +#define STV090x_WIDTH_STOP_CLKSAMP1_FIELD 1 +#define STV090x_OFFST_STOP_CLKVIT2_FIELD 2 +#define STV090x_WIDTH_STOP_CLKVIT2_FIELD 1 +#define STV090x_OFFST_STOP_CLKVIT1_FIELD 1 +#define STV090x_WIDTH_STOP_CLKVIT1_FIELD 1 +#define STV090x_OFFST_STOP_CLKTS_FIELD 0 +#define STV090x_WIDTH_STOP_CLKTS_FIELD 1 + +#define STV090x_TSTTNR0 0xf1df +#define STV090x_OFFST_SEL_FSK_FIELD 7 +#define STV090x_WIDTH_SEL_FSK_FIELD 1 +#define STV090x_OFFST_FSK_PON_FIELD 2 +#define STV090x_WIDTH_FSK_PON_FIELD 1 + +#define STV090x_TSTTNR1 0xf1e0 +#define STV090x_OFFST_ADC1_PON_FIELD 1 +#define STV090x_WIDTH_ADC1_PON_FIELD 1 +#define STV090x_OFFST_ADC1_INMODE_FIELD 0 +#define STV090x_WIDTH_ADC1_INMODE_FIELD 1 + +#define STV090x_TSTTNR2 0xf1e1 +#define STV090x_OFFST_DISEQC1_PON_FIELD 5 +#define STV090x_WIDTH_DISEQC1_PON_FIELD 1 + +#define STV090x_TSTTNR3 0xf1e2 +#define STV090x_OFFST_ADC2_PON_FIELD 1 +#define STV090x_WIDTH_ADC2_PON_FIELD 1 +#define STV090x_OFFST_ADC2_INMODE_FIELD 0 +#define STV090x_WIDTH_ADC2_INMODE_FIELD 1 + +#define STV090x_TSTTNR4 0xf1e3 +#define STV090x_OFFST_DISEQC2_PON_FIELD 5 +#define STV090x_WIDTH_DISEQC2_PON_FIELD 1 + +#define STV090x_FSKTFC2 0xf170 +#define STV090x_OFFST_FSKT_KMOD_FIELD 2 +#define STV090x_WIDTH_FSKT_KMOD_FIELD 6 +#define STV090x_OFFST_FSKT_CAR_FIELD 0 +#define STV090x_WIDTH_FSKT_CAR_FIELD 2 + +#define STV090x_FSKTFC1 0xf171 +#define STV090x_OFFST_FSKTC1_CAR_FIELD 0 +#define STV090x_WIDTH_FSKTC1_CAR_FIELD 8 + +#define STV090x_FSKTFC0 0xf172 +#define STV090x_OFFST_FSKTC0_CAR_FIELD 0 +#define STV090x_WIDTH_FSKTC0_CAR_FIELD 8 + +#define STV090x_FSKTDELTAF1 0xf173 +#define STV090x_OFFST_FSKTF1_DELTAF_FIELD 0 +#define STV090x_WIDTH_FSKTF1_DELTAF_FIELD 4 + +#define STV090x_FSKTDELTAF0 0xf174 +#define STV090x_OFFST_FSKTF0_DELTAF_FIELD 0 +#define STV090x_WIDTH_FSKTF0_DELTAF_FIELD 8 + +#define STV090x_FSKTCTRL 0xf175 +#define STV090x_OFFST_FSKT_EN_SGN_FIELD 6 +#define STV090x_WIDTH_FSKT_EN_SGN_FIELD 1 +#define STV090x_OFFST_FSKT_MOD_SGN_FIELD 5 +#define STV090x_WIDTH_FSKT_MOD_SGN_FIELD 1 +#define STV090x_OFFST_FSKT_MOD_EN_FIELD 2 +#define STV090x_WIDTH_FSKT_MOD_EN_FIELD 3 +#define STV090x_OFFST_FSKT_DACMODE_FIELD 0 +#define STV090x_WIDTH_FSKT_DACMODE_FIELD 2 + +#define STV090x_FSKRFC2 0xf176 +#define STV090x_OFFST_FSKRC2_DETSGN_FIELD 6 +#define STV090x_WIDTH_FSKRC2_DETSGN_FIELD 1 +#define STV090x_OFFST_FSKRC2_OUTSGN_FIELD 5 +#define STV090x_WIDTH_FSKRC2_OUTSGN_FIELD 1 +#define STV090x_OFFST_FSKRC2_KAGC_FIELD 2 +#define STV090x_WIDTH_FSKRC2_KAGC_FIELD 3 +#define STV090x_OFFST_FSKRC2_CAR_FIELD 0 +#define STV090x_WIDTH_FSKRC2_CAR_FIELD 2 + +#define STV090x_FSKRFC1 0xf177 +#define STV090x_OFFST_FSKRC1_CAR_FIELD 0 +#define STV090x_WIDTH_FSKRC1_CAR_FIELD 8 + +#define STV090x_FSKRFC0 0xf178 +#define STV090x_OFFST_FSKRC0_CAR_FIELD 0 +#define STV090x_WIDTH_FSKRC0_CAR_FIELD 8 + +#define STV090x_FSKRK1 0xf179 +#define STV090x_OFFST_FSKR_K1_EXP_FIELD 5 +#define STV090x_WIDTH_FSKR_K1_EXP_FIELD 3 +#define STV090x_OFFST_FSKR_K1_MANT_FIELD 0 +#define STV090x_WIDTH_FSKR_K1_MANT_FIELD 5 + +#define STV090x_FSKRK2 0xf17a +#define STV090x_OFFST_FSKR_K2_EXP_FIELD 5 +#define STV090x_WIDTH_FSKR_K2_EXP_FIELD 3 +#define STV090x_OFFST_FSKR_K2_MANT_FIELD 0 +#define STV090x_WIDTH_FSKR_K2_MANT_FIELD 5 + +#define STV090x_FSKRAGCR 0xf17b +#define STV090x_OFFST_FSKR_OUTCTL_FIELD 6 +#define STV090x_WIDTH_FSKR_OUTCTL_FIELD 2 +#define STV090x_OFFST_FSKR_AGC_REF_FIELD 0 +#define STV090x_WIDTH_FSKR_AGC_REF_FIELD 6 + +#define STV090x_FSKRAGC 0xf17c +#define STV090x_OFFST_FSKR_AGC_ACCU_FIELD 0 +#define STV090x_WIDTH_FSKR_AGC_ACCU_FIELD 8 + +#define STV090x_FSKRALPHA 0xf17d +#define STV090x_OFFST_FSKR_ALPHA_EXP_FIELD 2 +#define STV090x_WIDTH_FSKR_ALPHA_EXP_FIELD 3 +#define STV090x_OFFST_FSKR_ALPHA_M_FIELD 0 +#define STV090x_WIDTH_FSKR_ALPHA_M_FIELD 2 + +#define STV090x_FSKRPLTH1 0xf17e +#define STV090x_OFFST_FSKR_BETA_FIELD 4 +#define STV090x_WIDTH_FSKR_BETA_FIELD 4 +#define STV090x_OFFST_FSKR_PLL_TRESH1_FIELD 0 +#define STV090x_WIDTH_FSKR_PLL_TRESH1_FIELD 4 + +#define STV090x_FSKRPLTH0 0xf17f +#define STV090x_OFFST_FSKR_PLL_TRESH0_FIELD 0 +#define STV090x_WIDTH_FSKR_PLL_TRESH0_FIELD 8 + +#define STV090x_FSKRDF1 0xf180 +#define STV090x_OFFST_FSKR_DELTAF1_FIELD 0 +#define STV090x_WIDTH_FSKR_DELTAF1_FIELD 5 + +#define STV090x_FSKRDF0 0xf181 +#define STV090x_OFFST_FSKR_DELTAF0_FIELD 0 +#define STV090x_WIDTH_FSKR_DELTAF0_FIELD 8 + +#define STV090x_FSKRSTEPP 0xf182 +#define STV090x_OFFST_FSKR_STEP_PLUS_FIELD 0 +#define STV090x_WIDTH_FSKR_STEP_PLUS_FIELD 8 + +#define STV090x_FSKRSTEPM 0xf183 +#define STV090x_OFFST_FSKR_STEP_MINUS_FIELD 0 +#define STV090x_WIDTH_FSKR_STEP_MINUS_FIELD 8 + +#define STV090x_FSKRDET1 0xf184 +#define STV090x_OFFST_FSKR_CARDET1_ACCU_FIELD 0 +#define STV090x_WIDTH_FSKR_CARDET1_ACCU_FIELD 4 + +#define STV090x_FSKRDET0 0xf185 +#define STV090x_OFFST_FSKR_CARDET0_ACCU_FIELD 0 +#define STV090x_WIDTH_FSKR_CARDET0_ACCU_FIELD 8 + +#define STV090x_FSKRDTH1 0xf186 +#define STV090x_OFFST_FSKR_CARLOSS_THRESH1_FIELD 4 +#define STV090x_WIDTH_FSKR_CARLOSS_THRESH1_FIELD 4 +#define STV090x_OFFST_FSKR_CARDET_THRESH1_FIELD 0 +#define STV090x_WIDTH_FSKR_CARDET_THRESH1_FIELD 4 + +#define STV090x_FSKRDTH0 0xf187 +#define STV090x_OFFST_FSKR_CARDET_THRESH0_FIELD 0 +#define STV090x_WIDTH_FSKR_CARDET_THRESH0_FIELD 8 + +#define STV090x_FSKRLOSS 0xf188 +#define STV090x_OFFST_FSKR_CARLOSS_THRESH_FIELD 0 +#define STV090x_WIDTH_FSKR_CARLOSS_THRESH_FIELD 8 + +#define STV090x_Px_DISTXCTL(__x) (0xF1A0 - (__x - 1) * 0x10) +#define STV090x_P1_DISTXCTL STV090x_Px_DISTXCTL(1) +#define STV090x_P2_DISTXCTL STV090x_Px_DISTXCTL(2) +#define STV090x_OFFST_Px_TIM_OFF_FIELD 7 +#define STV090x_WIDTH_Px_TIM_OFF_FIELD 1 +#define STV090x_OFFST_Px_DISEQC_RESET_FIELD 6 +#define STV090x_WIDTH_Px_DISEQC_RESET_FIELD 1 +#define STV090x_OFFST_Px_TIM_CMD_FIELD 4 +#define STV090x_WIDTH_Px_TIM_CMD_FIELD 2 +#define STV090x_OFFST_Px_DIS_PRECHARGE_FIELD 3 +#define STV090x_WIDTH_Px_DIS_PRECHARGE_FIELD 1 +#define STV090x_OFFST_Px_DISTX_MODE_FIELD 0 +#define STV090x_WIDTH_Px_DISTX_MODE_FIELD 3 + +#define STV090x_Px_DISRXCTL(__x) (0xf1a1 - (__x - 1) * 0x10) +#define STV090x_P1_DISRXCTL STV090x_Px_DISRXCTL(1) +#define STV090x_P2_DISRXCTL STV090x_Px_DISRXCTL(2) +#define STV090x_OFFST_Px_RECEIVER_ON_FIELD 7 +#define STV090x_WIDTH_Px_RECEIVER_ON_FIELD 1 +#define STV090x_OFFST_Px_IGNO_SHORT22K_FIELD 6 +#define STV090x_WIDTH_Px_IGNO_SHORT22K_FIELD 1 +#define STV090x_OFFST_Px_ONECHIP_TRX_FIELD 5 +#define STV090x_WIDTH_Px_ONECHIP_TRX_FIELD 1 +#define STV090x_OFFST_Px_EXT_ENVELOP_FIELD 4 +#define STV090x_WIDTH_Px_EXT_ENVELOP_FIELD 1 +#define STV090x_OFFST_Px_PIN_SELECT_FIELD 2 +#define STV090x_WIDTH_Px_PIN_SELECT_FIELD 2 +#define STV090x_OFFST_Px_IRQ_RXEND_FIELD 1 +#define STV090x_WIDTH_Px_IRQ_RXEND_FIELD 1 +#define STV090x_OFFST_Px_IRQ_4NBYTES_FIELD 0 +#define STV090x_WIDTH_Px_IRQ_4NBYTES_FIELD 1 + +#define STV090x_Px_DISRX_ST0(__x) (0xf1a4 - (__x - 1) * 0x10) +#define STV090x_P1_DISRX_ST0 STV090x_Px_DISRX_ST0(1) +#define STV090x_P2_DISRX_ST0 STV090x_Px_DISRX_ST0(2) +#define STV090x_OFFST_Px_RX_END_FIELD 7 +#define STV090x_WIDTH_Px_RX_END_FIELD 1 +#define STV090x_OFFST_Px_RX_ACTIVE_FIELD 6 +#define STV090x_WIDTH_Px_RX_ACTIVE_FIELD 1 +#define STV090x_OFFST_Px_SHORT_22KHZ_FIELD 5 +#define STV090x_WIDTH_Px_SHORT_22KHZ_FIELD 1 +#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_OFFST_Px_FIFO_EMPTY_FIELD 2 +#define STV090x_WIDTH_Px_FIFO_EMPTY_FIELD 1 +#define STV090x_OFFST_Px_ABORT_DISRX_FIELD 0 +#define STV090x_WIDTH_Px_ABORT_DISRX_FIELD 1 + +#define STV090x_Px_DISRX_ST1(__x) (0xf1a5 - (__x - 1) * 0x10) +#define STV090x_P1_DISRX_ST1 STV090x_Px_DISRX_ST1(1) +#define STV090x_P2_DISRX_ST1 STV090x_Px_DISRX_ST1(2) +#define STV090x_OFFST_Px_RX_FAIL_FIELD 7 +#define STV090x_WIDTH_Px_RX_FAIL_FIELD 1 +#define STV090x_OFFST_Px_FIFO_PARITYFAIL_FIELD 6 +#define STV090x_WIDTH_Px_FIFO_PARITYFAIL_FIELD 1 +#define STV090x_OFFST_Px_RX_NONBYTE_FIELD 5 +#define STV090x_WIDTH_Px_RX_NONBYTE_FIELD 1 +#define STV090x_OFFST_Px_FIFO_OVERFLOW_FIELD 4 +#define STV090x_WIDTH_Px_FIFO_OVERFLOW_FIELD 1 +#define STV090x_OFFST_Px_FIFO_BYTENBR_FIELD 0 +#define STV090x_WIDTH_Px_FIFO_BYTENBR_FIELD 4 + +#define STV090x_Px_DISRXDATA(__x) (0xf1a6 - (__x - 1) * 0x10) +#define STV090x_P1_DISRXDATA STV090x_Px_DISRXDATA(1) +#define STV090x_P2_DISRXDATA STV090x_Px_DISRXDATA(2) +#define STV090x_OFFST_Px_DISRX_DATA_FIELD 0 +#define STV090x_WIDTH_Px_DISRX_DATA_FIELD 8 + +#define STV090x_Px_DISTXDATA(__x) (0xf1a7 - (__x - 1) * 0x10) +#define STV090x_P1_DISTXDATA STV090x_Px_DISTXDATA(1) +#define STV090x_P2_DISTXDATA STV090x_Px_DISTXDATA(2) +#define STV090x_OFFST_Px_DISEQC_FIFO_FIELD 0 +#define STV090x_WIDTH_Px_DISEQC_FIFO_FIELD 8 + +#define STV090x_Px_DISTXSTATUS(__x) (0xf1a8 - (__x - 1) * 0x10) +#define STV090x_P1_DISTXSTATUS STV090x_Px_DISTXSTATUS(1) +#define STV090x_P2_DISTXSTATUS STV090x_Px_DISTXSTATUS(2) +#define STV090x_OFFST_Px_TX_FAIL_FIELD 7 +#define STV090x_WIDTH_Px_TX_FAIL_FIELD 1 +#define STV090x_OFFST_Px_FIFO_FULL_FIELD 6 +#define STV090x_WIDTH_Px_FIFO_FULL_FIELD 1 +#define STV090x_OFFST_Px_TX_IDLE_FIELD 5 +#define STV090x_WIDTH_Px_TX_IDLE_FIELD 1 +#define STV090x_OFFST_Px_GAP_BURST_FIELD 4 +#define STV090x_WIDTH_Px_GAP_BURST_FIELD 1 +#define STV090x_OFFST_Px_TXFIFO_BYTES_FIELD 0 +#define STV090x_WIDTH_Px_TXFIFO_BYTES_FIELD 4 + +#define STV090x_Px_F22TX(__x) (0xf1a9 - (__x - 1) * 0x10) +#define STV090x_P1_F22TX STV090x_Px_F22TX(1) +#define STV090x_P2_F22TX STV090x_Px_F22TX(2) +#define STV090x_OFFST_Px_F22_REG_FIELD 0 +#define STV090x_WIDTH_Px_F22_REG_FIELD 8 + +#define STV090x_Px_F22RX(__x) (0xf1aa - (__x - 1) * 0x10) +#define STV090x_P1_F22RX STV090x_Px_F22RX(1) +#define STV090x_P2_F22RX STV090x_Px_F22RX(2) +#define STV090x_OFFST_Px_F22RX_REG_FIELD 0 +#define STV090x_WIDTH_Px_F22RX_REG_FIELD 8 + +#define STV090x_Px_ACRPRESC(__x) (0xf1ac - (__x - 1) * 0x10) +#define STV090x_P1_ACRPRESC STV090x_Px_ACRPRESC(1) +#define STV090x_P2_ACRPRESC STV090x_Px_ACRPRESC(2) +#define STV090x_OFFST_Px_ACR_PRESC_FIELD 0 +#define STV090x_WIDTH_Px_ACR_PRESC_FIELD 3 + +#define STV090x_Px_ACRDIV(__x) (0xf1ad - (__x - 1) * 0x10) +#define STV090x_P1_ACRDIV STV090x_Px_ACRDIV(1) +#define STV090x_P2_ACRDIV STV090x_Px_ACRDIV(2) +#define STV090x_OFFST_Px_ACR_DIV_FIELD 0 +#define STV090x_WIDTH_Px_ACR_DIV_FIELD 8 + +#define STV090x_Px_IQCONST(__x) (0xF400 - (__x - 1) * 0x200) +#define STV090x_P1_IQCONST STV090x_Px_IQCONST(1) +#define STV090x_P2_IQCONST STV090x_Px_IQCONST(2) +#define STV090x_OFFST_Px_CONSTEL_SELECT_FIELD 5 +#define STV090x_WIDTH_Px_CONSTEL_SELECT_FIELD 2 + +#define STV090x_Px_NOSCFG(__x) (0xF401 - (__x - 1) * 0x200) +#define STV090x_P1_NOSCFG STV090x_Px_NOSCFG(1) +#define STV090x_P2_NOSCFG STV090x_Px_NOSCFG(2) +#define STV090x_OFFST_Px_NOSPLH_BETA_FIELD 3 +#define STV090x_WIDTH_Px_NOSPLH_BETA_FIELD 2 +#define STV090x_OFFST_Px_NOSDATA_BETA_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATA_BETA_FIELD 3 + +#define STV090x_Px_ISYMB(__x) (0xF402 - (__x - 1) * 0x200) +#define STV090x_P1_ISYMB STV090x_Px_ISYMB(1) +#define STV090x_P2_ISYMB STV090x_Px_ISYMB(2) +#define STV090x_OFFST_Px_I_SYMBOL_FIELD 0 +#define STV090x_WIDTH_Px_I_SYMBOL_FIELD 8 + +#define STV090x_Px_QSYMB(__x) (0xF403 - (__x - 1) * 0x200) +#define STV090x_P1_QSYMB STV090x_Px_QSYMB(1) +#define STV090x_P2_QSYMB STV090x_Px_QSYMB(2) +#define STV090x_OFFST_Px_Q_SYMBOL_FIELD 0 +#define STV090x_WIDTH_Px_Q_SYMBOL_FIELD 8 + +#define STV090x_Px_AGC1CFG(__x) (0xF404 - (__x - 1) * 0x200) +#define STV090x_P1_AGC1CFG STV090x_Px_AGC1CFG(1) +#define STV090x_P2_AGC1CFG STV090x_Px_AGC1CFG(2) +#define STV090x_OFFST_Px_DC_FROZEN_FIELD 7 +#define STV090x_WIDTH_Px_DC_FROZEN_FIELD 1 +#define STV090x_OFFST_Px_DC_CORRECT_FIELD 6 +#define STV090x_WIDTH_Px_DC_CORRECT_FIELD 1 +#define STV090x_OFFST_Px_AMM_FROZEN_FIELD 5 +#define STV090x_WIDTH_Px_AMM_FROZEN_FIELD 1 +#define STV090x_OFFST_Px_AMM_CORRECT_FIELD 4 +#define STV090x_WIDTH_Px_AMM_CORRECT_FIELD 1 +#define STV090x_OFFST_Px_QUAD_FROZEN_FIELD 3 +#define STV090x_WIDTH_Px_QUAD_FROZEN_FIELD 1 +#define STV090x_OFFST_Px_QUAD_CORRECT_FIELD 2 +#define STV090x_WIDTH_Px_QUAD_CORRECT_FIELD 1 + +#define STV090x_Px_AGC1CN(__x) (0xF406 - (__x - 1) * 0x200) +#define STV090x_P1_AGC1CN STV090x_Px_AGC1CN(1) +#define STV090x_P2_AGC1CN STV090x_Px_AGC1CN(2) +#define STV090x_WIDTH_Px_AGC1_LOCKED_FIELD 7 +#define STV090x_OFFST_Px_AGC1_LOCKED_FIELD 1 +#define STV090x_OFFST_Px_AGC1_MINPOWER_FIELD 4 +#define STV090x_WIDTH_Px_AGC1_MINPOWER_FIELD 1 +#define STV090x_OFFST_Px_AGCOUT_FAST_FIELD 3 +#define STV090x_WIDTH_Px_AGCOUT_FAST_FIELD 1 +#define STV090x_OFFST_Px_AGCIQ_BETA_FIELD 0 +#define STV090x_WIDTH_Px_AGCIQ_BETA_FIELD 3 + +#define STV090x_Px_AGC1REF(__x) (0xF407 - (__x - 1) * 0x200) +#define STV090x_P1_AGC1REF STV090x_Px_AGC1REF(1) +#define STV090x_P2_AGC1REF STV090x_Px_AGC1REF(2) +#define STV090x_OFFST_Px_AGCIQ_REF_FIELD 0 +#define STV090x_WIDTH_Px_AGCIQ_REF_FIELD 8 + +#define STV090x_Px_IDCCOMP(__x) (0xF408 - (__x - 1) * 0x200) +#define STV090x_P1_IDCCOMP STV090x_Px_IDCCOMP(1) +#define STV090x_P2_IDCCOMP STV090x_Px_IDCCOMP(2) +#define STV090x_OFFST_Px_IAVERAGE_ADJ_FIELD 0 +#define STV090x_WIDTH_Px_IAVERAGE_ADJ_FIELD 8 + +#define STV090x_Px_QDCCOMP(__x) (0xF409 - (__x - 1) * 0x200) +#define STV090x_P1_QDCCOMP STV090x_Px_QDCCOMP(1) +#define STV090x_P2_QDCCOMP STV090x_Px_QDCCOMP(2) +#define STV090x_OFFST_Px_QAVERAGE_ADJ_FIELD 0 +#define STV090x_WIDTH_Px_QAVERAGE_ADJ_FIELD 8 + +#define STV090x_Px_POWERI(__x) (0xF40A - (__x - 1) * 0x200) +#define STV090x_P1_POWERI STV090x_Px_POWERI(1) +#define STV090x_P2_POWERI STV090x_Px_POWERI(2) +#define STV090x_OFFST_Px_POWER_I_FIELD 0 +#define STV090x_WIDTH_Px_POWER_I_FIELD 8 + +#define STV090x_Px_POWERQ(__x) (0xF40B - (__x - 1) * 0x200) +#define STV090x_P1_POWERQ STV090x_Px_POWERQ(1) +#define STV090x_P2_POWERQ STV090x_Px_POWERQ(2) +#define STV090x_OFFST_Px_POWER_Q_FIELD 0 +#define STV090x_WIDTH_Px_POWER_Q_FIELD 8 + +#define STV090x_Px_AGC1AMM(__x) (0xF40C - (__x - 1) * 0x200) +#define STV090x_P1_AGC1AMM STV090x_Px_AGC1AMM(1) +#define STV090x_P2_AGC1AMM STV090x_Px_AGC1AMM(2) +#define STV090x_OFFST_Px_AMM_VALUE_FIELD 0 +#define STV090x_WIDTH_Px_AMM_VALUE_FIELD 8 + +#define STV090x_Px_AGC1QUAD(__x) (0xF40D - (__x - 1) * 0x200) +#define STV090x_P1_AGC1QUAD STV090x_Px_AGC1QUAD(1) +#define STV090x_P2_AGC1QUAD STV090x_Px_AGC1QUAD(2) +#define STV090x_OFFST_Px_QUAD_VALUE_FIELD 0 +#define STV090x_WIDTH_Px_QUAD_VALUE_FIELD 8 + +#define STV090x_Px_AGCIQINy(__x, __y) (0xF40F - (__x-1) * 0x200 - __y * 0x1) +#define STV090x_P1_AGCIQIN0 STV090x_Px_AGCIQINy(1, 0) +#define STV090x_P1_AGCIQIN1 STV090x_Px_AGCIQINy(1, 1) +#define STV090x_P2_AGCIQIN0 STV090x_Px_AGCIQINy(2, 0) +#define STV090x_P2_AGCIQIN1 STV090x_Px_AGCIQINy(2, 1) +#define STV090x_OFFST_Px_AGCIQ_VALUE_FIELD 0 +#define STV090x_WIDTH_Px_AGCIQ_VALUE_FIELD 8 + +#define STV090x_Px_DEMOD(__x) (0xF410 - (__x - 1) * 0x200) +#define STV090x_P1_DEMOD STV090x_Px_DEMOD(1) +#define STV090x_P2_DEMOD STV090x_Px_DEMOD(2) +#define STV090x_OFFST_Px_MANUAL_S2ROLLOFF_FIELD 7 +#define STV090x_WIDTH_Px_MANUAL_S2ROLLOFF_FIELD 1 +#define STV090x_OFFST_Px_DEMOD_STOP_FIELD 6 +#define STV090x_WIDTH_Px_DEMOD_STOP_FIELD 1 +#define STV090x_OFFST_Px_SPECINV_CONTROL_FIELD 4 +#define STV090x_WIDTH_Px_SPECINV_CONTROL_FIELD 2 +#define STV090x_OFFST_Px_FORCE_ENASAMP_FIELD 3 +#define STV090x_WIDTH_Px_FORCE_ENASAMP_FIELD 1 +#define STV090x_OFFST_Px_MANUAL_SXROLLOFF_FIELD 2 +#define STV090x_WIDTH_Px_MANUAL_SXROLLOFF_FIELD 1 +#define STV090x_OFFST_Px_ROLLOFF_CONTROL_FIELD 0 +#define STV090x_WIDTH_Px_ROLLOFF_CONTROL_FIELD 2 + +#define STV090x_Px_DMDMODCOD(__x) (0xF411 - (__x - 1) * 0x200) +#define STV090x_P1_DMDMODCOD STV090x_Px_DMDMODCOD(1) +#define STV090x_P2_DMDMODCOD STV090x_Px_DMDMODCOD(2) +#define STV090x_OFFST_Px_MANUAL_MODCOD_FIELD 7 +#define STV090x_WIDTH_Px_MANUAL_MODCOD_FIELD 1 +#define STV090x_OFFST_Px_DEMOD_MODCOD_FIELD 2 +#define STV090x_WIDTH_Px_DEMOD_MODCOD_FIELD 5 +#define STV090x_OFFST_Px_DEMOD_TYPE_FIELD 0 +#define STV090x_WIDTH_Px_DEMOD_TYPE_FIELD 2 + +#define STV090x_Px_DSTATUS(__x) (0xF412 - (__x - 1) * 0x200) +#define STV090x_P1_DSTATUS STV090x_Px_DSTATUS(1) +#define STV090x_P2_DSTATUS STV090x_Px_DSTATUS(2) +#define STV090x_OFFST_Px_CAR_LOCK_FIELD 7 +#define STV090x_WIDTH_Px_CAR_LOCK_FIELD 1 +#define STV090x_OFFST_Px_TMGLOCK_QUALITY_FIELD 5 +#define STV090x_WIDTH_Px_TMGLOCK_QUALITY_FIELD 2 +#define STV090x_OFFST_Px_LOCK_DEFINITIF_FIELD 3 +#define STV090x_WIDTH_Px_LOCK_DEFINITIF_FIELD 1 + +#define STV090x_Px_DSTATUS2(__x) (0xF413 - (__x - 1) * 0x200) +#define STV090x_P1_DSTATUS2 STV090x_Px_DSTATUS2(1) +#define STV090x_P2_DSTATUS2 STV090x_Px_DSTATUS2(2) +#define STV090x_OFFST_Px_DEMOD_DELOCK_FIELD 7 +#define STV090x_WIDTH_Px_DEMOD_DELOCK_FIELD 1 +#define STV090x_OFFST_Px_AGC1_NOSIGNALACK_FIELD 3 +#define STV090x_WIDTH_Px_AGC1_NOSIGNALACK_FIELD 1 +#define STV090x_OFFST_Px_AGC2_OVERFLOW_FIELD 2 +#define STV090x_WIDTH_Px_AGC2_OVERFLOW_FIELD 1 +#define STV090x_OFFST_Px_CFR_OVERFLOW_FIELD 1 +#define STV090x_WIDTH_Px_CFR_OVERFLOW_FIELD 1 +#define STV090x_OFFST_Px_GAMMA_OVERUNDER_FIELD 0 +#define STV090x_WIDTH_Px_GAMMA_OVERUNDER_FIELD 1 + +#define STV090x_Px_DMDCFGMD(__x) (0xF414 - (__x - 1) * 0x200) +#define STV090x_P1_DMDCFGMD STV090x_Px_DMDCFGMD(1) +#define STV090x_P2_DMDCFGMD STV090x_Px_DMDCFGMD(2) +#define STV090x_OFFST_Px_DVBS2_ENABLE_FIELD 7 +#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_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_NOFORCE_RELOCK_FIELD 2 +#define STV090x_WIDTH_Px_NOFORCE_RELOCK_FIELD 1 +#define STV090x_OFFST_Px_TUN_RNG_FIELD 0 +#define STV090x_WIDTH_Px_TUN_RNG_FIELD 2 + +#define STV090x_Px_DMDCFG2(__x) (0xF415 - (__x - 1) * 0x200) +#define STV090x_P1_DMDCFG2 STV090x_Px_DMDCFG2(1) +#define STV090x_P2_DMDCFG2 STV090x_Px_DMDCFG2(2) +#define STV090x_OFFST_Px_S1S2_SEQUENTIAL_FIELD 6 +#define STV090x_WIDTH_Px_S1S2_SEQUENTIAL_FIELD 1 + +#define STV090x_Px_DMDISTATE(__x) (0xF416 - (__x - 1) * 0x200) +#define STV090x_P1_DMDISTATE STV090x_Px_DMDISTATE(1) +#define STV090x_P2_DMDISTATE STV090x_Px_DMDISTATE(2) +#define STV090x_OFFST_Px_I2C_DEMOD_MODE_FIELD 0 +#define STV090x_WIDTH_Px_I2C_DEMOD_MODE_FIELD 5 + +#define STV090x_Px_DMDTOM(__x) (0xF417 - (__x - 1) * 0x200) /* check */ +#define STV090x_P1_DMDTOM STV090x_Px_DMDTOM(1) +#define STV090x_P2_DMDTOM STV090x_Px_DMDTOM(2) + +#define STV090x_Px_DMDSTATE(__x) (0xF41B - (__x - 1) * 0x200) +#define STV090x_P1_DMDSTATE STV090x_Px_DMDSTATE(1) +#define STV090x_P2_DMDSTATE STV090x_Px_DMDSTATE(2) +#define STV090x_OFFST_Px_HEADER_MODE_FIELD 5 +#define STV090x_WIDTH_Px_HEADER_MODE_FIELD 2 + +#define STV090x_Px_DMDFLYW(__x) (0xF41C - (__x - 1) * 0x200) +#define STV090x_P1_DMDFLYW STV090x_Px_DMDFLYW(1) +#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_WIDTH_Px_FLYWHEEL_CPT_FIELD 4 + +#define STV090x_Px_DSTATUS3(__x) (0xF41D - (__x - 1) * 0x200) +#define STV090x_P1_DSTATUS3 STV090x_Px_DSTATUS3(1) +#define STV090x_P2_DSTATUS3 STV090x_Px_DSTATUS3(2) +#define STV090x_OFFST_Px_DEMOD_CFGMODE_FIELD 5 +#define STV090x_WIDTH_Px_DEMOD_CFGMODE_FIELD 2 + +#define STV090x_Px_DMDCFG3(__x) (0xF41E - (__x - 1) * 0x200) +#define STV090x_P1_DMDCFG3 STV090x_Px_DMDCFG3(1) +#define STV090x_P2_DMDCFG3 STV090x_Px_DMDCFG3(2) +#define STV090x_OFFST_Px_NOSTOP_FIFOFULL_FIELD 3 +#define STV090x_WIDTH_Px_NOSTOP_FIFOFULL_FIELD 1 + +#define STV090x_Px_DMDCFG4(__x) (0xf41f - (__x - 1) * 0x200) +#define STV090x_P1_DMDCFG4 STV090x_Px_DMDCFG4(1) +#define STV090x_P2_DMDCFG4 STV090x_Px_DMDCFG4(2) + +#define STV090x_Px_CORRELMANT(__x) (0xF420 - (__x - 1) * 0x200) +#define STV090x_P1_CORRELMANT STV090x_Px_CORRELMANT(1) +#define STV090x_P2_CORRELMANT STV090x_Px_CORRELMANT(2) +#define STV090x_OFFST_Px_CORREL_MANT_FIELD 0 +#define STV090x_WIDTH_Px_CORREL_MANT_FIELD 8 + +#define STV090x_Px_CORRELABS(__x) (0xF421 - (__x - 1) * 0x200) +#define STV090x_P1_CORRELABS STV090x_Px_CORRELABS(1) +#define STV090x_P2_CORRELABS STV090x_Px_CORRELABS(2) +#define STV090x_OFFST_Px_CORREL_ABS_FIELD 0 +#define STV090x_WIDTH_Px_CORREL_ABS_FIELD 8 + +#define STV090x_Px_CORRELEXP(__x) (0xF422 - (__x - 1) * 0x200) +#define STV090x_P1_CORRELEXP STV090x_Px_CORRELEXP(1) +#define STV090x_P2_CORRELEXP STV090x_Px_CORRELEXP(2) +#define STV090x_OFFST_Px_CORREL_ABSEXP_FIELD 4 +#define STV090x_WIDTH_Px_CORREL_ABSEXP_FIELD 4 +#define STV090x_OFFST_Px_CORREL_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CORREL_EXP_FIELD 4 + +#define STV090x_Px_PLHMODCOD(__x) (0xF424 - (__x - 1) * 0x200) +#define STV090x_P1_PLHMODCOD STV090x_Px_PLHMODCOD(1) +#define STV090x_P2_PLHMODCOD STV090x_Px_PLHMODCOD(2) +#define STV090x_OFFST_Px_SPECINV_DEMOD_FIELD 7 +#define STV090x_WIDTH_Px_SPECINV_DEMOD_FIELD 1 +#define STV090x_OFFST_Px_PLH_MODCOD_FIELD 2 +#define STV090x_WIDTH_Px_PLH_MODCOD_FIELD 5 +#define STV090x_OFFST_Px_PLH_TYPE_FIELD 0 +#define STV090x_WIDTH_Px_PLH_TYPE_FIELD 2 + +#define STV090x_Px_AGCK32(__x) (0xf42b - (__x - 1) * 0x200) +#define STV090x_P1_AGCK32 STV090x_Px_AGCK32(1) +#define STV090x_P2_AGCK32 STV090x_Px_AGCK32(2) + +#define STV090x_Px_AGC2O(__x) (0xF42C - (__x - 1) * 0x200) +#define STV090x_P1_AGC2O STV090x_Px_AGC2O(1) +#define STV090x_P2_AGC2O STV090x_Px_AGC2O(2) + +#define STV090x_Px_AGC2REF(__x) (0xF42D - (__x - 1) * 0x200) +#define STV090x_P1_AGC2REF STV090x_Px_AGC2REF(1) +#define STV090x_P2_AGC2REF STV090x_Px_AGC2REF(2) +#define STV090x_OFFST_Px_AGC2_REF_FIELD 0 +#define STV090x_WIDTH_Px_AGC2_REF_FIELD 8 + +#define STV090x_Px_AGC1ADJ(__x) (0xF42E - (__x - 1) * 0x200) +#define STV090x_P1_AGC1ADJ STV090x_Px_AGC1ADJ(1) +#define STV090x_P2_AGC1ADJ STV090x_Px_AGC1ADJ(2) +#define STV090x_OFFST_Px_AGC1_ADJUSTED_FIELD 0 +#define STV090x_WIDTH_Px_AGC1_ADJUSTED_FIELD 7 + +#define STV090x_Px_AGC2Iy(__x, __y) (0xF437 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_AGC2I0 STV090x_Px_AGC2Iy(1, 0) +#define STV090x_P1_AGC2I1 STV090x_Px_AGC2Iy(1, 1) +#define STV090x_P2_AGC2I0 STV090x_Px_AGC2Iy(2, 0) +#define STV090x_P2_AGC2I1 STV090x_Px_AGC2Iy(2, 1) +#define STV090x_OFFST_Px_AGC2_INTEGRATOR_FIELD 0 +#define STV090x_WIDTH_Px_AGC2_INTEGRATOR_FIELD 8 + +#define STV090x_Px_CARCFG(__x) (0xF438 - (__x - 1) * 0x200) +#define STV090x_P1_CARCFG STV090x_Px_CARCFG(1) +#define STV090x_P2_CARCFG STV090x_Px_CARCFG(2) +#define STV090x_OFFST_Px_EN_CAR2CENTER_FIELD 5 +#define STV090x_WIDTH_Px_EN_CAR2CENTER_FIELD 1 +#define STV090x_OFFST_Px_ROTATON_FIELD 2 +#define STV090x_WIDTH_Px_ROTATON_FIELD 1 +#define STV090x_OFFST_Px_PH_DET_ALGO_FIELD 0 +#define STV090x_WIDTH_Px_PH_DET_ALGO_FIELD 2 + +#define STV090x_Px_ACLC(__x) (0xF439 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC STV090x_Px_ACLC(1) +#define STV090x_P2_ACLC STV090x_Px_ACLC(2) +#define STV090x_OFFST_Px_CAR_ALPHA_MANT_FIELD 4 +#define STV090x_WIDTH_Px_CAR_ALPHA_MANT_FIELD 2 +#define STV090x_OFFST_Px_CAR_ALPHA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CAR_ALPHA_EXP_FIELD 4 + +#define STV090x_Px_BCLC(__x) (0xF43A - (__x - 1) * 0x200) +#define STV090x_P1_BCLC STV090x_Px_BCLC(1) +#define STV090x_P2_BCLC STV090x_Px_BCLC(2) +#define STV090x_OFFST_Px_CAR_BETA_MANT_FIELD 4 +#define STV090x_WIDTH_Px_CAR_BETA_MANT_FIELD 2 +#define STV090x_OFFST_Px_CAR_BETA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CAR_BETA_EXP_FIELD 4 + +#define STV090x_Px_CARFREQ(__x) (0xF43D - (__x - 1) * 0x200) +#define STV090x_P1_CARFREQ STV090x_Px_CARFREQ(1) +#define STV090x_P2_CARFREQ STV090x_Px_CARFREQ(2) +#define STV090x_OFFST_Px_KC_COARSE_EXP_FIELD 4 +#define STV090x_WIDTH_Px_KC_COARSE_EXP_FIELD 4 +#define STV090x_OFFST_Px_BETA_FREQ_FIELD 0 +#define STV090x_WIDTH_Px_BETA_FREQ_FIELD 4 + +#define STV090x_Px_CARHDR(__x) (0xF43E - (__x - 1) * 0x200) +#define STV090x_P1_CARHDR STV090x_Px_CARHDR(1) +#define STV090x_P2_CARHDR STV090x_Px_CARHDR(2) +#define STV090x_OFFST_Px_FREQ_HDR_FIELD 0 +#define STV090x_WIDTH_Px_FREQ_HDR_FIELD 8 + +#define STV090x_Px_LDT(__x) (0xF43F - (__x - 1) * 0x200) +#define STV090x_P1_LDT STV090x_Px_LDT(1) +#define STV090x_P2_LDT STV090x_Px_LDT(2) +#define STV090x_OFFST_Px_CARLOCK_THRES_FIELD 0 +#define STV090x_WIDTH_Px_CARLOCK_THRES_FIELD 8 + +#define STV090x_Px_LDT2(__x) (0xF440 - (__x - 1) * 0x200) +#define STV090x_P1_LDT2 STV090x_Px_LDT2(1) +#define STV090x_P2_LDT2 STV090x_Px_LDT2(2) +#define STV090x_OFFST_Px_CARLOCK_THRES2_FIELD 0 +#define STV090x_WIDTH_Px_CARLOCK_THRES2_FIELD 8 + +#define STV090x_Px_CFRICFG(__x) (0xF441 - (__x - 1) * 0x200) +#define STV090x_P1_CFRICFG STV090x_Px_CFRICFG(1) +#define STV090x_P2_CFRICFG STV090x_Px_CFRICFG(2) +#define STV090x_OFFST_Px_NEG_CFRSTEP_FIELD 0 +#define STV090x_WIDTH_Px_NEG_CFRSTEP_FIELD 1 + +#define STV090x_Pn_CFRUPy(__x, __y) (0xF443 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_CFRUP0 STV090x_Pn_CFRUPy(1, 0) +#define STV090x_P1_CFRUP1 STV090x_Pn_CFRUPy(1, 1) +#define STV090x_P2_CFRUP0 STV090x_Pn_CFRUPy(2, 0) +#define STV090x_P2_CFRUP1 STV090x_Pn_CFRUPy(2, 1) +#define STV090x_OFFST_Px_CFR_UP_FIELD 0 +#define STV090x_WIDTH_Px_CFR_UP_FIELD 8 + +#define STV090x_Pn_CFRLOWy(__x, __y) (0xF447 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_CFRLOW0 STV090x_Pn_CFRLOWy(1, 0) +#define STV090x_P1_CFRLOW1 STV090x_Pn_CFRLOWy(1, 1) +#define STV090x_P2_CFRLOW0 STV090x_Pn_CFRLOWy(2, 0) +#define STV090x_P2_CFRLOW1 STV090x_Pn_CFRLOWy(2, 1) +#define STV090x_OFFST_Px_CFR_LOW_FIELD 0 +#define STV090x_WIDTH_Px_CFR_LOW_FIELD 8 + +#define STV090x_Pn_CFRINITy(__x, __y) (0xF449 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_CFRINIT0 STV090x_Pn_CFRINITy(1, 0) +#define STV090x_P1_CFRINIT1 STV090x_Pn_CFRINITy(1, 1) +#define STV090x_P2_CFRINIT0 STV090x_Pn_CFRINITy(2, 0) +#define STV090x_P2_CFRINIT1 STV090x_Pn_CFRINITy(2, 1) +#define STV090x_OFFST_Px_CFR_INIT_FIELD 0 +#define STV090x_WIDTH_Px_CFR_INIT_FIELD 8 + +#define STV090x_Px_CFRINC1(__x) (0xF44A - (__x - 1) * 0x200) +#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_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_WIDTH_Px_CFR_INC0_FIELD 4 + +#define STV090x_Pn_CFRy(__x, __y) (0xF44E - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_CFR0 STV090x_Pn_CFRy(1, 0) +#define STV090x_P1_CFR1 STV090x_Pn_CFRy(1, 1) +#define STV090x_P1_CFR2 STV090x_Pn_CFRy(1, 2) +#define STV090x_P2_CFR0 STV090x_Pn_CFRy(2, 0) +#define STV090x_P2_CFR1 STV090x_Pn_CFRy(2, 1) +#define STV090x_P2_CFR2 STV090x_Pn_CFRy(2, 2) +#define STV090x_OFFST_Px_CAR_FREQ_FIELD 0 +#define STV090x_WIDTH_Px_CAR_FREQ_FIELD 8 + +#define STV090x_Px_LDI(__x) (0xF44F - (__x - 1) * 0x200) +#define STV090x_P1_LDI STV090x_Px_LDI(1) +#define STV090x_P2_LDI STV090x_Px_LDI(2) +#define STV090x_OFFST_Px_LOCK_DET_INTEGR_FIELD 0 +#define STV090x_WIDTH_Px_LOCK_DET_INTEGR_FIELD 8 + +#define STV090x_Px_TMGCFG(__x) (0xF450 - (__x - 1) * 0x200) +#define STV090x_P1_TMGCFG STV090x_Px_TMGCFG(1) +#define STV090x_P2_TMGCFG STV090x_Px_TMGCFG(2) +#define STV090x_OFFST_Px_TMGLOCK_BETA_FIELD 6 +#define STV090x_WIDTH_Px_TMGLOCK_BETA_FIELD 2 +#define STV090x_OFFST_Px_DO_TIMING_FIELD 4 +#define STV090x_WIDTH_Px_DO_TIMING_FIELD 1 +#define STV090x_OFFST_Px_TMG_MINFREQ_FIELD 0 +#define STV090x_WIDTH_Px_TMG_MINFREQ_FIELD 2 + +#define STV090x_Px_RTC(__x) (0xF451 - (__x - 1) * 0x200) +#define STV090x_P1_RTC STV090x_Px_RTC(1) +#define STV090x_P2_RTC STV090x_Px_RTC(2) +#define STV090x_OFFST_Px_TMGALPHA_EXP_FIELD 4 +#define STV090x_WIDTH_Px_TMGALPHA_EXP_FIELD 4 +#define STV090x_OFFST_Px_TMGBETA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_TMGBETA_EXP_FIELD 4 + +#define STV090x_Px_RTCS2(__x) (0xF452 - (__x - 1) * 0x200) +#define STV090x_P1_RTCS2 STV090x_Px_RTCS2(1) +#define STV090x_P2_RTCS2 STV090x_Px_RTCS2(2) +#define STV090x_OFFST_Px_TMGALPHAS2_EXP_FIELD 4 +#define STV090x_WIDTH_Px_TMGALPHAS2_EXP_FIELD 4 +#define STV090x_OFFST_Px_TMGBETAS2_EXP_FIELD 0 +#define STV090x_WIDTH_Px_TMGBETAS2_EXP_FIELD 4 + +#define STV090x_Px_TMGTHRISE(__x) (0xF453 - (__x - 1) * 0x200) +#define STV090x_P1_TMGTHRISE STV090x_Px_TMGTHRISE(1) +#define STV090x_P2_TMGTHRISE STV090x_Px_TMGTHRISE(2) +#define STV090x_OFFST_Px_TMGLOCK_THRISE_FIELD 0 +#define STV090x_WIDTH_Px_TMGLOCK_THRISE_FIELD 8 + +#define STV090x_Px_TMGTHFALL(__x) (0xF454 - (__x - 1) * 0x200) +#define STV090x_P1_TMGTHFALL STV090x_Px_TMGTHFALL(1) +#define STV090x_P2_TMGTHFALL STV090x_Px_TMGTHFALL(2) +#define STV090x_OFFST_Px_TMGLOCK_THFALL_FIELD 0 +#define STV090x_WIDTH_Px_TMGLOCK_THFALL_FIELD 8 + +#define STV090x_Px_SFRUPRATIO(__x) (0xF455 - (__x - 1) * 0x200) +#define STV090x_P1_SFRUPRATIO STV090x_Px_SFRUPRATIO(1) +#define STV090x_P2_SFRUPRATIO STV090x_Px_SFRUPRATIO(2) +#define STV090x_OFFST_Px_SFR_UPRATIO_FIELD 0 +#define STV090x_WIDTH_Px_SFR_UPRATIO_FIELD 8 + +#define STV090x_Px_SFRLOWRATIO(__x) (0xF456 - (__x - 1) * 0x200) +#define STV090x_P1_SFRLOWRATIO STV090x_Px_SFRLOWRATIO(1) +#define STV090x_P2_SFRLOWRATIO STV090x_Px_SFRLOWRATIO(2) +#define STV090x_OFFST_Px_SFR_LOWRATIO_FIELD 0 +#define STV090x_WIDTH_Px_SFR_LOWRATIO_FIELD 8 + +#define STV090x_Px_KREFTMG(__x) (0xF458 - (__x - 1) * 0x200) +#define STV090x_P1_KREFTMG STV090x_Px_KREFTMG(1) +#define STV090x_P2_KREFTMG STV090x_Px_KREFTMG(2) +#define STV090x_OFFST_Px_KREF_TMG_FIELD 0 +#define STV090x_WIDTH_Px_KREF_TMG_FIELD 8 + +#define STV090x_Px_SFRSTEP(__x) (0xF459 - (__x - 1) * 0x200) +#define STV090x_P1_SFRSTEP STV090x_Px_SFRSTEP(1) +#define STV090x_P2_SFRSTEP STV090x_Px_SFRSTEP(2) +#define STV090x_OFFST_Px_SFR_SCANSTEP_FIELD 4 +#define STV090x_WIDTH_Px_SFR_SCANSTEP_FIELD 4 +#define STV090x_OFFST_Px_SFR_CENTERSTEP_FIELD 0 +#define STV090x_WIDTH_Px_SFR_CENTERSTEP_FIELD 4 + +#define STV090x_Px_TMGCFG2(__x) (0xF45A - (__x - 1) * 0x200) +#define STV090x_P1_TMGCFG2 STV090x_Px_TMGCFG2(1) +#define STV090x_P2_TMGCFG2 STV090x_Px_TMGCFG2(2) +#define STV090x_OFFST_Px_SFRRATIO_FINE_FIELD 0 +#define STV090x_WIDTH_Px_SFRRATIO_FINE_FIELD 1 + +#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_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_Px_SFRUP1(__x) (0xF460 - (__x - 1) * 0x200) +#define STV090x_P1_SFRUP1 STV090x_Px_SFRUP1(1) +#define STV090x_P2_SFRUP1 STV090x_Px_SFRUP1(2) +#define STV090x_OFFST_Px_SYMB_FREQ_UP1_FIELD 0 +#define STV090x_WIDTH_Px_SYMB_FREQ_UP1_FIELD 7 + +#define STV090x_Px_SFRUP0(__x) (0xF461 - (__x - 1) * 0x200) +#define STV090x_P1_SFRUP0 STV090x_Px_SFRUP0(1) +#define STV090x_P2_SFRUP0 STV090x_Px_SFRUP0(2) +#define STV090x_OFFST_Px_SYMB_FREQ_UP0_FIELD 0 +#define STV090x_WIDTH_Px_SYMB_FREQ_UP0_FIELD 8 + +#define STV090x_Px_SFRLOW1(__x) (0xF462 - (__x - 1) * 0x200) +#define STV090x_P1_SFRLOW1 STV090x_Px_SFRLOW1(1) +#define STV090x_P2_SFRLOW1 STV090x_Px_SFRLOW1(2) +#define STV090x_OFFST_Px_SYMB_FREQ_LOW1_FIELD 0 +#define STV090x_WIDTH_Px_SYMB_FREQ_LOW1_FIELD 7 + +#define STV090x_Px_SFRLOW0(__x) (0xF463 - (__x - 1) * 0x200) +#define STV090x_P1_SFRLOW0 STV090x_Px_SFRLOW0(1) +#define STV090x_P2_SFRLOW0 STV090x_Px_SFRLOW0(2) +#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_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) +#define STV090x_P1_SFR3 STV090x_Px_SFRy(1, 3) +#define STV090x_P2_SFR0 STV090x_Px_SFRy(2, 0) +#define STV090x_P2_SFR1 STV090x_Px_SFRy(2, 1) +#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_Px_TMGREG2(__x) (0xF468 - (__x - 1) * 0x200) +#define STV090x_P1_TMGREG2 STV090x_Px_TMGREG2(1) +#define STV090x_P2_TMGREG2 STV090x_Px_TMGREG2(2) +#define STV090x_OFFST_Px_TMGREG_FIELD 0 +#define STV090x_WIDTH_Px_TMGREG_FIELD 8 + +#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_OFFST_Px_TMGREG_FIELD 0 +#define STV090x_WIDTH_Px_TMGREG_FIELD 8 + +#define STV090x_Px_TMGREG0(__x) (0xF46A - (__x - 1) * 0x200) +#define STV090x_P1_TMGREG0 STV090x_Px_TMGREG0(1) +#define STV090x_P2_TMGREG0 STV090x_Px_TMGREG0(2) +#define STV090x_OFFST_Px_TMGREG_FIELD 0 +#define STV090x_WIDTH_Px_TMGREG_FIELD 8 + +#define STV090x_Px_TMGLOCKy(__x, __y) (0xF46C - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_TMGLOCK0 STV090x_Px_TMGLOCKy(1, 0) +#define STV090x_P1_TMGLOCK1 STV090x_Px_TMGLOCKy(1, 1) +#define STV090x_P2_TMGLOCK0 STV090x_Px_TMGLOCKy(2, 0) +#define STV090x_P2_TMGLOCK1 STV090x_Px_TMGLOCKy(2, 1) +#define STV090x_OFFST_Px_TMGLOCK_LEVEL_FIELD 0 +#define STV090x_WIDTH_Px_TMGLOCK_LEVEL_FIELD 8 + +#define STV090x_Px_TMGOBS(__x) (0xF46D - (__x - 1) * 0x200) +#define STV090x_P1_TMGOBS STV090x_Px_TMGOBS(1) +#define STV090x_P2_TMGOBS STV090x_Px_TMGOBS(2) +#define STV090x_OFFST_Px_ROLLOFF_STATUS_FIELD 6 +#define STV090x_WIDTH_Px_ROLLOFF_STATUS_FIELD 2 + +#define STV090x_Px_EQUALCFG(__x) (0xF46F - (__x - 1) * 0x200) +#define STV090x_P1_EQUALCFG STV090x_Px_EQUALCFG(1) +#define STV090x_P2_EQUALCFG STV090x_Px_EQUALCFG(2) +#define STV090x_OFFST_Px_EQUAL_ON_FIELD 6 +#define STV090x_WIDTH_Px_EQUAL_ON_FIELD 1 +#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_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) +#define STV090x_P1_EQUAI4 STV090x_Px_EQUAIy(1, 4) +#define STV090x_P1_EQUAI5 STV090x_Px_EQUAIy(1, 5) +#define STV090x_P1_EQUAI6 STV090x_Px_EQUAIy(1, 6) +#define STV090x_P1_EQUAI7 STV090x_Px_EQUAIy(1, 7) +#define STV090x_P1_EQUAI8 STV090x_Px_EQUAIy(1, 8) + +#define STV090x_P2_EQUAI1 STV090x_Px_EQUAIy(2, 1) +#define STV090x_P2_EQUAI2 STV090x_Px_EQUAIy(2, 2) +#define STV090x_P2_EQUAI3 STV090x_Px_EQUAIy(2, 3) +#define STV090x_P2_EQUAI4 STV090x_Px_EQUAIy(2, 4) +#define STV090x_P2_EQUAI5 STV090x_Px_EQUAIy(2, 5) +#define STV090x_P2_EQUAI6 STV090x_Px_EQUAIy(2, 6) +#define STV090x_P2_EQUAI7 STV090x_Px_EQUAIy(2, 7) +#define STV090x_P2_EQUAI8 STV090x_Px_EQUAIy(2, 8) +#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_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) +#define STV090x_P1_EQUAQ4 STV090x_Px_EQUAQy(1, 4) +#define STV090x_P1_EQUAQ5 STV090x_Px_EQUAQy(1, 5) +#define STV090x_P1_EQUAQ6 STV090x_Px_EQUAQy(1, 6) +#define STV090x_P1_EQUAQ7 STV090x_Px_EQUAQy(1, 7) +#define STV090x_P1_EQUAQ8 STV090x_Px_EQUAQy(1, 8) + +#define STV090x_P2_EQUAQ1 STV090x_Px_EQUAQy(2, 1) +#define STV090x_P2_EQUAQ2 STV090x_Px_EQUAQy(2, 2) +#define STV090x_P2_EQUAQ3 STV090x_Px_EQUAQy(2, 3) +#define STV090x_P2_EQUAQ4 STV090x_Px_EQUAQy(2, 4) +#define STV090x_P2_EQUAQ5 STV090x_Px_EQUAQy(2, 5) +#define STV090x_P2_EQUAQ6 STV090x_Px_EQUAQy(2, 6) +#define STV090x_P2_EQUAQ7 STV090x_Px_EQUAQy(2, 7) +#define STV090x_P2_EQUAQ8 STV090x_Px_EQUAQy(2, 8) +#define STV090x_OFFST_Px_EQUA_ACCQy_FIELD 0 +#define STV090x_WIDTH_Px_EQUA_ACCQy_FIELD 8 + +#define STV090x_Px_NNOSDATATy(__x, __y) (0xf481 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NNOSDATAT0 STV090x_Px_NNOSDATATy(1, 0) +#define STV090x_P1_NNOSDATAT1 STV090x_Px_NNOSDATATy(1, 1) +#define STV090x_P2_NNOSDATAT0 STV090x_Px_NNOSDATATy(2, 0) +#define STV090x_P2_NNOSDATAT1 STV090x_Px_NNOSDATATy(2, 1) +#define STV090x_OFFST_Px_NOSDATAT_NORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATAT_NORMED_FIELD 8 + +#define STV090x_Px_NNOSDATAy(__x, __y) (0xf483 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NNOSDATA0 STV090x_Px_NNOSDATAy(1, 0) +#define STV090x_P1_NNOSDATA1 STV090x_Px_NNOSDATAy(1, 1) +#define STV090x_P2_NNOSDATA0 STV090x_Px_NNOSDATAy(2, 0) +#define STV090x_P2_NNOSDATA1 STV090x_Px_NNOSDATAy(2, 1) +#define STV090x_OFFST_Px_NOSDATA_NORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATA_NORMED_FIELD 8 + +#define STV090x_Px_NNOSPLHTy(__x, __y) (0xf485 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NNOSPLHT0 STV090x_Px_NNOSPLHTy(1, 0) +#define STV090x_P1_NNOSPLHT1 STV090x_Px_NNOSPLHTy(1, 1) +#define STV090x_P2_NNOSPLHT0 STV090x_Px_NNOSPLHTy(2, 0) +#define STV090x_P2_NNOSPLHT1 STV090x_Px_NNOSPLHTy(2, 1) +#define STV090x_OFFST_Px_NOSPLHT_NORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSPLHT_NORMED_FIELD 8 + +#define STV090x_Px_NNOSPLHy(__x, __y) (0xf487 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NNOSPLH0 STV090x_Px_NNOSPLHy(1, 0) +#define STV090x_P1_NNOSPLH1 STV090x_Px_NNOSPLHy(1, 1) +#define STV090x_P2_NNOSPLH0 STV090x_Px_NNOSPLHy(2, 0) +#define STV090x_P2_NNOSPLH1 STV090x_Px_NNOSPLHy(2, 1) +#define STV090x_OFFST_Px_NOSPLH_NORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSPLH_NORMED_FIELD 8 + +#define STV090x_Px_NOSDATATy(__x, __y) (0xf489 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NOSDATAT0 STV090x_Px_NOSDATATy(1, 0) +#define STV090x_P1_NOSDATAT1 STV090x_Px_NOSDATATy(1, 1) +#define STV090x_P2_NOSDATAT0 STV090x_Px_NOSDATATy(2, 0) +#define STV090x_P2_NOSDATAT1 STV090x_Px_NOSDATATy(2, 1) +#define STV090x_OFFST_Px_NOSDATAT_UNNORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATAT_UNNORMED_FIELD 8 + +#define STV090x_Px_NOSDATAy(__x, __y) (0xf48b - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NOSDATA0 STV090x_Px_NOSDATAy(1, 0) +#define STV090x_P1_NOSDATA1 STV090x_Px_NOSDATAy(1, 1) +#define STV090x_P2_NOSDATA0 STV090x_Px_NOSDATAy(2, 0) +#define STV090x_P2_NOSDATA1 STV090x_Px_NOSDATAy(2, 1) +#define STV090x_OFFST_Px_NOSDATA_UNNORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATA_UNNORMED_FIELD 8 + +#define STV090x_Px_NOSPLHTy(__x, __y) (0xf48d - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NOSPLHT0 STV090x_Px_NOSPLHTy(1, 0) +#define STV090x_P1_NOSPLHT1 STV090x_Px_NOSPLHTy(1, 1) +#define STV090x_P2_NOSPLHT0 STV090x_Px_NOSPLHTy(2, 0) +#define STV090x_P2_NOSPLHT1 STV090x_Px_NOSPLHTy(2, 1) +#define STV090x_OFFST_Px_NOSPLHT_UNNORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSPLHT_UNNORMED_FIELD 8 + +#define STV090x_Px_NOSPLHy(__x, __y) (0xf48f - (__x - 1) * 0x200 - __y * 0x1) +#define STv090x_P1_NOSPLH0 STV090x_Px_NOSPLHy(1, 0) +#define STv090x_P1_NOSPLH1 STV090x_Px_NOSPLHy(1, 1) +#define STv090x_P2_NOSPLH0 STV090x_Px_NOSPLHy(2, 0) +#define STv090x_P2_NOSPLH1 STV090x_Px_NOSPLHy(2, 1) +#define STV090x_OFFST_Px_NOSPLH_UNNORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSPLH_UNNORMED_FIELD 8 + +#define STV090x_Px_CAR2CFG(__x) (0xf490 - (__x - 1) * 0x200) +#define STV090x_P1_CAR2CFG STV090x_Px_CAR2CFG(1) +#define STV090x_P2_CAR2CFG STV090x_Px_CAR2CFG(2) +#define STV090x_OFFST_Px_PN4_SELECT_FIELD 6 +#define STV090x_WIDTH_Px_PN4_SELECT_FIELD 1 +#define STV090x_OFFST_Px_CFR2_STOPDVBS1_FIELD 5 +#define STV090x_WIDTH_Px_CFR2_STOPDVBS1_FIELD 1 +#define STV090x_OFFST_Px_ROTA2ON_FIELD 2 +#define STV090x_WIDTH_Px_ROTA2ON_FIELD 1 +#define STV090x_OFFST_Px_PH_DET_ALGO2_FIELD 0 +#define STV090x_WIDTH_Px_PH_DET_ALGO2_FIELD 2 + +#define STV090x_Px_ACLC2(__x) (0xf491 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2 STV090x_Px_ACLC2(1) +#define STV090x_P2_ACLC2 STV090x_Px_ACLC2(2) +#define STV090x_OFFST_Px_CAR2_ALPHA_MANT_FIELD 4 +#define STV090x_WIDTH_Px_CAR2_ALPHA_MANT_FIELD 2 +#define STV090x_OFFST_Px_CAR2_ALPHA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CAR2_ALPHA_EXP_FIELD 4 + +#define STV090x_Px_BCLC2(__x) (0xf492 - (__x - 1) * 0x200) +#define STV090x_P1_BCLC2 STV090x_Px_BCLC2(1) +#define STV090x_P2_BCLC2 STV090x_Px_BCLC2(2) +#define STV090x_OFFST_Px_CAR2_BETA_MANT_FIELD 4 +#define STV090x_WIDTH_Px_CAR2_BETA_MANT_FIELD 2 +#define STV090x_OFFST_Px_CAR2_BETA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CAR2_BETA_EXP_FIELD 4 + +#define STV090x_Px_ACLC2S2Q(__x) (0xf497 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2S2Q STV090x_Px_ACLC2S2Q(1) +#define STV090x_P2_ACLC2S2Q STV090x_Px_ACLC2S2Q(2) +#define STV090x_OFFST_Px_ENAB_SPSKSYMB_FIELD 7 +#define STV090x_WIDTH_Px_ENAB_SPSKSYMB_FIELD 1 +#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_E_FIELD 4 + +#define STV090x_Px_ACLC2S28(__x) (0xf498 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2S28 STV090x_Px_ACLC2S28(1) +#define STV090x_P2_ACLC2S28 STV090x_Px_ACLC2S28(2) +#define STV090x_OFFST_Px_CAR2S2_8_ALPH_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_8_ALPH_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_E_FIELD 4 + +#define STV090x_Px_ACLC2S216A(__x) (0xf499 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2S216A STV090x_Px_ACLC2S216A(1) +#define STV090x_P2_ACLC2S216A STV090x_Px_ACLC2S216A(2) +#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_M_FIELD 2 +#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_P1_ACLC2S232A STV090x_Px_ACLC2S232A(1) +#define STV090x_P2_ACLC2S232A STV090x_Px_ACLC2S232A(2) +#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_E_FIELD 4 + +#define STV090x_Px_BCLC2S2Q(__x) (0xf49c - (__x - 1) * 0x200) +#define STV090x_P1_BCLC2S2Q STV090x_Px_BCLC2S2Q(1) +#define STV090x_P2_BCLC2S2Q STV090x_Px_BCLC2S2Q(2) +#define STV090x_OFFST_Px_CAR2S2_Q_BETA_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_Q_BETA_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_E_FIELD 4 + +#define STV090x_Px_BCLC2S28(__x) (0xf49d - (__x - 1) * 0x200) +#define STV090x_P1_BCLC2S28 STV090x_Px_BCLC2S28(1) +#define STV090x_P2_BCLC2S28 STV090x_Px_BCLC2S28(1) +#define STV090x_OFFST_Px_CAR2S2_8_BETA_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_8_BETA_M_FIELD 2 +#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_P1_BCLC2S216A STV090x_Px_BCLC2S216A(1) +#define STV090x_P2_BCLC2S216A STV090x_Px_BCLC2S216A(1) +#define STV090x_OFFST_Px_CAR2S2_16A_BETA_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_M_FIELD 2 +#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_P1_BCLC2S232A STV090x_Px_BCLC2S232A(1) +#define STV090x_P2_BCLC2S232A STV090x_Px_BCLC2S232A(1) +#define STV090x_OFFST_Px_CAR2S2_32A_BETA_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_32A_BETA_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_E_FIELD 4 + +#define STV090x_Px_PLROOT2(__x) (0xf4ac - (__x - 1) * 0x200) +#define STV090x_P1_PLROOT2 STV090x_Px_PLROOT2(1) +#define STV090x_P2_PLROOT2 STV090x_Px_PLROOT2(2) +#define STV090x_OFFST_Px_PLSCRAMB_MODE_FIELD 2 +#define STV090x_WIDTH_Px_PLSCRAMB_MODE_FIELD 2 +#define STV090x_OFFST_Px_PLSCRAMB_ROOT_FIELD 0 +#define STV090x_WIDTH_Px_PLSCRAMB_ROOT_FIELD 2 + +#define STV090x_Px_PLROOT1(__x) (0xf4ad - (__x - 1) * 0x200) +#define STV090x_P1_PLROOT1 STV090x_Px_PLROOT1(1) +#define STV090x_P2_PLROOT1 STV090x_Px_PLROOT1(2) +#define STV090x_OFFST_Px_PLSCRAMB_ROOT1_FIELD 0 +#define STV090x_WIDTH_Px_PLSCRAMB_ROOT1_FIELD 8 + +#define STV090x_Px_PLROOT0(__x) (0xf4ae - (__x - 1) * 0x200) +#define STV090x_P1_PLROOT0 STV090x_Px_PLROOT0(1) +#define STV090x_P2_PLROOT0 STV090x_Px_PLROOT0(2) +#define STV090x_OFFST_Px_PLSCRAMB_ROOT0_FIELD 0 +#define STV090x_WIDTH_Px_PLSCRAMB_ROOT0_FIELD 8 + +#define STV090x_Px_MODCODLST0(__x) (0xf4b0 - (__x - 1) * 0x200) /* check */ +#define STV090x_P1_MODCODLST0 STV090x_Px_MODCODLST0(1) +#define STV090x_P2_MODCODLST0 STV090x_Px_MODCODLST0(2) + +#define STV090x_Px_MODCODLST1(__x) (0xf4b1 - (__x - 1) * 0x200) +#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_OFFST_Px_DIS_32PSK_9_10_FIELD 0 +#define STV090x_WIDTH_Px_DIS_32PSK_9_10_FIELD 4 + +#define STV090x_Px_MODCODLST2(__x) (0xf4b2 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST2 STV090x_Px_MODCODLST2(1) +#define STV090x_P2_MODCODLST2 STV090x_Px_MODCODLST2(2) +#define STV090x_OFFST_Px_DIS_32PSK_8_9_FIELD 4 +#define STV090x_WIDTH_Px_DIS_32PSK_8_9_FIELD 4 +#define STV090x_OFFST_Px_DIS_32PSK_5_6_FIELD 0 +#define STV090x_WIDTH_Px_DIS_32PSK_5_6_FIELD 4 + +#define STV090x_Px_MODCODLST3(__x) (0xf4b3 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST3 STV090x_Px_MODCODLST3(1) +#define STV090x_P2_MODCODLST3 STV090x_Px_MODCODLST3(2) +#define STV090x_OFFST_Px_DIS_32PSK_4_5_FIELD 4 +#define STV090x_WIDTH_Px_DIS_32PSK_4_5_FIELD 4 +#define STV090x_OFFST_Px_DIS_32PSK_3_4_FIELD 0 +#define STV090x_WIDTH_Px_DIS_32PSK_3_4_FIELD 4 + +#define STV090x_Px_MODCODLST4(__x) (0xf4b4 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST4 STV090x_Px_MODCODLST4(1) +#define STV090x_P2_MODCODLST4 STV090x_Px_MODCODLST4(2) +#define STV090x_OFFST_Px_DIS_16PSK_9_10_FIELD 4 +#define STV090x_WIDTH_Px_DIS_16PSK_9_10_FIELD 4 +#define STV090x_OFFST_Px_DIS_16PSK_8_9_FIELD 0 +#define STV090x_WIDTH_Px_DIS_16PSK_8_9_FIELD 4 + +#define STV090x_Px_MODCODLST5(__x) (0xf4b5 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST5 STV090x_Px_MODCODLST5(1) +#define STV090x_P2_MODCODLST5 STV090x_Px_MODCODLST5(2) +#define STV090x_OFFST_Px_DIS_16PSK_5_6_FIELD 4 +#define STV090x_WIDTH_Px_DIS_16PSK_5_6_FIELD 4 +#define STV090x_OFFST_Px_DIS_16PSK_4_5_FIELD 0 +#define STV090x_WIDTH_Px_DIS_16PSK_4_5_FIELD 4 + +#define STV090x_Px_MODCODLST6(__x) (0xf4b6 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST6 STV090x_Px_MODCODLST6(1) +#define STV090x_P2_MODCODLST6 STV090x_Px_MODCODLST6(2) +#define STV090x_OFFST_Px_DIS_16PSK_3_4_FIELD 4 +#define STV090x_WIDTH_Px_DIS_16PSK_3_4_FIELD 4 +#define STV090x_OFFST_Px_DIS_16PSK_2_3_FIELD 0 +#define STV090x_WIDTH_Px_DIS_16PSK_2_3_FIELD 4 + +#define STV090x_Px_MODCODLST7(__x) (0xf4b7 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST7 STV090x_Px_MODCODLST7(1) +#define STV090x_P2_MODCODLST7 STV090x_Px_MODCODLST7(2) +#define STV090x_OFFST_Px_DIS_8P_9_10_FIELD 4 +#define STV090x_WIDTH_Px_DIS_8P_9_10_FIELD 4 +#define STV090x_OFFST_Px_DIS_8P_8_9_FIELD 0 +#define STV090x_WIDTH_Px_DIS_8P_8_9_FIELD 4 + +#define STV090x_Px_MODCODLST8(__x) (0xf4b8 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST8 STV090x_Px_MODCODLST8(1) +#define STV090x_P2_MODCODLST8 STV090x_Px_MODCODLST8(2) +#define STV090x_OFFST_Px_DIS_8P_5_6_FIELD 4 +#define STV090x_WIDTH_Px_DIS_8P_5_6_FIELD 4 +#define STV090x_OFFST_Px_DIS_8P_3_4_FIELD 0 +#define STV090x_WIDTH_Px_DIS_8P_3_4_FIELD 4 + +#define STV090x_Px_MODCODLST9(__x) (0xf4b9 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST9 STV090x_Px_MODCODLST9(1) +#define STV090x_P2_MODCODLST9 STV090x_Px_MODCODLST9(2) +#define STV090x_OFFST_Px_DIS_8P_2_3_FIELD 4 +#define STV090x_WIDTH_Px_DIS_8P_2_3_FIELD 4 +#define STV090x_OFFST_Px_DIS_8P_3_5_FIELD 0 +#define STV090x_WIDTH_Px_DIS_8P_3_5_FIELD 4 + +#define STV090x_Px_MODCODLSTA(__x) (0xf4ba - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTA STV090x_Px_MODCODLSTA(1) +#define STV090x_P2_MODCODLSTA STV090x_Px_MODCODLSTA(2) +#define STV090x_OFFST_Px_DIS_QP_9_10_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_9_10_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_8_9_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_8_9_FIELD 4 + +#define STV090x_Px_MODCODLSTB(__x) (0xf4bb - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTB STV090x_Px_MODCODLSTB(1) +#define STV090x_P2_MODCODLSTB STV090x_Px_MODCODLSTB(2) +#define STV090x_OFFST_Px_DIS_QP_5_6_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_5_6_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_4_5_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_4_5_FIELD 4 + +#define STV090x_Px_MODCODLSTC(__x) (0xf4bc - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTC STV090x_Px_MODCODLSTC(1) +#define STV090x_P2_MODCODLSTC STV090x_Px_MODCODLSTC(2) +#define STV090x_OFFST_Px_DIS_QP_3_4_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_3_4_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_2_3_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_2_3_FIELD 4 + +#define STV090x_Px_MODCODLSTD(__x) (0xf4bd - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTD STV090x_Px_MODCODLSTD(1) +#define STV090x_P2_MODCODLSTD STV090x_Px_MODCODLSTD(2) +#define STV090x_OFFST_Px_DIS_QP_3_5_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_3_5_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_1_2_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_1_2_FIELD 4 + +#define STV090x_Px_MODCODLSTE(__x) (0xf4be - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTE STV090x_Px_MODCODLSTE(1) +#define STV090x_P2_MODCODLSTE STV090x_Px_MODCODLSTE(2) +#define STV090x_OFFST_Px_DIS_QP_2_5_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_2_5_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_1_3_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_1_3_FIELD 4 + +#define STV090x_Px_MODCODLSTF(__x) (0xf4bf - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTF STV090x_Px_MODCODLSTF(1) +#define STV090x_P2_MODCODLSTF STV090x_Px_MODCODLSTF(2) +#define STV090x_OFFST_Px_DIS_QP_1_4_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_1_4_FIELD 4 + +#define STV090x_Px_GAUSSR0(__x) (0xf4c0 - (__x - 1) * 0x200) +#define STV090x_P1_GAUSSR0 STV090x_Px_GAUSSR0(1) +#define STV090x_P2_GAUSSR0 STV090x_Px_GAUSSR0(2) +#define STV090x_OFFST_Px_EN_CCIMODE_FIELD 7 +#define STV090x_WIDTH_Px_EN_CCIMODE_FIELD 1 +#define STV090x_OFFST_Px_R0_GAUSSIEN_FIELD 0 +#define STV090x_WIDTH_Px_R0_GAUSSIEN_FIELD 7 + +#define STV090x_Px_CCIR0(__x) (0xf4c1 - (__x - 1) * 0x200) +#define STV090x_P1_CCIR0 STV090x_Px_CCIR0(1) +#define STV090x_P2_CCIR0 STV090x_Px_CCIR0(2) +#define STV090x_OFFST_Px_CCIDETECT_PLH_FIELD 7 +#define STV090x_WIDTH_Px_CCIDETECT_PLH_FIELD 1 +#define STV090x_OFFST_Px_R0_CCI_FIELD 0 +#define STV090x_WIDTH_Px_R0_CCI_FIELD 7 + +#define STV090x_Px_CCIQUANT(__x) (0xf4c2 - (__x - 1) * 0x200) +#define STV090x_P1_CCIQUANT STV090x_Px_CCIQUANT(1) +#define STV090x_P2_CCIQUANT STV090x_Px_CCIQUANT(2) +#define STV090x_OFFST_Px_CCI_BETA_FIELD 5 +#define STV090x_WIDTH_Px_CCI_BETA_FIELD 3 +#define STV090x_OFFST_Px_CCI_QUANT_FIELD 0 +#define STV090x_WIDTH_Px_CCI_QUANT_FIELD 5 + +#define STV090x_Px_CCITHRESH(__x) (0xf4c3 - (__x - 1) * 0x200) +#define STV090x_P1_CCITHRESH STV090x_Px_CCITHRESH(1) +#define STV090x_P2_CCITHRESH STV090x_Px_CCITHRESH(2) +#define STV090x_OFFST_Px_CCI_THRESHOLD_FIELD 0 +#define STV090x_WIDTH_Px_CCI_THRESHOLD_FIELD 8 + +#define STV090x_Px_CCIACC(__x) (0xf4c4 - (__x - 1) * 0x200) +#define STV090x_P1_CCIACC STV090x_Px_CCIACC(1) +#define STV090x_P2_CCIACC STV090x_Px_CCIACC(1) +#define STV090x_OFFST_Px_CCI_VALUE_FIELD 0 +#define STV090x_WIDTH_Px_CCI_VALUE_FIELD 8 + +#define STV090x_Px_DMDRESCFG(__x) (0xF4C6 - (__x - 1) * 0x200) +#define STV090x_P1_DMDRESCFG STV090x_Px_DMDRESCFG(1) +#define STV090x_P2_DMDRESCFG STV090x_Px_DMDRESCFG(2) +#define STV090x_OFFST_Px_DMDRES_RESET_FIELD 7 +#define STV090x_WIDTH_Px_DMDRES_RESET_FIELD 1 + +#define STV090x_Px_DMDRESADR(__x) (0xF4C7 - (__x - 1) * 0x200) +#define STV090x_P1_DMDRESADR STV090x_Px_DMDRESADR(1) +#define STV090x_P2_DMDRESADR STV090x_Px_DMDRESADR(2) +#define STV090x_OFFST_Px_DMDRES_RESNBR_FIELD 0 +#define STV090x_WIDTH_Px_DMDRES_RESNBR_FIELD 4 + +#define STV090x_Px_DMDRESDATAy(__x, __y) (0xF4C8 - (__x - 1) * 0x200 + (7 - __y)) +#define STV090x_P1_DMDRESDATA0 STV090x_Px_DMDRESDATAy(1, 0) +#define STV090x_P1_DMDRESDATA1 STV090x_Px_DMDRESDATAy(1, 1) +#define STV090x_P1_DMDRESDATA2 STV090x_Px_DMDRESDATAy(1, 2) +#define STV090x_P1_DMDRESDATA3 STV090x_Px_DMDRESDATAy(1, 3) +#define STV090x_P1_DMDRESDATA4 STV090x_Px_DMDRESDATAy(1, 4) +#define STV090x_P1_DMDRESDATA5 STV090x_Px_DMDRESDATAy(1, 5) +#define STV090x_P1_DMDRESDATA6 STV090x_Px_DMDRESDATAy(1, 6) +#define STV090x_P1_DMDRESDATA7 STV090x_Px_DMDRESDATAy(1, 7) +#define STV090x_P2_DMDRESDATA0 STV090x_Px_DMDRESDATAy(2, 0) +#define STV090x_P2_DMDRESDATA1 STV090x_Px_DMDRESDATAy(2, 1) +#define STV090x_P2_DMDRESDATA2 STV090x_Px_DMDRESDATAy(2, 2) +#define STV090x_P2_DMDRESDATA3 STV090x_Px_DMDRESDATAy(2, 3) +#define STV090x_P2_DMDRESDATA4 STV090x_Px_DMDRESDATAy(2, 4) +#define STV090x_P2_DMDRESDATA5 STV090x_Px_DMDRESDATAy(2, 5) +#define STV090x_P2_DMDRESDATA6 STV090x_Px_DMDRESDATAy(2, 6) +#define STV090x_P2_DMDRESDATA7 STV090x_Px_DMDRESDATAy(2, 7) +#define STV090x_OFFST_Px_DMDRES_DATA_FIELD 0 +#define STV090x_WIDTH_Px_DMDRES_DATA_FIELD 8 + +#define STV090x_Px_FFEIy(__x, __y) (0xf4d0 - (__x - 1) * 0x200 + 0x2 * (__y - 1)) +#define STV090x_P1_FFEI1 STV090x_Px_FFEIy(1, 1) +#define STV090x_P1_FFEI2 STV090x_Px_FFEIy(1, 2) +#define STV090x_P1_FFEI3 STV090x_Px_FFEIy(1, 3) +#define STV090x_P1_FFEI4 STV090x_Px_FFEIy(1, 4) +#define STV090x_P2_FFEI1 STV090x_Px_FFEIy(2, 1) +#define STV090x_P2_FFEI2 STV090x_Px_FFEIy(2, 2) +#define STV090x_P2_FFEI3 STV090x_Px_FFEIy(2, 3) +#define STV090x_P2_FFEI4 STV090x_Px_FFEIy(2, 4) +#define STV090x_OFFST_Px_FFE_ACCIy_FIELD 0 +#define STV090x_WIDTH_Px_FFE_ACCIy_FIELD 8 + +#define STV090x_Px_FFEQy(__x, __y) (0xf4d1 - (__x - 1) * 0x200 + 0x2 * (__y - 1)) +#define STV090x_P1_FFEQ1 STV090x_Px_FFEQy(1, 1) +#define STV090x_P1_FFEQ2 STV090x_Px_FFEQy(1, 2) +#define STV090x_P1_FFEQ3 STV090x_Px_FFEQy(1, 3) +#define STV090x_P1_FFEQ4 STV090x_Px_FFEQy(1, 4) +#define STV090x_P2_FFEQ1 STV090x_Px_FFEQy(2, 1) +#define STV090x_P2_FFEQ2 STV090x_Px_FFEQy(2, 2) +#define STV090x_P2_FFEQ3 STV090x_Px_FFEQy(2, 3) +#define STV090x_P2_FFEQ4 STV090x_Px_FFEQy(2, 4) +#define STV090x_OFFST_Px_FFE_ACCQy_FIELD 0 +#define STV090x_WIDTH_Px_FFE_ACCQy_FIELD 8 + +#define STV090x_Px_FFECFG(__x) (0xf4d8 - (__x - 1) * 0x200) +#define STV090x_P1_FFECFG STV090x_Px_FFECFG(1) +#define STV090x_P2_FFECFG STV090x_Px_FFECFG(2) +#define STV090x_OFFST_Px_EQUALFFE_ON_FIELD 6 +#define STV090x_WIDTH_Px_EQUALFFE_ON_FIELD 1 + +#define STV090x_Px_SMAPCOEF7(__x) (0xf500 - (__x - 1) * 0x200) +#define STV090x_P1_SMAPCOEF7 STV090x_Px_SMAPCOEF7(1) +#define STV090x_P2_SMAPCOEF7 STV090x_Px_SMAPCOEF7(2) +#define STV090x_OFFST_Px_DIS_QSCALE_FIELD 7 +#define STV090x_WIDTH_Px_DIS_QSCALE_FIELD 1 +#define STV090x_OFFST_Px_SMAPCOEF_Q_LLR12_FIELD 0 +#define STV090x_WIDTH_Px_SMAPCOEF_Q_LLR12_FIELD 7 + +#define STV090x_Px_SMAPCOEF6(__x) (0xf501 - (__x - 1) * 0x200) +#define STV090x_P1_SMAPCOEF6 STV090x_Px_SMAPCOEF6(1) +#define STV090x_P2_SMAPCOEF6 STV090x_Px_SMAPCOEF6(2) +#define STV090x_OFFST_Px_ADJ_8PSKLLR1_FIELD 2 +#define STV090x_WIDTH_Px_ADJ_8PSKLLR1_FIELD 1 +#define STV090x_OFFST_Px_OLD_8PSKLLR1_FIELD 1 +#define STV090x_WIDTH_Px_OLD_8PSKLLR1_FIELD 1 +#define STV090x_OFFST_Px_DIS_AB8PSK_FIELD 0 +#define STV090x_WIDTH_Px_DIS_AB8PSK_FIELD 1 + +#define STV090x_Px_SMAPCOEF5(__x) (0xf502 - (__x - 1) * 0x200) +#define STV090x_P1_SMAPCOEF5 STV090x_Px_SMAPCOEF5(1) +#define STV090x_P2_SMAPCOEF5 STV090x_Px_SMAPCOEF5(2) +#define STV090x_OFFST_Px_DIS_8SCALE_FIELD 7 +#define STV090x_WIDTH_Px_DIS_8SCALE_FIELD 1 +#define STV090x_OFFST_Px_SMAPCOEF_8P_LLR23_FIELD 0 +#define STV090x_WIDTH_Px_SMAPCOEF_8P_LLR23_FIELD 7 + +#define STV090x_Px_DMDPLHSTAT(__x) (0xF520 - (__x - 1) * 0x200) +#define STV090x_P1_DMDPLHSTAT STV090x_Px_DMDPLHSTAT(1) +#define STV090x_P2_DMDPLHSTAT STV090x_Px_DMDPLHSTAT(2) +#define STV090x_OFFST_Px_PLH_STATISTIC_FIELD 0 +#define STV090x_WIDTH_Px_PLH_STATISTIC_FIELD 8 + +#define STV090x_Px_LOCKTIMEy(__x, __y) (0xF525 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_LOCKTIME0 STV090x_Px_LOCKTIMEy(1, 0) +#define STV090x_P1_LOCKTIME1 STV090x_Px_LOCKTIMEy(1, 1) +#define STV090x_P1_LOCKTIME2 STV090x_Px_LOCKTIMEy(1, 2) +#define STV090x_P1_LOCKTIME3 STV090x_Px_LOCKTIMEy(1, 3) +#define STV090x_P2_LOCKTIME0 STV090x_Px_LOCKTIMEy(2, 0) +#define STV090x_P2_LOCKTIME1 STV090x_Px_LOCKTIMEy(2, 1) +#define STV090x_P2_LOCKTIME2 STV090x_Px_LOCKTIMEy(2, 2) +#define STV090x_P2_LOCKTIME3 STV090x_Px_LOCKTIMEy(2, 3) +#define STV090x_OFFST_Px_DEMOD_LOCKTIME_FIELD 0 +#define STV090x_WIDTH_Px_DEMOD_LOCKTIME_FIELD 8 + +#define STV090x_Px_TNRCFG(__x) (0xf4e0 - (__x - 1) * 0x200) /* check */ +#define STV090x_P1_TNRCFG STV090x_Px_TNRCFG(1) +#define STV090x_P2_TNRCFG STV090x_Px_TNRCFG(2) + +#define STV090x_Px_TNRCFG2(__x) (0xf4e1 - (__x - 1) * 0x200) +#define STV090x_P1_TNRCFG2 STV090x_Px_TNRCFG2(1) +#define STV090x_P2_TNRCFG2 STV090x_Px_TNRCFG2(2) +#define STV090x_OFFST_Px_TUN_IQSWAP_FIELD 7 +#define STV090x_WIDTH_Px_TUN_IQSWAP_FIELD 1 + +#define STV090x_Px_VITSCALE(__x) (0xf532 - (__x - 1) * 0x200) +#define STV090x_P1_VITSCALE STV090x_Px_VITSCALE(1) +#define STV090x_P2_VITSCALE STV090x_Px_VITSCALE(2) +#define STV090x_OFFST_Px_NVTH_NOSRANGE_FIELD 7 +#define STV090x_WIDTH_Px_NVTH_NOSRANGE_FIELD 1 +#define STV090x_OFFST_Px_VERROR_MAXMODE_FIELD 6 +#define STV090x_WIDTH_Px_VERROR_MAXMODE_FIELD 1 +#define STV090x_OFFST_Px_NSLOWSN_LOCKED_FIELD 3 +#define STV090x_WIDTH_Px_NSLOWSN_LOCKED_FIELD 1 +#define STV090x_OFFST_Px_DIS_RSFLOCK_FIELD 1 +#define STV090x_WIDTH_Px_DIS_RSFLOCK_FIELD 1 + +#define STV090x_Px_FECM(__x) (0xf533 - (__x - 1) * 0x200) +#define STV090x_P1_FECM STV090x_Px_FECM(1) +#define STV090x_P2_FECM STV090x_Px_FECM(2) +#define STV090x_OFFST_Px_DSS_DVB_FIELD 7 +#define STV090x_WIDTH_Px_DSS_DVB_FIELD 1 +#define STV090x_OFFST_Px_DSS_SRCH_FIELD 4 +#define STV090x_WIDTH_Px_DSS_SRCH_FIELD 1 +#define STV090x_OFFST_Px_SYNCVIT_FIELD 1 +#define STV090x_WIDTH_Px_SYNCVIT_FIELD 1 +#define STV090x_OFFST_Px_IQINV_FIELD 0 +#define STV090x_WIDTH_Px_IQINV_FIELD 1 + +#define STV090x_Px_VTH12(__x) (0xf534 - (__x - 1) * 0x200) +#define STV090x_P1_VTH12 STV090x_Px_VTH12(1) +#define STV090x_P2_VTH12 STV090x_Px_VTH12(2) +#define STV090x_OFFST_Px_VTH12_FIELD 0 +#define STV090x_WIDTH_Px_VTH12_FIELD 8 + +#define STV090x_Px_VTH23(__x) (0xf535 - (__x - 1) * 0x200) +#define STV090x_P1_VTH23 STV090x_Px_VTH23(1) +#define STV090x_P2_VTH23 STV090x_Px_VTH23(2) +#define STV090x_OFFST_Px_VTH23_FIELD 0 +#define STV090x_WIDTH_Px_VTH23_FIELD 8 + +#define STV090x_Px_VTH34(__x) (0xf536 - (__x - 1) * 0x200) +#define STV090x_P1_VTH34 STV090x_Px_VTH34(1) +#define STV090x_P2_VTH34 STV090x_Px_VTH34(2) +#define STV090x_OFFST_Px_VTH34_FIELD 0 +#define STV090x_WIDTH_Px_VTH34_FIELD 8 + +#define STV090x_Px_VTH56(__x) (0xf537 - (__x - 1) * 0x200) +#define STV090x_P1_VTH56 STV090x_Px_VTH56(1) +#define STV090x_P2_VTH56 STV090x_Px_VTH56(2) +#define STV090x_OFFST_Px_VTH56_FIELD 0 +#define STV090x_WIDTH_Px_VTH56_FIELD 8 + +#define STV090x_Px_VTH67(__x) (0xf538 - (__x - 1) * 0x200) +#define STV090x_P1_VTH67 STV090x_Px_VTH67(1) +#define STV090x_P2_VTH67 STV090x_Px_VTH67(2) +#define STV090x_OFFST_Px_VTH67_FIELD 0 +#define STV090x_WIDTH_Px_VTH67_FIELD 8 + +#define STV090x_Px_VTH78(__x) (0xf539 - (__x - 1) * 0x200) +#define STV090x_P1_VTH78 STV090x_Px_VTH78(1) +#define STV090x_P2_VTH78 STV090x_Px_VTH78(2) +#define STV090x_OFFST_Px_VTH78_FIELD 0 +#define STV090x_WIDTH_Px_VTH78_FIELD 8 + +#define STV090x_Px_VITCURPUN(__x) (0xf53a - (__x - 1) * 0x200) +#define STV090x_P1_VITCURPUN STV090x_Px_VITCURPUN(1) +#define STV090x_P2_VITCURPUN STV090x_Px_VITCURPUN(2) +#define STV090x_OFFST_Px_VIT_CURPUN_FIELD 0 +#define STV090x_WIDTH_Px_VIT_CURPUN_FIELD 5 + +#define STV090x_Px_VERROR(__x) (0xf53b - (__x - 1) * 0x200) +#define STV090x_P1_VERROR STV090x_Px_VERROR(1) +#define STV090x_P2_VERROR STV090x_Px_VERROR(2) +#define STV090x_OFFST_Px_REGERR_VIT_FIELD 0 +#define STV090x_WIDTH_Px_REGERR_VIT_FIELD 8 + +#define STV090x_Px_PRVIT(__x) (0xf53c - (__x - 1) * 0x200) +#define STV090x_P1_PRVIT STV090x_Px_PRVIT(1) +#define STV090x_P2_PRVIT STV090x_Px_PRVIT(2) +#define STV090x_OFFST_Px_DIS_VTHLOCK_FIELD 6 +#define STV090x_WIDTH_Px_DIS_VTHLOCK_FIELD 1 +#define STV090x_OFFST_Px_E7_8VIT_FIELD 5 +#define STV090x_WIDTH_Px_E7_8VIT_FIELD 1 +#define STV090x_OFFST_Px_E6_7VIT_FIELD 4 +#define STV090x_WIDTH_Px_E6_7VIT_FIELD 1 +#define STV090x_OFFST_Px_E5_6VIT_FIELD 3 +#define STV090x_WIDTH_Px_E5_6VIT_FIELD 1 +#define STV090x_OFFST_Px_E3_4VIT_FIELD 2 +#define STV090x_WIDTH_Px_E3_4VIT_FIELD 1 +#define STV090x_OFFST_Px_E2_3VIT_FIELD 1 +#define STV090x_WIDTH_Px_E2_3VIT_FIELD 1 +#define STV090x_OFFST_Px_E1_2VIT_FIELD 0 +#define STV090x_WIDTH_Px_E1_2VIT_FIELD 1 + +#define STV090x_Px_VAVSRVIT(__x) (0xf53d - (__x - 1) * 0x200) +#define STV090x_P1_VAVSRVIT STV090x_Px_VAVSRVIT(1) +#define STV090x_P2_VAVSRVIT STV090x_Px_VAVSRVIT(2) +#define STV090x_OFFST_Px_SNVIT_FIELD 4 +#define STV090x_WIDTH_Px_SNVIT_FIELD 2 +#define STV090x_OFFST_Px_TOVVIT_FIELD 2 +#define STV090x_WIDTH_Px_TOVVIT_FIELD 2 +#define STV090x_OFFST_Px_HYPVIT_FIELD 0 +#define STV090x_WIDTH_Px_HYPVIT_FIELD 2 + +#define STV090x_Px_VSTATUSVIT(__x) (0xf53e - (__x - 1) * 0x200) +#define STV090x_P1_VSTATUSVIT STV090x_Px_VSTATUSVIT(1) +#define STV090x_P2_VSTATUSVIT STV090x_Px_VSTATUSVIT(2) +#define STV090x_OFFST_Px_PRFVIT_FIELD 4 +#define STV090x_WIDTH_Px_PRFVIT_FIELD 1 +#define STV090x_OFFST_Px_LOCKEDVIT_FIELD 3 +#define STV090x_WIDTH_Px_LOCKEDVIT_FIELD 1 + +#define STV090x_Px_VTHINUSE(__x) (0xf53f - (__x - 1) * 0x200) +#define STV090x_P1_VTHINUSE STV090x_Px_VTHINUSE(1) +#define STV090x_P2_VTHINUSE STV090x_Px_VTHINUSE(2) +#define STV090x_OFFST_Px_VIT_INUSE_FIELD 0 +#define STV090x_WIDTH_Px_VIT_INUSE_FIELD 8 + +#define STV090x_Px_KDIV12(__x) (0xf540 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV12 STV090x_Px_KDIV12(1) +#define STV090x_P2_KDIV12 STV090x_Px_KDIV12(2) +#define STV090x_OFFST_Px_K_DIVIDER_12_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_12_FIELD 7 + +#define STV090x_Px_KDIV23(__x) (0xf541 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV23 STV090x_Px_KDIV23(1) +#define STV090x_P2_KDIV23 STV090x_Px_KDIV23(2) +#define STV090x_OFFST_Px_K_DIVIDER_23_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_23_FIELD 7 + +#define STV090x_Px_KDIV34(__x) (0xf542 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV34 STV090x_Px_KDIV34(1) +#define STV090x_P2_KDIV34 STV090x_Px_KDIV34(2) +#define STV090x_OFFST_Px_K_DIVIDER_34_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_34_FIELD 7 + +#define STV090x_Px_KDIV56(__x) (0xf543 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV56 STV090x_Px_KDIV56(1) +#define STV090x_P2_KDIV56 STV090x_Px_KDIV56(2) +#define STV090x_OFFST_Px_K_DIVIDER_56_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_56_FIELD 7 + +#define STV090x_Px_KDIV67(__x) (0xf544 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV67 STV090x_Px_KDIV67(1) +#define STV090x_P2_KDIV67 STV090x_Px_KDIV67(2) +#define STV090x_OFFST_Px_K_DIVIDER_67_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_67_FIELD 7 + +#define STV090x_Px_KDIV78(__x) (0xf545 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV78 STV090x_Px_KDIV78(1) +#define STV090x_P2_KDIV78 STV090x_Px_KDIV78(2) +#define STV090x_OFFST_Px_K_DIVIDER_78_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_78_FIELD 7 + +#define STV090x_Px_PDELCTRL1(__x) (0xf550 - (__x - 1) * 0x200) +#define STV090x_P1_PDELCTRL1 STV090x_Px_PDELCTRL1(1) +#define STV090x_P2_PDELCTRL1 STV090x_Px_PDELCTRL1(2) +#define STV090x_OFFST_Px_INV_MISMASK_FIELD 7 +#define STV090x_WIDTH_Px_INV_MISMASK_FIELD 1 +#define STV090x_OFFST_Px_FILTER_EN_FIELD 5 +#define STV090x_WIDTH_Px_FILTER_EN_FIELD 1 +#define STV090x_OFFST_Px_EN_MIS00_FIELD 1 +#define STV090x_WIDTH_Px_EN_MIS00_FIELD 1 +#define STV090x_OFFST_Px_ALGOSWRST_FIELD 0 +#define STV090x_WIDTH_Px_ALGOSWRST_FIELD 1 + +#define STV090x_Px_PDELCTRL2(__x) (0xf551 - (__x - 1) * 0x200) +#define STV090x_P1_PDELCTRL2 STV090x_Px_PDELCTRL2(1) +#define STV090x_P2_PDELCTRL2 STV090x_Px_PDELCTRL2(2) +#define STV090x_OFFST_Px_FORCE_CONTINUOUS 7 +#define STV090x_WIDTH_Px_FORCE_CONTINUOUS 1 +#define STV090x_OFFST_Px_RESET_UPKO_COUNT 6 +#define STV090x_WIDTH_Px_RESET_UPKO_COUNT 1 +#define STV090x_OFFST_Px_USER_PKTDELIN_NB 5 +#define STV090x_WIDTH_Px_USER_PKTDELIN_NB 1 +#define STV090x_OFFST_Px_FORCE_LOCKED 4 +#define STV090x_WIDTH_Px_FORCE_LOCKED 1 +#define STV090x_OFFST_Px_DATA_UNBBSCRAM 3 +#define STV090x_WIDTH_Px_DATA_UNBBSCRAM 1 +#define STV090x_OFFST_Px_FORCE_LONGPACKET 2 +#define STV090x_WIDTH_Px_FORCE_LONGPACKET 1 +#define STV090x_OFFST_Px_FRAME_MODE_FIELD 1 +#define STV090x_WIDTH_Px_FRAME_MODE_FIELD 1 + +#define STV090x_Px_HYSTTHRESH(__x) (0xf554 - (__x - 1) * 0x200) +#define STV090x_P1_HYSTTHRESH STV090x_Px_HYSTTHRESH(1) +#define STV090x_P2_HYSTTHRESH STV090x_Px_HYSTTHRESH(2) +#define STV090x_OFFST_Px_UNLCK_THRESH_FIELD 4 +#define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD 4 +#define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD 0 +#define STV090x_WIDTH_Px_DELIN_LCK_THRESH_FIELD 4 + +#define STV090x_Px_ISIENTRY(__x) (0xf55e - (__x - 1) * 0x200) +#define STV090x_P1_ISIENTRY STV090x_Px_ISIENTRY(1) +#define STV090x_P2_ISIENTRY STV090x_Px_ISIENTRY(2) +#define STV090x_OFFST_Px_ISI_ENTRY_FIELD 0 +#define STV090x_WIDTH_Px_ISI_ENTRY_FIELD 8 + +#define STV090x_Px_ISIBITENA(__x) (0xf55f - (__x - 1) * 0x200) +#define STV090x_P1_ISIBITENA STV090x_Px_ISIBITENA(1) +#define STV090x_P2_ISIBITENA STV090x_Px_ISIBITENA(2) +#define STV090x_OFFST_Px_ISI_BIT_EN_FIELD 0 +#define STV090x_WIDTH_Px_ISI_BIT_EN_FIELD 8 + +#define STV090x_Px_MATSTRy(__x, __y) (0xf561 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_MATSTR0 STV090x_Px_MATSTRy(1, 0) +#define STV090x_P1_MATSTR1 STV090x_Px_MATSTRy(1, 1) +#define STV090x_P2_MATSTR0 STV090x_Px_MATSTRy(2, 0) +#define STV090x_P2_MATSTR1 STV090x_Px_MATSTRy(2, 1) +#define STV090x_OFFST_Px_MATYPE_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_MATYPE_CURRENT_FIELD 8 + +#define STV090x_Px_UPLSTRy(__x, __y) (0xf563 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_UPLSTR0 STV090x_Px_UPLSTRy(1, 0) +#define STV090x_P1_UPLSTR1 STV090x_Px_UPLSTRy(1, 1) +#define STV090x_P2_UPLSTR0 STV090x_Px_UPLSTRy(2, 0) +#define STV090x_P2_UPLSTR1 STV090x_Px_UPLSTRy(2, 1) +#define STV090x_OFFST_Px_UPL_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_UPL_CURRENT_FIELD 8 + +#define STV090x_Px_DFLSTRy(__x, __y) (0xf565 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_DFLSTR0 STV090x_Px_DFLSTRy(1, 0) +#define STV090x_P1_DFLSTR1 STV090x_Px_DFLSTRy(1, 1) +#define STV090x_P2_DFLSTR0 STV090x_Px_DFLSTRy(2, 0) +#define STV090x_P2_DFLSTR1 STV090x_Px_DFLSTRy(2, 1) +#define STV090x_OFFST_Px_DFL_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_DFL_CURRENT_FIELD 8 + +#define STV090x_Px_SYNCSTR(__x) (0xf566 - (__x - 1) * 0x200) +#define STV090x_P1_SYNCSTR STV090x_Px_SYNCSTR(1) +#define STV090x_P2_SYNCSTR STV090x_Px_SYNCSTR(2) +#define STV090x_OFFST_Px_SYNC_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_SYNC_CURRENT_FIELD 8 + +#define STV090x_Px_SYNCDSTRy(__x, __y) (0xf568 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_SYNCDSTR0 STV090x_Px_SYNCDSTRy(1, 0) +#define STV090x_P1_SYNCDSTR1 STV090x_Px_SYNCDSTRy(1, 1) +#define STV090x_P2_SYNCDSTR0 STV090x_Px_SYNCDSTRy(2, 0) +#define STV090x_P2_SYNCDSTR1 STV090x_Px_SYNCDSTRy(2, 1) +#define STV090x_OFFST_Px_SYNCD_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_SYNCD_CURRENT_FIELD 8 + +#define STV090x_Px_PDELSTATUS1(__x) (0xf569 - (__x - 1) * 0x200) +#define STV090x_P1_PDELSTATUS1 STV090x_Px_PDELSTATUS1(1) +#define STV090x_P2_PDELSTATUS1 STV090x_Px_PDELSTATUS1(2) +#define STV090x_OFFST_Px_PKTDELIN_LOCK_FIELD 1 +#define STV090x_WIDTH_Px_PKTDELIN_LOCK_FIELD 1 +#define STV090x_OFFST_Px_FIRST_LOCK_FIELD 0 +#define STV090x_WIDTH_Px_FIRST_LOCK_FIELD 1 + +#define STV090x_Px_PDELSTATUS2(__x) (0xf56a - (__x - 1) * 0x200) +#define STV090x_P1_PDELSTATUS2 STV090x_Px_PDELSTATUS2(1) +#define STV090x_P2_PDELSTATUS2 STV090x_Px_PDELSTATUS2(2) +#define STV090x_OFFST_Px_FRAME_MODCOD_FIELD 2 +#define STV090x_WIDTH_Px_FRAME_MODCOD_FIELD 5 +#define STV090x_OFFST_Px_FRAME_TYPE_FIELD 0 +#define STV090x_WIDTH_Px_FRAME_TYPE_FIELD 2 + +#define STV090x_Px_BBFCRCKO1(__x) (0xf56b - (__x - 1) * 0x200) +#define STV090x_P1_BBFCRCKO1 STV090x_Px_BBFCRCKO1(1) +#define STV090x_P2_BBFCRCKO1 STV090x_Px_BBFCRCKO1(2) +#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD 0 +#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD 8 + +#define STV090x_Px_BBFCRCKO0(__x) (0xf56c - (__x - 1) * 0x200) +#define STV090x_P1_BBFCRCKO0 STV090x_Px_BBFCRCKO0(1) +#define STV090x_P2_BBFCRCKO0 STV090x_Px_BBFCRCKO0(2) +#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD 0 +#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD 8 + +#define STV090x_Px_UPCRCKO1(__x) (0xf56d - (__x - 1) * 0x200) +#define STV090x_P1_UPCRCKO1 STV090x_Px_UPCRCKO1(1) +#define STV090x_P2_UPCRCKO1 STV090x_Px_UPCRCKO1(2) +#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD 0 +#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD 8 + +#define STV090x_Px_UPCRCKO0(__x) (0xf56e - (__x - 1) * 0x200) +#define STV090x_P1_UPCRCKO0 STV090x_Px_UPCRCKO0(1) +#define STV090x_P2_UPCRCKO0 STV090x_Px_UPCRCKO0(2) +#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD 0 +#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD 8 + +#define STV090x_NBITER_NFx(__x) (0xFA03 + (__x - 4) * 0x1) +#define STV090x_NBITER_NF4 STV090x_NBITER_NFx(4) +#define STV090x_NBITER_NF5 STV090x_NBITER_NFx(5) +#define STV090x_NBITER_NF6 STV090x_NBITER_NFx(6) +#define STV090x_NBITER_NF7 STV090x_NBITER_NFx(7) +#define STV090x_NBITER_NF8 STV090x_NBITER_NFx(8) +#define STV090x_NBITER_NF9 STV090x_NBITER_NFx(9) +#define STV090x_NBITER_NF10 STV090x_NBITER_NFx(10) +#define STV090x_NBITER_NF11 STV090x_NBITER_NFx(11) +#define STV090x_NBITER_NF12 STV090x_NBITER_NFx(12) +#define STV090x_NBITER_NF13 STV090x_NBITER_NFx(13) +#define STV090x_NBITER_NF14 STV090x_NBITER_NFx(14) +#define STV090x_NBITER_NF15 STV090x_NBITER_NFx(15) +#define STV090x_NBITER_NF16 STV090x_NBITER_NFx(16) +#define STV090x_NBITER_NF17 STV090x_NBITER_NFx(17) + +#define STV090x_NBITERNOERR 0xFA3F +#define STV090x_OFFST_NBITER_STOP_CRIT_FIELD 0 +#define STV090x_WIDTH_NBITER_STOP_CRIT_FIELD 4 + +#define STV090x_GAINLLR_NFx(__x) (0xFA43 + (__x - 4) * 0x1) +#define STV090x_GAINLLR_NF4 STV090x_GAINLLR_NFx(4) +#define STV090x_OFFST_GAINLLR_NF_QP_1_2_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_1_2_FIELD 7 + +#define STV090x_GAINLLR_NF5 STV090x_GAINLLR_NFx(5) +#define STV090x_OFFST_GAINLLR_NF_QP_3_5_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_3_5_FIELD 7 + +#define STV090x_GAINLLR_NF6 STV090x_GAINLLR_NFx(6) +#define STV090x_OFFST_GAINLLR_NF_QP_2_3_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_2_3_FIELD 7 + +#define STV090x_GAINLLR_NF7 STV090x_GAINLLR_NFx(7) +#define STV090x_OFFST_GAINLLR_NF_QP_3_4_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_3_4_FIELD 7 + +#define STV090x_GAINLLR_NF8 STV090x_GAINLLR_NFx(8) +#define STV090x_OFFST_GAINLLR_NF_QP_4_5_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_4_5_FIELD 7 + +#define STV090x_GAINLLR_NF9 STV090x_GAINLLR_NFx(9) +#define STV090x_OFFST_GAINLLR_NF_QP_5_6_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_5_6_FIELD 7 + +#define STV090x_GAINLLR_NF10 STV090x_GAINLLR_NFx(10) +#define STV090x_OFFST_GAINLLR_NF_QP_8_9_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_8_9_FIELD 7 + +#define STV090x_GAINLLR_NF11 STV090x_GAINLLR_NFx(11) +#define STV090x_OFFST_GAINLLR_NF_QP_9_10_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_9_10_FIELD 7 + +#define STV090x_GAINLLR_NF12 STV090x_GAINLLR_NFx(12) +#define STV090x_OFFST_GAINLLR_NF_8P_3_5_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_3_5_FIELD 7 + +#define STV090x_GAINLLR_NF13 STV090x_GAINLLR_NFx(13) +#define STV090x_OFFST_GAINLLR_NF_8P_2_3_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_2_3_FIELD 7 + +#define STV090x_GAINLLR_NF14 STV090x_GAINLLR_NFx(14) +#define STV090x_OFFST_GAINLLR_NF_8P_3_4_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_3_4_FIELD 7 + +#define STV090x_GAINLLR_NF15 STV090x_GAINLLR_NFx(15) +#define STV090x_OFFST_GAINLLR_NF_8P_5_6_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_5_6_FIELD 7 + +#define STV090x_GAINLLR_NF16 STV090x_GAINLLR_NFx(16) +#define STV090x_OFFST_GAINLLR_NF_8P_8_9_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_8_9_FIELD 7 + +#define STV090x_GAINLLR_NF17 STV090x_GAINLLR_NFx(17) +#define STV090x_OFFST_GAINLLR_NF_8P_9_10_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_9_10_FIELD 7 + +#define STV090x_GENCFG 0xFA86 +#define STV090x_OFFST_BROADCAST_FIELD 4 +#define STV090x_WIDTH_BROADCAST_FIELD 1 +#define STV090x_OFFST_PRIORITY_FIELD 1 +#define STV090x_WIDTH_PRIORITY_FIELD 1 +#define STV090x_OFFST_DDEMOD_FIELD 0 +#define STV090x_WIDTH_DDEMOD_FIELD 1 + +#define STV090x_LDPCERRx(__x) (0xFA97 - (__x * 0x1)) +#define STV090x_LDPCERR0 STV090x_LDPCERRx(0) +#define STV090x_LDPCERR1 STV090x_LDPCERRx(1) +#define STV090x_OFFST_Px_LDPC_ERRORS_COUNTER_FIELD 0 +#define STV090x_WIDTH_Px_LDPC_ERRORS_COUNTER_FIELD 8 + +#define STV090x_BCHERR 0xFA98 +#define STV090x_OFFST_Px_ERRORFLAG_FIELD 4 +#define STV090x_WIDTH_Px_ERRORFLAG_FIELD 1 +#define STV090x_OFFST_Px_BCH_ERRORS_COUNTER_FIELD 0 +#define STV090x_WIDTH_Px_BCH_ERRORS_COUNTER_FIELD 4 + +#define STV090x_Px_TSSTATEM(__x) (0xF570 - (__x - 1) * 0x200) +#define STV090x_P1_TSSTATEM STV090x_Px_TSSTATEM(1) +#define STV090x_P2_TSSTATEM STV090x_Px_TSSTATEM(2) +#define STV090x_OFFST_Px_TSDIL_ON_FIELD 7 +#define STV090x_WIDTH_Px_TSDIL_ON_FIELD 1 +#define STV090x_OFFST_Px_TSRS_ON_FIELD 5 +#define STV090x_WIDTH_Px_TSRS_ON_FIELD 1 + +#define STV090x_Px_TSCFGH(__x) (0xF572 - (__x - 1) * 0x200) +#define STV090x_P1_TSCFGH STV090x_Px_TSCFGH(1) +#define STV090x_P2_TSCFGH STV090x_Px_TSCFGH(2) +#define STV090x_OFFST_Px_TSFIFO_DVBCI_FIELD 7 +#define STV090x_WIDTH_Px_TSFIFO_DVBCI_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_SERIAL_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFO_SERIAL_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_TEIUPDATE_FIELD 5 +#define STV090x_WIDTH_Px_TSFIFO_TEIUPDATE_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_DUTY50_FIELD 4 +#define STV090x_WIDTH_Px_TSFIFO_DUTY50_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_HSGNLOUT_FIELD 3 +#define STV090x_WIDTH_Px_TSFIFO_HSGNLOUT_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_ERRORMODE_FIELD 1 +#define STV090x_WIDTH_Px_TSFIFO_ERRORMODE_FIELD 2 +#define STV090x_OFFST_Px_RST_HWARE_FIELD 0 +#define STV090x_WIDTH_Px_RST_HWARE_FIELD 1 + +#define STV090x_Px_TSCFGM(__x) (0xF573 - (__x - 1) * 0x200) +#define STV090x_P1_TSCFGM STV090x_Px_TSCFGM(1) +#define STV090x_P2_TSCFGM STV090x_Px_TSCFGM(2) +#define STV090x_OFFST_Px_TSFIFO_MANSPEED_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFO_MANSPEED_FIELD 2 +#define STV090x_OFFST_Px_TSFIFO_PERMDATA_FIELD 5 +#define STV090x_WIDTH_Px_TSFIFO_PERMDATA_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_INVDATA_FIELD 0 +#define STV090x_WIDTH_Px_TSFIFO_INVDATA_FIELD 1 + +#define STV090x_Px_TSCFGL(__x) (0xF574 - (__x - 1) * 0x200) +#define STV090x_P1_TSCFGL STV090x_Px_TSCFGL(1) +#define STV090x_P2_TSCFGL STV090x_Px_TSCFGL(2) +#define STV090x_OFFST_Px_TSFIFO_BCLKDEL1CK_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFO_BCLKDEL1CK_FIELD 2 +#define STV090x_OFFST_Px_BCHERROR_MODE_FIELD 4 +#define STV090x_WIDTH_Px_BCHERROR_MODE_FIELD 2 +#define STV090x_OFFST_Px_TSFIFO_NSGNL2DATA_FIELD 3 +#define STV090x_WIDTH_Px_TSFIFO_NSGNL2DATA_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_EMBINDVB_FIELD 2 +#define STV090x_WIDTH_Px_TSFIFO_EMBINDVB_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_DPUNACT_FIELD 1 +#define STV090x_WIDTH_Px_TSFIFO_DPUNACT_FIELD 1 + +#define STV090x_Px_TSINSDELH(__x) (0xF576 - (__x - 1) * 0x200) +#define STV090x_P1_TSINSDELH STV090x_Px_TSINSDELH(1) +#define STV090x_P2_TSINSDELH STV090x_Px_TSINSDELH(2) +#define STV090x_OFFST_Px_TSDEL_SYNCBYTE_FIELD 7 +#define STV090x_WIDTH_Px_TSDEL_SYNCBYTE_FIELD 1 +#define STV090x_OFFST_Px_TSDEL_XXHEADER_FIELD 6 +#define STV090x_WIDTH_Px_TSDEL_XXHEADER_FIELD 1 + +#define STV090x_Px_TSSPEED(__x) (0xF580 - (__x - 1) * 0x200) +#define STV090x_P1_TSSPEED STV090x_Px_TSSPEED(1) +#define STV090x_P2_TSSPEED STV090x_Px_TSSPEED(2) +#define STV090x_OFFST_Px_TSFIFO_OUTSPEED_FIELD 0 +#define STV090x_WIDTH_Px_TSFIFO_OUTSPEED_FIELD 8 + +#define STV090x_Px_TSSTATUS(__x) (0xF581 - (__x - 1) * 0x200) +#define STV090x_P1_TSSTATUS STV090x_Px_TSSTATUS(1) +#define STV090x_P2_TSSTATUS STV090x_Px_TSSTATUS(2) +#define STV090x_OFFST_Px_TSFIFO_LINEOK_FIELD 7 +#define STV090x_WIDTH_Px_TSFIFO_LINEOK_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_ERROR_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFO_ERROR_FIELD 1 + +#define STV090x_Px_TSSTATUS2(__x) (0xF582 - (__x - 1) * 0x200) +#define STV090x_P1_TSSTATUS2 STV090x_Px_TSSTATUS2(1) +#define STV090x_P2_TSSTATUS2 STV090x_Px_TSSTATUS2(2) +#define STV090x_OFFST_Px_TSFIFO_DEMODSEL_FIELD 7 +#define STV090x_WIDTH_Px_TSFIFO_DEMODSEL_FIELD 1 +#define STV090x_OFFST_Px_TSFIFOSPEED_STORE_FIELD 6 +#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_WIDTH_Px_TSSERIAL_IMPOS_FIELD 1 +#define STV090x_OFFST_Px_SCRAMBDETECT_FIELD 1 +#define STV090x_WIDTH_Px_SCRAMBDETECT_FIELD 1 + +#define STV090x_Px_TSBITRATEy(__x, __y) (0xF584 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_TSBITRATE0 STV090x_Px_TSBITRATEy(1, 0) +#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_WIDTH_Px_TSFIFO_BITRATE_FIELD 8 + +#define STV090x_Px_ERRCTRL1(__x) (0xF598 - (__x - 1) * 0x200) +#define STV090x_P1_ERRCTRL1 STV090x_Px_ERRCTRL1(1) +#define STV090x_P2_ERRCTRL1 STV090x_Px_ERRCTRL1(2) +#define STV090x_OFFST_Px_ERR_SOURCE_FIELD 4 +#define STV090x_WIDTH_Px_ERR_SOURCE_FIELD 4 +#define STV090x_OFFST_Px_NUM_EVENT_FIELD 0 +#define STV090x_WIDTH_Px_NUM_EVENT_FIELD 3 + +#define STV090x_Px_ERRCNT12(__x) (0xF599 - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT12 STV090x_Px_ERRCNT12(1) +#define STV090x_P2_ERRCNT12 STV090x_Px_ERRCNT12(2) +#define STV090x_OFFST_Px_ERRCNT1_OLDVALUE_FIELD 7 +#define STV090x_WIDTH_Px_ERRCNT1_OLDVALUE_FIELD 1 +#define STV090x_OFFST_Px_ERR_CNT12_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT12_FIELD 7 + +#define STV090x_Px_ERRCNT11(__x) (0xF59A - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT11 STV090x_Px_ERRCNT11(1) +#define STV090x_P2_ERRCNT11 STV090x_Px_ERRCNT11(2) +#define STV090x_OFFST_Px_ERR_CNT11_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT11_FIELD 8 + +#define STV090x_Px_ERRCNT10(__x) (0xF59B - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT10 STV090x_Px_ERRCNT10(1) +#define STV090x_P2_ERRCNT10 STV090x_Px_ERRCNT10(2) +#define STV090x_OFFST_Px_ERR_CNT10_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT10_FIELD 8 + +#define STV090x_Px_ERRCTRL2(__x) (0xF59C - (__x - 1) * 0x200) +#define STV090x_P1_ERRCTRL2 STV090x_Px_ERRCTRL2(1) +#define STV090x_P2_ERRCTRL2 STV090x_Px_ERRCTRL2(2) +#define STV090x_OFFST_Px_ERR_SOURCE2_FIELD 4 +#define STV090x_WIDTH_Px_ERR_SOURCE2_FIELD 4 +#define STV090x_OFFST_Px_NUM_EVENT2_FIELD 0 +#define STV090x_WIDTH_Px_NUM_EVENT2_FIELD 3 + +#define STV090x_Px_ERRCNT22(__x) (0xF59D - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT22 STV090x_Px_ERRCNT22(1) +#define STV090x_P2_ERRCNT22 STV090x_Px_ERRCNT22(2) +#define STV090x_OFFST_Px_ERRCNT2_OLDVALUE_FIELD 7 +#define STV090x_WIDTH_Px_ERRCNT2_OLDVALUE_FIELD 1 +#define STV090x_OFFST_Px_ERR_CNT2_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT2_FIELD 7 + +#define STV090x_Px_ERRCNT21(__x) (0xF59E - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT21 STV090x_Px_ERRCNT21(1) +#define STV090x_P2_ERRCNT21 STV090x_Px_ERRCNT21(2) +#define STV090x_OFFST_Px_ERR_CNT21_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT21_FIELD 8 + +#define STV090x_Px_ERRCNT20(__x) (0xF59F - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT20 STV090x_Px_ERRCNT20(1) +#define STV090x_P2_ERRCNT20 STV090x_Px_ERRCNT20(2) +#define STV090x_OFFST_Px_ERR_CNT20_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT20_FIELD 8 + +#define STV090x_Px_FECSPY(__x) (0xF5A0 - (__x - 1) * 0x200) +#define STV090x_P1_FECSPY STV090x_Px_FECSPY(1) +#define STV090x_P2_FECSPY STV090x_Px_FECSPY(2) +#define STV090x_OFFST_Px_SPY_ENABLE_FIELD 7 +#define STV090x_WIDTH_Px_SPY_ENABLE_FIELD 1 +#define STV090x_OFFST_Px_BERMETER_DATAMAODE_FIELD 2 +#define STV090x_WIDTH_Px_BERMETER_DATAMAODE_FIELD 2 + +#define STV090x_Px_FSPYCFG(__x) (0xF5A1 - (__x - 1) * 0x200) +#define STV090x_P1_FSPYCFG STV090x_Px_FSPYCFG(1) +#define STV090x_P2_FSPYCFG STV090x_Px_FSPYCFG(2) +#define STV090x_OFFST_Px_RST_ON_ERROR_FIELD 5 +#define STV090x_WIDTH_Px_RST_ON_ERROR_FIELD 1 +#define STV090x_OFFST_Px_ONE_SHOT_FIELD 4 +#define STV090x_WIDTH_Px_ONE_SHOT_FIELD 1 +#define STV090x_OFFST_Px_I2C_MODE_FIELD 2 +#define STV090x_WIDTH_Px_I2C_MODE_FIELD 2 + +#define STV090x_Px_FSPYDATA(__x) (0xF5A2 - (__x - 1) * 0x200) +#define STV090x_P1_FSPYDATA STV090x_Px_FSPYDATA(1) +#define STV090x_P2_FSPYDATA STV090x_Px_FSPYDATA(2) +#define STV090x_OFFST_Px_SPY_STUFFING_FIELD 7 +#define STV090x_WIDTH_Px_SPY_STUFFING_FIELD 1 +#define STV090x_OFFST_Px_SPY_CNULLPKT_FIELD 5 +#define STV090x_WIDTH_Px_SPY_CNULLPKT_FIELD 1 +#define STV090x_OFFST_Px_SPY_OUTDATA_MODE_FIELD 0 +#define STV090x_WIDTH_Px_SPY_OUTDATA_MODE_FIELD 5 + +#define STV090x_Px_FSPYOUT(__x) (0xF5A3 - (__x - 1) * 0x200) +#define STV090x_P1_FSPYOUT STV090x_Px_FSPYOUT(1) +#define STV090x_P2_FSPYOUT STV090x_Px_FSPYOUT(2) +#define STV090x_OFFST_Px_FSPY_DIRECT_FIELD 7 +#define STV090x_WIDTH_Px_FSPY_DIRECT_FIELD 1 +#define STV090x_OFFST_Px_STUFF_MODE_FIELD 0 +#define STV090x_WIDTH_Px_STUFF_MODE_FIELD 3 + +#define STV090x_Px_FSTATUS(__x) (0xF5A4 - (__x - 1) * 0x200) +#define STV090x_P1_FSTATUS STV090x_Px_FSTATUS(1) +#define STV090x_P2_FSTATUS STV090x_Px_FSTATUS(2) +#define STV090x_OFFST_Px_SPY_ENDSIM_FIELD 7 +#define STV090x_WIDTH_Px_SPY_ENDSIM_FIELD 1 +#define STV090x_OFFST_Px_VALID_SIM_FIELD 6 +#define STV090x_WIDTH_Px_VALID_SIM_FIELD 1 +#define STV090x_OFFST_Px_FOUND_SIGNAL_FIELD 5 +#define STV090x_WIDTH_Px_FOUND_SIGNAL_FIELD 1 +#define STV090x_OFFST_Px_DSS_SYNCBYTE_FIELD 4 +#define STV090x_WIDTH_Px_DSS_SYNCBYTE_FIELD 1 +#define STV090x_OFFST_Px_RESULT_STATE_FIELD 0 +#define STV090x_WIDTH_Px_RESULT_STATE_FIELD 4 + +#define STV090x_Px_FBERCPT4(__x) (0xF5A8 - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT4 STV090x_Px_FBERCPT4(1) +#define STV090x_P2_FBERCPT4 STV090x_Px_FBERCPT4(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERCPT3(__x) (0xF5A9 - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT3 STV090x_Px_FBERCPT3(1) +#define STV090x_P2_FBERCPT3 STV090x_Px_FBERCPT3(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERCPT2(__x) (0xF5AA - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT2 STV090x_Px_FBERCPT2(1) +#define STV090x_P2_FBERCPT2 STV090x_Px_FBERCPT2(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERCPT1(__x) (0xF5AB - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT1 STV090x_Px_FBERCPT1(1) +#define STV090x_P2_FBERCPT1 STV090x_Px_FBERCPT1(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERCPT0(__x) (0xF5AC - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT0 STV090x_Px_FBERCPT0(1) +#define STV090x_P2_FBERCPT0 STV090x_Px_FBERCPT0(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERERRy(__x, __y) (0xF5AF - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_FBERERR0 STV090x_Px_FBERERRy(1, 0) +#define STV090x_P1_FBERERR1 STV090x_Px_FBERERRy(1, 1) +#define STV090x_P1_FBERERR2 STV090x_Px_FBERERRy(1, 2) +#define STV090x_P2_FBERERR0 STV090x_Px_FBERERRy(2, 0) +#define STV090x_P2_FBERERR1 STV090x_Px_FBERERRy(2, 1) +#define STV090x_P2_FBERERR2 STV090x_Px_FBERERRy(2, 2) +#define STV090x_OFFST_Px_FBERMETER_CPT_ERR_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_ERR_FIELD 8 + +#define STV090x_Px_FSPYBER(__x) (0xF5B2 - (__x - 1) * 0x200) +#define STV090x_P1_FSPYBER STV090x_Px_FSPYBER(1) +#define STV090x_P2_FSPYBER STV090x_Px_FSPYBER(2) +#define STV090x_OFFST_Px_FSPYBER_SYNCBYTE_FIELD 4 +#define STV090x_WIDTH_Px_FSPYBER_SYNCBYTE_FIELD 1 +#define STV090x_OFFST_Px_FSPYBER_UNSYNC_FIELD 3 +#define STV090x_WIDTH_Px_FSPYBER_UNSYNC_FIELD 1 +#define STV090x_OFFST_Px_FSPYBER_CTIME_FIELD 0 +#define STV090x_WIDTH_Px_FSPYBER_CTIME_FIELD 3 + +#define STV090x_RCCFGH 0xf600 + +#define STV090x_TSGENERAL 0xF630 +#define STV090x_OFFST_Px_MUXSTREAM_OUT_FIELD 3 +#define STV090x_WIDTH_Px_MUXSTREAM_OUT_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_PERMPARAL_FIELD 1 +#define STV090x_WIDTH_Px_TSFIFO_PERMPARAL_FIELD 2 + +#define STV090x_TSGENERAL1X 0xf670 +#define STV090x_CFGEXT 0xfa80 + +#define STV090x_TSTRES0 0xFF11 +#define STV090x_OFFST_FRESFEC_FIELD 7 +#define STV090x_WIDTH_FRESFEC_FIELD 1 + +#define STV090x_Px_TSTDISRX(__x) (0xFF67 - (__x - 1) * 0x2) +#define STV090x_P1_TSTDISRX STV090x_Px_TSTDISRX(1) +#define STV090x_P2_TSTDISRX STV090x_Px_TSTDISRX(2) +#define STV090x_OFFST_Px_TSTDISRX_SELECT_FIELD 3 +#define STV090x_WIDTH_Px_TSTDISRX_SELECT_FIELD 1 + +#endif /* __STV090x_REG_H */ diff --git a/linux/drivers/media/dvb/frontends/stv6110x.c b/linux/drivers/media/dvb/frontends/stv6110x.c new file mode 100644 index 000000000..cca32f3d6 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110x.c @@ -0,0 +1,443 @@ +/* + STV6110(A) Silicon tuner driver + + Copyright (C) Manu Abraham <abraham.manu@gmail.com> + + Copyright (C) ST Microelectronics + + 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 <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> + +#include "dvb_frontend.h" + +#include "stv6110x_reg.h" +#include "stv6110x.h" +#include "stv6110x_priv.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "Set Verbosity level"); + +static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; + +static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) +{ + int ret; + const struct stv6110x_config *config = stv6110x->config; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { .addr = config->addr, .flags = 0, .buf = b0, .len = 1 }, + { .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } + }; + + ret = i2c_transfer(stv6110x->i2c, msg, 2); + if (ret != 2) { + dprintk(FE_ERROR, 1, "I/O Error"); + return -EREMOTEIO; + } + *data = b1[0]; + + return 0; +} + +static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) +{ + int ret; + const struct stv6110x_config *config = stv6110x->config; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 }; + + ret = i2c_transfer(stv6110x->i2c, &msg, 1); + if (ret != 1) { + dprintk(FE_ERROR, 1, "I/O Error"); + return -EREMOTEIO; + } + + return 0; +} + +static int stv6110x_init(struct dvb_frontend *fe) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + int ret; + u8 i; + + for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) { + ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]); + if (ret < 0) { + dprintk(FE_ERROR, 1, "Initialization failed"); + return -1; + } + } + + return 0; +} + +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; + u8 i; + + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16)); + + if (frequency <= 1023000) { + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); + pVal = 40; + } else if (frequency <= 1300000) { + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); + pVal = 40; + } else if (frequency <= 2046000) { + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); + pVal = 20; + } else { + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); + pVal = 20; + } + + for (rDiv = 0; rDiv <= 3; rDiv++) { + pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv); + + if ((abs((s32)(pCalc - pVal))) < (abs((s32)(1000 - pVal)))) + rDivOpt = rDiv; + } + + divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz; + divider = (divider + 5) / 10; + + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider)); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider)); + + /* VCO Auto calibration */ + STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1); + + stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]); + stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]); + stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]); + stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]); + + for (i = 0; i < TRIALS; i++) { + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); + if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1])) + break; + msleep(1); + } + + return 0; +} + +static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]); + stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]); + + *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]), + STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz; + + *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) + + STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1]))); + + *frequency >>= 2; + + return 0; +} + +static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + u32 halfbw; + u8 i; + + halfbw = bandwidth >> 1; + + if (halfbw > 36000000) + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */ + else if (halfbw < 5000000) + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */ + else + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */ + + + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */ + STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */ + + stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]); + stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]); + + for (i = 0; i < TRIALS; i++) { + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); + if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1])) + break; + msleep(1); + } + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */ + stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]); + + return 0; +} + +static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]); + *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000; + + return 0; +} + +static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + /* setup divider */ + switch (refclock) { + default: + case 1: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); + break; + case 2: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); + break; + case 4: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); + break; + case 8: + case 0: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); + break; + } + stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]); + + return 0; +} + +static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]); + *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]); + + return 0; +} + +static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2); + stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]); + + return 0; +} + +static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + int ret; + + switch (mode) { + case TUNER_SLEEP: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0); + break; + + case TUNER_WAKE: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1); + break; + } + + ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]); + if (ret < 0) { + dprintk(FE_ERROR, 1, "I/O Error"); + return -EIO; + } + + return 0; +} + +static int stv6110x_sleep(struct dvb_frontend *fe) +{ + return stv6110x_set_mode(fe, TUNER_SLEEP); +} + +static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); + + if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1])) + *status = TUNER_PHASELOCKED; + else + *status = 0; + + return 0; +} + +#if 0 +static int stv6110x_get_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *state) +{ + switch (param) { + case DVBFE_TUNER_FREQUENCY: + stv6110x_get_frequency(fe, &state->frequency); + break; + + case DVBFE_TUNER_TUNERSTEP: + break; + + case DVBFE_TUNER_IFFREQ: + break; + + case DVBFE_TUNER_BANDWIDTH: + stv6110x_get_bandwidth(fe, &state->bandwidth); + break; + + case DVBFE_TUNER_REFCLOCK: + break; + + default: + break; + } + + return 0; +} + +static int stv6110x_set_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *tstate) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + switch (param) { + case DVBFE_TUNER_FREQUENCY: + stv6110x_set_frequency(fe, stv6110x->frequency); + tstate->frequency = stv6110x->frequency; + break; + + case DVBFE_TUNER_TUNERSTEP: + break; + + case DVBFE_TUNER_IFFREQ: + break; + + case DVBFE_TUNER_BANDWIDTH: + stv6110x_set_bandwidth(fe, stv6110x->bandwidth); + tstate->bandwidth = stv6110x->bandwidth; + break; + + case DVBFE_TUNER_REFCLOCK: + stv6110x_set_refclock(fe, stv6110x->reference); + tstate->refclock = stv6110x->reference; + break; + + default: + break; + } + + return 0; +} +#endif + +static int stv6110x_release(struct dvb_frontend *fe) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + fe->tuner_priv = NULL; + kfree(stv6110x); + + return 0; +} + +static struct dvb_tuner_ops stv6110x_ops = { + .info = { + .name = "STV6110(A) Silicon Tuner", + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = 0, + }, + + .init = stv6110x_init, + .sleep = stv6110x_sleep, +#if 0 + .get_status = stv6110x_get_status, + .get_state = stv6110x_get_state, + .set_state = stv6110x_set_state, +#endif + .release = stv6110x_release +}; + +static struct stv6110x_devctl stv6110x_ctl = { + .tuner_init = stv6110x_init, + .tuner_set_mode = stv6110x_set_mode, + .tuner_set_frequency = stv6110x_set_frequency, + .tuner_get_frequency = stv6110x_get_frequency, + .tuner_set_bandwidth = stv6110x_set_bandwidth, + .tuner_get_bandwidth = stv6110x_get_bandwidth, + .tuner_set_bbgain = stv6110x_set_bbgain, + .tuner_get_bbgain = stv6110x_get_bbgain, + .tuner_set_refclk = stv6110x_set_refclock, + .tuner_get_status = stv6110x_get_status, +}; + +struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, + const struct stv6110x_config *config, + struct i2c_adapter *i2c) +{ + struct stv6110x_state *stv6110x; + + stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); + if (stv6110x == NULL) + goto error; + + stv6110x->i2c = i2c; + stv6110x->config = config; + stv6110x->devctl = &stv6110x_ctl; + + fe->tuner_priv = stv6110x; + fe->ops.tuner_ops = stv6110x_ops; + + printk("%s: Attaching STV6110x \n", __func__); + return stv6110x->devctl; + +error: + kfree(stv6110x); + return NULL; +} +EXPORT_SYMBOL(stv6110x_attach); + +MODULE_AUTHOR("Manu Abraham"); +MODULE_DESCRIPTION("STV6110x Silicon tuner"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/stv6110x.h b/linux/drivers/media/dvb/frontends/stv6110x.h new file mode 100644 index 000000000..a38257080 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110x.h @@ -0,0 +1,71 @@ +/* + STV6110(A) Silicon tuner driver + + Copyright (C) Manu Abraham <abraham.manu@gmail.com> + + Copyright (C) ST Microelectronics + + 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 __STV6110x_H +#define __STV6110x_H + +struct stv6110x_config { + u8 addr; + u32 refclk; +}; + +enum tuner_mode { + TUNER_SLEEP = 1, + TUNER_WAKE, +}; + +enum tuner_status { + TUNER_PHASELOCKED = 1, +}; + +struct stv6110x_devctl { + int (*tuner_init) (struct dvb_frontend *fe); + int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); + int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); + int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); + int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth); + int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth); + int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain); + int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain); + int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk); + int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status); +}; + + +#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE)) + +extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, + const struct stv6110x_config *config, + struct i2c_adapter *i2c); + +#else +static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, + const struct stv6110x_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif /* CONFIG_DVB_STV6110x */ + +#endif /* __STV6110x_H */ diff --git a/linux/drivers/media/dvb/frontends/stv6110x_priv.h b/linux/drivers/media/dvb/frontends/stv6110x_priv.h new file mode 100644 index 000000000..7260da633 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110x_priv.h @@ -0,0 +1,75 @@ +/* + STV6110(A) Silicon tuner driver + + Copyright (C) Manu Abraham <abraham.manu@gmail.com> + + Copyright (C) ST Microelectronics + + 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 __STV6110x_PRIV_H +#define __STV6110x_PRIV_H + +#define FE_ERROR 0 +#define FE_NOTICE 1 +#define FE_INFO 2 +#define FE_DEBUG 3 +#define FE_DEBUGREG 4 + +#define dprintk(__y, __z, format, arg...) do { \ + if (__z) { \ + if ((verbose > FE_ERROR) && (verbose > __y)) \ + printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_NOTICE) && (verbose > __y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_INFO) && (verbose > __y)) \ + printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_DEBUG) && (verbose > __y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ + } else { \ + if (verbose > __y) \ + printk(format, ##arg); \ + } \ +} while (0) + + +#define STV6110x_SETFIELD(mask, bitf, val) \ + (mask = (mask & (~(((1 << STV6110x_WIDTH_##bitf) - 1) << \ + STV6110x_OFFST_##bitf))) | \ + (val << STV6110x_OFFST_##bitf)) + +#define STV6110x_GETFIELD(bitf, val) \ + ((val >> STV6110x_OFFST_##bitf) & \ + ((1 << STV6110x_WIDTH_##bitf) - 1)) + +#define MAKEWORD16(a, b) (((a) << 8) | (b)) + +#define LSB(x) ((x & 0xff)) +#define MSB(y) ((y >> 8) & 0xff) + +#define TRIALS 10 +#define R_DIV(__div) (1 << (__div + 1)) +#define REFCLOCK_kHz (stv6110x->config->refclk / 1000) +#define REFCLOCK_MHz (stv6110x->config->refclk / 1000000) + +struct stv6110x_state { + struct i2c_adapter *i2c; + const struct stv6110x_config *config; + + struct stv6110x_devctl *devctl; +}; + +#endif /* __STV6110x_PRIV_H */ diff --git a/linux/drivers/media/dvb/frontends/stv6110x_reg.h b/linux/drivers/media/dvb/frontends/stv6110x_reg.h new file mode 100644 index 000000000..93e5c70e5 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110x_reg.h @@ -0,0 +1,82 @@ +/* + STV6110(A) Silicon tuner driver + + Copyright (C) Manu Abraham <abraham.manu@gmail.com> + + Copyright (C) ST Microelectronics + + 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 __STV6110x_REG_H +#define __STV6110x_REG_H + +#define STV6110x_CTRL1 0x00 +#define STV6110x_OFFST_CTRL1_K 3 +#define STV6110x_WIDTH_CTRL1_K 5 +#define STV6110x_OFFST_CTRL1_LPT 2 +#define STV6110x_WIDTH_CTRL1_LPT 1 +#define STV6110x_OFFST_CTRL1_RX 1 +#define STV6110x_WIDTH_CTRL1_RX 1 +#define STV6110x_OFFST_CTRL1_SYN 0 +#define STV6110x_WIDTH_CTRL1_SYN 1 + +#define STV6110x_CTRL2 0x01 +#define STV6110x_OFFST_CTRL2_CO_DIV 6 +#define STV6110x_WIDTH_CTRL2_CO_DIV 2 +#define STV6110x_OFFST_CTRL2_RSVD 5 +#define STV6110x_WIDTH_CTRL2_RSVD 1 +#define STV6110x_OFFST_CTRL2_REFOUT_SEL 4 +#define STV6110x_WIDTH_CTRL2_REFOUT_SEL 1 +#define STV6110x_OFFST_CTRL2_BBGAIN 0 +#define STV6110x_WIDTH_CTRL2_BBGAIN 4 + +#define STV6110x_TNG0 0x02 +#define STV6110x_OFFST_TNG0_N_DIV_7_0 0 +#define STV6110x_WIDTH_TNG0_N_DIV_7_0 8 + +#define STV6110x_TNG1 0x03 +#define STV6110x_OFFST_TNG1_R_DIV 6 +#define STV6110x_WIDTH_TNG1_R_DIV 2 +#define STV6110x_OFFST_TNG1_PRESC32_ON 5 +#define STV6110x_WIDTH_TNG1_PRESC32_ON 1 +#define STV6110x_OFFST_TNG1_DIV4SEL 4 +#define STV6110x_WIDTH_TNG1_DIV4SEL 1 +#define STV6110x_OFFST_TNG1_N_DIV_11_8 0 +#define STV6110x_WIDTH_TNG1_N_DIV_11_8 4 + + +#define STV6110x_CTRL3 0x04 +#define STV6110x_OFFST_CTRL3_DCLOOP_OFF 7 +#define STV6110x_WIDTH_CTRL3_DCLOOP_OFF 1 +#define STV6110x_OFFST_CTRL3_RCCLK_OFF 6 +#define STV6110x_WIDTH_CTRL3_RCCLK_OFF 1 +#define STV6110x_OFFST_CTRL3_ICP 5 +#define STV6110x_WIDTH_CTRL3_ICP 1 +#define STV6110x_OFFST_CTRL3_CF 0 +#define STV6110x_WIDTH_CTRL3_CF 5 + +#define STV6110x_STAT1 0x05 +#define STV6110x_OFFST_STAT1_CALVCO_STRT 2 +#define STV6110x_WIDTH_STAT1_CALVCO_STRT 1 +#define STV6110x_OFFST_STAT1_CALRC_STRT 1 +#define STV6110x_WIDTH_STAT1_CALRC_STRT 1 +#define STV6110x_OFFST_STAT1_LOCK 0 +#define STV6110x_WIDTH_STAT1_LOCK 1 + +#define STV6110x_STAT2 0x06 +#define STV6110x_STAT3 0x07 + +#endif /* __STV6110x_REG_H */ diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index cb5b1efd8..a223e617f 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -25,6 +25,7 @@ #include <linux/string.h> #include <linux/slab.h> #include <linux/delay.h> +#include <asm/div64.h> #include "dvb_frontend.h" #include "dvb_math.h" #include "tda10048.h" @@ -143,6 +144,15 @@ struct tda10048_state { struct dvb_frontend frontend; int fwloaded; + + u32 freq_if_hz; + u32 xtal_hz; + u32 pll_mfactor; + u32 pll_nfactor; + u32 pll_pfactor; + u32 sample_freq; + + enum fe_bandwidth bandwidth; }; static struct init_tab { @@ -271,6 +281,199 @@ error: return ret; } +static int tda10048_set_phy2(struct dvb_frontend *fe, u32 sample_freq_hz, + u32 if_hz) +{ + struct tda10048_state *state = fe->demodulator_priv; + u64 t; + + dprintk(1, "%s()\n", __func__); + + if (sample_freq_hz == 0) + return -EINVAL; + + if (if_hz < (sample_freq_hz / 2)) { + /* PHY2 = (if2/fs) * 2^15 */ + t = if_hz; + t *= 10; + t *= 32768; + do_div(t, sample_freq_hz); + t += 5; + do_div(t, 10); + } else { + /* PHY2 = ((IF1-fs)/fs) * 2^15 */ + t = sample_freq_hz - if_hz; + t *= 10; + t *= 32768; + do_div(t, sample_freq_hz); + t += 5; + do_div(t, 10); + t = ~t + 1; + } + + tda10048_writereg(state, TDA10048_FREQ_PHY2_LSB, (u8)t); + tda10048_writereg(state, TDA10048_FREQ_PHY2_MSB, (u8)(t >> 8)); + + return 0; +} + +static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz, + u32 bw) +{ + struct tda10048_state *state = fe->demodulator_priv; + u64 t, z; + u32 b = 8000000; + + dprintk(1, "%s()\n", __func__); + + if (sample_freq_hz == 0) + return -EINVAL; + + if (bw == BANDWIDTH_6_MHZ) + b = 6000000; + else + if (bw == BANDWIDTH_7_MHZ) + b = 7000000; + + /* WREF = (B / (7 * fs)) * 2^31 */ + t = b * 10; + /* avoid warning: this decimal constant is unsigned only in ISO C90 */ + /* t *= 2147483648 on 32bit platforms */ + t *= (2048 * 1024); + t *= 1024; + z = 7 * sample_freq_hz; + do_div(t, z); + t += 5; + do_div(t, 10); + + tda10048_writereg(state, TDA10048_TIME_WREF_LSB, (u8)t); + tda10048_writereg(state, TDA10048_TIME_WREF_MID1, (u8)(t >> 8)); + tda10048_writereg(state, TDA10048_TIME_WREF_MID2, (u8)(t >> 16)); + tda10048_writereg(state, TDA10048_TIME_WREF_MSB, (u8)(t >> 24)); + + return 0; +} + +static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz, + u32 bw) +{ + struct tda10048_state *state = fe->demodulator_priv; + u64 t; + u32 b = 8000000; + + dprintk(1, "%s()\n", __func__); + + if (sample_freq_hz == 0) + return -EINVAL; + + if (bw == BANDWIDTH_6_MHZ) + b = 6000000; + else + if (bw == BANDWIDTH_7_MHZ) + b = 7000000; + + /* INVWREF = ((7 * fs) / B) * 2^5 */ + t = sample_freq_hz; + t *= 7; + t *= 32; + t *= 10; + do_div(t, b); + t += 5; + do_div(t, 10); + + tda10048_writereg(state, TDA10048_TIME_INVWREF_LSB, (u8)t); + tda10048_writereg(state, TDA10048_TIME_INVWREF_MSB, (u8)(t >> 8)); + + return 0; +} + +static int tda10048_set_bandwidth(struct dvb_frontend *fe, + enum fe_bandwidth bw) +{ + struct tda10048_state *state = fe->demodulator_priv; + dprintk(1, "%s(bw=%d)\n", __func__, bw); + + /* Bandwidth setting may need to be adjusted */ + switch (bw) { + case BANDWIDTH_6_MHZ: + case BANDWIDTH_7_MHZ: + case BANDWIDTH_8_MHZ: + tda10048_set_wref(fe, state->sample_freq, bw); + tda10048_set_invwref(fe, state->sample_freq, bw); + break; + default: + printk(KERN_ERR "%s() invalid bandwidth\n", __func__); + return -EINVAL; + } + + state->bandwidth = bw; + + return 0; +} + +static int tda10048_set_pll(struct dvb_frontend *fe) +{ + struct tda10048_state *state = fe->demodulator_priv; + int ret = 0; + + dprintk(1, "%s()\n", __func__); + + if ((state->config->clk_freq_khz == TDA10048_CLK_4000) && + (state->config->if_freq_khz == TDA10048_IF_36130)) { + state->freq_if_hz = TDA10048_IF_36130 * 1000; + state->xtal_hz = TDA10048_CLK_4000 * 1000; + state->pll_mfactor = 10; + state->pll_nfactor = 0; + state->pll_pfactor = 0; + } else + if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && + (state->config->if_freq_khz == TDA10048_IF_4300)) { + state->freq_if_hz = TDA10048_IF_4300 * 1000; + state->xtal_hz = TDA10048_CLK_16000 * 1000; + state->pll_mfactor = 10; + state->pll_nfactor = 3; + state->pll_pfactor = 0; + } else + if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && + (state->config->if_freq_khz == TDA10048_IF_4000)) { + state->freq_if_hz = TDA10048_IF_4000 * 1000; + state->xtal_hz = TDA10048_CLK_16000 * 1000; + state->pll_mfactor = 10; + state->pll_nfactor = 3; + state->pll_pfactor = 0; + } else + if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && + (state->config->if_freq_khz == TDA10048_IF_36130)) { + state->freq_if_hz = TDA10048_IF_36130 * 1000; + state->xtal_hz = TDA10048_CLK_16000 * 1000; + state->pll_mfactor = 10; + state->pll_nfactor = 3; + state->pll_pfactor = 0; + } else { + printk(KERN_ERR "%s() Incorrect attach settings\n", __func__); + ret = -EINVAL; + } + + dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz); + dprintk(1, "- xtal_hz = %d\n", state->xtal_hz); + dprintk(1, "- pll_mfactor = %d\n", state->pll_mfactor); + dprintk(1, "- pll_nfactor = %d\n", state->pll_nfactor); + dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor); + + /* Calculate the sample frequency */ + state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45); + state->sample_freq /= (state->pll_nfactor + 1); + state->sample_freq /= (state->pll_pfactor + 4); + dprintk(1, "- sample_freq = %d\n", state->sample_freq); + + tda10048_set_phy2(fe, state->sample_freq, + state->config->if_freq_khz * 1000); + tda10048_set_wref(fe, state->sample_freq, state->bandwidth); + tda10048_set_invwref(fe, state->sample_freq, state->bandwidth); + + return ret; +} + static int tda10048_firmware_upload(struct dvb_frontend *fe) { struct tda10048_state *state = fe->demodulator_priv; @@ -289,7 +492,7 @@ static int tda10048_firmware_upload(struct dvb_frontend *fe) TDA10048_DEFAULT_FIRMWARE); ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE, - &state->i2c->dev); + state->i2c->dev.parent); if (ret) { printk(KERN_ERR "%s: Upload failed. (file not found?)\n", __func__); @@ -486,6 +689,9 @@ static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) struct tda10048_state *state = fe->demodulator_priv; dprintk(1, "%s(%d)\n", __func__, enable); + if (state->config->disable_gate_access) + return 0; + if (enable) return tda10048_writereg(state, TDA10048_CONF_C4_1, tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02); @@ -523,6 +729,9 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency); + if (p->u.ofdm.bandwidth != state->bandwidth) + tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth); + if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) @@ -558,9 +767,15 @@ static int tda10048_init(struct dvb_frontend *fe) /* Set either serial or parallel */ tda10048_output_mode(fe, state->config->output_mode); - /* set inversion */ + /* Set inversion */ tda10048_set_inversion(fe, state->config->inversion); + /* Establish default PLL values */ + tda10048_set_pll(fe); + + /* Establish default bandwidth */ + tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ); + /* Ensure we leave the gate closed */ tda10048_i2c_gate_ctrl(fe, 0); @@ -835,6 +1050,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, state->config = config; state->i2c = i2c; state->fwloaded = 0; + state->bandwidth = BANDWIDTH_8_MHZ; /* check if the demod is present */ if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048) @@ -845,6 +1061,10 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; + /* Set the xtal and freq defaults */ + if (tda10048_set_pll(&state->frontend) != 0) + goto error; + /* Leave the gate closed */ tda10048_i2c_gate_ctrl(&state->frontend, 0); diff --git a/linux/drivers/media/dvb/frontends/tda10048.h b/linux/drivers/media/dvb/frontends/tda10048.h index 0457b2460..ee07b50e9 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.h +++ b/linux/drivers/media/dvb/frontends/tda10048.h @@ -43,6 +43,23 @@ struct tda10048_config { #define TDA10048_INVERSION_OFF 0 #define TDA10048_INVERSION_ON 1 u8 inversion; + +#define TDA10048_IF_3300 3300 +#define TDA10048_IF_3500 3500 +#define TDA10048_IF_3800 3800 +#define TDA10048_IF_4000 4000 +#define TDA10048_IF_4300 4300 +#define TDA10048_IF_4500 4500 +#define TDA10048_IF_4750 4750 +#define TDA10048_IF_36130 36130 + u16 if_freq_khz; + +#define TDA10048_CLK_4000 4000 +#define TDA10048_CLK_16000 16000 + u16 clk_freq_khz; + + /* Disable I2C gate access */ + u8 disable_gate_access; }; #if defined(CONFIG_DVB_TDA10048) || \ diff --git a/linux/drivers/media/dvb/siano/Makefile b/linux/drivers/media/dvb/siano/Makefile index bcf93f482..c6644d909 100644 --- a/linux/drivers/media/dvb/siano/Makefile +++ b/linux/drivers/media/dvb/siano/Makefile @@ -1,4 +1,4 @@ -sms1xxx-objs := smscoreapi.o sms-cards.o +sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 63e4d0ec6..fda483f07 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -18,6 +18,7 @@ */ #include "sms-cards.h" +#include "smsir.h" static int sms_dbg; module_param_named(cards_dbg, sms_dbg, int, 0644); @@ -30,17 +31,14 @@ static struct sms_board sms_boards[] = { [SMS1XXX_BOARD_SIANO_STELLAR] = { .name = "Siano Stellar Digital Receiver", .type = SMS_STELLAR, - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw", }, [SMS1XXX_BOARD_SIANO_NOVA_A] = { .name = "Siano Nova A Digital Receiver", .type = SMS_NOVA_A0, - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw", }, [SMS1XXX_BOARD_SIANO_NOVA_B] = { .name = "Siano Nova B Digital Receiver", .type = SMS_NOVA_B0, - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw", }, [SMS1XXX_BOARD_SIANO_VEGA] = { .name = "Siano Vega Digital Receiver", @@ -65,6 +63,9 @@ static struct sms_board sms_boards[] = { .name = "Hauppauge WinTV MiniStick", .type = SMS_NOVA_B0, .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", + .board_cfg.leds_power = 26, + .board_cfg.led0 = 27, + .board_cfg.led1 = 28, .led_power = 26, .led_lo = 27, .led_hi = 28, @@ -74,7 +75,9 @@ static struct sms_board sms_boards[] = { .type = SMS_NOVA_B0, .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", .lna_ctrl = 29, + .board_cfg.foreign_lna0_ctrl = 29, .rf_switch = 17, + .board_cfg.rf_switch_uhf = 17, }, [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { .name = "Hauppauge WinTV MiniCard", diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h index 64d74c59c..447481ab5 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.h +++ b/linux/drivers/media/dvb/siano/sms-cards.h @@ -22,6 +22,7 @@ #include <linux/usb.h> #include "smscoreapi.h" +#include "smsir.h" #define SMS_BOARD_UNKNOWN 0 #define SMS1XXX_BOARD_SIANO_STELLAR 1 @@ -35,9 +36,44 @@ #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9 #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10 +struct sms_board_gpio_cfg { + int lna_vhf_exist; + int lna_vhf_ctrl; + int lna_uhf_exist; + int lna_uhf_ctrl; + int lna_uhf_d_ctrl; + int lna_sband_exist; + int lna_sband_ctrl; + int lna_sband_d_ctrl; + int foreign_lna0_ctrl; + int foreign_lna1_ctrl; + int foreign_lna2_ctrl; + int rf_switch_vhf; + int rf_switch_uhf; + int rf_switch_sband; + int leds_power; + int led0; + int led1; + int led2; + int led3; + int led4; + int ir; + int eeprom_wp; + int mrc_sense; + int mrc_pdn_resetn; + int mrc_gp0; /* mrcs spi int */ + int mrc_gp1; + int mrc_gp2; + int mrc_gp3; + int mrc_gp4; + int host_spi_gsp_ts_int; +}; + struct sms_board { enum sms_device_type_st type; char *name, *fw[DEVICE_MODE_MAX]; + struct sms_board_gpio_cfg board_cfg; + enum ir_kb_type ir_kb_type; /* gpios */ int led_power, led_hi, led_lo, lna_ctrl, rf_switch; @@ -45,6 +81,8 @@ struct sms_board { struct sms_board *sms_get_board(int id); +extern struct smscore_device_t *coredev; + int sms_board_setup(struct smscore_device_t *coredev); #define SMS_LED_OFF 0 diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 9a9db2588..16917016c 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -30,9 +30,13 @@ #include <linux/io.h> #include <linux/firmware.h> +#include <linux/wait.h> +#include <asm/byteorder.h> #include "smscoreapi.h" #include "sms-cards.h" +#include "smsir.h" +#include "smsendian.h" static int sms_dbg; module_param_named(debug, sms_dbg, int, 0644); @@ -348,6 +352,10 @@ int smscore_register_device(struct smsdevice_params_t *params, init_completion(&dev->init_device_done); init_completion(&dev->reload_start_done); init_completion(&dev->resume_done); + init_completion(&dev->ir_init_done); + + /* Buffer management */ + init_waitqueue_head(&dev->buffer_mng_waitq); /* alloc common buffer */ dev->common_buffer_size = params->buffer_size * params->num_buffers; @@ -403,6 +411,71 @@ int smscore_register_device(struct smsdevice_params_t *params, } EXPORT_SYMBOL_GPL(smscore_register_device); + +static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, + void *buffer, size_t size, struct completion *completion) { + int rc = coredev->sendrequest_handler(coredev->context, buffer, size); + if (rc < 0) { + sms_info("sendrequest returned error %d", rc); + return rc; + } + + return wait_for_completion_timeout(completion, + msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ? + 0 : -ETIME; +} + +/** + * Starts & enables IR operations + * + * @return 0 on success, < 0 on error. + */ +static int smscore_init_ir(struct smscore_device_t *coredev) +{ + int ir_io; + int rc; + void *buffer; + + coredev->ir.input_dev = NULL; + ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir; + if (ir_io) {/* only if IR port exist we use IR sub-module */ + sms_info("IR loading"); + rc = sms_ir_init(coredev); + + if (rc != 0) + sms_err("Error initialization DTV IR sub-module"); + else { + buffer = kmalloc(sizeof(struct SmsMsgData_ST2) + + SMS_DMA_ALIGNMENT, + GFP_KERNEL | GFP_DMA); + if (buffer) { + struct SmsMsgData_ST2 *msg = + (struct SmsMsgData_ST2 *) + SMS_ALIGN_ADDRESS(buffer); + + SMS_INIT_MSG(&msg->xMsgHeader, + MSG_SMS_START_IR_REQ, + sizeof(struct SmsMsgData_ST2)); + msg->msgData[0] = coredev->ir.controller; + msg->msgData[1] = coredev->ir.timeout; + + smsendian_handle_tx_message( + (struct SmsMsgHdr_ST2 *)msg); + rc = smscore_sendrequest_and_wait(coredev, msg, + msg->xMsgHeader. msgLength, + &coredev->ir_init_done); + + kfree(buffer); + } else + sms_err + ("Sending IR initialization message failed"); + } + } else + sms_info("IR port has not been detected"); + + return 0; +} + /** * sets initial device mode and notifies client hotplugs that device is ready * @@ -423,6 +496,7 @@ int smscore_start_device(struct smscore_device_t *coredev) kmutex_lock(&g_smscore_deviceslock); rc = smscore_notify_callbacks(coredev, coredev->device, 1); + smscore_init_ir(coredev); sms_info("device %p started, rc %d", coredev, rc); @@ -432,29 +506,19 @@ int smscore_start_device(struct smscore_device_t *coredev) } EXPORT_SYMBOL_GPL(smscore_start_device); -static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, - void *buffer, size_t size, - struct completion *completion) -{ - int rc = coredev->sendrequest_handler(coredev->context, buffer, size); - if (rc < 0) { - sms_info("sendrequest returned error %d", rc); - return rc; - } - - return wait_for_completion_timeout(completion, - msecs_to_jiffies(10000)) ? - 0 : -ETIME; -} static int smscore_load_firmware_family2(struct smscore_device_t *coredev, void *buffer, size_t size) { struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; struct SmsMsgHdr_ST *msg; - u32 mem_address = firmware->StartAddress; + u32 mem_address; u8 *payload = firmware->Payload; int rc = 0; + firmware->StartAddress = le32_to_cpu(firmware->StartAddress); + firmware->Length = le32_to_cpu(firmware->Length); + + mem_address = firmware->StartAddress; sms_info("loading FW to addr 0x%x size %d", mem_address, firmware->Length); @@ -621,6 +685,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev) kmutex_lock(&g_smscore_deviceslock); + /* Release input device (IR) resources */ + sms_ir_exit(coredev); + smscore_notify_clients(coredev); smscore_notify_callbacks(coredev, NULL, 0); @@ -628,7 +695,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev) * onresponse must no longer be called */ while (1) { - while ((cb = smscore_getbuffer(coredev))) { + while (!list_empty(&coredev->buffers)) { + cb = (struct smscore_buffer_t *) coredev->buffers.next; + list_del(&cb->entry); kfree(cb); num_buffers++; } @@ -649,8 +718,10 @@ void smscore_unregister_device(struct smscore_device_t *coredev) if (coredev->common_buffer) dma_free_coherent(NULL, coredev->common_buffer_size, - coredev->common_buffer, - coredev->common_buffer_phys); + coredev->common_buffer, coredev->common_buffer_phys); + + if (coredev->fw_buf != NULL) + kfree(coredev->fw_buf); list_del(&coredev->entry); kfree(coredev); @@ -710,7 +781,7 @@ static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { /*BDA*/ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, /*ISDBT*/ - {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"}, + {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, /*ISDBTBDA*/ {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, /*CMMB*/ @@ -834,7 +905,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) coredev->device_flags &= ~SMS_DEVICE_NOT_READY; } - if (rc != 0) + if (rc < 0) sms_err("return error code %d.", rc); return rc; } @@ -904,15 +975,11 @@ smscore_client_t *smscore_find_client(struct smscore_device_t *coredev, * */ void smscore_onresponse(struct smscore_device_t *coredev, - struct smscore_buffer_t *cb) -{ - struct SmsMsgHdr_ST *phdr = - (struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset); - struct smscore_client_t *client = - smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); + struct smscore_buffer_t *cb) { + struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p + + cb->offset); + struct smscore_client_t *client; int rc = -EBUSY; - -#if 1 static unsigned long last_sample_time; /* = 0; */ static int data_total; /* = 0; */ unsigned long time_now = jiffies_to_msecs(jiffies); @@ -930,7 +997,16 @@ void smscore_onresponse(struct smscore_device_t *coredev, } data_total += cb->size; -#endif + /* Do we need to re-route? */ + if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) || + (phdr->msgType == MSG_SMS_TRANSMISSION_IND)) { + if (coredev->mode == DEVICE_MODE_DVBT_BDA) + phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID; + } + + + client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); + /* If no client registered for type & id, * check for control client where type is not registered */ if (client) @@ -975,6 +1051,18 @@ void smscore_onresponse(struct smscore_device_t *coredev, case MSG_SMS_SLEEP_RESUME_COMP_IND: complete(&coredev->resume_done); break; + case MSG_SMS_START_IR_RES: + complete(&coredev->ir_init_done); + break; + case MSG_SMS_IR_SAMPLES_IND: + sms_ir_event(coredev, + (const char *) + ((char *)phdr + + sizeof(struct SmsMsgHdr_ST)), + (int)phdr->msgLength + - sizeof(struct SmsMsgHdr_ST)); + break; + default: #if 0 sms_info("no client (%p) or error (%d), " @@ -1001,12 +1089,24 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) struct smscore_buffer_t *cb = NULL; unsigned long flags; + DEFINE_WAIT(wait); + spin_lock_irqsave(&coredev->bufferslock, flags); - if (!list_empty(&coredev->buffers)) { - cb = (struct smscore_buffer_t *) coredev->buffers.next; - list_del(&cb->entry); - } + /* This function must return a valid buffer, since the buffer list is + * finite, we check that there is an available buffer, if not, we wait + * until such buffer become available. + */ + + prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE); + + if (list_empty(&coredev->buffers)) + schedule(); + + finish_wait(&coredev->buffer_mng_waitq, &wait); + + cb = (struct smscore_buffer_t *) coredev->buffers.next; + list_del(&cb->entry); spin_unlock_irqrestore(&coredev->bufferslock, flags); @@ -1023,8 +1123,8 @@ EXPORT_SYMBOL_GPL(smscore_getbuffer); * */ void smscore_putbuffer(struct smscore_device_t *coredev, - struct smscore_buffer_t *cb) -{ + struct smscore_buffer_t *cb) { + wake_up_interruptible(&coredev->buffer_mng_waitq); list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); } EXPORT_SYMBOL_GPL(smscore_putbuffer); diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 83e0e55f7..f4aa406ef 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -1,26 +1,26 @@ -/* - * Driver for the Siano SMS1xxx USB dongle - * - * author: Anatoly Greenblat - * - * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. - * - * 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; - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * - * 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 __smscoreapi_h__ -#define __smscoreapi_h__ +/**************************************************************** + +Siano Mobile Silicon, Inc. +MDTV receiver kernel modules. +Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat + +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, see <http://www.gnu.org/licenses/>. + +****************************************************************/ + +#ifndef __SMS_CORE_API_H__ +#define __SMS_CORE_API_H__ #include <linux/version.h> #include <linux/device.h> @@ -28,15 +28,14 @@ #include <linux/mm.h> #include <linux/scatterlist.h> #include <linux/types.h> -#include <asm/page.h> #include <linux/mutex.h> -#include "compat.h" +#include <linux/wait.h> +#include <linux/timer.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" +#include <asm/page.h> +#include "compat.h" +#include "smsir.h" #define kmutex_init(_p_) mutex_init(_p_) #define kmutex_lock(_p_) mutex_lock(_p_) @@ -170,7 +169,7 @@ struct smscore_device_t { u32 fw_buf_size; /* Infrared (IR) */ - /* struct ir_t ir; */ + struct ir_t ir; int led_state; }; @@ -209,19 +208,15 @@ struct smscore_device_t { #define MSG_SMS_INIT_DEVICE_RES 579 #define MSG_SMS_ADD_PID_FILTER_REQ 601 #define MSG_SMS_ADD_PID_FILTER_RES 602 -#define MSG_SMS_REMOVE_PID_FILTER_REQ 603 -#define MSG_SMS_REMOVE_PID_FILTER_RES 604 -#define MSG_SMS_DAB_CHANNEL 607 -#define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 -#define MSG_SMS_GET_PID_FILTER_LIST_RES 609 -#define MSG_SMS_GET_STATISTICS_REQ 615 -#define MSG_SMS_GET_STATISTICS_RES 616 +#define MSG_SMS_REMOVE_PID_FILTER_REQ 603 +#define MSG_SMS_REMOVE_PID_FILTER_RES 604 +#define MSG_SMS_DAB_CHANNEL 607 +#define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 +#define MSG_SMS_GET_PID_FILTER_LIST_RES 609 #define MSG_SMS_HO_PER_SLICES_IND 630 -#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 -#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 -#define MSG_SMS_GET_STATISTICS_EX_REQ 653 -#define MSG_SMS_GET_STATISTICS_EX_RES 654 -#define MSG_SMS_SLEEP_RESUME_COMP_IND 655 +#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 +#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 +#define MSG_SMS_SLEEP_RESUME_COMP_IND 655 #define MSG_SMS_DATA_DOWNLOAD_REQ 660 #define MSG_SMS_DATA_DOWNLOAD_RES 661 #define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664 @@ -343,225 +338,202 @@ struct SmsFirmware_ST { u8 Payload[1]; }; -struct SMSHOSTLIB_STATISTICS_ST { - u32 Reserved; /* Reserved */ +/* Statistics information returned as response for + * SmsHostApiGetStatistics_Req */ +struct SMSHOSTLIB_STATISTICS_S { + u32 Reserved; /* Reserved */ /* Common parameters */ - u32 IsRfLocked; /* 0 - not locked, 1 - locked */ - u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ - u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ + u32 IsRfLocked; /* 0 - not locked, 1 - locked */ + u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ + u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ /* Reception quality */ - s32 SNR; /* dB */ - u32 BER; /* Post Viterbi BER [1E-5] */ - u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ - /* Transport stream PER, 0xFFFFFFFF indicate N/A, - * valid only for DVB-T/H */ - u32 TS_PER; - /* DVB-H frame error rate in percentage, - * 0xFFFFFFFF indicate N/A, valid only for DVB-H */ - u32 MFER; - s32 RSSI; /* dBm */ - s32 InBandPwr; /* In band power in dBM */ - s32 CarrierOffset; /* Carrier Offset in bin/1024 */ - - /* Transmission parameters, valid only for DVB-T/H */ - u32 Frequency; /* Frequency in Hz */ - u32 Bandwidth; /* Bandwidth in MHz */ - /* Transmission Mode, for DAB modes 1-4, - * for DVB-T/H FFT mode carriers in Kilos */ - u32 TransmissionMode; - u32 ModemState; /* from SMS_DvbModemState_ET */ - u32 GuardInterval; /* Guard Interval, 1 divided by value */ - u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */ - u32 LPCodeRate; /* Low Priority Code Rate from SMS_DvbModemState_ET */ - u32 Hierarchy; /* Hierarchy from SMS_Hierarchy_ET */ - u32 Constellation; /* Constellation from SMS_Constellation_ET */ + s32 SNR; /* dB */ + u32 BER; /* Post Viterbi BER [1E-5] */ + u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ + u32 TS_PER; /* Transport stream PER, + 0xFFFFFFFF indicate N/A, valid only for DVB-T/H */ + u32 MFER; /* DVB-H frame error rate in percentage, + 0xFFFFFFFF indicate N/A, valid only for DVB-H */ + s32 RSSI; /* dBm */ + s32 InBandPwr; /* In band power in dBM */ + s32 CarrierOffset; /* Carrier Offset in bin/1024 */ - /* Burst parameters, valid only for DVB-H */ - u32 BurstSize; /* Current burst size in bytes */ - u32 BurstDuration; /* Current burst duration in mSec */ - u32 BurstCycleTime; /* Current burst cycle time in mSec */ - u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec, - * as calculated by demodulator */ - u32 NumOfRows; /* Number of rows in MPE table */ - u32 NumOfPaddCols; /* Number of padding columns in MPE table */ - u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */ - /* Burst parameters */ - u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ - u32 TotalTSPackets; /* Total number of transport-stream packets */ - u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include - * errors after MPE RS decoding */ - u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include errors - * after MPE RS decoding */ - u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were corrected - * by MPE RS decoding */ + /* Transmission parameters */ + u32 Frequency; /* Frequency in Hz */ + u32 Bandwidth; /* Bandwidth in MHz, valid only for DVB-T/H */ + u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4, + for DVB-T/H FFT mode carriers in Kilos */ + u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET, + valid only for DVB-T/H */ + u32 GuardInterval; /* Guard Interval from + SMSHOSTLIB_GUARD_INTERVALS_ET, valid only for DVB-T/H */ + u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, + valid only for DVB-T/H */ + u32 LPCodeRate; /* Low Priority Code Rate from + SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */ + u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET, + valid only for DVB-T/H */ + u32 Constellation; /* Constellation from + SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */ + /* Burst parameters, valid only for DVB-H */ + u32 BurstSize; /* Current burst size in bytes, + valid only for DVB-H */ + u32 BurstDuration; /* Current burst duration in mSec, + valid only for DVB-H */ + u32 BurstCycleTime; /* Current burst cycle time in mSec, + valid only for DVB-H */ + u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec, + as calculated by demodulator, valid only for DVB-H */ + u32 NumOfRows; /* Number of rows in MPE table, + valid only for DVB-H */ + u32 NumOfPaddCols; /* Number of padding columns in MPE table, + valid only for DVB-H */ + u32 NumOfPunctCols; /* Number of puncturing columns in MPE table, + valid only for DVB-H */ + u32 ErrorTSPackets; /* Number of erroneous + transport-stream packets */ + u32 TotalTSPackets; /* Total number of transport-stream packets */ + u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include + errors after MPE RS decoding */ + u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors + after MPE RS decoding */ + u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were + corrected by MPE RS decoding */ /* Common params */ - u32 BERErrorCount; /* Number of errornous SYNC bits. */ - u32 BERBitCount; /* Total number of SYNC bits. */ + u32 BERErrorCount; /* Number of errornous SYNC bits. */ + u32 BERBitCount; /* Total number of SYNC bits. */ /* Interface information */ - u32 SmsToHostTxErrors; /* Total number of transmission errors. */ + u32 SmsToHostTxErrors; /* Total number of transmission errors. */ /* DAB/T-DMB */ - u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */ + u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */ /* DVB-H TPS parameters */ - u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; - * if set to 0xFFFFFFFF cell_id not yet recovered */ - -}; + u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; + if set to 0xFFFFFFFF cell_id not yet recovered */ + u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - + Time Slicing indicator, bit 0 - MPE-FEC indicator */ + u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - + Time Slicing indicator, bit 0 - MPE-FEC indicator */ -struct SmsMsgStatisticsInfo_ST { - u32 RequestResult; - - struct SMSHOSTLIB_STATISTICS_ST Stat; - - /* Split the calc of the SNR in DAB */ - u32 Signal; /* dB */ - u32 Noise; /* dB */ + u32 NumMPEReceived; /* DVB-H, Num MPE section received */ + u32 ReservedFields[10]; /* Reserved */ }; -#if 0 -struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST { - /* Per-layer information */ - u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, - * 255 means layer does not exist */ - u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET, - * 255 means layer does not exist */ - u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ - u32 BERErrorCount; /* Post Viterbi Error Bits Count */ - u32 BERBitCount; /* Post Viterbi Total Bits Count */ - u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ - u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */ - u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ - u32 TotalTSPackets; /* Total number of transport-stream packets */ - u32 TILdepthI; /* Time interleaver depth I parameter, - * 255 means layer does not exist */ - u32 NumberOfSegments; /* Number of segments in layer A, - * 255 means layer does not exist */ - u32 TMCCErrors; /* TMCC errors */ +struct PID_STATISTICS_DATA_S { + struct PID_BURST_S { + u32 size; + u32 padding_cols; + u32 punct_cols; + u32 duration; + u32 cycle; + u32 calc_cycle; + } burst; + + u32 tot_tbl_cnt; + u32 invalid_tbl_cnt; + u32 tot_cor_tbl; }; -struct SMSHOSTLIB_STATISTICS_ISDBT_ST { - u32 StatisticsType; /* Enumerator identifying the type of the - * structure. Values are the same as - * SMSHOSTLIB_DEVICE_MODES_E - * - * This field MUST always be first in any - * statistics structure */ - - u32 FullSize; /* Total size of the structure returned by the modem. - * If the size requested by the host is smaller than - * FullSize, the struct will be truncated */ - - /* Common parameters */ - u32 IsRfLocked; /* 0 - not locked, 1 - locked */ - u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ - u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ - - /* Reception quality */ - s32 SNR; /* dB */ - s32 RSSI; /* dBm */ - s32 InBandPwr; /* In band power in dBM */ - s32 CarrierOffset; /* Carrier Offset in Hz */ - - /* Transmission parameters */ - u32 Frequency; /* Frequency in Hz */ - u32 Bandwidth; /* Bandwidth in MHz */ - u32 TransmissionMode; /* ISDB-T transmission mode */ - u32 ModemState; /* 0 - Acquisition, 1 - Locked */ - u32 GuardInterval; /* Guard Interval, 1 divided by value */ - u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */ - u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */ - u32 NumOfLayers; /* Number of ISDB-T layers in the network */ - - /* Per-layer information */ - /* Layers A, B and C */ - struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST LayerInfo[3]; - /* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */ +struct PID_DATA_S { + u32 pid; + u32 num_rows; + struct PID_STATISTICS_DATA_S pid_statistics; +}; - /* Interface information */ - u32 SmsToHostTxErrors; /* Total number of transmission errors. */ +#define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1) +#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth) +#define CORRECT_STAT_TRANSMISSON_MODE(_stat) \ + if (_stat.TransmissionMode == 0) \ + _stat.TransmissionMode = 2; \ + else if (_stat.TransmissionMode == 1) \ + _stat.TransmissionMode = 8; \ + else \ + _stat.TransmissionMode = 4; + +struct TRANSMISSION_STATISTICS_S { + u32 Frequency; /* Frequency in Hz */ + u32 Bandwidth; /* Bandwidth in MHz */ + u32 TransmissionMode; /* FFT mode carriers in Kilos */ + u32 GuardInterval; /* Guard Interval from + SMSHOSTLIB_GUARD_INTERVALS_ET */ + u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET */ + u32 LPCodeRate; /* Low Priority Code Rate from + SMSHOSTLIB_CODE_RATE_ET */ + u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */ + u32 Constellation; /* Constellation from + SMSHOSTLIB_CONSTELLATION_ET */ + /* DVB-H TPS parameters */ + u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; + if set to 0xFFFFFFFF cell_id not yet recovered */ + u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - + Time Slicing indicator, bit 0 - MPE-FEC indicator */ + u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - + Time Slicing indicator, bit 0 - MPE-FEC indicator */ + u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ }; -struct SMSHOSTLIB_STATISTICS_DVB_ST { - u32 StatisticsType; /* Enumerator identifying the type of the - * structure. Values are the same as - * SMSHOSTLIB_DEVICE_MODES_E - * This field MUST always first in any - * statistics structure */ +struct RECEPTION_STATISTICS_S { + u32 IsRfLocked; /* 0 - not locked, 1 - locked */ + u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ + u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ + + u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ + s32 SNR; /* dB */ + u32 BER; /* Post Viterbi BER [1E-5] */ + u32 BERErrorCount; /* Number of erronous SYNC bits. */ + u32 BERBitCount; /* Total number of SYNC bits. */ + u32 TS_PER; /* Transport stream PER, + 0xFFFFFFFF indicate N/A */ + u32 MFER; /* DVB-H frame error rate in percentage, + 0xFFFFFFFF indicate N/A, valid only for DVB-H */ + s32 RSSI; /* dBm */ + s32 InBandPwr; /* In band power in dBM */ + s32 CarrierOffset; /* Carrier Offset in bin/1024 */ + u32 ErrorTSPackets; /* Number of erroneous + transport-stream packets */ + u32 TotalTSPackets; /* Total number of transport-stream packets */ + + s32 MRC_SNR; /* dB */ + s32 MRC_RSSI; /* dBm */ + s32 MRC_InBandPwr; /* In band power in dBM */ +}; - u32 FullSize; /* Total size of the structure returned by the modem. - * If the size requested by the host is smaller than - * FullSize, the struct will be truncated */ - /* Common parameters */ - u32 IsRfLocked; /* 0 - not locked, 1 - locked */ - u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ - u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ - /* Reception quality */ - s32 SNR; /* dB */ - u32 BER; /* Post Viterbi BER [1E-5] */ - u32 BERErrorCount; /* Number of errornous SYNC bits. */ - u32 BERBitCount; /* Total number of SYNC bits. */ - u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A */ - u32 MFER; /* DVB-H frame error rate in percentage, - * 0xFFFFFFFF indicate N/A, valid only for DVB-H */ - s32 RSSI; /* dBm */ - s32 InBandPwr; /* In band power in dBM */ - s32 CarrierOffset; /* Carrier Offset in bin/1024 */ +/* Statistics information returned as response for + * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */ +struct SMSHOSTLIB_STATISTICS_DVB_S { + /* Reception */ + struct RECEPTION_STATISTICS_S ReceptionData; /* Transmission parameters */ - u32 Frequency; /* Frequency in Hz */ - u32 Bandwidth; /* Bandwidth in MHz */ - u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ - u32 TransmissionMode; /* FFT mode carriers in Kilos */ - u32 GuardInterval; /* Guard Interval, 1 divided by value */ - u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET */ - u32 LPCodeRate; /* Low Priority Code Rate from - * SMSHOSTLIB_CODE_RATE_ET */ - u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */ - u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET */ + struct TRANSMISSION_STATISTICS_S TransmissionData; /* Burst parameters, valid only for DVB-H */ - u32 BurstSize; /* Current burst size in bytes */ - u32 BurstDuration; /* Current burst duration in mSec */ - u32 BurstCycleTime; /* Current burst cycle time in mSec */ - u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec, - * as calculated by demodulator */ - u32 NumOfRows; /* Number of rows in MPE table */ - u32 NumOfPaddCols; /* Number of padding columns in MPE table */ - u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */ - - u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ - u32 TotalTSPackets; /* Total number of transport-stream packets */ - - u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include - * errors after MPE RS decoding */ - u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include - * errors after MPE RS decoding */ - u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were - * corrected by MPE RS decoding */ - - u32 NumMPEReceived; /* DVB-H, Num MPE section received */ - - /* DVB-H TPS parameters */ - u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; - * if set to 0xFFFFFFFF cell_id not yet recovered */ - u32 DvbhSrvIndHP; /* DVB-H service indication info, - * bit 1 - Time Slicing indicator, - * bit 0 - MPE-FEC indicator */ - u32 DvbhSrvIndLP; /* DVB-H service indication info, - * bit 1 - Time Slicing indicator, - * bit 0 - MPE-FEC indicator */ - - /* Interface information */ - u32 SmsToHostTxErrors; /* Total number of transmission errors. */ +#define SRVM_MAX_PID_FILTERS 8 + struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS]; +}; +struct SRVM_SIGNAL_STATUS_S { + u32 result; + u32 snr; + u32 tsPackets; + u32 etsPackets; + u32 constellation; + u32 hpCode; + u32 tpsSrvIndLP; + u32 tpsSrvIndHP; + u32 cellId; + u32 reason; + + s32 inBandPower; + u32 requestId; }; struct SMSHOSTLIB_I2C_REQ_ST { @@ -576,7 +548,7 @@ struct SMSHOSTLIB_I2C_RES_ST { u32 ReadCount; /* number of bytes read */ u8 Data[1]; }; -#endif + struct smscore_gpio_config { #define SMS_GPIO_DIRECTION_INPUT 0 @@ -679,4 +651,4 @@ int smscore_led_state(struct smscore_device_t *core, int led); dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg) -#endif /* __smscoreapi_h__ */ +#endif /* __SMS_CORE_API_H__ */ diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index 035bd52c9..39421ee6f 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -1,28 +1,34 @@ -/* - * Driver for the Siano SMS1xxx USB dongle - * - * Author: Uri Shkolni - * - * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. - * - * 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; - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * - * 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. - */ +/**************************************************************** + +Siano Mobile Silicon, Inc. +MDTV receiver kernel modules. +Copyright (C) 2006-2008, Uri Shkolnik + +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, see <http://www.gnu.org/licenses/>. + +****************************************************************/ #include <linux/module.h> #include <linux/init.h> +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" + #include "smscoreapi.h" +#include "smsendian.h" #include "sms-cards.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -39,12 +45,15 @@ struct smsdvb_client_t { struct dvb_frontend frontend; fe_status_t fe_status; - int fe_ber, fe_snr, fe_unc, fe_signal_strength; - struct completion tune_done, stat_done; + struct completion tune_done; /* todo: save freq/band instead whole struct */ struct dvb_frontend_parameters fe_params; + + struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb; + int event_fe_state; + int event_unc_state; }; static struct list_head g_smsdvb_clients; @@ -54,11 +63,21 @@ static int sms_dbg; module_param_named(debug, sms_dbg, int, 0644); MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); +/* Events that may come from DVB v3 adapter */ +static void sms_board_dvb3_event(struct smsdvb_client_t *client, + enum SMS_DVB3_EVENTS event) { +} + static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; - struct SmsMsgHdr_ST *phdr = - (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset); + struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p) + + cb->offset); + u32 *pMsgData = (u32 *) phdr + 1; + /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/ + bool is_status_update = false; + + smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); switch (phdr->msgType) { case MSG_SMS_DVBT_BDA_DATA: @@ -70,43 +89,110 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) complete(&client->tune_done); break; - case MSG_SMS_GET_STATISTICS_RES: - { - struct SmsMsgStatisticsInfo_ST *p = - (struct SmsMsgStatisticsInfo_ST *)(phdr + 1); - - if (p->Stat.IsDemodLocked) { - client->fe_status = FE_HAS_SIGNAL | - FE_HAS_CARRIER | - FE_HAS_VITERBI | - FE_HAS_SYNC | - FE_HAS_LOCK; - - client->fe_snr = p->Stat.SNR; - client->fe_ber = p->Stat.BER; - client->fe_unc = p->Stat.BERErrorCount; - - if (p->Stat.InBandPwr < -95) - client->fe_signal_strength = 0; - else if (p->Stat.InBandPwr > -29) - client->fe_signal_strength = 100; - else - client->fe_signal_strength = - (p->Stat.InBandPwr + 95) * 3 / 2; + case MSG_SMS_SIGNAL_DETECTED_IND: + sms_info("MSG_SMS_SIGNAL_DETECTED_IND"); + client->sms_stat_dvb.TransmissionData.IsDemodLocked = true; + is_status_update = true; + break; + + case MSG_SMS_NO_SIGNAL_IND: + sms_info("MSG_SMS_NO_SIGNAL_IND"); + client->sms_stat_dvb.TransmissionData.IsDemodLocked = false; + is_status_update = true; + break; + + case MSG_SMS_TRANSMISSION_IND: { + sms_info("MSG_SMS_TRANSMISSION_IND"); + + pMsgData++; + memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData, + sizeof(struct TRANSMISSION_STATISTICS_S)); + + /* Mo need to correct guard interval + * (as opposed to old statistics message). + */ + CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData); + CORRECT_STAT_TRANSMISSON_MODE( + client->sms_stat_dvb.TransmissionData); + is_status_update = true; + break; + } + case MSG_SMS_HO_PER_SLICES_IND: { + struct RECEPTION_STATISTICS_S *pReceptionData = + &client->sms_stat_dvb.ReceptionData; + struct SRVM_SIGNAL_STATUS_S SignalStatusData; + + /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/ + pMsgData++; + SignalStatusData.result = pMsgData[0]; + SignalStatusData.snr = pMsgData[1]; + SignalStatusData.inBandPower = (s32) pMsgData[2]; + SignalStatusData.tsPackets = pMsgData[3]; + SignalStatusData.etsPackets = pMsgData[4]; + SignalStatusData.constellation = pMsgData[5]; + SignalStatusData.hpCode = pMsgData[6]; + SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03; + SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03; + SignalStatusData.cellId = pMsgData[9] & 0xFFFF; + SignalStatusData.reason = pMsgData[10]; + SignalStatusData.requestId = pMsgData[11]; + pReceptionData->IsRfLocked = pMsgData[16]; + pReceptionData->IsDemodLocked = pMsgData[17]; + pReceptionData->ModemState = pMsgData[12]; + pReceptionData->SNR = pMsgData[1]; + pReceptionData->BER = pMsgData[13]; + pReceptionData->RSSI = pMsgData[14]; + CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData); + + pReceptionData->InBandPwr = (s32) pMsgData[2]; + pReceptionData->CarrierOffset = (s32) pMsgData[15]; + pReceptionData->TotalTSPackets = pMsgData[3]; + pReceptionData->ErrorTSPackets = pMsgData[4]; + + /* TS PER */ + if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) + > 0) { + pReceptionData->TS_PER = (SignalStatusData.etsPackets + * 100) / (SignalStatusData.tsPackets + + SignalStatusData.etsPackets); } else { - client->fe_status = 0; - client->fe_snr = - client->fe_ber = - client->fe_unc = - client->fe_signal_strength = 0; + pReceptionData->TS_PER = 0; } - complete(&client->stat_done); - break; - } } + pReceptionData->BERBitCount = pMsgData[18]; + pReceptionData->BERErrorCount = pMsgData[19]; + pReceptionData->MRC_SNR = pMsgData[20]; + pReceptionData->MRC_InBandPwr = pMsgData[21]; + pReceptionData->MRC_RSSI = pMsgData[22]; + + is_status_update = true; + break; + } + } smscore_putbuffer(client->coredev, cb); + if (is_status_update) { + if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) { + client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER + | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); + if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets + == 0) + sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); + else + sms_board_dvb3_event(client, + DVB3_EVENT_UNC_ERR); + + } else { + /*client->fe_status = + (phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ? + 0 : FE_HAS_SIGNAL;*/ + client->fe_status = 0; + sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); + } + } + return 0; } @@ -149,6 +235,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed) PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); PidMsg.msgData[0] = feed->pid; + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); return smsclient_sendrequest(client->smsclient, &PidMsg, sizeof(PidMsg)); } @@ -169,6 +256,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed) PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); PidMsg.msgData[0] = feed->pid; + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); return smsclient_sendrequest(client->smsclient, &PidMsg, sizeof(PidMsg)); } @@ -177,7 +265,10 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, void *buffer, size_t size, struct completion *completion) { - int rc = smsclient_sendrequest(client->smsclient, buffer, size); + int rc; + + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer); + rc = smsclient_sendrequest(client->smsclient, buffer, size); if (rc < 0) return rc; @@ -186,83 +277,61 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, 0 : -ETIME; } -static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) -{ - struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, - DVBT_BDA_CONTROL_MSG_ID, - HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 }; - int ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), - &client->stat_done); - if (ret < 0) - return ret; - - if (client->fe_status & FE_HAS_LOCK) - sms_board_led_feedback(client->coredev, - (client->fe_unc == 0) ? - SMS_LED_HI : SMS_LED_LO); - else - sms_board_led_feedback(client->coredev, SMS_LED_OFF); - return ret; -} - static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *stat = client->fe_status; + *stat = client->fe_status; - return rc; + return 0; } static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *ber = client->fe_ber; + *ber = client->sms_stat_dvb.ReceptionData.BER; - return rc; + return 0; } static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *strength = client->fe_signal_strength; + if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) + *strength = 0; + else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) + *strength = 100; + else + *strength = + (client->sms_stat_dvb.ReceptionData.InBandPwr + + 95) * 3 / 2; - return rc; + return 0; } static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *snr = client->fe_snr; + *snr = client->sms_stat_dvb.ReceptionData.SNR; - return rc; + return 0; } static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *ucblocks = client->fe_unc; + *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; - return rc; + return 0; } static int smsdvb_get_tune_settings(struct dvb_frontend *fe, @@ -286,12 +355,15 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, struct SmsMsgHdr_ST Msg; u32 Data[3]; } Msg; - int ret; - Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; - Msg.Msg.msgDstId = HIF_TASK; - Msg.Msg.msgFlags = 0; - Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; + client->fe_status = FE_HAS_SIGNAL; + client->event_fe_state = -1; + client->event_unc_state = -1; + + Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; + Msg.Msg.msgDstId = HIF_TASK; + Msg.Msg.msgFlags = 0; + Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; Msg.Msg.msgLength = sizeof(Msg); Msg.Data[0] = fep->frequency; Msg.Data[2] = 12000000; @@ -310,24 +382,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, default: return -EINVAL; } - /* Disable LNA, if any. An error is returned if no LNA is present */ - ret = sms_board_lna_control(client->coredev, 0); - if (ret == 0) { - fe_status_t status; - - /* tune with LNA off at first */ - ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), - &client->tune_done); - - smsdvb_read_status(fe, &status); - - if (status & FE_HAS_LOCK) - return ret; - - /* previous tune didnt lock - enable LNA and tune again */ - sms_board_lna_control(client->coredev, 1); - } - return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->tune_done); } @@ -352,8 +406,7 @@ static int smsdvb_init(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); - sms_board_power(client->coredev, 1); - + sms_board_dvb3_event(client, DVB3_EVENT_INIT); return 0; } @@ -362,8 +415,7 @@ static int smsdvb_sleep(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); - sms_board_led_feedback(client->coredev, SMS_LED_OFF); - sms_board_power(client->coredev, 0); + sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); return 0; } @@ -488,7 +540,6 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, client->coredev = coredev; init_completion(&client->tune_done); - init_completion(&client->stat_done); kmutex_lock(&g_smsdvb_clientslock); @@ -496,8 +547,11 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, kmutex_unlock(&g_smsdvb_clientslock); - sms_info("success"); + client->event_fe_state = -1; + client->event_unc_state = -1; + sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); + sms_info("success"); sms_board_setup(coredev); return 0; @@ -550,5 +604,5 @@ module_init(smsdvb_module_init); module_exit(smsdvb_module_exit); MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); -MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); +MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/siano/smsendian.c b/linux/drivers/media/dvb/siano/smsendian.c index d79aa0512..457b6d02e 100644 --- a/linux/drivers/media/dvb/siano/smsendian.c +++ b/linux/drivers/media/dvb/siano/smsendian.c @@ -49,6 +49,7 @@ void smsendian_handle_tx_message(void *buffer) } #endif /* __BIG_ENDIAN */ } +EXPORT_SYMBOL_GPL(smsendian_handle_tx_message); void smsendian_handle_rx_message(void *buffer) { @@ -86,6 +87,7 @@ void smsendian_handle_rx_message(void *buffer) } #endif /* __BIG_ENDIAN */ } +EXPORT_SYMBOL_GPL(smsendian_handle_rx_message); void smsendian_handle_message_header(void *msg) { @@ -97,4 +99,4 @@ void smsendian_handle_message_header(void *msg) phdr->msgFlags = le16_to_cpu(phdr->msgFlags); #endif /* __BIG_ENDIAN */ } - +EXPORT_SYMBOL_GPL(smsendian_handle_message_header); diff --git a/linux/drivers/media/dvb/siano/smsir.c b/linux/drivers/media/dvb/siano/smsir.c index a5f302c58..e3d776fee 100644 --- a/linux/drivers/media/dvb/siano/smsir.c +++ b/linux/drivers/media/dvb/siano/smsir.c @@ -99,7 +99,7 @@ static void sms_ir_rc5_event(struct smscore_device_t *coredev, bool toggle_changed; u16 keycode; - sms_info("IR RC5 word: address %d, command %d, toggle %d", + sms_log("IR RC5 word: address %d, command %d, toggle %d", addr, cmd, toggle); toggle_changed = ir_toggle != toggle; @@ -118,7 +118,7 @@ static void sms_ir_rc5_event(struct smscore_device_t *coredev, (keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN)) return; /* accept only repeated volume, reject other keys */ - sms_info("kernel input keycode (from ir) %d", keycode); + sms_log("kernel input keycode (from ir) %d", keycode); input_report_key(coredev->ir.input_dev, keycode, 1); input_sync(coredev->ir.input_dev); @@ -147,7 +147,7 @@ static u32 ir_rc5_decode(unsigned int code) break; case 3: /* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/ - sms_info("bad code"); + sms_log("bad code"); return 0; } } @@ -175,7 +175,7 @@ static void sms_rc5_parse_word(struct smscore_device_t *coredev) RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j) rc5_word = ir_rc5_decode(rc5_word); - /* sms_info("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */ + /* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */ sms_ir_rc5_event(coredev, RC5_TOGGLE(rc5_word), @@ -210,11 +210,11 @@ static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev, if (ir_pos == RC5_WORD_LEN) sms_rc5_parse_word(coredev); else if (ir_pos) /* timeout within a word */ - sms_info("IR error parsing a word"); + sms_log("IR error parsing a word"); ir_pos = 0; ir_word = 0; - /* sms_info("timeout %d", time); */ + /* sms_log("timeout %d", time); */ break; } /* The time is within the range of this number of bits */ @@ -236,7 +236,7 @@ void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) int count = len>>2; samples = (s32 *)buf; -/* sms_info("IR buffer received, length = %d", count);*/ +/* sms_log("IR buffer received, length = %d", count);*/ for (i = 0; i < count; i++) if (ir_protocol == IR_RC5) @@ -248,7 +248,7 @@ int sms_ir_init(struct smscore_device_t *coredev) { struct input_dev *input_dev; - sms_info("Allocating input device"); + sms_log("Allocating input device"); input_dev = input_allocate_device(); if (!input_dev) { sms_err("Not enough memory"); @@ -261,11 +261,11 @@ int sms_ir_init(struct smscore_device_t *coredev) coredev->ir.keyboard_layout_map = keyboard_layout_maps[coredev->ir.ir_kb_type]. keyboard_layout_map; - sms_info("IR remote keyboard type is %d", coredev->ir.ir_kb_type); + sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type); coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ coredev->ir.timeout = IR_DEFAULT_TIMEOUT; - sms_info("IR port %d, timeout %d ms", + sms_log("IR port %d, timeout %d ms", coredev->ir.controller, coredev->ir.timeout); snprintf(coredev->ir.name, @@ -280,7 +280,7 @@ int sms_ir_init(struct smscore_device_t *coredev) input_dev->evbit[0] = BIT_MASK(EV_KEY); input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); - sms_info("Input device (IR) %s is set for key events", input_dev->name); + sms_log("Input device (IR) %s is set for key events", input_dev->name); if (input_register_device(input_dev)) { sms_err("Failed to register device"); @@ -296,6 +296,6 @@ void sms_ir_exit(struct smscore_device_t *coredev) if (coredev->ir.input_dev) input_unregister_device(coredev->ir.input_dev); - sms_info(""); + sms_log(""); } diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index 67be79549..3bbbdb197 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -1,23 +1,23 @@ -/* - * Driver for the Siano SMS1xxx USB dongle - * - * author: Anatoly Greenblat - * - * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. - * - * 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; - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * - * 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. - */ +/**************************************************************** + +Siano Mobile Silicon, Inc. +MDTV receiver kernel modules. +Copyright (C) 2005-2009, Uri Shkolnik, Anatoly Greenblat + +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, see <http://www.gnu.org/licenses/>. + +****************************************************************/ #include <linux/kernel.h> #include <linux/init.h> @@ -26,6 +26,7 @@ #include "smscoreapi.h" #include "sms-cards.h" +#include "smsendian.h" static int sms_dbg; module_param_named(debug, sms_dbg, int, 0644); @@ -68,15 +69,16 @@ static void smsusb_onresponse(struct urb *urb, struct pt_regs *regs) struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context; struct smsusb_device_t *dev = surb->dev; - if (urb->status < 0) { - sms_err("error, urb status %d, %d bytes", + if (urb->status == -ESHUTDOWN) { + sms_err("error, urb status %d (-ESHUTDOWN), %d bytes", urb->status, urb->actual_length); return; } - if (urb->actual_length > 0) { - struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) surb->cb->p; + if ((urb->actual_length > 0) && (urb->status == 0)) { + struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p; + smsendian_handle_message_header(phdr); if (urb->actual_length >= phdr->msgLength) { surb->cb->size = phdr->msgLength; @@ -113,7 +115,10 @@ static void smsusb_onresponse(struct urb *urb, struct pt_regs *regs) "msglen %d actual %d", phdr->msgLength, urb->actual_length); } - } + } else + sms_err("error, urb status %d, %d bytes", + urb->status, urb->actual_length); + exit_and_resubmit: smsusb_submit_urb(dev, surb); @@ -180,6 +185,7 @@ static int smsusb_sendrequest(void *context, void *buffer, size_t size) struct smsusb_device_t *dev = (struct smsusb_device_t *) context; int dummy; + smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer); return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), buffer, size, &dummy, 1000); } @@ -337,8 +343,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) case SMS_VEGA: dev->buffer_size = USB2_BUFFER_SIZE; dev->response_alignment = - dev->udev->ep_in[1]->desc.wMaxPacketSize - - sizeof(struct SmsMsgHdr_ST); + le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - + sizeof(struct SmsMsgHdr_ST); params.flags |= SMS_DEVICE_FAMILY2; break; @@ -552,14 +558,14 @@ int smsusb_module_init(void) void smsusb_module_exit(void) { - sms_debug(""); /* Regular USB Cleanup */ usb_deregister(&smsusb_driver); + sms_info("end"); } module_init(smsusb_module_init); module_exit(smsusb_module_exit); -MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle"); +MODULE_DESCRIPTION("Driver for the Siano SMS1xxx USB dongle"); MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index e4d0900d5..538848141 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -89,6 +89,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, struct dvb_demux_feed *feed); +static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len); int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) @@ -192,8 +193,6 @@ int av7110_av_start_play(struct av7110 *av7110, int av) ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); break; } - if (!ret) - ret = av7110->playing; return ret; } @@ -437,6 +436,45 @@ static void play_audio_cb(u8 *buf, int count, void *priv) aux_ring_buffer_write(&av7110->aout, buf, count); } + +#define FREE_COND_TS (dvb_ringbuffer_free(rb) >= 4096) + +static ssize_t ts_play(struct av7110 *av7110, const char __user *buf, + unsigned long count, int nonblock, int type) +{ + struct dvb_ringbuffer *rb; + u8 *kb; + unsigned long todo = count; + + dprintk(2, "%s: type %d cnt %lu\n", __func__, type, count); + + rb = (type) ? &av7110->avout : &av7110->aout; + kb = av7110->kbuf[type]; + + if (!kb) + return -ENOBUFS; + + if (nonblock && !FREE_COND_TS) + return -EWOULDBLOCK; + + while (todo >= TS_SIZE) { + if (!FREE_COND_TS) { + if (nonblock) + return count - todo; + if (wait_event_interruptible(rb->queue, FREE_COND_TS)) + return count - todo; + } + if (copy_from_user(kb, buf, TS_SIZE)) + return -EFAULT; + write_ts_to_decoder(av7110, type, kb, TS_SIZE); + todo -= TS_SIZE; + buf += TS_SIZE; + } + + return count - todo; +} + + #define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \ dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024) @@ -780,11 +818,37 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, } +static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len) +{ + struct ipack *ipack = &av7110->ipack[type]; + + if (buf[1] & TRANS_ERROR) { + av7110_ipack_reset(ipack); + return -1; + } + + if (!(buf[3] & PAYLOAD)) + return -1; + + if (buf[1] & PAY_START) + av7110_ipack_flush(ipack); + + if (buf[3] & ADAPT_FIELD) { + len -= buf[4] + 1; + buf += buf[4] + 1; + if (!len) + return 0; + } + + av7110_ipack_instant_repack(buf + 4, len - 4, ipack); + return 0; +} + + int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) { struct dvb_demux *demux = feed->demux; struct av7110 *av7110 = (struct av7110 *) demux->priv; - struct ipack *ipack = &av7110->ipack[feed->pes_type]; dprintk(2, "av7110:%p, \n", av7110); @@ -804,20 +868,7 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l return -1; } - if (!(buf[3] & 0x10)) /* no payload? */ - return -1; - if (buf[1] & 0x40) - av7110_ipack_flush(ipack); - - if (buf[3] & 0x20) { /* adaptation field? */ - len -= buf[4] + 1; - buf += buf[4] + 1; - if (!len) - return 0; - } - - av7110_ipack_instant_repack(buf + 4, len - 4, &av7110->ipack[feed->pes_type]); - return 0; + return write_ts_to_decoder(av7110, feed->pes_type, buf, len); } @@ -916,6 +967,7 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf, { struct dvb_device *dvbdev = file->private_data; struct av7110 *av7110 = dvbdev->priv; + unsigned char c; dprintk(2, "av7110:%p, \n", av7110); @@ -925,7 +977,12 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf, if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) return -EPERM; - return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); + if (get_user(c, buf)) + return -EFAULT; + if (c == 0x47 && count % TS_SIZE == 0) + return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); + else + return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); } static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) @@ -952,6 +1009,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf, { struct dvb_device *dvbdev = file->private_data; struct av7110 *av7110 = dvbdev->priv; + unsigned char c; dprintk(2, "av7110:%p, \n", av7110); @@ -959,7 +1017,13 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf, printk(KERN_ERR "not audio source memory\n"); return -EPERM; } - return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); + + if (get_user(c, buf)) + return -EFAULT; + if (c == 0x47 && count % TS_SIZE == 0) + return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); + else + return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); } static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 }; @@ -1062,7 +1126,6 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, if (ret) break; } - if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) { if (av7110->playing == RP_AV) { ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0); @@ -1122,20 +1185,16 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, case VIDEO_SET_DISPLAY_FORMAT: { video_displayformat_t format = (video_displayformat_t) arg; - switch (format) { case VIDEO_PAN_SCAN: av7110->display_panscan = VID_PAN_SCAN_PREF; break; - case VIDEO_LETTER_BOX: av7110->display_panscan = VID_VC_AND_PS_PREF; break; - case VIDEO_CENTER_CUT_OUT: av7110->display_panscan = VID_CENTRE_CUT_PREF; break; - default: ret = -EINVAL; } @@ -1183,7 +1242,8 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, case VIDEO_SLOWMOTION: if (av7110->playing&RP_VIDEO) { - ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0); + if (av7110->trickmode != TRICK_SLOW) + ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0); if (!ret) ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg); } else { @@ -1207,7 +1267,6 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, case VIDEO_CLEAR_BUFFER: dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); av7110_ipack_reset(&av7110->ipack[1]); - if (av7110->playing == RP_AV) { ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); @@ -1228,13 +1287,13 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, break; case VIDEO_SET_STREAMTYPE: - break; default: ret = -ENOIOCTLCMD; break; } + return ret; } @@ -1309,7 +1368,6 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, case AUDIO_CHANNEL_SELECT: av7110->audiostate.channel_select = (audio_channel_select_t) arg; - switch(av7110->audiostate.channel_select) { case AUDIO_STEREO: ret = audcom(av7110, AUDIO_CMD_STEREO); @@ -1320,7 +1378,6 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); } break; - case AUDIO_MONO_LEFT: ret = audcom(av7110, AUDIO_CMD_MONO_L); if (!ret) { @@ -1330,7 +1387,6 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200); } break; - case AUDIO_MONO_RIGHT: ret = audcom(av7110, AUDIO_CMD_MONO_R); if (!ret) { @@ -1340,7 +1396,6 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210); } break; - default: ret = -EINVAL; break; @@ -1366,21 +1421,24 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); break; - case AUDIO_SET_ID: + case AUDIO_SET_ID: break; + case AUDIO_SET_MIXER: { struct audio_mixer *amix = (struct audio_mixer *)parg; - ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right); break; } + case AUDIO_SET_STREAMTYPE: break; + default: ret = -ENOIOCTLCMD; } + return ret; } diff --git a/linux/drivers/media/dvb/ttpci/av7110_hw.c b/linux/drivers/media/dvb/ttpci/av7110_hw.c index 276be4056..9c91e3b88 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_hw.c +++ b/linux/drivers/media/dvb/ttpci/av7110_hw.c @@ -1089,7 +1089,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) else { int i, len = dc->x0-dc->color+1; u8 __user *colors = (u8 __user *)dc->data; - u8 r, g, b, blend; + u8 r, g = 0, b = 0, blend = 0; ret = 0; for (i = 0; i<len; i++) { if (get_user(r, colors + i * 4) || diff --git a/linux/drivers/media/dvb/ttpci/av7110_v4l.c b/linux/drivers/media/dvb/ttpci/av7110_v4l.c index 2210cff73..ce64c6214 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c @@ -458,7 +458,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); if (av7110->analog_tuner_flags) { - if (i->index < 0 || i->index >= 4) + if (i->index >= 4) return -EINVAL; } else { if (i->index != 0) diff --git a/linux/drivers/media/dvb/ttpci/budget-av.c b/linux/drivers/media/dvb/ttpci/budget-av.c index 855fe74b6..8ea915227 100644 --- a/linux/drivers/media/dvb/ttpci/budget-av.c +++ b/linux/drivers/media/dvb/ttpci/budget-av.c @@ -1413,7 +1413,7 @@ static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index); - if (i->index < 0 || i->index >= KNC1_INPUTS) + if (i->index >= KNC1_INPUTS) return -EINVAL; memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); return 0; diff --git a/linux/drivers/media/dvb/ttpci/budget.c b/linux/drivers/media/dvb/ttpci/budget.c index 83e9e7750..e48380c48 100644 --- a/linux/drivers/media/dvb/ttpci/budget.c +++ b/linux/drivers/media/dvb/ttpci/budget.c @@ -47,6 +47,9 @@ #include "bsru6.h" #include "bsbe1.h" #include "tdhd1.h" +#include "stv6110x.h" +#include "stv090x.h" +#include "isl6423.h" static int diseqc_method; module_param(diseqc_method, int, 0444); @@ -425,6 +428,44 @@ static u8 read_pwm(struct budget* budget) return pwm; } +static struct stv090x_config tt1600_stv090x_config = { + .device = STV0903, + .demod_mode = STV090x_SINGLE, + .clk_mode = STV090x_CLK_EXT, + + .xtal = 27000000, + .address = 0x68, + .ref_clk = 27000000, + + .ts1_mode = STV090x_TSMODE_DVBCI, + .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, + + .repeater_level = STV090x_RPTLEVEL_16, + + .tuner_init = NULL, + .tuner_set_mode = NULL, + .tuner_set_frequency = NULL, + .tuner_get_frequency = NULL, + .tuner_set_bandwidth = NULL, + .tuner_get_bandwidth = NULL, + .tuner_set_bbgain = NULL, + .tuner_get_bbgain = NULL, + .tuner_set_refclk = NULL, + .tuner_get_status = NULL, +}; + +static struct stv6110x_config tt1600_stv6110x_config = { + .addr = 0x60, + .refclk = 27000000, +}; + +static struct isl6423_config tt1600_isl6423_config = { + .current_max = SEC_CURRENT_515m, + .curlim = SEC_CURRENT_LIM_ON, + .mod_extern = 1, + .addr = 0x08, +}; + static void frontend_init(struct budget *budget) { (void)alps_bsbe1_config; /* avoid warning */ @@ -566,6 +607,48 @@ static void frontend_init(struct budget *budget) } break; } + + case 0x101c: { /* TT S2-1600 */ + struct stv6110x_devctl *ctl; + saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); + msleep(50); + saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); + msleep(250); + + budget->dvb_frontend = dvb_attach(stv090x_attach, + &tt1600_stv090x_config, + &budget->i2c_adap, + STV090x_DEMODULATOR_0); + + if (budget->dvb_frontend) { + + ctl = dvb_attach(stv6110x_attach, + budget->dvb_frontend, + &tt1600_stv6110x_config, + &budget->i2c_adap); + + tt1600_stv090x_config.tuner_init = ctl->tuner_init; + tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; + tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; + tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; + tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; + tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; + tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; + tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; + tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; + tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; + + dvb_attach(isl6423_attach, + budget->dvb_frontend, + &budget->i2c_adap, + &tt1600_isl6423_config); + + } else { + dvb_frontend_detach(budget->dvb_frontend); + budget->dvb_frontend = NULL; + } + } + break; } if (budget->dvb_frontend == NULL) { @@ -641,6 +724,7 @@ MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT); +MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT); MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); @@ -653,6 +737,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016), MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), + MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c), MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60), diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index ae2b3e6a1..891617ee1 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -50,7 +50,6 @@ struct fmi int io; int curvol; /* 1 or 0 */ unsigned long curfreq; /* freq in kHz */ - __u32 flags; struct mutex lock; }; @@ -58,7 +57,7 @@ static struct fmi fmi_card; static struct pnp_dev *dev; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ -/* It is only useful to give freq in intervall of 800 (=0.05Mhz), +/* It is only useful to give freq in interval of 800 (=0.05Mhz), * other bits will be truncated, e.g 92.7400016 -> 92.7, but * 92.7400017 -> 92.75 */ @@ -143,7 +142,6 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - int mult; struct fmi *fmi = video_drvdata(file); if (v->index > 0) @@ -151,11 +149,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ / mult; - v->rangehigh = RSF16_MAXFREQ / mult; - v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; - v->capability = fmi->flags & V4L2_TUNER_CAP_LOW; + v->rangelow = RSF16_MINFREQ; + v->rangehigh = RSF16_MAXFREQ; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = fmi_getsigstr(fmi); return 0; @@ -172,8 +169,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct fmi *fmi = video_drvdata(file); - if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) - f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || f->frequency > RSF16_MAXFREQ) return -EINVAL; @@ -190,8 +185,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = V4L2_TUNER_RADIO; f->frequency = fmi->curfreq; - if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) - f->frequency /= 1000; return 0; } @@ -348,7 +341,6 @@ static int __init fmi_init(void) return res; } - fmi->flags = V4L2_TUNER_CAP_LOW; strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name)); fmi->vdev.v4l2_dev = v4l2_dev; fmi->vdev.fops = &fmi_fops; diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index bb92b329c..df8c10a50 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -62,13 +62,12 @@ struct fmr2 int stereo; /* card is producing stereo audio */ unsigned long curfreq; /* freq in kHz */ int card_type; - u32 flags; }; static struct fmr2 fmr2_card; /* hw precision is 12.5 kHz - * It is only useful to give freq in intervall of 200 (=0.0125Mhz), + * It is only useful to give freq in interval of 200 (=0.0125Mhz), * other bits will be truncated */ #define RSF16_ENCODE(x) ((x) / 200 + 856) @@ -222,7 +221,6 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - int mult; struct fmr2 *fmr2 = video_drvdata(file); if (v->index > 0) @@ -231,13 +229,12 @@ static int vidioc_g_tuner(struct file *file, void *priv, strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ / mult; - v->rangehigh = RSF16_MAXFREQ / mult; - v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; - v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; - v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: - V4L2_TUNER_MODE_MONO; + v->rangelow = RSF16_MINFREQ; + v->rangehigh = RSF16_MAXFREQ; + v->rxsubchans = fmr2->stereo ? V4L2_TUNER_SUB_STEREO : + V4L2_TUNER_SUB_MONO; + v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW; + v->audmode = V4L2_TUNER_MODE_STEREO; mutex_lock(&fmr2->lock); v->signal = fmr2_getsigstr(fmr2); mutex_unlock(&fmr2->lock); @@ -255,8 +252,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct fmr2 *fmr2 = video_drvdata(file); - if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) - f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || f->frequency > RSF16_MAXFREQ) return -EINVAL; @@ -280,8 +275,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = V4L2_TUNER_RADIO; f->frequency = fmr2->curfreq; - if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) - f->frequency /= 1000; return 0; } @@ -407,7 +400,6 @@ static int __init fmr2_init(void) strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name)); fmr2->io = io; fmr2->stereo = 1; - fmr2->flags = V4L2_TUNER_CAP_LOW; mutex_init(&fmr2->lock); if (!request_region(fmr2->io, 2, "sf16fmr2")) { diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index b4d6641b4..101ede1cf 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1201,7 +1201,7 @@ static int si470x_fops_release(struct file *file) video_unregister_device(radio->videodev); kfree(radio->buffer); kfree(radio); - goto unlock; + goto done; } /* stop rds reception */ @@ -1215,7 +1215,6 @@ static int si470x_fops_release(struct file *file) usb_autopm_put_interface(radio->intf); } -unlock: mutex_unlock(&radio->disconnect_lock); done: diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 9d48da2fb..8de867d30 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -440,6 +440,24 @@ config VIDEO_ADV7175 To compile this driver as a module, choose M here: the module will be called adv7175. +config VIDEO_THS7303 + tristate "THS7303 Video Amplifier" + depends on I2C + help + Support for TI THS7303 video amplifier + + To compile this driver as a module, choose M here: the + module will be called ths7303. + +config VIDEO_ADV7343 + tristate "ADV7343 video encoder" + depends on I2C + help + Support for Analog Devices I2C bus based ADV7343 encoder. + + To compile this driver as a module, choose M here: the + module will be called adv7343. + comment "Video improvement chips" config VIDEO_UPD64031A @@ -694,7 +712,7 @@ config VIDEO_CAFE_CCIC config SOC_CAMERA tristate "SoC camera support" - depends on VIDEO_V4L2 && HAS_DMA + depends on VIDEO_V4L2 && HAS_DMA && I2C select VIDEOBUF_GEN help SoC Camera is a common API to several cameras, not connecting diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 3f1a0350a..f7d9a4c6f 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -49,11 +49,13 @@ obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o +obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o obj-$(CONFIG_VIDEO_BT819) += bt819.o obj-$(CONFIG_VIDEO_BT856) += bt856.o obj-$(CONFIG_VIDEO_BT866) += bt866.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o +obj-$(CONFIG_VIDEO_THS7303) += ths7303.o obj-$(CONFIG_VIDEO_ZORAN) += zoran/ @@ -134,10 +136,6 @@ obj-$(CONFIG_VIDEO_CX18) += cx18/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ -obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o -obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o -obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o -obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o @@ -147,6 +145,11 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o +# soc-camera host drivers have to be linked after camera drivers +obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o +obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o +obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o +obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_AU0828) += au0828/ diff --git a/linux/drivers/media/video/adv7343.c b/linux/drivers/media/video/adv7343.c new file mode 100644 index 000000000..30f5caf5d --- /dev/null +++ b/linux/drivers/media/video/adv7343.c @@ -0,0 +1,534 @@ +/* + * adv7343 - ADV7343 Video Encoder Driver + * + * The encoder hardware does not support SECAM. + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/ctype.h> +#include <linux/i2c.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/videodev2.h> +#include <linux/uaccess.h> +#include <linux/version.h> + +#include <media/adv7343.h> +#include <media/v4l2-device.h> +#include <media/v4l2-chip-ident.h> + +#include "adv7343_regs.h" + +MODULE_DESCRIPTION("ADV7343 video encoder driver"); +MODULE_LICENSE("GPL"); + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level 0-1"); + +struct adv7343_state { + struct v4l2_subdev sd; + u8 reg00; + u8 reg01; + u8 reg02; + u8 reg35; + u8 reg80; + u8 reg82; + int bright; + int hue; + int gain; + u32 output; + v4l2_std_id std; +}; + +static inline struct adv7343_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct adv7343_state, sd); +} + +static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_write_byte_data(client, reg, value); +} + +static const u8 adv7343_init_reg_val[] = { + ADV7343_SOFT_RESET, ADV7343_SOFT_RESET_DEFAULT, + ADV7343_POWER_MODE_REG, ADV7343_POWER_MODE_REG_DEFAULT, + + ADV7343_HD_MODE_REG1, ADV7343_HD_MODE_REG1_DEFAULT, + ADV7343_HD_MODE_REG2, ADV7343_HD_MODE_REG2_DEFAULT, + ADV7343_HD_MODE_REG3, ADV7343_HD_MODE_REG3_DEFAULT, + ADV7343_HD_MODE_REG4, ADV7343_HD_MODE_REG4_DEFAULT, + ADV7343_HD_MODE_REG5, ADV7343_HD_MODE_REG5_DEFAULT, + ADV7343_HD_MODE_REG6, ADV7343_HD_MODE_REG6_DEFAULT, + ADV7343_HD_MODE_REG7, ADV7343_HD_MODE_REG7_DEFAULT, + + ADV7343_SD_MODE_REG1, ADV7343_SD_MODE_REG1_DEFAULT, + ADV7343_SD_MODE_REG2, ADV7343_SD_MODE_REG2_DEFAULT, + ADV7343_SD_MODE_REG3, ADV7343_SD_MODE_REG3_DEFAULT, + ADV7343_SD_MODE_REG4, ADV7343_SD_MODE_REG4_DEFAULT, + ADV7343_SD_MODE_REG5, ADV7343_SD_MODE_REG5_DEFAULT, + ADV7343_SD_MODE_REG6, ADV7343_SD_MODE_REG6_DEFAULT, + ADV7343_SD_MODE_REG7, ADV7343_SD_MODE_REG7_DEFAULT, + ADV7343_SD_MODE_REG8, ADV7343_SD_MODE_REG8_DEFAULT, + + ADV7343_SD_HUE_REG, ADV7343_SD_HUE_REG_DEFAULT, + ADV7343_SD_CGMS_WSS0, ADV7343_SD_CGMS_WSS0_DEFAULT, + ADV7343_SD_BRIGHTNESS_WSS, ADV7343_SD_BRIGHTNESS_WSS_DEFAULT, +}; + +/* + * 2^32 + * FSC(reg) = FSC (HZ) * -------- + * 27000000 + */ +static const struct adv7343_std_info stdinfo[] = { + { + /* FSC(Hz) = 3,579,545.45 Hz */ + SD_STD_NTSC, 569408542, V4L2_STD_NTSC, + }, { + /* FSC(Hz) = 3,575,611.00 Hz */ + SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M, + }, { + /* FSC(Hz) = 3,582,056.00 */ + SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60, + }, +}; + +static int adv7343_setstd(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct adv7343_state *state = to_state(sd); + struct adv7343_std_info *std_info; + int output_idx, num_std; + char *fsc_ptr; + u8 reg, val; + int err = 0; + int i = 0; + + output_idx = state->output; + + std_info = (struct adv7343_std_info *)stdinfo; + num_std = ARRAY_SIZE(stdinfo); + + for (i = 0; i < num_std; i++) { + if (std_info[i].stdid & std) + break; + } + + if (i == num_std) { + v4l2_dbg(1, debug, sd, + "Invalid std or std is not supported: %llx\n", + (unsigned long long)std); + return -EINVAL; + } + + /* Set the standard */ + val = state->reg80 & (~(SD_STD_MASK)); + val |= std_info[i].standard_val3; + err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val); + if (err < 0) + goto setstd_exit; + + state->reg80 = val; + + /* Configure the input mode register */ + val = state->reg01 & (~((u8) INPUT_MODE_MASK)); + val |= SD_INPUT_MODE; + err = adv7343_write(sd, ADV7343_MODE_SELECT_REG, val); + if (err < 0) + goto setstd_exit; + + state->reg01 = val; + + /* Program the sub carrier frequency registers */ + fsc_ptr = (unsigned char *)&std_info[i].fsc_val; + reg = ADV7343_FSC_REG0; + for (i = 0; i < 4; i++, reg++, fsc_ptr++) { + err = adv7343_write(sd, reg, *fsc_ptr); + if (err < 0) + goto setstd_exit; + } + + val = state->reg80; + + /* Filter settings */ + if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443)) + val &= 0x03; + else if (std & ~V4L2_STD_SECAM) + val |= 0x04; + + err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val); + if (err < 0) + goto setstd_exit; + + state->reg80 = val; + +setstd_exit: + if (err != 0) + v4l2_err(sd, "Error setting std, write failed\n"); + + return err; +} + +static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type) +{ + struct adv7343_state *state = to_state(sd); + unsigned char val; + int err = 0; + + if (output_type > ADV7343_SVIDEO_ID) { + v4l2_dbg(1, debug, sd, + "Invalid output type or output type not supported:%d\n", + output_type); + return -EINVAL; + } + + /* Enable Appropriate DAC */ + val = state->reg00 & 0x03; + + if (output_type == ADV7343_COMPOSITE_ID) + val |= ADV7343_COMPOSITE_POWER_VALUE; + else if (output_type == ADV7343_COMPONENT_ID) + val |= ADV7343_COMPONENT_POWER_VALUE; + else + val |= ADV7343_SVIDEO_POWER_VALUE; + + err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val); + if (err < 0) + goto setoutput_exit; + + state->reg00 = val; + + /* Enable YUV output */ + val = state->reg02 | YUV_OUTPUT_SELECT; + err = adv7343_write(sd, ADV7343_MODE_REG0, val); + if (err < 0) + goto setoutput_exit; + + state->reg02 = val; + + /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */ + val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI); + err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val); + if (err < 0) + goto setoutput_exit; + + state->reg82 = val; + + /* configure ED/HD Color DAC Swap and ED/HD RGB Input Enable bit to + * zero */ + val = state->reg35 & (HD_RGB_INPUT_DI & HD_DAC_SWAP_DI); + err = adv7343_write(sd, ADV7343_HD_MODE_REG6, val); + if (err < 0) + goto setoutput_exit; + + state->reg35 = val; + +setoutput_exit: + if (err != 0) + v4l2_err(sd, "Error setting output, write failed\n"); + + return err; +} + +static int adv7343_log_status(struct v4l2_subdev *sd) +{ + struct adv7343_state *state = to_state(sd); + + v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std); + v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" : + ((state->output == 1) ? "Component" : "S-Video")); + return 0; +} + +static int adv7343_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, ADV7343_BRIGHTNESS_MIN, + ADV7343_BRIGHTNESS_MAX, 1, + ADV7343_BRIGHTNESS_DEF); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, ADV7343_HUE_MIN, + ADV7343_HUE_MAX, 1 , + ADV7343_HUE_DEF); + case V4L2_CID_GAIN: + return v4l2_ctrl_query_fill(qc, ADV7343_GAIN_MIN, + ADV7343_GAIN_MAX, 1, + ADV7343_GAIN_DEF); + default: + break; + } + + return 0; +} + +static int adv7343_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct adv7343_state *state = to_state(sd); + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value < ADV7343_BRIGHTNESS_MIN || + ctrl->value > ADV7343_BRIGHTNESS_MAX) { + v4l2_dbg(1, debug, sd, + "invalid brightness settings %d\n", + ctrl->value); + return -ERANGE; + } + + state->bright = ctrl->value; + err = adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS, + state->bright); + break; + + case V4L2_CID_HUE: + if (ctrl->value < ADV7343_HUE_MIN || + ctrl->value > ADV7343_HUE_MAX) { + v4l2_dbg(1, debug, sd, "invalid hue settings %d\n", + ctrl->value); + return -ERANGE; + } + + state->hue = ctrl->value; + err = adv7343_write(sd, ADV7343_SD_HUE_REG, state->hue); + break; + + case V4L2_CID_GAIN: + if (ctrl->value < ADV7343_GAIN_MIN || + ctrl->value > ADV7343_GAIN_MAX) { + v4l2_dbg(1, debug, sd, "invalid gain settings %d\n", + ctrl->value); + return -ERANGE; + } + + if ((ctrl->value > POSITIVE_GAIN_MAX) && + (ctrl->value < NEGATIVE_GAIN_MIN)) { + v4l2_dbg(1, debug, sd, + "gain settings not within the specified range\n"); + return -ERANGE; + } + + state->gain = ctrl->value; + err = adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, state->gain); + break; + + default: + return -EINVAL; + } + + if (err < 0) + v4l2_err(sd, "Failed to set the encoder controls\n"); + + return err; +} + +static int adv7343_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct adv7343_state *state = to_state(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = state->bright; + break; + + case V4L2_CID_HUE: + ctrl->value = state->hue; + break; + + case V4L2_CID_GAIN: + ctrl->value = state->gain; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int adv7343_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_ADV7343, 0); +} + +static const struct v4l2_subdev_core_ops adv7343_core_ops = { + .log_status = adv7343_log_status, + .g_chip_ident = adv7343_g_chip_ident, + .g_ctrl = adv7343_g_ctrl, + .s_ctrl = adv7343_s_ctrl, + .queryctrl = adv7343_queryctrl, +}; + +static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct adv7343_state *state = to_state(sd); + int err = 0; + + if (state->std == std) + return 0; + + err = adv7343_setstd(sd, std); + if (!err) + state->std = std; + + return err; +} + +static int adv7343_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) +{ + struct adv7343_state *state = to_state(sd); + int err = 0; + + if (state->output == output) + return 0; + + err = adv7343_setoutput(sd, output); + if (!err) + state->output = output; + + return err; +} + +static const struct v4l2_subdev_video_ops adv7343_video_ops = { + .s_std_output = adv7343_s_std_output, + .s_routing = adv7343_s_routing, +}; + +static const struct v4l2_subdev_ops adv7343_ops = { + .core = &adv7343_core_ops, + .video = &adv7343_video_ops, +}; + +static int adv7343_initialize(struct v4l2_subdev *sd) +{ + struct adv7343_state *state = to_state(sd); + int err = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(adv7343_init_reg_val); i += 2) { + + err = adv7343_write(sd, adv7343_init_reg_val[i], + adv7343_init_reg_val[i+1]); + if (err) { + v4l2_err(sd, "Error initializing\n"); + return err; + } + } + + /* Configure for default video standard */ + err = adv7343_setoutput(sd, state->output); + if (err < 0) { + v4l2_err(sd, "Error setting output during init\n"); + return -EINVAL; + } + + err = adv7343_setstd(sd, state->std); + if (err < 0) { + v4l2_err(sd, "Error setting std during init\n"); + return -EINVAL; + } + + return err; +} + +static int adv7343_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adv7343_state *state; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + + state = kzalloc(sizeof(struct adv7343_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + + state->reg00 = 0x80; + state->reg01 = 0x00; + state->reg02 = 0x20; + state->reg35 = 0x00; + state->reg80 = ADV7343_SD_MODE_REG1_DEFAULT; + state->reg82 = ADV7343_SD_MODE_REG2_DEFAULT; + + state->output = ADV7343_COMPOSITE_ID; + state->std = V4L2_STD_NTSC; + + v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops); + return adv7343_initialize(&state->sd); +} + +static int adv7343_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 adv7343_id[] = { + {"adv7343", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, adv7343_id); + +static struct i2c_driver adv7343_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "adv7343", + }, + .probe = adv7343_probe, + .remove = adv7343_remove, + .id_table = adv7343_id, +}; + +static __init int init_adv7343(void) +{ + return i2c_add_driver(&adv7343_driver); +} + +static __exit void exit_adv7343(void) +{ + i2c_del_driver(&adv7343_driver); +} + +module_init(init_adv7343); +module_exit(exit_adv7343); diff --git a/linux/drivers/media/video/adv7343_regs.h b/linux/drivers/media/video/adv7343_regs.h new file mode 100644 index 000000000..3431045b3 --- /dev/null +++ b/linux/drivers/media/video/adv7343_regs.h @@ -0,0 +1,185 @@ +/* + * ADV7343 encoder related structure and register definitions + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef ADV7343_REG_H +#define ADV7343_REGS_H + +struct adv7343_std_info { + u32 standard_val3; + u32 fsc_val; + v4l2_std_id stdid; +}; + +/* Register offset macros */ +#define ADV7343_POWER_MODE_REG (0x00) +#define ADV7343_MODE_SELECT_REG (0x01) +#define ADV7343_MODE_REG0 (0x02) + +#define ADV7343_DAC2_OUTPUT_LEVEL (0x0b) + +#define ADV7343_SOFT_RESET (0x17) + +#define ADV7343_HD_MODE_REG1 (0x30) +#define ADV7343_HD_MODE_REG2 (0x31) +#define ADV7343_HD_MODE_REG3 (0x32) +#define ADV7343_HD_MODE_REG4 (0x33) +#define ADV7343_HD_MODE_REG5 (0x34) +#define ADV7343_HD_MODE_REG6 (0x35) + +#define ADV7343_HD_MODE_REG7 (0x39) + +#define ADV7343_SD_MODE_REG1 (0x80) +#define ADV7343_SD_MODE_REG2 (0x82) +#define ADV7343_SD_MODE_REG3 (0x83) +#define ADV7343_SD_MODE_REG4 (0x84) +#define ADV7343_SD_MODE_REG5 (0x86) +#define ADV7343_SD_MODE_REG6 (0x87) +#define ADV7343_SD_MODE_REG7 (0x88) +#define ADV7343_SD_MODE_REG8 (0x89) + +#define ADV7343_FSC_REG0 (0x8C) +#define ADV7343_FSC_REG1 (0x8D) +#define ADV7343_FSC_REG2 (0x8E) +#define ADV7343_FSC_REG3 (0x8F) + +#define ADV7343_SD_CGMS_WSS0 (0x99) + +#define ADV7343_SD_HUE_REG (0xA0) +#define ADV7343_SD_BRIGHTNESS_WSS (0xA1) + +/* Default values for the registers */ +#define ADV7343_POWER_MODE_REG_DEFAULT (0x10) +#define ADV7343_HD_MODE_REG1_DEFAULT (0x3C) /* Changed Default + 720p EAVSAV code*/ +#define ADV7343_HD_MODE_REG2_DEFAULT (0x01) /* Changed Pixel data + valid */ +#define ADV7343_HD_MODE_REG3_DEFAULT (0x00) /* Color delay 0 clks */ +#define ADV7343_HD_MODE_REG4_DEFAULT (0xE8) /* Changed */ +#define ADV7343_HD_MODE_REG5_DEFAULT (0x08) +#define ADV7343_HD_MODE_REG6_DEFAULT (0x00) +#define ADV7343_HD_MODE_REG7_DEFAULT (0x00) +#define ADV7343_SD_MODE_REG8_DEFAULT (0x00) +#define ADV7343_SOFT_RESET_DEFAULT (0x02) +#define ADV7343_COMPOSITE_POWER_VALUE (0x80) +#define ADV7343_COMPONENT_POWER_VALUE (0x1C) +#define ADV7343_SVIDEO_POWER_VALUE (0x60) +#define ADV7343_SD_HUE_REG_DEFAULT (127) +#define ADV7343_SD_BRIGHTNESS_WSS_DEFAULT (0x03) + +#define ADV7343_SD_CGMS_WSS0_DEFAULT (0x10) + +#define ADV7343_SD_MODE_REG1_DEFAULT (0x00) +#define ADV7343_SD_MODE_REG2_DEFAULT (0xC9) +#define ADV7343_SD_MODE_REG3_DEFAULT (0x10) +#define ADV7343_SD_MODE_REG4_DEFAULT (0x01) +#define ADV7343_SD_MODE_REG5_DEFAULT (0x02) +#define ADV7343_SD_MODE_REG6_DEFAULT (0x0C) +#define ADV7343_SD_MODE_REG7_DEFAULT (0x04) +#define ADV7343_SD_MODE_REG8_DEFAULT (0x00) + +/* Bit masks for Mode Select Register */ +#define INPUT_MODE_MASK (0x70) +#define SD_INPUT_MODE (0x00) +#define HD_720P_INPUT_MODE (0x10) +#define HD_1080I_INPUT_MODE (0x10) + +/* Bit masks for Mode Register 0 */ +#define TEST_PATTERN_BLACK_BAR_EN (0x04) +#define YUV_OUTPUT_SELECT (0x20) +#define RGB_OUTPUT_SELECT (0xDF) + +/* Bit masks for DAC output levels */ +#define DAC_OUTPUT_LEVEL_MASK (0xFF) +#define POSITIVE_GAIN_MAX (0x40) +#define POSITIVE_GAIN_MIN (0x00) +#define NEGATIVE_GAIN_MAX (0xFF) +#define NEGATIVE_GAIN_MIN (0xC0) + +/* Bit masks for soft reset register */ +#define SOFT_RESET (0x02) + +/* Bit masks for HD Mode Register 1 */ +#define OUTPUT_STD_MASK (0x03) +#define OUTPUT_STD_SHIFT (0) +#define OUTPUT_STD_EIA0_2 (0x00) +#define OUTPUT_STD_EIA0_1 (0x01) +#define OUTPUT_STD_FULL (0x02) +#define EMBEDDED_SYNC (0x04) +#define EXTERNAL_SYNC (0xFB) +#define STD_MODE_SHIFT (3) +#define STD_MODE_MASK (0x1F) +#define STD_MODE_720P (0x05) +#define STD_MODE_720P_25 (0x08) +#define STD_MODE_720P_30 (0x07) +#define STD_MODE_720P_50 (0x06) +#define STD_MODE_1080I (0x0D) +#define STD_MODE_1080I_25fps (0x0E) +#define STD_MODE_1080P_24 (0x12) +#define STD_MODE_1080P_25 (0x10) +#define STD_MODE_1080P_30 (0x0F) +#define STD_MODE_525P (0x00) +#define STD_MODE_625P (0x03) + +/* Bit masks for SD Mode Register 1 */ +#define SD_STD_MASK (0x03) +#define SD_STD_NTSC (0x00) +#define SD_STD_PAL_BDGHI (0x01) +#define SD_STD_PAL_M (0x02) +#define SD_STD_PAL_N (0x03) +#define SD_LUMA_FLTR_MASK (0x7) +#define SD_LUMA_FLTR_SHIFT (0x2) +#define SD_CHROMA_FLTR_MASK (0x7) +#define SD_CHROMA_FLTR_SHIFT (0x5) + +/* Bit masks for SD Mode Register 2 */ +#define SD_PBPR_SSAF_EN (0x01) +#define SD_PBPR_SSAF_DI (0xFE) +#define SD_DAC_1_DI (0xFD) +#define SD_DAC_2_DI (0xFB) +#define SD_PEDESTAL_EN (0x08) +#define SD_PEDESTAL_DI (0xF7) +#define SD_SQUARE_PIXEL_EN (0x10) +#define SD_SQUARE_PIXEL_DI (0xEF) +#define SD_PIXEL_DATA_VALID (0x40) +#define SD_ACTIVE_EDGE_EN (0x80) +#define SD_ACTIVE_EDGE_DI (0x7F) + +/* Bit masks for HD Mode Register 6 */ +#define HD_RGB_INPUT_EN (0x02) +#define HD_RGB_INPUT_DI (0xFD) +#define HD_PBPR_SYNC_EN (0x04) +#define HD_PBPR_SYNC_DI (0xFB) +#define HD_DAC_SWAP_EN (0x08) +#define HD_DAC_SWAP_DI (0xF7) +#define HD_GAMMA_CURVE_A (0xEF) +#define HD_GAMMA_CURVE_B (0x10) +#define HD_GAMMA_EN (0x20) +#define HD_GAMMA_DI (0xDF) +#define HD_ADPT_FLTR_MODEB (0x40) +#define HD_ADPT_FLTR_MODEA (0xBF) +#define HD_ADPT_FLTR_EN (0x80) +#define HD_ADPT_FLTR_DI (0x7F) + +#define ADV7343_BRIGHTNESS_MAX (127) +#define ADV7343_BRIGHTNESS_MIN (0) +#define ADV7343_BRIGHTNESS_DEF (3) +#define ADV7343_HUE_MAX (255) +#define ADV7343_HUE_MIN (0) +#define ADV7343_HUE_DEF (127) +#define ADV7343_GAIN_MAX (255) +#define ADV7343_GAIN_MIN (0) +#define ADV7343_GAIN_DEF (0) + +#endif diff --git a/linux/drivers/media/video/au0828/au0828-cards.c b/linux/drivers/media/video/au0828/au0828-cards.c index 053bbe8c8..830c4a933 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -136,9 +136,9 @@ int au0828_tuner_callback(void *priv, int component, int command, int arg) /* Tuner Reset Command from xc5000 */ /* Drive the tuner into reset and out */ au0828_clear(dev, REG_001, 2); - mdelay(200); + mdelay(10); au0828_set(dev, REG_001, 2); - mdelay(50); + mdelay(10); return 0; } else { printk(KERN_ERR diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index ab25af430..4da5b7909 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -193,8 +193,6 @@ static int au0828_usb_probe(struct usb_interface *interface, dev->usbdev = usbdev; dev->boardnr = id->driver_info; - usb_set_intfdata(interface, dev); - /* Create the v4l2_device */ retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval) { @@ -223,6 +221,10 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Digital TV */ au0828_dvb_register(dev); + /* Store the pointer to the au0828_dev so it can be accessed in + au0828_usb_disconnect */ + usb_set_intfdata(interface, dev); + printk(KERN_INFO "Registered device AU0828 [%s]\n", dev->board.name == NULL ? "Unset" : dev->board.name); diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index 8bc0f0481..ef44aa831 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -834,6 +834,9 @@ 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); + /* When close the device, set the usb intf0 into alt0 to free USB bandwidth */ ret = usb_set_interface(dev->usbdev, 0, 0); @@ -915,11 +918,6 @@ static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - dprintk(2, "vma start=0x%08lx, size=%ld, ret=%d\n", - (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, - rc); - return rc; } diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 40eb073fb..4b8ecad1b 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -775,6 +775,7 @@ static int cafe_cam_init(struct cafe_camera *cam) ret = __cafe_cam_reset(cam); if (ret) goto out; + chip.ident = V4L2_IDENT_NONE; chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; chip.match.addr = cam->sensor_addr; ret = sensor_call(cam, core, g_chip_ident, &chip); diff --git a/linux/drivers/media/video/cpia2/cpia2_v4l.c b/linux/drivers/media/video/cpia2/cpia2_v4l.c index d4099f531..0b4a8f309 100644 --- a/linux/drivers/media/video/cpia2/cpia2_v4l.c +++ b/linux/drivers/media/video/cpia2/cpia2_v4l.c @@ -1064,7 +1064,7 @@ static int ioctl_querymenu(void *arg,struct camera_data *cam) switch(m->id) { case CPIA2_CID_FLICKER_MODE: - if(m->index < 0 || m->index >= NUM_FLICKER_CONTROLS) + if (m->index >= NUM_FLICKER_CONTROLS) return -EINVAL; strcpy(m->name, flicker_controls[m->index].name); @@ -1082,14 +1082,14 @@ static int ioctl_querymenu(void *arg,struct camera_data *cam) maximum = i; } } - if(m->index < 0 || m->index > maximum) + if (m->index > maximum) return -EINVAL; strcpy(m->name, framerate_controls[m->index].name); break; } case CPIA2_CID_LIGHTS: - if(m->index < 0 || m->index >= NUM_LIGHTS_CONTROLS) + if (m->index >= NUM_LIGHTS_CONTROLS) return -EINVAL; strcpy(m->name, lights_controls[m->index].name); diff --git a/linux/drivers/media/video/cx18/cx18-audio.c b/linux/drivers/media/video/cx18/cx18-audio.c index 7a8ad5963..352689239 100644 --- a/linux/drivers/media/video/cx18/cx18-audio.c +++ b/linux/drivers/media/video/cx18/cx18-audio.c @@ -26,14 +26,18 @@ #include "cx18-cards.h" #include "cx18-audio.h" -#define CX18_AUDIO_ENABLE 0xc72014 +#define CX18_AUDIO_ENABLE 0xc72014 +#define CX18_AI1_MUX_MASK 0x30 +#define CX18_AI1_MUX_I2S1 0x00 +#define CX18_AI1_MUX_I2S2 0x10 +#define CX18_AI1_MUX_843_I2S 0x20 /* Selects the audio input and output according to the current settings. */ int cx18_audio_set_io(struct cx18 *cx) { const struct cx18_card_audio_input *in; - u32 val; + u32 u, v; int err; /* Determine which input to use */ @@ -52,9 +56,37 @@ int cx18_audio_set_io(struct cx18 *cx) return err; /* FIXME - this internal mux should be abstracted to a subdev */ - val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30; - val |= (in->audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : - (in->audio_input << 4); - cx18_write_reg_expect(cx, val | 0xb00, CX18_AUDIO_ENABLE, val, 0x30); + u = cx18_read_reg(cx, CX18_AUDIO_ENABLE); + v = u & ~CX18_AI1_MUX_MASK; + switch (in->audio_input) { + case CX18_AV_AUDIO_SERIAL1: + v |= CX18_AI1_MUX_I2S1; + break; + case CX18_AV_AUDIO_SERIAL2: + v |= CX18_AI1_MUX_I2S2; + break; + default: + v |= CX18_AI1_MUX_843_I2S; + break; + } + if (v == u) { + /* force a toggle of some AI1 MUX control bits */ + u &= ~CX18_AI1_MUX_MASK; + switch (in->audio_input) { + case CX18_AV_AUDIO_SERIAL1: + u |= CX18_AI1_MUX_843_I2S; + break; + case CX18_AV_AUDIO_SERIAL2: + u |= CX18_AI1_MUX_843_I2S; + break; + default: + u |= CX18_AI1_MUX_I2S1; + break; + } + cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE, + u, CX18_AI1_MUX_MASK); + } + cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, + v, CX18_AI1_MUX_MASK); return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index cf2bd888a..2b07b1563 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -99,9 +99,39 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask, or_value); } -static void cx18_av_initialize(struct cx18 *cx) +static int cx18_av_init(struct v4l2_subdev *sd, u32 val) { - struct cx18_av_state *state = &cx->av_state; + struct cx18 *cx = v4l2_get_subdevdata(sd); + + /* + * The crystal freq used in calculations in this driver will be + * 28.636360 MHz. + * Aim to run the PLLs' VCOs near 400 MHz to minimze errors. + */ + + /* + * VDCLK Integer = 0x0f, Post Divider = 0x04 + * AIMCLK Integer = 0x0e, Post Divider = 0x16 + */ + cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); + + /* VDCLK Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ + cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); + + /* AIMCLK Fraction = 0x05227ad */ + /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/ + cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); + + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ + cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); + return 0; +} + +static void cx18_av_initialize(struct v4l2_subdev *sd) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); u32 v; cx18_av_loadfw(cx); @@ -150,6 +180,26 @@ static void cx18_av_initialize(struct cx18 *cx) cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000); cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0); + /* + * Disable Video Auto-config of the Analog Front End and Video PLL. + * + * Since we only use BT.656 pixel mode, which works for both 525 and 625 + * line systems, it's just easier for us to set registers + * 0x102 (CXADEC_CHIP_CTRL), 0x104-0x106 (CXADEC_AFE_CTRL), + * 0x108-0x109 (CXADEC_PLL_CTRL1), and 0x10c-0x10f (CXADEC_VID_PLL_FRAC) + * ourselves, than to run around cleaning up after the auto-config. + * + * (Note: my CX23418 chip doesn't seem to let the ACFG_DIS bit + * get set to 1, but OTOH, it doesn't seem to do AFE and VID PLL + * autoconfig either.) + * + * As a default, also turn off Dual mode for ADC2 and set ADC2 to CH3. + */ + cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000); + + /* Setup the Video and and Aux/Audio PLLs */ + cx18_av_init(sd, 0); + /* set video to auto-detect */ /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */ /* set the comb notch = 1 */ @@ -176,12 +226,23 @@ static void cx18_av_initialize(struct cx18 *cx) /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */ /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */ - v = cx18_av_read4(cx, CXADEC_AFE_CTRL); - v &= 0xFFFBFFFF; /* turn OFF bit 18 for droop_comp_ch1 */ - v &= 0xFFFF7FFF; /* turn OFF bit 9 for clamp_sel_ch1 */ - v &= 0xFFFFFFFE; /* turn OFF bit 0 for 12db_ch1 */ - /* v |= 0x00000001;*/ /* turn ON bit 0 for 12db_ch1 */ - cx18_av_write4(cx, CXADEC_AFE_CTRL, v); + /* + * Analog Front End (AFE) + * Default to luma on ch1/ADC1, chroma on ch2/ADC2, SIF on ch3/ADC2 + * bypass_ch[1-3] use filter + * droop_comp_ch[1-3] disable + * clamp_en_ch[1-3] disable + * aud_in_sel ADC2 + * luma_in_sel ADC1 + * chroma_in_sel ADC2 + * clamp_sel_ch[2-3] midcode + * clamp_sel_ch1 video decoder + * vga_sel_ch3 audio decoder + * vga_sel_ch[1-2] video decoder + * half_bw_ch[1-3] disable + * +12db_ch[1-3] disable + */ + cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00); /* if(dwEnable && dw3DCombAvailable) { */ /* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */ @@ -195,50 +256,18 @@ static void cx18_av_initialize(struct cx18 *cx) static int cx18_av_reset(struct v4l2_subdev *sd, u32 val) { - struct cx18 *cx = v4l2_get_subdevdata(sd); - - cx18_av_initialize(cx); - return 0; -} - -static int cx18_av_init(struct v4l2_subdev *sd, u32 val) -{ - struct cx18 *cx = v4l2_get_subdevdata(sd); - - /* - * The crystal freq used in calculations in this driver will be - * 28.636360 MHz. - * Aim to run the PLLs' VCOs near 400 MHz to minimze errors. - */ - - /* - * VDCLK Integer = 0x0f, Post Divider = 0x04 - * AIMCLK Integer = 0x0e, Post Divider = 0x16 - */ - cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); - - /* VDCLK Fraction = 0x2be2fe */ - /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ - cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); - - /* AIMCLK Fraction = 0x05227ad */ - /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/ - cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); - - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ - cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); + cx18_av_initialize(sd); return 0; } static int cx18_av_load_fw(struct v4l2_subdev *sd) { struct cx18_av_state *state = to_cx18_av_state(sd); - struct cx18 *cx = v4l2_get_subdevdata(sd); if (!state->is_initialized) { /* initialize on first use */ state->is_initialized = 1; - cx18_av_initialize(cx); + cx18_av_initialize(sd); } return 0; } @@ -470,16 +499,23 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, { struct cx18_av_state *state = &cx->av_state; struct v4l2_subdev *sd = &state->sd; - u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 && - vid_input <= CX18_AV_COMPOSITE8); - u8 reg; - u8 v; + + enum analog_signal_type { + NONE, CVBS, Y, C, SIF, Pb, Pr + } ch[3] = {NONE, NONE, NONE}; + + u8 afe_mux_cfg; + u8 adc2_cfg; + u32 afe_cfg; + int i; CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n", vid_input, aud_input); - if (is_composite) { - reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); + if (vid_input >= CX18_AV_COMPOSITE1 && + vid_input <= CX18_AV_COMPOSITE8) { + afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); + ch[0] = CVBS; } else { int luma = vid_input & 0xf0; int chroma = vid_input & 0xf00; @@ -493,26 +529,45 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, vid_input); return -EINVAL; } - reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4); + afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4); + ch[0] = Y; if (chroma >= CX18_AV_SVIDEO_CHROMA7) { - reg &= 0x3f; - reg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2; + afe_mux_cfg &= 0x3f; + afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2; + ch[2] = C; } else { - reg &= 0xcf; - reg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4; + afe_mux_cfg &= 0xcf; + afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4; + ch[1] = C; } } + /* TODO: LeadTek WinFast DVR3100 H & WinFast PVR2100 can do Y/Pb/Pr */ switch (aud_input) { case CX18_AV_AUDIO_SERIAL1: case CX18_AV_AUDIO_SERIAL2: /* do nothing, use serial audio input */ break; - case CX18_AV_AUDIO4: reg &= ~0x30; break; - case CX18_AV_AUDIO5: reg &= ~0x30; reg |= 0x10; break; - case CX18_AV_AUDIO6: reg &= ~0x30; reg |= 0x20; break; - case CX18_AV_AUDIO7: reg &= ~0xc0; break; - case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break; + case CX18_AV_AUDIO4: + afe_mux_cfg &= ~0x30; + ch[1] = SIF; + break; + case CX18_AV_AUDIO5: + afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10; + ch[1] = SIF; + break; + case CX18_AV_AUDIO6: + afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20; + ch[1] = SIF; + break; + case CX18_AV_AUDIO7: + afe_mux_cfg &= ~0xc0; + ch[2] = SIF; + break; + case CX18_AV_AUDIO8: + afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40; + ch[2] = SIF; + break; default: CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n", @@ -520,24 +575,65 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, return -EINVAL; } - cx18_av_write_expect(cx, 0x103, reg, reg, 0xf7); + /* Set up analog front end multiplexers */ + cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7); /* Set INPUT_MODE to Composite (0) or S-Video (1) */ - cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02); + cx18_av_and_or(cx, 0x401, ~0x6, ch[0] == CVBS ? 0 : 0x02); /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ - v = cx18_av_read(cx, 0x102); - if (reg & 0x80) - v &= ~0x2; + adc2_cfg = cx18_av_read(cx, 0x102); + if (ch[2] == NONE) + adc2_cfg &= ~0x2; /* No sig on CH3, set ADC2 to CH2 for input */ else - v |= 0x2; + adc2_cfg |= 0x2; /* Signal on CH3, set ADC2 to CH3 for input */ + /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ - if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30) - v |= 0x4; + if (ch[1] != NONE && ch[2] != NONE) + adc2_cfg |= 0x4; /* Set dual mode */ else - v &= ~0x4; - cx18_av_write_expect(cx, 0x102, v, v, 0x17); + adc2_cfg &= ~0x4; /* Clear dual mode */ + cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17); + + /* Configure the analog front end */ + afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL); + afe_cfg &= 0xff000000; + afe_cfg |= 0x00005000; /* CHROMA_IN, AUD_IN: ADC2; LUMA_IN: ADC1 */ + if (ch[1] != NONE && ch[2] != NONE) + afe_cfg |= 0x00000030; /* half_bw_ch[2-3] since in dual mode */ + + for (i = 0; i < 3; i++) { + switch (ch[i]) { + default: + case NONE: + /* CLAMP_SEL = Fixed to midcode clamp level */ + afe_cfg |= (0x00000200 << i); + break; + case CVBS: + case Y: + if (i > 0) + afe_cfg |= 0x00002000; /* LUMA_IN_SEL: ADC2 */ + break; + case C: + case Pb: + case Pr: + /* CLAMP_SEL = Fixed to midcode clamp level */ + afe_cfg |= (0x00000200 << i); + if (i == 0 && ch[i] == C) + afe_cfg &= ~0x00001000; /* CHROMA_IN_SEL ADC1 */ + break; + case SIF: + /* + * VGA_GAIN_SEL = Audio Decoder + * CLAMP_SEL = Fixed to midcode clamp level + */ + afe_cfg |= (0x00000240 << i); + if (i == 0) + afe_cfg &= ~0x00004000; /* AUD_IN_SEL ADC1 */ + break; + } + } - /*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/ + cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg); state->vid_input = vid_input; state->aud_input = aud_input; diff --git a/linux/drivers/media/video/cx18/cx18-av-firmware.c b/linux/drivers/media/video/cx18/cx18-av-firmware.c index 49a55cc8d..b9e8cc5d2 100644 --- a/linux/drivers/media/video/cx18/cx18-av-firmware.c +++ b/linux/drivers/media/video/cx18/cx18-av-firmware.c @@ -24,15 +24,63 @@ #include "cx18-io.h" #include <linux/firmware.h> -#define CX18_AUDIO_ENABLE 0xc72014 +#define CX18_AUDIO_ENABLE 0xc72014 +#define CX18_AI1_MUX_MASK 0x30 +#define CX18_AI1_MUX_I2S1 0x00 +#define CX18_AI1_MUX_I2S2 0x10 +#define CX18_AI1_MUX_843_I2S 0x20 +#define CX18_AI1_MUX_INVALID 0x30 + #define FWFILE "v4l-cx23418-dig.fw" +static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw) +{ + struct v4l2_subdev *sd = &cx->av_state.sd; + int ret = 0; + const u8 *data; + u32 size; + int addr; + u32 expected, dl_control; + + /* Ensure we put the 8051 in reset and enable firmware upload mode */ + dl_control = cx18_av_read4(cx, CXADEC_DL_CTL); + do { + dl_control &= 0x00ffffff; + dl_control |= 0x0f000000; + cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control); + dl_control = cx18_av_read4(cx, CXADEC_DL_CTL); + } while ((dl_control & 0xff000000) != 0x0f000000); + + /* Read and auto increment until at address 0x0000 */ + while (dl_control & 0x3fff) + dl_control = cx18_av_read4(cx, CXADEC_DL_CTL); + + data = fw->data; + size = fw->size; + for (addr = 0; addr < size; addr++) { + dl_control &= 0xffff3fff; /* ignore top 2 bits of address */ + expected = 0x0f000000 | ((u32)data[addr] << 16) | addr; + if (expected != dl_control) { + CX18_ERR_DEV(sd, "verification of %s firmware load " + "failed: expected %#010x got %#010x\n", + FWFILE, expected, dl_control); + ret = -EIO; + break; + } + dl_control = cx18_av_read4(cx, CXADEC_DL_CTL); + } + if (ret == 0) + CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n", + FWFILE, size); + return ret; +} + int cx18_av_loadfw(struct cx18 *cx) { struct v4l2_subdev *sd = &cx->av_state.sd; const struct firmware *fw = NULL; u32 size; - u32 v; + u32 u, v; const u8 *ptr; int i; int retries1 = 0; @@ -95,6 +143,12 @@ int cx18_av_loadfw(struct cx18 *cx) } cx18_av_write4_expect(cx, CXADEC_DL_CTL, + 0x03000000 | fw->size, 0x03000000, 0x13000000); + + CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size); + + if (cx18_av_verifyfw(cx, fw) == 0) + cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x13000000 | fw->size, 0x13000000, 0x13000000); /* Output to the 416 */ @@ -135,6 +189,28 @@ int cx18_av_loadfw(struct cx18 *cx) cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE, 0, 0x400); + /* Toggle the AI1 MUX */ + v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); + u = v & CX18_AI1_MUX_MASK; + v &= ~CX18_AI1_MUX_MASK; + if (u == CX18_AI1_MUX_843_I2S || u == CX18_AI1_MUX_INVALID) { + /* Switch to I2S1 */ + v |= CX18_AI1_MUX_I2S1; + cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, + v, CX18_AI1_MUX_MASK); + /* Switch back to the A/V decoder core I2S output */ + v = (v & ~CX18_AI1_MUX_MASK) | CX18_AI1_MUX_843_I2S; + } else { + /* Switch to the A/V decoder core I2S output */ + v |= CX18_AI1_MUX_843_I2S; + cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, + v, CX18_AI1_MUX_MASK); + /* Switch back to I2S1 or I2S2 */ + v = (v & ~CX18_AI1_MUX_MASK) | u; + } + cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, + v, CX18_AI1_MUX_MASK); + /* Enable WW auto audio standard detection */ v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); v |= 0xFF; /* Auto by default */ @@ -143,7 +219,5 @@ int cx18_av_loadfw(struct cx18 *cx) cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF); release_firmware(fw); - - CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size); return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index 82fc2f9d4..8e35c3aed 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -176,8 +176,10 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, return -EBUSY; if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV || - type != V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { - /* We don't do VBI insertion aside from IVTV format in a PS */ + !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS || + type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD || + type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) { + /* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */ cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE; CX18_DEBUG_INFO("disabled insertion of sliced VBI data into " "the MPEG stream\n"); diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 062129fb5..f42a97314 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -30,6 +30,7 @@ #include "cx18-irq.h" #include "cx18-gpio.h" #include "cx18-firmware.h" +#include "cx18-queue.h" #include "cx18-streams.h" #include "cx18-av-core.h" #include "cx18-scb.h" @@ -312,7 +313,7 @@ static void cx18_process_eeprom(struct cx18 *cx) CX18_INFO("Autodetected %s\n", cx->card_name); if (tv.tuner_type == TUNER_ABSENT) - CX18_ERR("tveeprom cannot autodetect tuner!"); + CX18_ERR("tveeprom cannot autodetect tuner!\n"); if (cx->options.tuner == -1) cx->options.tuner = tv.tuner_type; @@ -546,6 +547,45 @@ done: cx->card_i2c = cx->card->i2c; } +static int __devinit cx18_create_in_workq(struct cx18 *cx) +{ + snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in", + cx->v4l2_dev.name); + cx->in_work_queue = create_singlethread_workqueue(cx->in_workq_name); + if (cx->in_work_queue == NULL) { + CX18_ERR("Unable to create incoming mailbox handler thread\n"); + return -ENOMEM; + } + return 0; +} + +static int __devinit cx18_create_out_workq(struct cx18 *cx) +{ + snprintf(cx->out_workq_name, sizeof(cx->out_workq_name), "%s-out", + cx->v4l2_dev.name); + cx->out_work_queue = create_workqueue(cx->out_workq_name); + if (cx->out_work_queue == NULL) { + CX18_ERR("Unable to create outgoing mailbox handler threads\n"); + return -ENOMEM; + } + return 0; +} + +static void __devinit cx18_init_in_work_orders(struct cx18 *cx) +{ + int i; + for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) { + cx->in_work_order[i].cx = cx; + cx->in_work_order[i].str = cx->epu_debug_str; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) + INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler); +#else + INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler, + &cx->in_work_order[i].work); +#endif + } +} + /* Precondition: the cx18 structure has been memset to 0. Only the dev and instance fields have been filled in. No assumptions on the card type may be made here (see cx18_init_struct2 @@ -553,7 +593,7 @@ done: */ static int __devinit cx18_init_struct1(struct cx18 *cx) { - int i; + int ret; cx->base_addr = pci_resource_start(cx->pci_dev, 0); @@ -562,23 +602,18 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->epu2apu_mb_lock); mutex_init(&cx->epu2cpu_mb_lock); - cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name); - if (cx->work_queue == NULL) { - CX18_ERR("Unable to create work hander thread\n"); - return -ENOMEM; - } + ret = cx18_create_out_workq(cx); + if (ret) + return ret; - for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) { - cx->epu_work_order[i].cx = cx; - cx->epu_work_order[i].str = cx->epu_debug_str; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) - INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler); -#else - INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler, - &cx->epu_work_order[i].work); -#endif + ret = cx18_create_in_workq(cx); + if (ret) { + destroy_workqueue(cx->out_work_queue); + return ret; } + cx18_init_in_work_orders(cx); + /* start counting open_id at 1 */ cx->open_id = 1; @@ -764,17 +799,17 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, retval = -ENODEV; goto err; } - if (cx18_init_struct1(cx)) { - retval = -ENOMEM; + + retval = cx18_init_struct1(cx); + if (retval) goto err; - } CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr); /* PCI Device Setup */ retval = cx18_setup_pci(cx, pci_dev, pci_id); if (retval != 0) - goto free_workqueue; + goto free_workqueues; /* map io memory */ CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", @@ -948,8 +983,9 @@ free_map: cx18_iounmap(cx); free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); -free_workqueue: - destroy_workqueue(cx->work_queue); +free_workqueues: + destroy_workqueue(cx->in_work_queue); + destroy_workqueue(cx->out_work_queue); err: if (retval == 0) retval = -ENODEV; @@ -1059,11 +1095,19 @@ int cx18_init_on_first_open(struct cx18 *cx) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) -static void cx18_cancel_epu_work_orders(struct cx18 *cx) +static void cx18_cancel_in_work_orders(struct cx18 *cx) { int i; - for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) - cancel_work_sync(&cx->epu_work_order[i].work); + for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) + cancel_work_sync(&cx->in_work_order[i].work); +} + +static void cx18_cancel_out_work_orders(struct cx18 *cx) +{ + int i; + for (i = 0; i < CX18_MAX_STREAMS; i++) + if (&cx->streams[i].video_dev != NULL) + cancel_work_sync(&cx->streams[i].out_work_order); } #endif @@ -1080,24 +1124,25 @@ static void cx18_remove(struct pci_dev *pci_dev) if (atomic_read(&cx->tot_capturing) > 0) cx18_stop_all_captures(cx); - /* Interrupts */ + /* Stop interrupts that cause incoming work to be queued */ cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) - cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); - - cx18_halt_firmware(cx); - cx18_cancel_epu_work_orders(cx); + /* Incoming work can cause outgoing work, so clean up incoming first */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + cx18_cancel_in_work_orders(cx); + cx18_cancel_out_work_orders(cx); #else + flush_workqueue(cx->in_work_queue); + flush_workqueue(cx->out_work_queue); +#endif - flush_workqueue(cx->work_queue); - + /* Stop ack interrupts that may have been needed for work to finish */ cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); cx18_halt_firmware(cx); -#endif - destroy_workqueue(cx->work_queue); + destroy_workqueue(cx->in_work_queue); + destroy_workqueue(cx->out_work_queue); cx18_streams_cleanup(cx, 1); diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index ece4f281e..f89b82367 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -254,6 +254,7 @@ struct cx18_options { #define CX18_F_S_INTERNAL_USE 5 /* this stream is used internally (sliced VBI processing) */ #define CX18_F_S_STREAMOFF 7 /* signal end of stream EOS */ #define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */ +#define CX18_F_S_STOPPING 9 /* telling the fw to stop capturing */ /* per-cx18, i_flags */ #define CX18_F_I_LOADED_FW 0 /* Loaded firmware 1st time */ @@ -285,6 +286,7 @@ struct cx18_queue { struct list_head list; atomic_t buffers; u32 bytesused; + spinlock_t lock; }; struct cx18_dvb { @@ -305,7 +307,7 @@ struct cx18_scb; /* forward reference */ #define CX18_MAX_MDL_ACKS 2 -#define CX18_MAX_EPU_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7) +#define CX18_MAX_IN_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7) /* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */ #define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1 @@ -313,7 +315,7 @@ struct cx18_scb; /* forward reference */ #define CX18_F_EWO_MB_STALE \ (CX18_F_EWO_MB_STALE_UPON_RECEIPT | CX18_F_EWO_MB_STALE_WHILE_PROC) -struct cx18_epu_work_order { +struct cx18_in_work_order { struct work_struct work; atomic_t pending; struct cx18 *cx; @@ -337,7 +339,6 @@ struct cx18_stream { unsigned mdl_offset; u32 id; - struct mutex qlock; /* locks access to the queues */ unsigned long s_flags; /* status flags, see above */ int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or @@ -353,6 +354,8 @@ struct cx18_stream { struct cx18_queue q_busy; /* busy buffers - in use by firmware */ struct cx18_queue q_full; /* full buffers - data for user apps */ + struct work_struct out_work_order; + /* DVB / Digital Transport */ struct cx18_dvb dvb; }; @@ -568,10 +571,14 @@ struct cx18 { u32 sw2_irq_mask; u32 hw2_irq_mask; - struct workqueue_struct *work_queue; - struct cx18_epu_work_order epu_work_order[CX18_MAX_EPU_WORK_ORDERS]; + struct workqueue_struct *in_work_queue; + char in_workq_name[11]; /* "cx18-NN-in" */ + struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS]; char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */ + struct workqueue_struct *out_work_queue; + char out_workq_name[12]; /* "cx18-NN-out" */ + /* i2c */ struct i2c_adapter i2c_adap[2]; struct i2c_algo_bit_data i2c_algo[2]; diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c index 3b86f57cd..e7285a109 100644 --- a/linux/drivers/media/video/cx18/cx18-dvb.c +++ b/linux/drivers/media/video/cx18/cx18-dvb.c @@ -23,6 +23,7 @@ #include "cx18-version.h" #include "cx18-dvb.h" #include "cx18-io.h" +#include "cx18-queue.h" #include "cx18-streams.h" #include "cx18-cards.h" #include "s5h1409.h" diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index d20ac818f..817bb9263 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -301,8 +301,13 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, * an MPEG-2 Program Pack start code, and provide only * up to that point to the user, so it's easy to insert VBI data * the next time around. + * + * This will not work for an MPEG-2 TS and has only been + * verified by analysis to work for an MPEG-2 PS. Helen Buus + * pointed out this works for the CX23416 MPEG-2 DVD compatible + * stream, and research indicates both the MPEG 2 SVCD and DVD + * stream types use an MPEG-2 PS container. */ - /* FIXME - This only works for an MPEG-2 PS, not a TS */ /* * An MPEG-2 Program Stream (PS) is a series of * MPEG-2 Program Packs terminated by an diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index 4bf737849..3c76a1e27 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -214,7 +214,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = { /* init + register i2c algo-bit adapter */ int init_cx18_i2c(struct cx18 *cx) { - int i; + int i, err; CX18_DEBUG_I2C("i2c init\n"); for (i = 0; i < 2; i++) { @@ -273,8 +273,18 @@ int init_cx18_i2c(struct cx18 *cx) cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset, (u32) CX18_GPIO_RESET_I2C); - return i2c_bit_add_bus(&cx->i2c_adap[0]) || - i2c_bit_add_bus(&cx->i2c_adap[1]); + err = i2c_bit_add_bus(&cx->i2c_adap[0]); + if (err) + goto err; + err = i2c_bit_add_bus(&cx->i2c_adap[1]); + if (err) + goto err_del_bus_0; + return 0; + + err_del_bus_0: + i2c_del_adapter(&cx->i2c_adap[0]); + err: + return err; } void exit_cx18_i2c(struct cx18 *cx) diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index 66964722f..36f4d3dd7 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -131,7 +131,7 @@ 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 epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) +static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) { u32 handle, mdl_ack_count, id; struct cx18_mailbox *mb; @@ -191,29 +191,30 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) if (buf == NULL) { CX18_WARN("Could not find buf %d for stream %s\n", id, s->name); - /* Put as many buffers as possible back into fw use */ - cx18_stream_load_fw_queue(s); continue; } - if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { - CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n", - buf->bytesused); - dvb_dmx_swfilter(&s->dvb.demux, buf->buf, - buf->bytesused); + CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", + s->name, buf->bytesused); + + if (s->type != CX18_ENC_STREAM_TYPE_TS) + cx18_enqueue(s, buf, &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); } - /* Put as many buffers as possible back into fw use */ - cx18_stream_load_fw_queue(s); - /* Put back TS buffer, since it was removed from all queues */ - if (s->type == CX18_ENC_STREAM_TYPE_TS) - cx18_stream_put_buf_fw(s, buf); } + /* Put as many buffers as possible back into fw use */ + cx18_stream_load_fw_queue(s); + wake_up(&cx->dma_waitq); if (s->id != -1) wake_up(&s->waitq); } -static void epu_debug(struct cx18 *cx, struct cx18_epu_work_order *order) +static void epu_debug(struct cx18 *cx, struct cx18_in_work_order *order) { char *p; char *str = order->str; @@ -224,7 +225,7 @@ static void epu_debug(struct cx18 *cx, struct cx18_epu_work_order *order) CX18_INFO("FW version: %s\n", p - 1); } -static void epu_cmd(struct cx18 *cx, struct cx18_epu_work_order *order) +static void epu_cmd(struct cx18 *cx, struct cx18_in_work_order *order) { switch (order->rpu) { case CPU: @@ -253,24 +254,24 @@ static void epu_cmd(struct cx18 *cx, struct cx18_epu_work_order *order) } static -void free_epu_work_order(struct cx18 *cx, struct cx18_epu_work_order *order) +void free_in_work_order(struct cx18 *cx, struct cx18_in_work_order *order) { atomic_set(&order->pending, 0); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -void cx18_epu_work_handler(struct work_struct *work) +void cx18_in_work_handler(struct work_struct *work) { - struct cx18_epu_work_order *order = - container_of(work, struct cx18_epu_work_order, work); + struct cx18_in_work_order *order = + container_of(work, struct cx18_in_work_order, work); #else -void cx18_epu_work_handler(void *arg) +void cx18_in_work_handler(void *arg) { - struct cx18_epu_work_order *order = arg; + struct cx18_in_work_order *order = arg; #endif struct cx18 *cx = order->cx; epu_cmd(cx, order); - free_epu_work_order(cx, order); + free_in_work_order(cx, order); } @@ -278,7 +279,7 @@ void cx18_epu_work_handler(void *arg) * Functions that run in an interrupt handling context */ -static void mb_ack_irq(struct cx18 *cx, struct cx18_epu_work_order *order) +static void mb_ack_irq(struct cx18 *cx, struct cx18_in_work_order *order) { struct cx18_mailbox __iomem *ack_mb; u32 ack_irq, req; @@ -314,7 +315,7 @@ static void mb_ack_irq(struct cx18 *cx, struct cx18_epu_work_order *order) return; } -static int epu_dma_done_irq(struct cx18 *cx, struct cx18_epu_work_order *order) +static int epu_dma_done_irq(struct cx18 *cx, struct cx18_in_work_order *order) { u32 handle, mdl_ack_offset, mdl_ack_count; struct cx18_mailbox *mb; @@ -340,7 +341,7 @@ static int epu_dma_done_irq(struct cx18 *cx, struct cx18_epu_work_order *order) } static -int epu_debug_irq(struct cx18 *cx, struct cx18_epu_work_order *order) +int epu_debug_irq(struct cx18 *cx, struct cx18_in_work_order *order) { u32 str_offset; char *str = order->str; @@ -361,7 +362,7 @@ int epu_debug_irq(struct cx18 *cx, struct cx18_epu_work_order *order) } static inline -int epu_cmd_irq(struct cx18 *cx, struct cx18_epu_work_order *order) +int epu_cmd_irq(struct cx18 *cx, struct cx18_in_work_order *order) { int ret = -1; @@ -393,12 +394,12 @@ int epu_cmd_irq(struct cx18 *cx, struct cx18_epu_work_order *order) } static inline -struct cx18_epu_work_order *alloc_epu_work_order_irq(struct cx18 *cx) +struct cx18_in_work_order *alloc_in_work_order_irq(struct cx18 *cx) { int i; - struct cx18_epu_work_order *order = NULL; + struct cx18_in_work_order *order = NULL; - for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) { + for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) { /* * We only need "pending" atomic to inspect its contents, * and need not do a check and set because: @@ -407,8 +408,8 @@ struct cx18_epu_work_order *alloc_epu_work_order_irq(struct cx18 *cx) * 2. "pending" is only set here, and we're serialized because * we're called in an IRQ handler context. */ - if (atomic_read(&cx->epu_work_order[i].pending) == 0) { - order = &cx->epu_work_order[i]; + if (atomic_read(&cx->in_work_order[i].pending) == 0) { + order = &cx->in_work_order[i]; atomic_set(&order->pending, 1); break; } @@ -420,7 +421,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu) { struct cx18_mailbox __iomem *mb; struct cx18_mailbox *order_mb; - struct cx18_epu_work_order *order; + struct cx18_in_work_order *order; int submit; switch (rpu) { @@ -434,7 +435,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu) return; } - order = alloc_epu_work_order_irq(cx); + order = alloc_in_work_order_irq(cx); if (order == NULL) { CX18_WARN("Unable to find blank work order form to schedule " "incoming mailbox command processing\n"); @@ -467,7 +468,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu) */ submit = epu_cmd_irq(cx, order); if (submit > 0) { - queue_work(cx->work_queue, &order->work); + queue_work(cx->in_work_queue, &order->work); } } @@ -484,9 +485,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) u32 __iomem *xpu_state; wait_queue_head_t *waitq; struct mutex *mb_lock; - long int timeout, ret; + unsigned long int t0, timeout, ret; int i; char argstr[MAX_MB_ARGUMENTS*11+1]; + DEFINE_WAIT(w); if (info == NULL) { CX18_WARN("unknown cmd %x\n", cmd); @@ -568,25 +570,49 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n", irq, info->name); + + /* So we don't miss the wakeup, prepare to wait before notifying fw */ + prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE); cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); - ret = wait_event_timeout( - *waitq, - cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request), - timeout); + t0 = jiffies; + ack = cx18_readl(cx, &mb->ack); + if (ack != req) { + schedule_timeout(timeout); + ret = jiffies - t0; + ack = cx18_readl(cx, &mb->ack); + } else { + ret = jiffies - t0; + } - if (ret == 0) { - /* Timed out */ + finish_wait(waitq, &w); + + if (req != ack) { mutex_unlock(mb_lock); - CX18_DEBUG_WARN("sending %s timed out waiting %d msecs for RPU " - "acknowledgement\n", - info->name, jiffies_to_msecs(timeout)); + if (ret >= timeout) { + /* Timed out */ + CX18_DEBUG_WARN("sending %s timed out waiting %d msecs " + "for RPU acknowledgement\n", + info->name, jiffies_to_msecs(ret)); + } else { + CX18_DEBUG_WARN("woken up before mailbox ack was ready " + "after submitting %s to RPU. only " + "waited %d msecs on req %u but awakened" + " with unmatched ack %u\n", + info->name, + jiffies_to_msecs(ret), + req, ack); + } return -EINVAL; } - if (ret != timeout) + if (ret >= timeout) + CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment " + "sending %s; timed out waiting %d msecs\n", + info->name, jiffies_to_msecs(ret)); + else CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n", - jiffies_to_msecs(timeout-ret), info->name); + jiffies_to_msecs(ret), info->name); /* Collect data returned by the XPU */ for (i = 0; i < MAX_MB_ARGUMENTS; i++) diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.h b/linux/drivers/media/video/cx18/cx18-mailbox.h index a667f1ae4..4bd0ba57f 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.h +++ b/linux/drivers/media/video/cx18/cx18-mailbox.h @@ -96,9 +96,9 @@ int cx18_api_func(void *priv, u32 cmd, int in, int out, void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -void cx18_epu_work_handler(struct work_struct *work); +void cx18_in_work_handler(struct work_struct *work); #else -void cx18_epu_work_handler(void *arg); +void cx18_in_work_handler(void *arg); #endif #endif diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index 3046b8e74..fa1ed7897 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -23,8 +23,8 @@ */ #include "cx18-driver.h" -#include "cx18-streams.h" #include "cx18-queue.h" +#include "cx18-streams.h" #include "cx18-scb.h" void cx18_buf_swap(struct cx18_buffer *buf) @@ -53,13 +53,13 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, buf->skipped = 0; } - mutex_lock(&s->qlock); - /* q_busy is restricted to a max buffer count imposed by firmware */ if (q == &s->q_busy && atomic_read(&q->buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) q = &s->q_free; + spin_lock(&q->lock); + if (to_front) list_add(&buf->list, &q->list); /* LIFO */ else @@ -67,7 +67,7 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, q->bytesused += buf->bytesused - buf->readpos; atomic_inc(&q->buffers); - mutex_unlock(&s->qlock); + spin_unlock(&q->lock); return q; } @@ -75,7 +75,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) { struct cx18_buffer *buf = NULL; - mutex_lock(&s->qlock); + spin_lock(&q->lock); if (!list_empty(&q->list)) { buf = list_first_entry(&q->list, struct cx18_buffer, list); list_del_init(&buf->list); @@ -83,7 +83,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) buf->skipped = 0; atomic_dec(&q->buffers); } - mutex_unlock(&s->qlock); + spin_unlock(&q->lock); return buf; } @@ -94,9 +94,23 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, struct cx18_buffer *buf; struct cx18_buffer *tmp; struct cx18_buffer *ret = NULL; - - mutex_lock(&s->qlock); + 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 + * 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) { + /* + * 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 + * q_busy, we have high confidence we've missed it. + */ if (buf->id != id) { buf->skipped++; if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { @@ -105,38 +119,41 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, "times - it must have dropped out of " "rotation\n", s->name, buf->id, buf->skipped); - /* move it to q_free */ - list_move_tail(&buf->list, &s->q_free.list); - buf->bytesused = buf->readpos = buf->b_flags = - buf->skipped = 0; + /* Sweep it up to put it back into rotation */ + list_move_tail(&buf->list, &sweep_up); atomic_dec(&s->q_busy.buffers); - atomic_inc(&s->q_free.buffers); } continue; } - - buf->bytesused = bytesused; - /* Sync the buffer before we release the qlock */ - cx18_buf_sync_for_cpu(s, buf); - if (s->type == CX18_ENC_STREAM_TYPE_TS) { - /* - * TS doesn't use q_full. As we pull the buffer off of - * the queue here, the caller will have to put it back. - */ - list_del_init(&buf->list); - } else { - /* Move buffer from q_busy to q_full */ - list_move_tail(&buf->list, &s->q_full.list); - set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); - s->q_full.bytesused += buf->bytesused; - atomic_inc(&s->q_full.buffers); - } + /* + * We pull the desired buffer off of the queue here. Something + * will have to put it back on a queue later. + */ + list_del_init(&buf->list); atomic_dec(&s->q_busy.buffers); - ret = buf; break; } - mutex_unlock(&s->qlock); + spin_unlock(&s->q_busy.lock); + + /* + * We found the buffer 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); + if (s->type != CX18_ENC_STREAM_TYPE_TS) + set_bit(CX18_F_B_NEED_BUF_SWAP, &ret->b_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); + } return ret; } @@ -148,7 +165,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) if (q == &s->q_free) return; - mutex_lock(&s->qlock); + 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); @@ -156,7 +173,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) atomic_inc(&s->q_free.buffers); } cx18_queue_init(q); - mutex_unlock(&s->qlock); + spin_unlock(&q->lock); } void cx18_flush_queues(struct cx18_stream *s) diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 7c1db9c18..142302ba5 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -116,12 +116,21 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->buffers = cx->stream_buffers[type]; s->buf_size = cx->stream_buf_size[type]; - mutex_init(&s->qlock); init_waitqueue_head(&s->waitq); s->id = -1; + spin_lock_init(&s->q_free.lock); cx18_queue_init(&s->q_free); + spin_lock_init(&s->q_busy.lock); cx18_queue_init(&s->q_busy); + spin_lock_init(&s->q_full.lock); cx18_queue_init(&s->q_full); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) + INIT_WORK(&s->out_work_order, cx18_out_work_handler); +#else + INIT_WORK(&s->out_work_order, cx18_out_work_handler, + &s->out_work_order); +#endif } static int cx18_prep_dev(struct cx18 *cx, int type) @@ -431,14 +440,16 @@ static void cx18_vbi_setup(struct cx18_stream *s) cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); } -struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, - struct cx18_buffer *buf) +static +struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, + struct cx18_buffer *buf) { struct cx18 *cx = s->cx; struct cx18_queue *q; /* Don't give it to the firmware, if we're not running a capture */ if (s->handle == CX18_INVALID_TASK_HANDLE || + test_bit(CX18_F_S_STOPPING, &s->s_flags) || !test_bit(CX18_F_S_STREAMING, &s->s_flags)) return cx18_enqueue(s, buf, &s->q_free); @@ -453,7 +464,8 @@ struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, return q; } -void cx18_stream_load_fw_queue(struct cx18_stream *s) +static +void _cx18_stream_load_fw_queue(struct cx18_stream *s) { struct cx18_queue *q; struct cx18_buffer *buf; @@ -467,11 +479,25 @@ void cx18_stream_load_fw_queue(struct cx18_stream *s) buf = cx18_dequeue(s, &s->q_free); if (buf == NULL) break; - q = cx18_stream_put_buf_fw(s, buf); + q = _cx18_stream_put_buf_fw(s, buf); } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM && q == &s->q_busy); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) +void cx18_out_work_handler(struct work_struct *work) +{ +#else +void cx18_out_work_handler(void *arg) +{ + struct work_struct *work = arg; +#endif + struct cx18_stream *s = + container_of(work, struct cx18_stream, out_work_order); + + _cx18_stream_load_fw_queue(s); +} + int cx18_start_v4l2_encode_stream(struct cx18_stream *s) { u32 data[MAX_MB_ARGUMENTS]; @@ -600,19 +626,20 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) /* Init all the cpu_mdls for this stream */ cx18_flush_queues(s); - mutex_lock(&s->qlock); + 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); } - mutex_unlock(&s->qlock); - cx18_stream_load_fw_queue(s); + spin_unlock(&s->q_free.lock); + _cx18_stream_load_fw_queue(s); /* begin_capture */ if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { CX18_DEBUG_WARN("Error starting capture!\n"); /* Ensure we're really not capturing before releasing MDLs */ + set_bit(CX18_F_S_STOPPING, &s->s_flags); if (s->type == CX18_ENC_STREAM_TYPE_MPG) cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); else @@ -622,6 +649,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); s->handle = CX18_INVALID_TASK_HANDLE; + clear_bit(CX18_F_S_STOPPING, &s->s_flags); if (atomic_read(&cx->tot_capturing) == 0) { set_bit(CX18_F_I_EOS, &cx->i_flags); cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK); @@ -666,6 +694,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) if (atomic_read(&cx->tot_capturing) == 0) return 0; + set_bit(CX18_F_S_STOPPING, &s->s_flags); if (s->type == CX18_ENC_STREAM_TYPE_MPG) cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end); else @@ -716,6 +745,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); s->handle = CX18_INVALID_TASK_HANDLE; + clear_bit(CX18_F_S_STOPPING, &s->s_flags); if (atomic_read(&cx->tot_capturing) > 0) return 0; diff --git a/linux/drivers/media/video/cx18/cx18-streams.h b/linux/drivers/media/video/cx18/cx18-streams.h index 420e0a172..b51a014b5 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.h +++ b/linux/drivers/media/video/cx18/cx18-streams.h @@ -28,10 +28,28 @@ 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 */ +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) +{ + /* Put buf on q_free; the out work handler will move buf(s) to q_busy */ + cx18_enqueue(s, buf, &s->q_free); + cx18_stream_load_fw_queue(s); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) +void cx18_out_work_handler(struct work_struct *work); +#else +void cx18_out_work_handler(void *arg); +#endif + /* Capture related */ -void cx18_stream_load_fw_queue(struct cx18_stream *s); -struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, - struct cx18_buffer *buf); int cx18_start_v4l2_encode_stream(struct cx18_stream *s); int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end); diff --git a/linux/drivers/media/video/cx18/cx18-version.h b/linux/drivers/media/video/cx18/cx18-version.h index bd9bd44da..45494b094 100644 --- a/linux/drivers/media/video/cx18/cx18-version.h +++ b/linux/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 1 +#define CX18_DRIVER_VERSION_MINOR 2 #define CX18_DRIVER_VERSION_PATCHLEVEL 0 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index 1be3881be..6a9464079 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -29,7 +29,6 @@ #include <linux/bitmap.h> #include <linux/usb.h> #include <linux/i2c.h> -#include <linux/version.h> #include <linux/mm.h> #include <linux/mutex.h> diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c index 020aa13b8..d9c8e1c58 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -26,7 +26,6 @@ #include <linux/bitmap.h> #include <linux/usb.h> #include <linux/i2c.h> -#include <linux/version.h> #include <linux/mm.h> #include <linux/mutex.h> diff --git a/linux/drivers/media/video/cx23885/cimax2.c b/linux/drivers/media/video/cx23885/cimax2.c index 0e29f97f3..fed6d9f9f 100644 --- a/linux/drivers/media/video/cx23885/cimax2.c +++ b/linux/drivers/media/video/cx23885/cimax2.c @@ -320,7 +320,7 @@ static void netup_read_ci_status(struct work_struct *work) "TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0], buf[32]); - if (buf[0] && 1) + if (buf[0] & 1) state->status = DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; else diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 454470ffc..93176fe4b 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -182,6 +182,22 @@ struct cx23885_board cx23885_boards[] = { .portb = CX23885_MPEG_DVB, .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1270] = { + .name = "Hauppauge WinTV-HVR1270", + .portc = CX23885_MPEG_DVB, + }, + [CX23885_BOARD_HAUPPAUGE_HVR1275] = { + .name = "Hauppauge WinTV-HVR1275", + .portc = CX23885_MPEG_DVB, + }, + [CX23885_BOARD_HAUPPAUGE_HVR1255] = { + .name = "Hauppauge WinTV-HVR1255", + .portc = CX23885_MPEG_DVB, + }, + [CX23885_BOARD_HAUPPAUGE_HVR1210] = { + .name = "Hauppauge WinTV-HVR1210", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -281,6 +297,26 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x1b55, .subdevice = 0x2a2c, .card = CX23885_BOARD_NETUP_DUAL_DVBS2_CI, + }, { + .subvendor = 0x0070, + .subdevice = 0x2211, + .card = CX23885_BOARD_HAUPPAUGE_HVR1270, + }, { + .subvendor = 0x0070, + .subdevice = 0x2215, + .card = CX23885_BOARD_HAUPPAUGE_HVR1275, + }, { + .subvendor = 0x0070, + .subdevice = 0x2251, + .card = CX23885_BOARD_HAUPPAUGE_HVR1255, + }, { + .subvendor = 0x0070, + .subdevice = 0x2291, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, + }, { + .subvendor = 0x0070, + .subdevice = 0x2295, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -322,6 +358,42 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) /* Make sure we support the board model */ switch (tv.model) { + case 22001: + /* WinTV-HVR1270 (PCIe, Retail, half height) + * ATSC/QAM and basic analog, IR Blast */ + case 22009: + /* WinTV-HVR1210 (PCIe, Retail, half height) + * DVB-T and basic analog, IR Blast */ + case 22011: + /* WinTV-HVR1270 (PCIe, Retail, half height) + * ATSC/QAM and basic analog, IR Recv */ + case 22019: + /* WinTV-HVR1210 (PCIe, Retail, half height) + * DVB-T and basic analog, IR Recv */ + case 22021: + /* WinTV-HVR1275 (PCIe, Retail, half height) + * ATSC/QAM and basic analog, IR Recv */ + case 22029: + /* WinTV-HVR1210 (PCIe, Retail, half height) + * DVB-T and basic analog, IR Recv */ + case 22101: + /* WinTV-HVR1270 (PCIe, Retail, full height) + * ATSC/QAM and basic analog, IR Blast */ + case 22109: + /* WinTV-HVR1210 (PCIe, Retail, full height) + * DVB-T and basic analog, IR Blast */ + case 22111: + /* WinTV-HVR1270 (PCIe, Retail, full height) + * ATSC/QAM and basic analog, IR Recv */ + case 22119: + /* WinTV-HVR1210 (PCIe, Retail, full height) + * DVB-T and basic analog, IR Recv */ + case 22121: + /* WinTV-HVR1275 (PCIe, Retail, full height) + * ATSC/QAM and basic analog, IR Recv */ + case 22129: + /* WinTV-HVR1210 (PCIe, Retail, full height) + * DVB-T and basic analog, IR Recv */ case 71009: /* WinTV-HVR1200 (PCIe, Retail, full height) * DVB-T and basic analog */ @@ -442,9 +514,9 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: /* Two identical tuners on two different i2c buses, * we need to reset the correct gpio. */ - if (port->nr == 0) + if (port->nr == 1) bitmask = 0x01; - else if (port->nr == 1) + else if (port->nr == 2) bitmask = 0x04; break; } @@ -620,6 +692,21 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* enable irq */ cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ break; + case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: + case CX23885_BOARD_HAUPPAUGE_HVR1255: + case CX23885_BOARD_HAUPPAUGE_HVR1210: + /* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */ + /* GPIO-6 I2C Gate which can isolate the demod from the bus */ + /* GPIO-9 Demod reset */ + + /* Put the parts into reset and back */ + cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1); + cx23885_gpio_set(dev, GPIO_9 | GPIO_6 | GPIO_5); + cx23885_gpio_clear(dev, GPIO_9); + mdelay(20); + cx23885_gpio_set(dev, GPIO_9); + break; } } @@ -632,6 +719,10 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1400: + case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: + case CX23885_BOARD_HAUPPAUGE_HVR1255: + case CX23885_BOARD_HAUPPAUGE_HVR1210: /* FIXME: Implement me */ break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: @@ -667,6 +758,10 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: + case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: + case CX23885_BOARD_HAUPPAUGE_HVR1255: + case CX23885_BOARD_HAUPPAUGE_HVR1210: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -724,6 +819,10 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1400: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: + case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: + case CX23885_BOARD_HAUPPAUGE_HVR1255: + case CX23885_BOARD_HAUPPAUGE_HVR1210: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 81fa577a6..6988361c9 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -1711,9 +1711,13 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) } if (cx23885_boards[dev->board].cimax > 0 && - ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1))) - /* handled += cx23885_irq_gpio(dev, pci_status); */ - handled += netup_ci_slot_status(dev, pci_status); + ((pci_status & PCI_MSK_GPIO0) || + (pci_status & PCI_MSK_GPIO1))) { + + if (cx23885_boards[dev->board].cimax > 0) + handled += netup_ci_slot_status(dev, pci_status); + + } if (ts1_status) { if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) @@ -1740,6 +1744,88 @@ out: return IRQ_RETVAL(handled); } +static inline int encoder_on_portb(struct cx23885_dev *dev) +{ + return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; +} + +static inline int encoder_on_portc(struct cx23885_dev *dev) +{ + return cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER; +} + +/* Mask represents 32 different GPIOs, GPIO's are split into multiple + * registers depending on the board configuration (and whether the + * 417 encoder (wi it's own GPIO's) are present. Each GPIO bit will + * be pushed into the correct hardware register, regardless of the + * physical location. Certain registers are shared so we sanity check + * and report errors if we think we're tampering with a GPIo that might + * be assigned to the encoder (and used for the host bus). + * + * GPIO 2 thru 0 - On the cx23885 bridge + * GPIO 18 thru 3 - On the cx23417 host bus interface + * GPIO 23 thru 19 - On the cx25840 a/v core + */ +void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask) +{ + if (mask & 0x7) + cx_set(GP0_IO, mask & 0x7); + + if (mask & 0x0007fff8) { + if (encoder_on_portb(dev) || encoder_on_portc(dev)) + printk(KERN_ERR + "%s: Setting GPIO on encoder ports\n", + dev->name); + cx_set(MC417_RWD, (mask & 0x0007fff8) >> 3); + } + + /* TODO: 23-19 */ + if (mask & 0x00f80000) + printk(KERN_INFO "%s: Unsupported\n", dev->name); +} + +void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask) +{ + if (mask & 0x00000007) + cx_clear(GP0_IO, mask & 0x7); + + if (mask & 0x0007fff8) { + if (encoder_on_portb(dev) || encoder_on_portc(dev)) + printk(KERN_ERR + "%s: Clearing GPIO moving on encoder ports\n", + dev->name); + cx_clear(MC417_RWD, (mask & 0x7fff8) >> 3); + } + + /* TODO: 23-19 */ + if (mask & 0x00f80000) + printk(KERN_INFO "%s: Unsupported\n", dev->name); +} + +void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput) +{ + if ((mask & 0x00000007) && asoutput) + cx_set(GP0_IO, (mask & 0x7) << 16); + else if ((mask & 0x00000007) && !asoutput) + cx_clear(GP0_IO, (mask & 0x7) << 16); + + if (mask & 0x0007fff8) { + if (encoder_on_portb(dev) || encoder_on_portc(dev)) + printk(KERN_ERR + "%s: Enabling GPIO on encoder ports\n", + dev->name); + } + + /* MC417_OEN is active low for output, write 1 for an input */ + if ((mask & 0x0007fff8) && asoutput) + cx_clear(MC417_OEN, (mask & 0x7fff8) >> 3); + + else if ((mask & 0x0007fff8) && !asoutput) + cx_set(MC417_OEN, (mask & 0x7fff8) >> 3); + + /* TODO: 23-19 */ +} + static int __devinit cx23885_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index c4c1d396c..ba120b9cf 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -52,6 +52,7 @@ #include "cimax2.h" #include "netup-eeprom.h" #include "netup-init.h" +#include "lgdt3305.h" static unsigned int debug; @@ -123,7 +124,18 @@ static struct tda10048_config hauppauge_hvr1200_config = { .demod_address = 0x10 >> 1, .output_mode = TDA10048_SERIAL_OUTPUT, .fwbulkwritelen = TDA10048_BULKWRITE_200, - .inversion = TDA10048_INVERSION_ON + .inversion = TDA10048_INVERSION_ON, + .if_freq_khz = TDA10048_IF_4300, + .clk_freq_khz = TDA10048_CLK_16000, +}; + +static struct tda10048_config hauppauge_hvr1210_config = { + .demod_address = 0x10 >> 1, + .output_mode = TDA10048_SERIAL_OUTPUT, + .fwbulkwritelen = TDA10048_BULKWRITE_200, + .inversion = TDA10048_INVERSION_ON, + .if_freq_khz = TDA10048_IF_4000, + .clk_freq_khz = TDA10048_CLK_16000, }; static struct s5h1409_config hauppauge_ezqam_config = { @@ -195,6 +207,16 @@ static struct s5h1411_config dvico_s5h1411_config = { .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, }; +static struct s5h1411_config hcw_s5h1411_config = { + .output_mode = S5H1411_SERIAL_OUTPUT, + .gpio = S5H1411_GPIO_OFF, + .vsb_if = S5H1411_IF_44000, + .qam_if = S5H1411_IF_4000, + .inversion = S5H1411_INVERSION_ON, + .status_mode = S5H1411_DEMODLOCKING, + .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, +}; + static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { .i2c_address = 0x61, .if_khz = 5380, @@ -225,6 +247,32 @@ static struct tda18271_config hauppauge_hvr1200_tuner_config = { .gate = TDA18271_GATE_ANALOG, }; +static struct tda18271_config hauppauge_hvr1210_tuner_config = { + .gate = TDA18271_GATE_DIGITAL, +}; + +static struct tda18271_std_map hauppauge_hvr127x_std_map = { + .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x58 }, + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x58 }, +}; + +static struct tda18271_config hauppauge_hvr127x_config = { + .std_map = &hauppauge_hvr127x_std_map, +}; + +static struct lgdt3305_config hauppauge_lgdt3305_config = { + .i2c_addr = 0x0e, + .mpeg_mode = LGDT3305_MPEG_SERIAL, + .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, + .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, + .deny_i2c_rptr = 1, + .spectral_inversion = 1, + .qam_if_khz = 4000, + .vsb_if_khz = 3250, +}; + static struct dibx000_agc_config xc3028_agc_config = { BAND_VHF | BAND_UHF, /* band_caps */ @@ -315,6 +363,7 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { .demod_address = 0x0f, .if2 = 45600, .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, }; static struct stv0900_config netup_stv0900_config = { @@ -396,6 +445,29 @@ static int dvb_register(struct cx23885_tsport *port) &hauppauge_generic_tunerconfig, 0); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(lgdt3305_attach, + &hauppauge_lgdt3305_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + &hauppauge_hvr127x_config); + } + break; + case CX23885_BOARD_HAUPPAUGE_HVR1255: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(s5h1411_attach, + &hcw_s5h1411_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + &hauppauge_tda18271_config); + } + break; case CX23885_BOARD_HAUPPAUGE_HVR1800: i2c_bus = &dev->i2c_bus[0]; switch (alt_tuner) { @@ -472,7 +544,7 @@ static int dvb_register(struct cx23885_tsport *port) static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, - .scode_table = XC3028_FE_OREN538, + .demod = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, @@ -496,6 +568,17 @@ static int dvb_register(struct cx23885_tsport *port) &hauppauge_hvr1200_tuner_config); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1210: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(tda10048_attach, + &hauppauge_hvr1210_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + &hauppauge_hvr1210_tuner_config); + } + break; case CX23885_BOARD_HAUPPAUGE_HVR1400: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(dib7000p_attach, diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 92828c9ce..8dba2fdd6 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -72,6 +72,21 @@ #define CX23885_BOARD_TEVII_S470 15 #define CX23885_BOARD_DVBWORLD_2005 16 #define CX23885_BOARD_NETUP_DUAL_DVBS2_CI 17 +#define CX23885_BOARD_HAUPPAUGE_HVR1270 18 +#define CX23885_BOARD_HAUPPAUGE_HVR1275 19 +#define CX23885_BOARD_HAUPPAUGE_HVR1255 20 +#define CX23885_BOARD_HAUPPAUGE_HVR1210 21 + +#define GPIO_0 0x00000001 +#define GPIO_1 0x00000002 +#define GPIO_2 0x00000004 +#define GPIO_3 0x00000008 +#define GPIO_4 0x00000010 +#define GPIO_5 0x00000020 +#define GPIO_6 0x00000040 +#define GPIO_7 0x00000080 +#define GPIO_8 0x00000100 +#define GPIO_9 0x00000200 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ @@ -423,6 +438,11 @@ extern int cx23885_restart_queue(struct cx23885_tsport *port, extern void cx23885_wakeup(struct cx23885_tsport *port, struct cx23885_dmaqueue *q, u32 count); +extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask); +extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask); +extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, + int asoutput); + /* ----------------------------------------------------------- */ /* cx23885-cards.c */ diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index a4d49fbf7..546793c02 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -2002,6 +2002,13 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_HAUPPAUGE_IRONLY] = { + .name = "Hauppauge WinTV-IR Only", + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, }; /* ------------------------------------------------------------------ */ @@ -2415,6 +2422,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x153b, .subdevice = 0x1177, .card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII, + }, { + .subvendor = 0x0070, + .subdevice = 0x9290, + .card = CX88_BOARD_HAUPPAUGE_IRONLY, }, }; @@ -2481,6 +2492,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) case 90500: /* Nova-T-PCI (oem) */ case 90501: /* Nova-T-PCI (oem/IR) */ case 92000: /* Nova-SE2 (OEM, No Video or IR) */ + case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */ case 94009: /* WinTV-HVR1100 (Video and IR Retail) */ case 94501: /* WinTV-HVR1100 (Video and IR OEM) */ case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */ @@ -2723,10 +2735,22 @@ static int cx88_xc5000_tuner_callback(struct cx88_core *core, switch (core->boardnr) { case CX88_BOARD_PINNACLE_PCTV_HD_800i: if (command == 0) { /* This is the reset command from xc5000 */ - /* Reset XC5000 tuner via SYS_RSTO_pin */ - cx_write(MO_SRST_IO, 0); - msleep(10); - cx_write(MO_SRST_IO, 1); + + /* djh - According to the engineer at PCTV Systems, + the xc5000 reset pin is supposed to be on GPIO12. + However, despite three nights of effort, pulling + that GPIO low didn't reset the xc5000. While + pulling MO_SRST_IO low does reset the xc5000, this + also resets in the s5h1409 being reset as well. + This causes tuning to always fail since the internal + state of the s5h1409 does not match the driver's + state. Given that the only two conditions in which + the driver performs a reset is during firmware load + and powering down the chip, I am taking out the + reset. We know that the chip is being reset + when the cx88 comes online, and not being able to + do power management for this board is worse than + not having any tuning at all. */ return 0; } else { err_printk(core, "xc5000: unknown tuner " @@ -2940,6 +2964,7 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR1300: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + case CX88_BOARD_HAUPPAUGE_IRONLY: if (0 == core->i2c_rc) hauppauge_eeprom(core, eeprom); break; diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 8a2e631b7..dad809335 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -92,6 +92,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) gpio=(gpio & 0x7fd) + (auxgpio & 0xef); break; case CX88_BOARD_WINFAST_DTV1000: + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900); auxgpio = gpio; break; @@ -230,6 +231,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_HAUPPAUGE_HVR4000LITE: case CX88_BOARD_PCHDTV_HD3000: case CX88_BOARD_PCHDTV_HD5500: + case CX88_BOARD_HAUPPAUGE_IRONLY: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; @@ -243,6 +245,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_WINFAST2000XP_EXPERT: case CX88_BOARD_WINFAST_DTV1000: + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; @@ -476,6 +479,7 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR4000LITE: case CX88_BOARD_PCHDTV_HD3000: case CX88_BOARD_PCHDTV_HD5500: + case CX88_BOARD_HAUPPAUGE_IRONLY: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); /* diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 88a326f61..2dfa4c9c3 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1152,8 +1152,10 @@ static int video_release(struct file *file) file->private_data = NULL; kfree(fh); + mutex_lock(&dev->core->lock); if(atomic_dec_and_test(&dev->core->users)) call_all(dev->core, tuner, s_standby); + mutex_unlock(&dev->core->lock); return 0; } diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 1cf6900e0..0c00c34bc 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -236,6 +236,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_TBS_8910 77 #define CX88_BOARD_PROF_6200 78 #define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 +#define CX88_BOARD_HAUPPAUGE_IRONLY 80 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index fb83e4f6e..1dff7528a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -153,6 +153,16 @@ static struct em28xx_reg_seq compro_mute_gpio[] = { { -1, -1, -1, -1}, }; +/* Terratec AV350 */ +static struct em28xx_reg_seq terratec_av350_mute_gpio[] = { + {EM28XX_R08_GPIO, 0xff, 0x7f, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { + {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + { -1, -1, -1, -1}, +}; /* * Board definitions */ @@ -1412,6 +1422,42 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, } }, }, + [EM2860_BOARD_TERRATEC_GRABBY] = { + .name = "Terratec Grabby", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_SAA711X, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO2, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_VIDEO2, + } }, + }, + [EM2860_BOARD_TERRATEC_AV350] = { + .name = "Terratec AV350", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_TVP5150, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .mute_gpio = terratec_av350_mute_gpio, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AUDIO_SRC_LINE, + .gpio = terratec_av350_unmute_gpio, + + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AUDIO_SRC_LINE, + .gpio = terratec_av350_unmute_gpio, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1479,6 +1525,10 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2870_BOARD_TERRATEC_XS }, { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, + { USB_DEVICE(0x0ccd, 0x0084), + .driver_info = EM2860_BOARD_TERRATEC_AV350 }, + { USB_DEVICE(0x0ccd, 0x0096), + .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, { USB_DEVICE(0x185b, 0x2870), .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE }, { USB_DEVICE(0x185b, 0x2041), diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 401dc4e39..02e51af9d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -1021,6 +1021,41 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, } EXPORT_SYMBOL_GPL(em28xx_init_isoc); +/* Determine the packet size for the DVB stream for the given device + (underlying value programmed into the eeprom) */ +int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev) +{ + unsigned int chip_cfg2; + unsigned int packet_size = 564; + + if (dev->chip_id == CHIP_ID_EM2874) { + /* FIXME - for now assume 564 like it was before, but the + em2874 code should be added to return the proper value... */ + packet_size = 564; + } else { + /* TS max packet size stored in bits 1-0 of R01 */ + chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2); + switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) { + case EM28XX_CHIPCFG2_TS_PACKETSIZE_188: + packet_size = 188; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_376: + packet_size = 376; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_564: + packet_size = 564; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_752: + packet_size = 752; + break; + } + } + + em28xx_coredbg("dvb max packet size=%d\n", packet_size); + return packet_size; +} +EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize); + /* * em28xx_wake_i2c() * configure i2c attached devices diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index dd749442d..de919504f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -47,7 +47,6 @@ if (debug >= level) \ } while (0) #define EM28XX_DVB_NUM_BUFS 5 -#define EM28XX_DVB_MAX_PACKETSIZE 564 #define EM28XX_DVB_MAX_PACKETS 64 struct em28xx_dvb { @@ -143,14 +142,17 @@ static int start_streaming(struct em28xx_dvb *dvb) { int rc; struct em28xx *dev = dvb->adapter.priv; + int max_dvb_packet_size; usb_set_interface(dev->udev, 0, 1); rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); if (rc < 0) return rc; + max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); + return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, - EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE, + EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, dvb_isoc_copy); } diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 24e39c568..a2676d63c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -27,6 +27,22 @@ #define EM28XX_CHIPCFG_AC97 0x10 #define EM28XX_CHIPCFG_AUDIOMASK 0x30 +#define EM28XX_R01_CHIPCFG2 0x01 + +/* em28xx Chip Configuration 2 0x01 */ +#define EM28XX_CHIPCFG2_TS_PRESENT 0x10 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK 0x0c /* bits 3-2 */ +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF 0x00 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF 0x04 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF 0x08 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF 0x0c +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK 0x03 /* bits 0-1 */ +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188 0x00 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376 0x01 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564 0x02 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752 0x03 + + /* GPIO/GPO registers */ #define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ #define EM28XX_R08_GPIO 0x08 /* em2820 or upper */ diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 966a3b924..1bb4a8242 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -104,6 +104,8 @@ #define EM2860_BOARD_EASYCAP 64 #define EM2820_BOARD_IODATA_GVMVP_SZ 65 #define EM2880_BOARD_EMPIRE_DUAL_TV 66 +#define EM2860_BOARD_TERRATEC_GRABBY 67 +#define EM2860_BOARD_TERRATEC_AV350 68 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -625,6 +627,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, int num_bufs, int max_pkt_size, int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); void em28xx_uninit_isoc(struct em28xx *dev); +int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); void em28xx_wake_i2c(struct em28xx *dev); diff --git a/linux/drivers/media/video/gspca/finepix.c b/linux/drivers/media/video/gspca/finepix.c index 00e6863ed..480ec5c87 100644 --- a/linux/drivers/media/video/gspca/finepix.c +++ b/linux/drivers/media/video/gspca/finepix.c @@ -168,6 +168,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = fpix_mode; cam->nmodes = 1; + cam->bulk = 1; cam->bulk_size = FPIX_MAX_TRANSFER; INIT_WORK(&dev->work_struct, dostream); diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index b12974d5e..c3c17faa3 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1,7 +1,7 @@ /* * Main USB camera driver * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> + * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.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 @@ -51,7 +51,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 5, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 6, 0) #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; @@ -453,7 +453,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) * look for an input transfer endpoint in an alternate setting */ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, - __u8 xfer) + int xfer) { struct usb_host_endpoint *ep; int i, attr; @@ -461,7 +461,8 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, for (i = 0; i < alt->desc.bNumEndpoints; i++) { ep = &alt->endpoint[i]; attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (attr == xfer) + if (attr == xfer + && ep->desc.wMaxPacketSize != 0) return ep; } return NULL; @@ -479,37 +480,28 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) { struct usb_interface *intf; struct usb_host_endpoint *ep; - int i, ret; + int xfer, i, ret; intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); ep = NULL; + xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK + : USB_ENDPOINT_XFER_ISOC; i = gspca_dev->alt; /* previous alt setting */ - - /* try isoc */ while (--i >= 0) { - ep = alt_xfer(&intf->altsetting[i], - USB_ENDPOINT_XFER_ISOC); + ep = alt_xfer(&intf->altsetting[i], xfer); if (ep) break; } - - /* if no isoc, try bulk (alt 0 only) */ if (ep == NULL) { - ep = alt_xfer(&intf->altsetting[0], - USB_ENDPOINT_XFER_BULK); - if (ep == NULL) { - err("no transfer endpoint found"); - return NULL; - } - i = 0; - gspca_dev->bulk = 1; + err("no transfer endpoint found"); + return NULL; } PDEBUG(D_STREAM, "use alt %d ep 0x%02x", i, ep->desc.bEndpointAddress); - if (i > 0) { + if (gspca_dev->nbalt > 1) { ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); if (ret < 0) { - err("set interface err %d", ret); + err("set alt %d err %d", i, ret); return NULL; } } @@ -529,13 +521,13 @@ static int create_urbs(struct gspca_dev *gspca_dev, /* calculate the packet size and the number of packets */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); - if (!gspca_dev->bulk) { /* isoc */ + if (!gspca_dev->cam.bulk) { /* isoc */ /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - npkt = ISO_MAX_SIZE / psize; - if (npkt > ISO_MAX_PKT) - npkt = ISO_MAX_PKT; + npkt = gspca_dev->cam.npkt; + if (npkt == 0) + npkt = 32; /* default value */ bsize = psize * npkt; PDEBUG(D_STREAM, "isoc %d pkts size %d = bsize:%d", @@ -629,7 +621,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) goto out; /* clear the bulk endpoint */ - if (gspca_dev->bulk) + if (gspca_dev->cam.bulk) usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); @@ -642,7 +634,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->streaming = 1; /* some bulk transfers are started by the subdriver */ - if (gspca_dev->bulk && gspca_dev->cam.bulk_nurbs == 0) + if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0) break; /* submit the URBs */ @@ -673,6 +665,8 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) { int ret; + if (gspca_dev->alt == 0) + return 0; ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0); if (ret < 0) PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret); diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index 58e8ff021..bd1faff88 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -44,8 +44,6 @@ extern int gspca_debug; #define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ /* image transfers */ #define MAX_NURBS 4 /* max number of URBs */ -#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */ -#define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */ /* device information - set at probe time */ struct cam { @@ -56,6 +54,9 @@ struct cam { * - cannot be > MAX_NURBS * - when 0 and bulk_size != 0 means * 1 URB and submit done by subdriver */ + u8 bulk; /* image transfer by 0:isoc / 1:bulk */ + 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 */ }; @@ -168,7 +169,6 @@ struct gspca_dev { __u8 iface; /* USB interface number */ __u8 alt; /* USB alternate setting */ __u8 nbalt; /* number of USB alternate settings */ - u8 bulk; /* image transfer by 0:isoc / 1:bulk */ }; int gspca_dev_probe(struct usb_interface *intf, diff --git a/linux/drivers/media/video/gspca/m5602/Makefile b/linux/drivers/media/video/gspca/m5602/Makefile index 9fa3644f4..bf7a19a1e 100644 --- a/linux/drivers/media/video/gspca/m5602/Makefile +++ b/linux/drivers/media/video/gspca/m5602/Makefile @@ -2,9 +2,10 @@ obj-$(CONFIG_USB_M5602) += gspca_m5602.o gspca_m5602-objs := m5602_core.o \ m5602_ov9650.o \ + m5602_ov7660.o \ m5602_mt9m111.o \ m5602_po1030.o \ m5602_s5k83a.o \ m5602_s5k4aa.o -EXTRA_CFLAGS += -Idrivers/media/video/gspca
\ No newline at end of file +EXTRA_CFLAGS += -Idrivers/media/video/gspca diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index 34515e54c..1127a405c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -148,10 +148,10 @@ struct sd { }; int m5602_read_bridge( - struct sd *sd, u8 address, u8 *i2c_data); + struct sd *sd, const u8 address, u8 *i2c_data); int m5602_write_bridge( - struct sd *sd, u8 address, u8 i2c_data); + struct sd *sd, const u8 address, const u8 i2c_data); int m5602_write_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 93302f31a..8a5bba16f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -17,6 +17,7 @@ */ #include "m5602_ov9650.h" +#include "m5602_ov7660.h" #include "m5602_mt9m111.h" #include "m5602_po1030.h" #include "m5602_s5k83a.h" @@ -35,7 +36,7 @@ static const __devinitdata struct usb_device_id m5602_table[] = { MODULE_DEVICE_TABLE(usb, m5602_table); /* Reads a byte from the m5602 */ -int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) +int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data) { int err; struct usb_device *udev = sd->gspca_dev.dev; @@ -56,7 +57,7 @@ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) } /* Writes a byte to to the m5602 */ -int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) +int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data) { int err; struct usb_device *udev = sd->gspca_dev.dev; @@ -84,10 +85,11 @@ int m5602_wait_for_i2c(struct sd *sd) { int err; u8 data; + do { err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data); } while ((data & I2C_BUSY) && !err); - return (err < 0) ? err : 0; + return err; } int m5602_read_sensor(struct sd *sd, const u8 address, @@ -111,18 +113,18 @@ int m5602_read_sensor(struct sd *sd, const u8 address, if (err < 0) return err; + /* Sensors with registers that are of only + one byte width are differently read */ + + /* FIXME: This works with the ov9650, but has issues with the po1030 */ if (sd->sensor->i2c_regW == 1) { - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, len); + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1); if (err < 0) return err; err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); - if (err < 0) - return err; } else { err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); - if (err < 0) - return err; } for (i = 0; (i < len) && !err; i++) { @@ -218,6 +220,11 @@ static int m5602_probe_sensor(struct sd *sd) if (!sd->sensor->probe(sd)) return 0; + /* Try the ov7660 */ + sd->sensor = &ov7660; + if (!sd->sensor->probe(sd)) + return 0; + /* Try the s5k83a */ sd->sensor = &s5k83a; if (!sd->sensor->probe(sd)) @@ -421,8 +428,9 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(force_sensor, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(force_sensor, - "force detection of sensor, " - "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030"); + "forces detection of a sensor, " + "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, " + "4 = MT9M111, 5 = PO1030, 6 = OV7660"); module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 241108c78..8c6d2a229 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -36,6 +36,7 @@ static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); static struct v4l2_pix_format mt9m111_modes[] = { +#if 0 { 320, 240, @@ -45,7 +46,9 @@ static struct v4l2_pix_format mt9m111_modes[] = { .bytesperline = 320, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0 - }, { + }, +#endif + { 640, 480, V4L2_PIX_FMT_SBGGR8, @@ -67,7 +70,7 @@ const static struct ctrl mt9m111_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1 + .default_value = 0 }, .set = mt9m111_set_vflip, .get = mt9m111_get_vflip @@ -81,7 +84,7 @@ const static struct ctrl mt9m111_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1 + .default_value = 0 }, .set = mt9m111_set_hflip, .get = mt9m111_get_hflip @@ -95,7 +98,7 @@ const static struct ctrl mt9m111_ctrls[] = { .minimum = 0, .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, .step = 1, - .default_value = DEFAULT_GAIN, + .default_value = MT9M111_DEFAULT_GAIN, .flags = V4L2_CTRL_FLAG_SLIDER }, .set = mt9m111_set_gain, @@ -347,7 +350,8 @@ int mt9m111_start(struct sd *sd) (sensor_settings[VFLIP_IDX] << 0) | (sensor_settings[HFLIP_IDX] << 1); - err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + err = m5602_write_sensor(sd, + MT9M111_SC_R_MODE_CONTEXT_B, data, 2); break; case 320: @@ -357,7 +361,8 @@ int mt9m111_start(struct sd *sd) MT9M111_RMB_COLUMN_SKIP_4X | (sensor_settings[VFLIP_IDX] << 0) | (sensor_settings[HFLIP_IDX] << 1); - err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + err = m5602_write_sensor(sd, + MT9M111_SC_R_MODE_CONTEXT_B, data, 2); break; } return err; @@ -391,6 +396,9 @@ static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) sensor_settings[VFLIP_IDX] = val; + /* The mt9m111 is flipped by default */ + val = !val; + /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) @@ -427,6 +435,10 @@ static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set horizontal flip to %d", val); sensor_settings[HFLIP_IDX] = val; + + /* The mt9m111 is flipped by default */ + val = !val; + /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 716aba523..b3de77823 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -97,7 +97,7 @@ #define MT9M111_2D_DEFECT_CORRECTION_ENABLE (1 << 0) #define INITIAL_MAX_GAIN 64 -#define DEFAULT_GAIN 283 +#define MT9M111_DEFAULT_GAIN 283 #define MT9M111_GREEN_GAIN_DEFAULT 0x20 #define MT9M111_BLUE_GAIN_DEFAULT 0x20 #define MT9M111_RED_GAIN_DEFAULT 0x20 @@ -113,7 +113,7 @@ int mt9m111_init(struct sd *sd); int mt9m111_start(struct sd *sd); void mt9m111_disconnect(struct sd *sd); -const static struct m5602_sensor mt9m111 = { +static const struct m5602_sensor mt9m111 = { .name = "MT9M111", .i2c_slave_id = 0xba, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c new file mode 100644 index 000000000..7aafeb7cf --- /dev/null +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c @@ -0,0 +1,227 @@ +/* + * Driver for the ov7660 sensor + * + * Copyright (C) 2009 Erik Andrén + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include "m5602_ov7660.h" + +static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val); + +const static struct ctrl ov7660_ctrls[] = { +#define GAIN_IDX 1 + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = OV7660_DEFAULT_GAIN, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov7660_set_gain, + .get = ov7660_get_gain + }, +}; + +static struct v4l2_pix_format ov7660_modes[] = { + { + 640, + 480, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 640 * 480, + .bytesperline = 640, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + +static void ov7660_dump_registers(struct sd *sd); + +int ov7660_probe(struct sd *sd) +{ + int err = 0, i; + u8 prod_id = 0, ver_id = 0; + + s32 *sensor_settings; + + if (force_sensor) { + if (force_sensor == OV7660_SENSOR) { + info("Forcing an %s sensor", ov7660.name); + goto sensor_found; + } + /* If we want to force another sensor, + don't try to probe this one */ + return -ENODEV; + } + + /* Do the preinit */ + for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) { + u8 data[2]; + + if (preinit_ov7660[i][0] == BRIDGE) { + err = m5602_write_bridge(sd, + preinit_ov7660[i][1], + preinit_ov7660[i][2]); + } else { + data[0] = preinit_ov7660[i][2]; + err = m5602_write_sensor(sd, + preinit_ov7660[i][1], data, 1); + } + } + if (err < 0) + return err; + + if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1)) + return -ENODEV; + + if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1)) + return -ENODEV; + + info("Sensor reported 0x%x%x", prod_id, ver_id); + + if ((prod_id == 0x76) && (ver_id == 0x60)) { + info("Detected a ov7660 sensor"); + goto sensor_found; + } + return -ENODEV; + +sensor_found: + sensor_settings = kmalloc( + ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + + sd->gspca_dev.cam.cam_mode = ov7660_modes; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); + sd->desc->ctrls = ov7660_ctrls; + sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls); + + for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++) + sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value; + sd->sensor_priv = sensor_settings; + + return 0; +} + +int ov7660_init(struct sd *sd) +{ + int i, err = 0; + s32 *sensor_settings = sd->sensor_priv; + + /* Init the sensor */ + for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) { + u8 data[2]; + + if (init_ov7660[i][0] == BRIDGE) { + err = m5602_write_bridge(sd, + init_ov7660[i][1], + init_ov7660[i][2]); + } else { + data[0] = init_ov7660[i][2]; + err = m5602_write_sensor(sd, + init_ov7660[i][1], data, 1); + } + } + + if (dump_sensor) + ov7660_dump_registers(sd); + + err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + + return err; +} + +int ov7660_start(struct sd *sd) +{ + return 0; +} + +int ov7660_stop(struct sd *sd) +{ + return 0; +} + +void ov7660_disconnect(struct sd *sd) +{ + ov7660_stop(sd); + + sd->sensor = NULL; + kfree(sd->sensor_priv); +} + +static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[GAIN_IDX]; + PDEBUG(D_V4L2, "Read gain %d", *val); + return 0; +} + +static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + PDEBUG(D_V4L2, "Setting gain to %d", val); + + sensor_settings[GAIN_IDX] = val; + + err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1); + return err; +} + +static void ov7660_dump_registers(struct sd *sd) +{ + int address; + info("Dumping the ov7660 register state"); + for (address = 0; address < 0xa9; address++) { + u8 value; + m5602_read_sensor(sd, address, &value, 1); + info("register 0x%x contains 0x%x", + address, value); + } + + info("ov7660 register state dump complete"); + + info("Probing for which registers that are read/write"); + for (address = 0; address < 0xff; address++) { + u8 old_value, ctrl_value; + u8 test_value[2] = {0xff, 0xff}; + + m5602_read_sensor(sd, address, &old_value, 1); + m5602_write_sensor(sd, address, test_value, 1); + m5602_read_sensor(sd, address, &ctrl_value, 1); + + if (ctrl_value == test_value[0]) + info("register 0x%x is writeable", address); + else + info("register 0x%x is read only", address); + + /* Restore original value */ + m5602_write_sensor(sd, address, &old_value, 1); + } +} diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h new file mode 100644 index 000000000..3f2c169a9 --- /dev/null +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h @@ -0,0 +1,279 @@ +/* + * Driver for the ov7660 sensor + * + * Copyright (C) 2009 Erik Andrén + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_OV7660_H_ +#define M5602_OV7660_H_ + +#include "m5602_sensor.h" + +#define OV7660_GAIN 0x00 +#define OV7660_BLUE_GAIN 0x01 +#define OV7660_RED_GAIN 0x02 +#define OV7660_VREF 0x03 +#define OV7660_COM1 0x04 +#define OV7660_BAVE 0x05 +#define OV7660_GEAVE 0x06 +#define OV7660_AECHH 0x07 +#define OV7660_RAVE 0x08 +#define OV7660_COM2 0x09 +#define OV7660_PID 0x0a +#define OV7660_VER 0x0b +#define OV7660_COM3 0x0c +#define OV7660_COM4 0x0d +#define OV7660_COM5 0x0e +#define OV7660_COM6 0x0f +#define OV7660_AECH 0x10 +#define OV7660_CLKRC 0x11 +#define OV7660_COM7 0x12 +#define OV7660_COM8 0x13 +#define OV7660_COM9 0x14 +#define OV7660_COM10 0x15 +#define OV7660_RSVD16 0x16 +#define OV7660_HSTART 0x17 +#define OV7660_HSTOP 0x18 +#define OV7660_VSTART 0x19 +#define OV7660_VSTOP 0x1a +#define OV7660_PSHFT 0x1b +#define OV7660_MIDH 0x1c +#define OV7660_MIDL 0x1d +#define OV7660_MVFP 0x1e +#define OV7660_LAEC 0x1f +#define OV7660_BOS 0x20 +#define OV7660_GBOS 0x21 +#define OV7660_GROS 0x22 +#define OV7660_ROS 0x23 +#define OV7660_AEW 0x24 +#define OV7660_AEB 0x25 +#define OV7660_VPT 0x26 +#define OV7660_BBIAS 0x27 +#define OV7660_GbBIAS 0x28 +#define OV7660_RSVD29 0x29 +#define OV7660_RBIAS 0x2c +#define OV7660_HREF 0x32 +#define OV7660_ADC 0x37 +#define OV7660_OFON 0x39 +#define OV7660_TSLB 0x3a +#define OV7660_COM12 0x3c +#define OV7660_COM13 0x3d +#define OV7660_LCC1 0x62 +#define OV7660_LCC2 0x63 +#define OV7660_LCC3 0x64 +#define OV7660_LCC4 0x65 +#define OV7660_LCC5 0x66 +#define OV7660_HV 0x69 +#define OV7660_RSVDA1 0xa1 + +#define OV7660_DEFAULT_GAIN 0x0e +#define OV7660_DEFAULT_RED_GAIN 0x80 +#define OV7660_DEFAULT_BLUE_GAIN 0x80 +#define OV7660_DEFAULT_SATURATION 0x00 +#define OV7660_DEFAULT_EXPOSURE 0x20 + +/* Kernel module parameters */ +extern int force_sensor; +extern int dump_sensor; + +int ov7660_probe(struct sd *sd); +int ov7660_init(struct sd *sd); +int ov7660_start(struct sd *sd); +int ov7660_stop(struct sd *sd); +void ov7660_disconnect(struct sd *sd); + +const static struct m5602_sensor ov7660 = { + .name = "ov7660", + .i2c_slave_id = 0x42, + .i2c_regW = 1, + .probe = ov7660_probe, + .init = ov7660_init, + .start = ov7660_start, + .stop = ov7660_stop, + .disconnect = ov7660_disconnect, +}; + +static const unsigned char preinit_ov7660[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + + {SENSOR, OV7660_OFON, 0x0c}, + {SENSOR, OV7660_COM2, 0x11}, + {SENSOR, OV7660_COM7, 0x05}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00} +}; + +static const unsigned char init_ov7660[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + + {SENSOR, OV7660_OFON, 0x0c}, + {SENSOR, OV7660_COM2, 0x11}, + {SENSOR, OV7660_COM7, 0x05}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + + {SENSOR, OV7660_AECH, OV7660_DEFAULT_EXPOSURE}, + {SENSOR, OV7660_COM1, 0x00}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, + + {SENSOR, OV7660_COM7, 0x80}, + {SENSOR, OV7660_CLKRC, 0x80}, + {SENSOR, OV7660_BLUE_GAIN, 0x80}, + {SENSOR, OV7660_RED_GAIN, 0x80}, + {SENSOR, OV7660_COM9, 0x4c}, + {SENSOR, OV7660_OFON, 0x43}, + {SENSOR, OV7660_COM12, 0x28}, + {SENSOR, OV7660_COM8, 0x00}, + {SENSOR, OV7660_COM10, 0x40}, + {SENSOR, OV7660_HSTART, 0x0c}, + {SENSOR, OV7660_HSTOP, 0x61}, + {SENSOR, OV7660_HREF, 0xa4}, + {SENSOR, OV7660_PSHFT, 0x0b}, + {SENSOR, OV7660_VSTART, 0x01}, + {SENSOR, OV7660_VSTOP, 0x7a}, + {SENSOR, OV7660_VREF, 0x00}, + {SENSOR, OV7660_COM7, 0x05}, + {SENSOR, OV7660_COM6, 0x4b}, + {SENSOR, OV7660_BBIAS, 0x98}, + {SENSOR, OV7660_GbBIAS, 0x98}, + {SENSOR, OV7660_RSVD29, 0x98}, + {SENSOR, OV7660_RBIAS, 0x98}, + {SENSOR, OV7660_COM1, 0x00}, + {SENSOR, OV7660_AECH, 0x00}, + {SENSOR, OV7660_AECHH, 0x00}, + {SENSOR, OV7660_ADC, 0x04}, + {SENSOR, OV7660_COM13, 0x00}, + {SENSOR, OV7660_RSVDA1, 0x23}, + {SENSOR, OV7660_TSLB, 0x0d}, + {SENSOR, OV7660_HV, 0x80}, + {SENSOR, OV7660_LCC1, 0x00}, + {SENSOR, OV7660_LCC2, 0x00}, + {SENSOR, OV7660_LCC3, 0x10}, + {SENSOR, OV7660_LCC4, 0x40}, + {SENSOR, OV7660_LCC5, 0x01}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x27}, /* 39 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xa7}, /* 679 */ + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + + {SENSOR, OV7660_AECH, 0x20}, + {SENSOR, OV7660_COM1, 0x00}, + {SENSOR, OV7660_OFON, 0x0c}, + {SENSOR, OV7660_COM2, 0x11}, + {SENSOR, OV7660_COM7, 0x05}, + {SENSOR, OV7660_BLUE_GAIN, 0x80}, + {SENSOR, OV7660_RED_GAIN, 0x80}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0} +}; + +#endif diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index f0e335533..bbf9935df 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -47,6 +47,14 @@ static #endif struct dmi_system_id ov9650_flip_dmi_table[] = { { + .ident = "ASUS A6VA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6VA") + } + }, + { + .ident = "ASUS A6VC", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), @@ -82,6 +90,13 @@ static } }, { + .ident = "ASUS A6K", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6K") + } + }, + { .ident = "Alienware Aurora m9700", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "alienware"), @@ -91,7 +106,7 @@ static {} }; -const static struct ctrl ov9650_ctrls[] = { +static const struct ctrl ov9650_ctrls[] = { #define EXPOSURE_IDX 0 { { @@ -125,6 +140,7 @@ const static struct ctrl ov9650_ctrls[] = { #define RED_BALANCE_IDX 2 { { + .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "red balance", .minimum = 0x00, @@ -139,6 +155,7 @@ const static struct ctrl ov9650_ctrls[] = { #define BLUE_BALANCE_IDX 3 { { + .id = V4L2_CID_BLUE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "blue balance", .minimum = 0x00, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 27fe54204..c98c40d69 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -143,7 +143,7 @@ int ov9650_start(struct sd *sd); int ov9650_stop(struct sd *sd); void ov9650_disconnect(struct sd *sd); -const static struct m5602_sensor ov9650 = { +static const struct m5602_sensor ov9650 = { .name = "OV9650", .i2c_slave_id = 0x60, .i2c_regW = 1, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 840a3ca53..633636365 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -42,6 +42,7 @@ static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); static struct v4l2_pix_format po1030_modes[] = { +#if 0 { 320, 240, @@ -51,7 +52,9 @@ static struct v4l2_pix_format po1030_modes[] = { .bytesperline = 320, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 2 - }, { + }, +#endif + { 640, 480, V4L2_PIX_FMT_SBGGR8, @@ -63,7 +66,7 @@ static struct v4l2_pix_format po1030_modes[] = { } }; -const static struct ctrl po1030_ctrls[] = { +static const struct ctrl po1030_ctrls[] = { #define GAIN_IDX 0 { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 06da4b3ed..81f24d413 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -61,6 +61,12 @@ static DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700") } + }, { + .ident = "MSI L735", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X") + } }, { } }; @@ -76,10 +82,21 @@ static struct v4l2_pix_format s5k4aa_modes[] = { .bytesperline = 640, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0 + }, + { + 1280, + 1024, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 1280 * 1024, + .bytesperline = 1280, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 } }; -const static struct ctrl s5k4aa_ctrls[] = { +static const struct ctrl s5k4aa_ctrls[] = { #define VFLIP_IDX 0 { { @@ -257,8 +274,45 @@ int s5k4aa_start(struct sd *sd) int i, err = 0; u8 data[2]; struct cam *cam = &sd->gspca_dev.cam; + s32 *sensor_settings = sd->sensor_priv; switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { + case 1280: + PDEBUG(D_V4L2, "Configuring camera for SXGA mode"); + + for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) { + switch (SXGA_s5k4aa[i][0]) { + case BRIDGE: + err = m5602_write_bridge(sd, + SXGA_s5k4aa[i][1], + SXGA_s5k4aa[i][2]); + break; + + case SENSOR: + data[0] = SXGA_s5k4aa[i][2]; + err = m5602_write_sensor(sd, + SXGA_s5k4aa[i][1], + data, 1); + break; + + case SENSOR_LONG: + data[0] = SXGA_s5k4aa[i][2]; + data[1] = SXGA_s5k4aa[i][3]; + err = m5602_write_sensor(sd, + SXGA_s5k4aa[i][1], + data, 2); + break; + + default: + err("Invalid stream command, exiting init"); + return -EINVAL; + } + } + err = s5k4aa_set_noise(&sd->gspca_dev, 0); + if (err < 0) + return err; + break; + case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); @@ -290,14 +344,42 @@ int s5k4aa_start(struct sd *sd) return -EINVAL; } } + err = s5k4aa_set_noise(&sd->gspca_dev, 1); + if (err < 0) + return err; + break; } - return err; + if (err < 0) + return err; + + err = s5k4aa_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + + err = s5k4aa_set_brightness(&sd->gspca_dev, + sensor_settings[BRIGHTNESS_IDX]); + if (err < 0) + return err; + + err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]); + if (err < 0) + return err; + + err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + if (err < 0) + return err; + + return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); } int s5k4aa_init(struct sd *sd) { int i, err = 0; - s32 *sensor_settings = sd->sensor_priv; for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) { u8 data[2] = {0x00, 0x00}; @@ -330,29 +412,7 @@ int s5k4aa_init(struct sd *sd) if (dump_sensor) s5k4aa_dump_registers(sd); - err = s5k4aa_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_brightness(&sd->gspca_dev, - sensor_settings[BRIGHTNESS_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); - if (err < 0) - return err; - - return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + return err; } static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) @@ -423,31 +483,16 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (dmi_check_system(s5k4aa_vflip_dmi_table)) val = !val; - data = ((data & ~S5K4AA_RM_V_FLIP) - | ((val & 0x01) << 7)); + data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) return err; - if (dmi_check_system(s5k4aa_vflip_dmi_table)) - val = !val; - - if (val) { - err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - if (err < 0) - return err; - - data++; - err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - } else { - err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - if (err < 0) - return err; - - data--; - err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - } - + err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + if (err < 0) + return err; + data = (data & 0xfe) | !val; + err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); return err; } @@ -483,27 +528,19 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; + if (dmi_check_system(s5k4aa_vflip_dmi_table)) + val = !val; + data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) return err; - if (val) { - err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - if (err < 0) - return err; - data++; - err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - if (err < 0) - return err; - } else { - err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - if (err < 0) - return err; - data--; - err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - } - + err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + if (err < 0) + return err; + data = (data & 0xfe) | !val; + err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 2349174ad..4440da4e7 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -175,27 +175,12 @@ static const unsigned char init_s5k4aa[][4] = {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, {SENSOR, 0x0c, 0x05, 0x00}, {SENSOR, 0x02, 0x0e, 0x00}, - {SENSOR, 0x11, 0x00, 0x00}, - {SENSOR, 0x12, 0x00, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00}, {SENSOR, 0x37, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, - {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00}, - {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, - {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00}, - {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00}, - {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00}, - {SENSOR, 0x11, 0x04, 0x00}, - {SENSOR, 0x12, 0xc3, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, +}; +static const unsigned char VGA_s5k4aa[][4] = +{ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, @@ -231,7 +216,7 @@ static const unsigned char init_s5k4aa[][4] = {SENSOR, 0x37, 0x01, 0x00}, /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, + {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00}, {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, /* window_height_hi, window_height_lo : 960 = 0x03c0 */ @@ -250,7 +235,7 @@ static const unsigned char init_s5k4aa[][4] = {SENSOR, 0x02, 0x0e, 0x00}, }; -static const unsigned char VGA_s5k4aa[][4] = +static const unsigned char SXGA_s5k4aa[][4] = { {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, @@ -263,41 +248,35 @@ static const unsigned char VGA_s5k4aa[][4] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, + /* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00}, + /* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X - | S5K4AA_RM_COL_SKIP_2X, 0x00}, - /* 0x37 : Fix image stability when light is too bright and improves - * image quality in 640x480, but worsens it in 1280x1024 */ + {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00}, {SENSOR, 0x37, 0x01, 0x00}, - /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00}, + {SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00}, {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, - /* window_height_hi, window_height_lo : 960 = 0x03c0 */ - {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00}, - /* window_width_hi, window_width_lo : 1280 = 0x0500 */ + {SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00}, + {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00}, + {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00}, {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */ + {SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00}, + {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, {SENSOR, 0x11, 0x04, 0x00}, @@ -306,4 +285,5 @@ static const unsigned char VGA_s5k4aa[][4] = {SENSOR, 0x02, 0x0e, 0x00}, }; + #endif diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index e1529afd4..7127321ac 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -44,7 +44,7 @@ static struct v4l2_pix_format s5k83a_modes[] = { } }; -const static struct ctrl s5k83a_ctrls[] = { +static const struct ctrl s5k83a_ctrls[] = { #define GAIN_IDX 0 { { @@ -124,7 +124,8 @@ const static struct ctrl s5k83a_ctrls[] = { static void s5k83a_dump_registers(struct sd *sd); static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data); static int s5k83a_set_led_indication(struct sd *sd, u8 val); -int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip); +static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, + __s32 vflip, __s32 hflip); int s5k83a_probe(struct sd *sd) { @@ -198,6 +199,8 @@ sensor_found: int s5k83a_init(struct sd *sd) { int i, err = 0; + s32 *sensor_settings = + ((struct s5k83a_priv *) sd->sensor_priv)->settings; for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) { u8 data[2] = {0x00, 0x00}; @@ -230,7 +233,27 @@ int s5k83a_init(struct sd *sd) if (dump_sensor) s5k83a_dump_registers(sd); - return (err < 0) ? err : 0; + err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + + err = s5k83a_set_brightness(&sd->gspca_dev, + sensor_settings[BRIGHTNESS_IDX]); + if (err < 0) + return err; + + err = s5k83a_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + if (err < 0) + return err; + + err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + + return err; } static int rotation_thread_function(void *data) @@ -257,7 +280,8 @@ static int rotation_thread_function(void *data) vflip = !vflip; hflip = !hflip; } - s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip); + s5k83a_set_flip_real((struct gspca_dev *) sd, + vflip, hflip); } mutex_unlock(&sd->gspca_dev.usb_lock); @@ -277,14 +301,29 @@ static int rotation_thread_function(void *data) int s5k83a_start(struct sd *sd) { + int i, err = 0; struct s5k83a_priv *sens_priv = sd->sensor_priv; /* Create another thread, polling the GPIO ports of the camera to check if it got rotated. This is how the windows driver does it so we have to assume that there is no better way of accomplishing this */ - sens_priv->rotation_thread = kthread_create(rotation_thread_function, sd, "rotation thread"); + sens_priv->rotation_thread = kthread_create(rotation_thread_function, + sd, "rotation thread"); wake_up_process(sens_priv->rotation_thread); + /* Preinit the sensor */ + for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) { + u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]}; + if (start_s5k83a[i][0] == SENSOR) + err = m5602_write_sensor(sd, start_s5k83a[i][1], + data, 2); + else + err = m5602_write_bridge(sd, start_s5k83a[i][1], + data[0]); + } + if (err < 0) + return err; + return s5k83a_set_led_indication(sd, 1); } @@ -402,7 +441,8 @@ static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip) +static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, + __s32 vflip, __s32 hflip) { int err; u8 data[1]; @@ -505,7 +545,7 @@ static int s5k83a_set_led_indication(struct sd *sd, u8 val) err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]); - return (err < 0) ? err : 0; + return err; } /* Get camera rotation on Acer notebooks */ diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 0697f8a99..7814b078a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -110,32 +110,8 @@ static const unsigned char preinit_s5k83a[][4] = */ static const unsigned char init_s5k83a[][4] = { - {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, - {SENSOR, 0xaf, 0x01, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, - {SENSOR, 0x7b, 0xff, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR, 0x01, 0x50, 0x00}, - {SENSOR, 0x12, 0x20, 0x00}, - {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, 0x1c, 0x00, 0x00}, - {SENSOR, 0x02, 0x70, 0x00}, - {SENSOR, 0x03, 0x0b, 0x00}, - {SENSOR, 0x04, 0xf0, 0x00}, - {SENSOR, 0x05, 0x0b, 0x00}, - - {SENSOR, 0x06, 0x71, 0x00}, - {SENSOR, 0x07, 0xe8, 0x00}, - {SENSOR, 0x08, 0x02, 0x00}, - {SENSOR, 0x09, 0x88, 0x00}, - {SENSOR, 0x14, 0x00, 0x00}, - {SENSOR, 0x15, 0x20, 0x00}, - {SENSOR, 0x19, 0x00, 0x00}, - {SENSOR, 0x1a, 0x98, 0x00}, - {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, - - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + /* The following sequence is useless after a clean boot + but is necessary after resume from suspend */ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, @@ -155,7 +131,7 @@ static const unsigned char init_s5k83a[][4] = {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, @@ -164,8 +140,7 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, {SENSOR, 0xaf, 0x01, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - /* ff ( init value )is very dark) || 71 and f0 better */ + {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, {SENSOR, 0x7b, 0xff, 0x00}, {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, {SENSOR, 0x01, 0x50, 0x00}, @@ -173,66 +148,26 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x17, 0x40, 0x00}, {SENSOR, 0x1c, 0x00, 0x00}, {SENSOR, 0x02, 0x70, 0x00}, - /* some values like 0x10 give a blue-purple image */ {SENSOR, 0x03, 0x0b, 0x00}, {SENSOR, 0x04, 0xf0, 0x00}, {SENSOR, 0x05, 0x0b, 0x00}, - {SENSOR, 0x06, 0x71, 0x00}, - {SENSOR, 0x07, 0xe8, 0x00}, + {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */ {SENSOR, 0x08, 0x02, 0x00}, - {SENSOR, 0x09, 0x88, 0x00}, + {SENSOR, 0x09, 0x88, 0x00}, /* 648 */ {SENSOR, 0x14, 0x00, 0x00}, - {SENSOR, 0x15, 0x20, 0x00}, + {SENSOR, 0x15, 0x20, 0x00}, /* 32 */ {SENSOR, 0x19, 0x00, 0x00}, - {SENSOR, 0x1a, 0x98, 0x00}, + {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */ {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, - - /* The following sequence is useless after a clean boot - but is necessary after resume from suspend */ - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, - - {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, - {SENSOR, 0xaf, 0x01, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, - {SENSOR, 0x7b, 0xff, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR, 0x01, 0x50, 0x00}, - {SENSOR, 0x12, 0x20, 0x00}, - {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, S5K83A_GAIN, 0x0f, 0x00}, - {SENSOR, 0x1c, 0x00, 0x00}, - {SENSOR, 0x02, 0x70, 0x00}, - {SENSOR, 0x03, 0x0b, 0x00}, - {SENSOR, 0x04, 0xf0, 0x00}, - {SENSOR, 0x05, 0x0b, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */ + /* normal colors + (this is value after boot, but after tries can be different) */ + {SENSOR, 0x00, 0x06, 0x00}, +}; +static const unsigned char start_s5k83a[][4] = +{ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, @@ -257,22 +192,6 @@ static const unsigned char init_s5k83a[][4] = {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - - {SENSOR, 0x06, 0x71, 0x00}, - {SENSOR, 0x07, 0xe8, 0x00}, - {SENSOR, 0x08, 0x02, 0x00}, - {SENSOR, 0x09, 0x88, 0x00}, - {SENSOR, 0x14, 0x00, 0x00}, - {SENSOR, 0x15, 0x20, 0x00}, - {SENSOR, 0x19, 0x00, 0x00}, - {SENSOR, 0x1a, 0x98, 0x00}, - {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - - /* normal colors - (this is value after boot, but after tries can be different) */ - {SENSOR, 0x00, 0x06, 0x00}, }; #endif diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index c3a72117b..edff4f1f5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -30,7 +30,8 @@ enum sensors { S5K83A_SENSOR = 2, S5K4AA_SENSOR = 3, MT9M111_SENSOR = 4, - PO1030_SENSOR = 5 + PO1030_SENSOR = 5, + OV7660_SENSOR = 6, }; /* Enumerates all possible instruction types */ diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 0f5ec9317..1e00e46b1 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -727,8 +727,11 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - cam->bulk_size = 16384; - cam->bulk_nurbs = 2; + if (sd->sensor == SENSOR_OV772X) { + cam->bulk = 1; + cam->bulk_size = 16384; + cam->bulk_nurbs = 2; + } return 0; } @@ -887,18 +890,16 @@ 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) { - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - NULL, 0); + if (gspca_dev->last_packet_type == INTER_PACKET) + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, frame, + NULL, 0); sd->last_pts = this_pts; sd->last_fid = this_fid; - } - - /* Add the data from this payload */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data + 12, len - 12); - /* If this packet is marked as EOF, end the frame */ - if (data[1] & UVC_STREAM_EOF) { + } else if (data[1] & UVC_STREAM_EOF) { sd->last_pts = 0; if (frame->data_end - frame->data != @@ -906,11 +907,16 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, PDEBUG(D_PACK, "short frame"); goto discard; } - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - NULL, 0); + data + 12, len - 12); + } else { + + /* Add the data from this payload */ + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data + 12, len - 12); } + /* Done this payload */ goto scan_next; diff --git a/linux/drivers/media/video/gspca/sonixb.c b/linux/drivers/media/video/gspca/sonixb.c index edb2bfa85..4141cf494 100644 --- a/linux/drivers/media/video/gspca/sonixb.c +++ b/linux/drivers/media/video/gspca/sonixb.c @@ -907,6 +907,8 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); } + cam->npkt = 36; /* 36 packets per ISOC message */ + sd->brightness = BRIGHTNESS_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index c3959f00a..a4c935d69 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -62,7 +62,6 @@ struct sd { #define BRIDGE_SN9C105 1 #define BRIDGE_SN9C110 2 #define BRIDGE_SN9C120 3 -#define BRIDGE_SN9C325 4 u8 sensor; /* Type of image sensor chip */ #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 @@ -358,9 +357,9 @@ static const u8 sn_ov7648[0x1c] = { static const u8 sn_ov7660[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, + 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, /* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20, /* reg18 reg19 reg1a reg1b */ @@ -765,6 +764,7 @@ 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 */ + {0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, /****** (some exchanges in the win trace) ******/ {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ /* bits[3..0]reserved */ @@ -1073,9 +1073,13 @@ static int configure_gpio(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; const u8 *reg9a; static const u8 reg9a_def[] = - {0x08, 0x40, 0x20, 0x10, 0x00, 0x04}; - static const u8 reg9a_sn9c325[] = - {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20}; +#if 1 + {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; +#else + {0x00, 0x40, 0x20, 0x10, 0x00, 0x04}; +#endif + static const u8 reg9a_spec[] = + {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; static const u8 regd4[] = {0x60, 0x00, 0x00}; reg_w1(gspca_dev, 0xf1, 0x00); @@ -1089,9 +1093,10 @@ static int configure_gpio(struct gspca_dev *gspca_dev, 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 */ - switch (sd->bridge) { - case BRIDGE_SN9C325: - reg9a = reg9a_sn9c325; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_SP80708: + reg9a = reg9a_spec; break; default: reg9a = reg9a_def; @@ -1116,32 +1121,24 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x17, 0x64); reg_w1(gspca_dev, 0x01, 0x42); break; -#if 1 -/*jfm: from win trace */ case SENSOR_OV7630: reg_w1(gspca_dev, 0x01, 0x61); reg_w1(gspca_dev, 0x17, 0xe2); reg_w1(gspca_dev, 0x01, 0x60); reg_w1(gspca_dev, 0x01, 0x40); break; -#endif case SENSOR_OV7648: reg_w1(gspca_dev, 0x01, 0x63); reg_w1(gspca_dev, 0x17, 0x20); + reg_w1(gspca_dev, 0x01, 0x62); reg_w1(gspca_dev, 0x01, 0x42); break; -#if 1 -/*jfm: from win trace */ case SENSOR_OV7660: - if (sd->bridge == BRIDGE_SN9C120) { - 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; - } - /* fall thru */ -#endif + 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_SP80708: reg_w1(gspca_dev, 0x01, 0x63); reg_w1(gspca_dev, 0x17, 0x20); @@ -1150,6 +1147,9 @@ static int configure_gpio(struct gspca_dev *gspca_dev, mdelay(100); reg_w1(gspca_dev, 0x02, 0x62); break; +/* case SENSOR_HV7131R: */ +/* case SENSOR_MI0360: */ +/* case SENSOR_MO4000: */ default: reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0x61); @@ -1296,6 +1296,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); + cam->npkt = 24; /* 24 packets per ISOC message */ sd->bridge = id->driver_info >> 16; sd->sensor = id->driver_info >> 8; @@ -1715,15 +1716,9 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7648: reg17 = 0x20; break; -#if 1 -/*jfm: from win trace */ case SENSOR_OV7660: - if (sd->bridge == BRIDGE_SN9C120) { - reg17 = 0xa0; - break; - } - /* fall thru */ -#endif + reg17 = 0xa0; + break; default: reg17 = 0x60; break; @@ -1748,16 +1743,17 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x9a, 0x0a); reg_w1(gspca_dev, 0x99, 0x60); break; + case SENSOR_OV7660: + reg_w1(gspca_dev, 0x9a, 0x05); + if (sd->bridge == BRIDGE_SN9C105) + reg_w1(gspca_dev, 0x99, 0xff); + else + reg_w1(gspca_dev, 0x99, 0x5b); + break; case SENSOR_SP80708: reg_w1(gspca_dev, 0x9a, 0x05); reg_w1(gspca_dev, 0x99, 0x59); break; - case SENSOR_OV7660: - if (sd->bridge == BRIDGE_SN9C120) { - reg_w1(gspca_dev, 0x9a, 0x05); - break; - } - /* fall thru */ default: reg_w1(gspca_dev, 0x9a, 0x08); reg_w1(gspca_dev, 0x99, 0x59); @@ -2232,6 +2228,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {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, 0x6040), BSI(SN9C102P, HV7131R, 0x11)}, /* bw600.inf: {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */ @@ -2250,7 +2247,12 @@ static const __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, #endif + {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ + {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, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/ diff --git a/linux/drivers/media/video/gspca/spca500.c b/linux/drivers/media/video/gspca/spca500.c index 8cfb7cad9..9717da6af 100644 --- a/linux/drivers/media/video/gspca/spca500.c +++ b/linux/drivers/media/video/gspca/spca500.c @@ -32,9 +32,6 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u8 packet[ISO_MAX_SIZE + 128]; - /* !! no more than 128 ff in an ISO packet */ - unsigned char brightness; unsigned char contrast; unsigned char colors; @@ -923,7 +920,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; int i; - __u8 *s, *d; static __u8 ffd9[] = {0xff, 0xd9}; /* frames are jpeg 4.1.1 without 0xff escape */ @@ -947,22 +943,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } /* add 0x00 after 0xff */ - for (i = len; --i >= 0; ) - if (data[i] == 0xff) - break; - if (i < 0) { /* no 0xff */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); - return; - } - s = data; - d = sd->packet; - for (i = 0; i < len; i++) { - *d++ = *s++; - if (s[-1] == 0xff) - *d++ = 0x00; - } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - sd->packet, d - sd->packet); + i = 0; + do { + if (data[i] == 0xff) { + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, i + 1); + len -= i; + data += i; + *data = 0x00; + i = 0; + } + i++; + } while (i < len); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } static void setbrightness(struct gspca_dev *gspca_dev) diff --git a/linux/drivers/media/video/gspca/sq905.c b/linux/drivers/media/video/gspca/sq905.c index 2e1cdf068..715a68f01 100644 --- a/linux/drivers/media/video/gspca/sq905.c +++ b/linux/drivers/media/video/gspca/sq905.c @@ -309,6 +309,7 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *dev = (struct sd *) gspca_dev; /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk = 1; cam->bulk_size = 64; INIT_WORK(&dev->work_struct, sq905_dostream); diff --git a/linux/drivers/media/video/gspca/sq905c.c b/linux/drivers/media/video/gspca/sq905c.c index 0bcb74a1b..916892505 100644 --- a/linux/drivers/media/video/gspca/sq905c.c +++ b/linux/drivers/media/video/gspca/sq905c.c @@ -206,6 +206,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = 1; /* We don't use the buffer gspca allocates so make it small. */ cam->bulk_size = 32; + cam->bulk = 1; INIT_WORK(&dev->work_struct, sq905c_dostream); return 0; } diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c index 69c77c932..11a0c002f 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c @@ -80,12 +80,26 @@ static const struct ctrl vv6410_ctrl[] = { .minimum = 0, .maximum = 15, .step = 1, - .default_value = 0 + .default_value = 10 }, .set = vv6410_set_analog_gain, .get = vv6410_get_analog_gain + }, +#define EXPOSURE_IDX 3 + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0, + .maximum = 32768, + .step = 1, + .default_value = 20000 + }, + .set = vv6410_set_exposure, + .get = vv6410_get_exposure } -}; + }; static int vv6410_probe(struct sd *sd) { @@ -121,6 +135,7 @@ static int vv6410_probe(struct sd *sd) static int vv6410_init(struct sd *sd) { int err = 0, i; + s32 *sensor_settings = sd->sensor_priv; for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) { /* if NULL then len contains single value */ @@ -142,6 +157,16 @@ static int vv6410_init(struct sd *sd) err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init, ARRAY_SIZE(vv6410_sensor_init)); + if (err < 0) + return err; + + err = vv6410_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = vv6410_set_analog_gain(&sd->gspca_dev, + sensor_settings[GAIN_IDX]); return (err < 0) ? err : 0; } @@ -318,3 +343,50 @@ static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val) return (err < 0) ? err : 0; } + +static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[EXPOSURE_IDX]; + + PDEBUG(D_V4L2, "Read exposure %d", *val); + + return 0; +} + +static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + unsigned int fine, coarse; + + sensor_settings[EXPOSURE_IDX] = val; + + val = (val * val >> 14) + val / 4; + + fine = val % VV6410_CIF_LINELENGTH; + coarse = min(512, val / VV6410_CIF_LINELENGTH); + + PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d", + coarse, fine); + + err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8); + if (err < 0) + goto out; + + err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff); + if (err < 0) + goto out; + + err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8); + if (err < 0) + goto out; + + err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff); + +out: + return err; +} diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index 95ac55891..487d40555 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -173,6 +173,8 @@ #define VV6410_SUBSAMPLE 0x01 #define VV6410_CROP_TO_QVGA 0x02 +#define VV6410_CIF_LINELENGTH 415 + static int vv6410_probe(struct sd *sd); static int vv6410_start(struct sd *sd); static int vv6410_init(struct sd *sd); @@ -187,6 +189,8 @@ static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val); static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val); static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val); +static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val); const struct stv06xx_sensor stv06xx_sensor_vv6410 = { .name = "ST VV6410", @@ -242,12 +246,6 @@ static const u8 vv6410_sensor_init[][2] = { /* Pre-clock generator divide off */ {VV6410_DATAFORMAT, BIT(7) | BIT(0)}, - /* Exposure registers */ - {VV6410_FINEH, VV6410_FINE_EXPOSURE >> 8}, - {VV6410_FINEL, VV6410_FINE_EXPOSURE & 0xff}, - {VV6410_COARSEH, VV6410_COARSE_EXPOSURE >> 8}, - {VV6410_COARSEL, VV6410_COARSE_EXPOSURE & 0xff}, - {VV6410_ANALOGGAIN, 0xf0 | VV6410_DEFAULT_GAIN}, {VV6410_CLKDIV, VV6410_CLK_DIV_2}, /* System registers */ diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 428b1e2b7..16bc65dc7 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -32,9 +32,6 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u8 packet[ISO_MAX_SIZE + 128]; - /* !! no more than 128 ff in an ISO packet */ - unsigned char brightness; unsigned char contrast; unsigned char colors; @@ -1134,7 +1131,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; int i, sof = 0; - unsigned char *s, *d; static unsigned char ffd9[] = {0xff, 0xd9}; /* frames are jpeg 4.1.1 without 0xff escape */ @@ -1208,22 +1204,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } /* add 0x00 after 0xff */ - for (i = len; --i >= 0; ) - if (data[i] == 0xff) - break; - if (i < 0) { /* no 0xff */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); - return; - } - s = data; - d = sd->packet; - for (i = 0; i < len; i++) { - *d++ = *s++; - if (s[-1] == 0xff) - *d++ = 0x00; - } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - sd->packet, d - sd->packet); + i = 0; + do { + if (data[i] == 0xff) { + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, i + 1); + len -= i; + data += i; + *data = 0x00; + i = 0; + } + i++; + } while (i < len); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } static void setbrightness(struct gspca_dev *gspca_dev) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index b5026a2d1..a29c85cac 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -42,7 +42,7 @@ struct sd { char bridge; #define BRIDGE_VC0321 0 #define BRIDGE_VC0323 1 - char sensor; + u8 sensor; #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 #define SENSOR_MI1310_SOC 2 @@ -166,7 +166,7 @@ static const struct v4l2_pix_format bi_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 5}, #endif - {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 2, .colorspace = V4L2_COLORSPACE_SRGB, @@ -178,7 +178,7 @@ static const struct v4l2_pix_format bi_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 4}, #endif - {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 2, .colorspace = V4L2_COLORSPACE_SRGB, @@ -190,7 +190,7 @@ static const struct v4l2_pix_format bi_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 3}, #endif - {1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 1280, .sizeimage = 1280 * 1024 * 2, .colorspace = V4L2_COLORSPACE_SRGB, @@ -2905,6 +2905,17 @@ static int sd_config(struct gspca_dev *gspca_dev, struct usb_device *dev = gspca_dev->dev; struct cam *cam; int sensor; + static u8 npkt[] = { /* number of packets per ISOC message */ + 64, /* HV7131R 0 */ + 32, /* MI0360 1 */ + 32, /* MI1310_SOC 2 */ + 64, /* MI1320 3 */ + 128, /* MI1320_SOC 4 */ + 32, /* OV7660 5 */ + 64, /* OV7670 6 */ + 128, /* PO1200 7 */ + 128, /* PO3130NC 8 */ + }; cam = &gspca_dev->cam; sd->bridge = id->driver_info; @@ -2963,6 +2974,8 @@ static int sd_config(struct gspca_dev *gspca_dev, case SENSOR_MI1320_SOC: cam->cam_mode = bi_mode; cam->nmodes = ARRAY_SIZE(bi_mode); + cam->input_flags = V4L2_IN_ST_VFLIP | + V4L2_IN_ST_HFLIP; break; default: cam->cam_mode = vc0323_mode; @@ -2970,6 +2983,7 @@ static int sd_config(struct gspca_dev *gspca_dev, break; } } + cam->npkt = npkt[sd->sensor]; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index 18a7ca2b6..2855ebf90 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -6336,7 +6336,7 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev, retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ - PDEBUG(D_USBO, "i2c r [%02x] -> %04x (%02x)", + PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", reg, retval, retbyte); return retval; } diff --git a/linux/drivers/media/video/hexium_gemini.c b/linux/drivers/media/video/hexium_gemini.c index bcd8144c5..e7dc0aa61 100644 --- a/linux/drivers/media/video/hexium_gemini.c +++ b/linux/drivers/media/video/hexium_gemini.c @@ -225,7 +225,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); - if (i->index < 0 || i->index >= HEXIUM_INPUTS) + if (i->index >= HEXIUM_INPUTS) return -EINVAL; memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); diff --git a/linux/drivers/media/video/hexium_orion.c b/linux/drivers/media/video/hexium_orion.c index 4178edcc2..d559c0e0c 100644 --- a/linux/drivers/media/video/hexium_orion.c +++ b/linux/drivers/media/video/hexium_orion.c @@ -326,7 +326,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); - if (i->index < 0 || i->index >= HEXIUM_INPUTS) + if (i->index >= HEXIUM_INPUTS) return -EINVAL; memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 4ddeb165d..edb81a948 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -305,14 +305,17 @@ int ivtv_waitq(wait_queue_head_t *waitq) /* Generic utility functions */ int ivtv_msleep_timeout(unsigned int msecs, int intr) { - int ret; int timeout = msecs_to_jiffies(msecs); do { set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); timeout = schedule_timeout(timeout); - if (intr && (ret = signal_pending(current))) - return ret; + if (intr) { + int ret = signal_pending(current); + + if (ret) + return ret; + } } while (timeout); return 0; } @@ -947,17 +950,14 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, if (itv == NULL) return -ENOMEM; itv->pdev = pdev; - itv->instance = atomic_inc_return(&ivtv_instance) - 1; + itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv", + &ivtv_instance); retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev); if (retval) { kfree(itv); return retval; } - /* "ivtv + PCI ID" is a bit of a mouthful, so use - "ivtv + instance" instead. */ - snprintf(itv->v4l2_dev.name, sizeof(itv->v4l2_dev.name), - "ivtv%d", itv->instance); IVTV_INFO("Initializing card %d\n", itv->instance); ivtv_process_options(itv); diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c index ceb05bdca..85ac70722 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.c +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c @@ -190,8 +190,8 @@ static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) mask = itv->card->gpio_audio_detect.mask; if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) - vt->rxsubchans = V4L2_TUNER_MODE_STEREO | - V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + vt->rxsubchans = V4L2_TUNER_SUB_STEREO | + V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; else vt->rxsubchans = V4L2_TUNER_SUB_MONO; return 0; diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 4a2d464f0..99f3c39a1 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -180,7 +180,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) /* Wait for any DMA to finish */ prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); - while (itv->i_flags & IVTV_F_I_DMA) { + while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { got_sig = signal_pending(current); if (got_sig) break; @@ -709,7 +709,7 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET && regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE) reg_start = itv->dec_mem - IVTV_DECODER_OFFSET; - else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE) + else if (regs->reg < IVTV_ENCODER_SIZE) reg_start = itv->enc_mem; else return -EINVAL; @@ -1710,7 +1710,8 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) we are waiting unlock first and later lock again. */ mutex_unlock(&itv->serialize_lock); prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); - if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) + if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) && + !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) schedule(); finish_wait(&itv->event_waitq, &wait); mutex_lock(&itv->serialize_lock); diff --git a/linux/drivers/media/video/ivtv/ivtv-irq.c b/linux/drivers/media/video/ivtv/ivtv-irq.c index 6dda1dd03..981171915 100644 --- a/linux/drivers/media/video/ivtv/ivtv-irq.c +++ b/linux/drivers/media/video/ivtv/ivtv-irq.c @@ -202,7 +202,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA bytes_needed, s->name); return -1; } - if (rc && !s->buffers_stolen && (s->s_flags & IVTV_F_S_APPL_IO)) { + if (rc && !s->buffers_stolen && test_bit(IVTV_F_S_APPL_IO, &s->s_flags)) { IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name); IVTV_WARN("Cause: the application is not reading fast enough.\n"); } diff --git a/linux/drivers/media/video/ivtv/ivtv-yuv.c b/linux/drivers/media/video/ivtv/ivtv-yuv.c index 7912ed6b7..c0875378a 100644 --- a/linux/drivers/media/video/ivtv/ivtv-yuv.c +++ b/linux/drivers/media/video/ivtv/ivtv-yuv.c @@ -1063,7 +1063,8 @@ static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); /* if no UDMA is pending and no UDMA is in progress, then the DMA is finished */ - while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { + while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || + test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { /* don't interrupt if the DMA is in progress but break off a still pending DMA. */ got_sig = signal_pending(current); diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c index a48fe216b..caa72fa4c 100644 --- a/linux/drivers/media/video/ivtv/ivtvfb.c +++ b/linux/drivers/media/video/ivtv/ivtvfb.c @@ -298,7 +298,8 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); /* if no UDMA is pending and no UDMA is in progress, then the DMA is finished */ - while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { + while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || + test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { /* don't interrupt if the DMA is in progress but break off a still pending DMA. */ got_sig = signal_pending(current); diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 83f3cae47..8d61ad30a 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -75,53 +75,50 @@ struct mt9m001 { unsigned char autoexposure; }; -static int reg_read(struct soc_camera_device *icd, const u8 reg) +static int reg_read(struct i2c_client *client, const u8 reg) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct i2c_client *client = mt9m001->client; s32 data = i2c_smbus_read_word_data(client, reg); return data < 0 ? data : swab16(data); } -static int reg_write(struct soc_camera_device *icd, const u8 reg, +static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data)); + return i2c_smbus_write_word_data(client, reg, swab16(data)); } -static int reg_set(struct soc_camera_device *icd, const u8 reg, +static int reg_set(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret | data); + return reg_write(client, reg, ret | data); } -static int reg_clear(struct soc_camera_device *icd, const u8 reg, +static int reg_clear(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret & ~data); + return reg_write(client, reg, ret & ~data); } static int mt9m001_init(struct soc_camera_device *icd) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; int ret; dev_dbg(icd->vdev->parent, "%s\n", __func__); if (icl->power) { - ret = icl->power(&mt9m001->client->dev, 1); + ret = icl->power(&client->dev, 1); if (ret < 0) { dev_err(icd->vdev->parent, "Platform failed to power-on the camera.\n"); @@ -131,49 +128,53 @@ static int mt9m001_init(struct soc_camera_device *icd) /* The camera could have been already on, we reset it additionally */ if (icl->reset) - ret = icl->reset(&mt9m001->client->dev); + ret = icl->reset(&client->dev); else ret = -ENODEV; if (ret < 0) { /* Either no platform reset, or platform reset failed */ - ret = reg_write(icd, MT9M001_RESET, 1); + ret = reg_write(client, MT9M001_RESET, 1); if (!ret) - ret = reg_write(icd, MT9M001_RESET, 0); + ret = reg_write(client, MT9M001_RESET, 0); } /* Disable chip, synchronous option update */ if (!ret) - ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0); return ret; } static int mt9m001_release(struct soc_camera_device *icd) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; /* Disable the chip */ - reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + reg_write(client, MT9M001_OUTPUT_CONTROL, 0); if (icl->power) - icl->power(&mt9m001->client->dev, 0); + icl->power(&client->dev, 0); return 0; } static int mt9m001_start_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); + /* Switch to master "normal" mode */ - if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0) + if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } static int mt9m001_stop_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); + /* Stop sensor readout */ - if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0) + if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) return -EIO; return 0; } @@ -222,28 +223,29 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) static int mt9m001_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); int ret; const u16 hblank = 9, vblank = 25; /* Blanking and start values - default... */ - ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); + ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); if (!ret) - ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); + ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank); /* The caller provides a supported format, as verified per * call to icd->try_fmt() */ if (!ret) - ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); + ret = reg_write(client, MT9M001_COLUMN_START, rect->left); if (!ret) - ret = reg_write(icd, MT9M001_ROW_START, rect->top); + ret = reg_write(client, MT9M001_ROW_START, rect->top); if (!ret) - ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); + ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect->width - 1); if (!ret) - ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, + ret = reg_write(client, MT9M001_WINDOW_HEIGHT, rect->height + icd->y_skip_top - 1); if (!ret && mt9m001->autoexposure) { - ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, + ret = reg_write(client, MT9M001_SHUTTER_WIDTH, rect->height + icd->y_skip_top + vblank); if (!ret) { const struct v4l2_queryctrl *qctrl = @@ -312,16 +314,16 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, static int mt9m001_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9m001->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; reg->size = 2; - reg->val = reg_read(icd, reg->reg); + reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) return -EIO; @@ -332,15 +334,15 @@ static int mt9m001_get_register(struct soc_camera_device *icd, static int mt9m001_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9m001->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - if (reg_write(icd, reg->reg, reg->val) < 0) + if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; return 0; @@ -416,12 +418,13 @@ static struct soc_camera_ops mt9m001_ops = { static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); int data; switch (ctrl->id) { case V4L2_CID_VFLIP: - data = reg_read(icd, MT9M001_READ_OPTIONS2); + data = reg_read(client, MT9M001_READ_OPTIONS2); if (data < 0) return -EIO; ctrl->value = !!(data & 0x8000); @@ -435,6 +438,7 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); const struct v4l2_queryctrl *qctrl; int data; @@ -447,9 +451,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro switch (ctrl->id) { case V4L2_CID_VFLIP: if (ctrl->value) - data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000); + data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000); else - data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000); + data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000); if (data < 0) return -EIO; break; @@ -463,7 +467,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; dev_dbg(&icd->dev, "Setting gain %d\n", data); - data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + data = reg_write(client, MT9M001_GLOBAL_GAIN, data); if (data < 0) return -EIO; } else { @@ -481,8 +485,8 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro data = ((gain - 64) * 7 + 28) / 56 + 96; dev_dbg(&icd->dev, "Setting gain from %d to %d\n", - reg_read(icd, MT9M001_GLOBAL_GAIN), data); - data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + reg_read(client, MT9M001_GLOBAL_GAIN), data); + data = reg_write(client, MT9M001_GLOBAL_GAIN, data); if (data < 0) return -EIO; } @@ -500,8 +504,8 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro range / 2) / range + 1; dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n", - reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter); - if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0) + reg_read(client, MT9M001_SHUTTER_WIDTH), shutter); + if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0) return -EIO; icd->exposure = ctrl->value; mt9m001->autoexposure = 0; @@ -510,7 +514,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro case V4L2_CID_EXPOSURE_AUTO: if (ctrl->value) { const u16 vblank = 25; - if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height + + if (reg_write(client, MT9M001_SHUTTER_WIDTH, icd->height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); @@ -529,8 +533,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro * this wasn't our capture interface, so, we wait for the right one */ static int mt9m001_video_probe(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; s32 data; int ret; unsigned long flags; @@ -542,11 +547,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) return -ENODEV; /* Enable the chip */ - data = reg_write(icd, MT9M001_CHIP_ENABLE, 1); + data = reg_write(client, MT9M001_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); /* Read out the chip version register */ - data = reg_read(icd, MT9M001_CHIP_VERSION); + data = reg_read(client, MT9M001_CHIP_VERSION); /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ switch (data) { @@ -604,10 +609,13 @@ ei2c: static void mt9m001_video_remove(struct soc_camera_device *icd) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, icd->dev.parent, icd->vdev); soc_camera_video_stop(icd); + if (icl->free_bus) + icl->free_bus(icl); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 69498d519..77639ae5c 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -113,10 +113,10 @@ * mt9m111: Camera control register addresses (0x200..0x2ff not implemented) */ -#define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg) -#define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val)) -#define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val)) -#define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val)) +#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg) +#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val)) +#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val)) +#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val)) #define MT9M111_MIN_DARK_ROWS 8 #define MT9M111_MIN_DARK_COLS 24 @@ -184,58 +184,55 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg) return ret; } -static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg) +static int mt9m111_reg_read(struct i2c_client *client, const u16 reg) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct i2c_client *client = mt9m111->client; int ret; ret = reg_page_map_set(client, reg); if (!ret) ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff))); - dev_dbg(&icd->dev, "read reg.%03x -> %04x\n", reg, ret); + dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret); return ret; } -static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg, +static int mt9m111_reg_write(struct i2c_client *client, const u16 reg, const u16 data) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct i2c_client *client = mt9m111->client; int ret; ret = reg_page_map_set(client, reg); if (!ret) - ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff), + ret = i2c_smbus_write_word_data(client, (reg & 0xff), swab16(data)); - dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); + dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); return ret; } -static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg, +static int mt9m111_reg_set(struct i2c_client *client, const u16 reg, const u16 data) { int ret; - ret = mt9m111_reg_read(icd, reg); + ret = mt9m111_reg_read(client, reg); if (ret >= 0) - ret = mt9m111_reg_write(icd, reg, ret | data); + ret = mt9m111_reg_write(client, reg, ret | data); return ret; } -static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg, +static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, const u16 data) { int ret; - ret = mt9m111_reg_read(icd, reg); - return mt9m111_reg_write(icd, reg, ret & ~data); + ret = mt9m111_reg_read(client, reg); + return mt9m111_reg_write(client, reg, ret & ~data); } static int mt9m111_set_context(struct soc_camera_device *icd, enum mt9m111_context ctxt) { + struct i2c_client *client = to_i2c_client(icd->control); int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B @@ -252,6 +249,7 @@ static int mt9m111_set_context(struct soc_camera_device *icd, static int mt9m111_setup_rect(struct soc_camera_device *icd, struct v4l2_rect *rect) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret, is_raw_format; int width = rect->width; @@ -296,6 +294,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) { + struct i2c_client *client = to_i2c_client(icd->control); int ret; ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); @@ -357,12 +356,13 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) static int mt9m111_enable(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; int ret; if (icl->power) { - ret = icl->power(&mt9m111->client->dev, 1); + ret = icl->power(&client->dev, 1); if (ret < 0) { dev_err(icd->vdev->parent, "Platform failed to power-on the camera.\n"); @@ -378,8 +378,9 @@ static int mt9m111_enable(struct soc_camera_device *icd) static int mt9m111_disable(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; int ret; ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); @@ -387,15 +388,15 @@ static int mt9m111_disable(struct soc_camera_device *icd) mt9m111->powered = 0; if (icl->power) - icl->power(&mt9m111->client->dev, 0); + icl->power(&client->dev, 0); return ret; } static int mt9m111_reset(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); @@ -406,7 +407,7 @@ static int mt9m111_reset(struct soc_camera_device *icd) | MT9M111_RESET_RESET_SOC); if (icl->reset) - icl->reset(&mt9m111->client->dev); + icl->reset(&client->dev); return ret; } @@ -562,15 +563,14 @@ static int mt9m111_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { int val; - - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; - if (reg->match.addr != mt9m111->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - val = mt9m111_reg_read(icd, reg->reg); + val = mt9m111_reg_read(client, reg->reg); reg->size = 2; reg->val = (u64)val; @@ -583,15 +583,15 @@ static int mt9m111_get_register(struct soc_camera_device *icd, static int mt9m111_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; - if (reg->match.addr != mt9m111->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0) + if (mt9m111_reg_write(client, reg->reg, reg->val) < 0) return -EIO; return 0; @@ -672,6 +672,7 @@ static struct soc_camera_ops mt9m111_ops = { static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret; @@ -692,6 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) static int mt9m111_get_global_gain(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); int data; data = reg_read(GLOBAL_GAIN); @@ -703,6 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) { + struct i2c_client *client = to_i2c_client(icd->control); u16 val; if (gain > 63 * 2 * 2) @@ -721,6 +724,7 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret; @@ -737,6 +741,7 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret; @@ -754,6 +759,7 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) static int mt9m111_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int data; @@ -898,6 +904,7 @@ static int mt9m111_release(struct soc_camera_device *icd) */ static int mt9m111_video_probe(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); s32 data; int ret; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index f4e597e6c..381dd0fbe 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -76,64 +76,61 @@ struct mt9t031 { u16 yskip; }; -static int reg_read(struct soc_camera_device *icd, const u8 reg) +static int reg_read(struct i2c_client *client, const u8 reg) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - struct i2c_client *client = mt9t031->client; s32 data = i2c_smbus_read_word_data(client, reg); return data < 0 ? data : swab16(data); } -static int reg_write(struct soc_camera_device *icd, const u8 reg, +static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - return i2c_smbus_write_word_data(mt9t031->client, reg, swab16(data)); + return i2c_smbus_write_word_data(client, reg, swab16(data)); } -static int reg_set(struct soc_camera_device *icd, const u8 reg, +static int reg_set(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret | data); + return reg_write(client, reg, ret | data); } -static int reg_clear(struct soc_camera_device *icd, const u8 reg, +static int reg_clear(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret & ~data); + return reg_write(client, reg, ret & ~data); } -static int set_shutter(struct soc_camera_device *icd, const u32 data) +static int set_shutter(struct i2c_client *client, const u32 data) { int ret; - ret = reg_write(icd, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16); + ret = reg_write(client, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16); if (ret >= 0) - ret = reg_write(icd, MT9T031_SHUTTER_WIDTH, data & 0xffff); + ret = reg_write(client, MT9T031_SHUTTER_WIDTH, data & 0xffff); return ret; } -static int get_shutter(struct soc_camera_device *icd, u32 *data) +static int get_shutter(struct i2c_client *client, u32 *data) { int ret; - ret = reg_read(icd, MT9T031_SHUTTER_WIDTH_UPPER); + ret = reg_read(client, MT9T031_SHUTTER_WIDTH_UPPER); *data = ret << 16; if (ret >= 0) - ret = reg_read(icd, MT9T031_SHUTTER_WIDTH); + ret = reg_read(client, MT9T031_SHUTTER_WIDTH); *data |= ret & 0xffff; return ret < 0 ? ret : 0; @@ -141,12 +138,12 @@ static int get_shutter(struct soc_camera_device *icd, u32 *data) static int mt9t031_init(struct soc_camera_device *icd) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - struct soc_camera_link *icl = mt9t031->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; int ret; if (icl->power) { - ret = icl->power(&mt9t031->client->dev, 1); + ret = icl->power(&client->dev, 1); if (ret < 0) { dev_err(icd->vdev->parent, "Platform failed to power-on the camera.\n"); @@ -155,44 +152,48 @@ static int mt9t031_init(struct soc_camera_device *icd) } /* Disable chip output, synchronous option update */ - ret = reg_write(icd, MT9T031_RESET, 1); + ret = reg_write(client, MT9T031_RESET, 1); if (ret >= 0) - ret = reg_write(icd, MT9T031_RESET, 0); + ret = reg_write(client, MT9T031_RESET, 0); if (ret >= 0) - ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); + ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); if (ret < 0 && icl->power) - icl->power(&mt9t031->client->dev, 0); + icl->power(&client->dev, 0); return ret >= 0 ? 0 : -EIO; } static int mt9t031_release(struct soc_camera_device *icd) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - struct soc_camera_link *icl = mt9t031->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; /* Disable the chip */ - reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); + reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); if (icl->power) - icl->power(&mt9t031->client->dev, 0); + icl->power(&client->dev, 0); return 0; } static int mt9t031_start_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); + /* Switch to master "normal" mode */ - if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 2) < 0) + if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } static int mt9t031_stop_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); + /* Stop sensor readout */ - if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2) < 0) + if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } @@ -200,14 +201,16 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd) static int mt9t031_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { + struct i2c_client *client = to_i2c_client(icd->control); + /* The caller should have queried our parameters, check anyway */ if (flags & ~MT9T031_BUS_PARAM) return -EINVAL; if (flags & SOCAM_PCLK_SAMPLE_FALLING) - reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); + reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); else - reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); + reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); return 0; } @@ -235,6 +238,7 @@ static void recalculate_limits(struct soc_camera_device *icd, static int mt9t031_set_params(struct soc_camera_device *icd, struct v4l2_rect *rect, u16 xskip, u16 yskip) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); int ret; u16 xbin, ybin, width, height, left, top; @@ -277,22 +281,22 @@ static int mt9t031_set_params(struct soc_camera_device *icd, } /* Disable register update, reconfigure atomically */ - ret = reg_set(icd, MT9T031_OUTPUT_CONTROL, 1); + ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1); if (ret < 0) return ret; /* Blanking and start values - default... */ - ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank); + ret = reg_write(client, MT9T031_HORIZONTAL_BLANKING, hblank); if (ret >= 0) - ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank); + ret = reg_write(client, MT9T031_VERTICAL_BLANKING, vblank); if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) { /* Binning, skipping */ if (ret >= 0) - ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE, + ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE, ((xbin - 1) << 4) | (xskip - 1)); if (ret >= 0) - ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE, + ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, ((ybin - 1) << 4) | (yskip - 1)); } dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top); @@ -300,16 +304,16 @@ static int mt9t031_set_params(struct soc_camera_device *icd, /* The caller provides a supported format, as guaranteed by * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ if (ret >= 0) - ret = reg_write(icd, MT9T031_COLUMN_START, left); + ret = reg_write(client, MT9T031_COLUMN_START, left); if (ret >= 0) - ret = reg_write(icd, MT9T031_ROW_START, top); + ret = reg_write(client, MT9T031_ROW_START, top); if (ret >= 0) - ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1); + ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1); if (ret >= 0) - ret = reg_write(icd, MT9T031_WINDOW_HEIGHT, + ret = reg_write(client, MT9T031_WINDOW_HEIGHT, height + icd->y_skip_top - 1); if (ret >= 0 && mt9t031->autoexposure) { - ret = set_shutter(icd, height + icd->y_skip_top + vblank); + ret = set_shutter(client, height + icd->y_skip_top + vblank); if (ret >= 0) { const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; const struct v4l2_queryctrl *qctrl = @@ -324,7 +328,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd, /* Re-enable register update, commit all changes */ if (ret >= 0) - ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); + ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1); return ret < 0 ? ret : 0; } @@ -417,15 +421,15 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, static int mt9t031_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9t031->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - reg->val = reg_read(icd, reg->reg); + reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) return -EIO; @@ -436,15 +440,15 @@ static int mt9t031_get_register(struct soc_camera_device *icd, static int mt9t031_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9t031->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - if (reg_write(icd, reg->reg, reg->val) < 0) + if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; return 0; @@ -528,18 +532,19 @@ static struct soc_camera_ops mt9t031_ops = { static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); int data; switch (ctrl->id) { case V4L2_CID_VFLIP: - data = reg_read(icd, MT9T031_READ_MODE_2); + data = reg_read(client, MT9T031_READ_MODE_2); if (data < 0) return -EIO; ctrl->value = !!(data & 0x8000); break; case V4L2_CID_HFLIP: - data = reg_read(icd, MT9T031_READ_MODE_2); + data = reg_read(client, MT9T031_READ_MODE_2); if (data < 0) return -EIO; ctrl->value = !!(data & 0x4000); @@ -553,6 +558,7 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); const struct v4l2_queryctrl *qctrl; int data; @@ -565,17 +571,17 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro switch (ctrl->id) { case V4L2_CID_VFLIP: if (ctrl->value) - data = reg_set(icd, MT9T031_READ_MODE_2, 0x8000); + data = reg_set(client, MT9T031_READ_MODE_2, 0x8000); else - data = reg_clear(icd, MT9T031_READ_MODE_2, 0x8000); + data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000); if (data < 0) return -EIO; break; case V4L2_CID_HFLIP: if (ctrl->value) - data = reg_set(icd, MT9T031_READ_MODE_2, 0x4000); + data = reg_set(client, MT9T031_READ_MODE_2, 0x4000); else - data = reg_clear(icd, MT9T031_READ_MODE_2, 0x4000); + data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000); if (data < 0) return -EIO; break; @@ -589,7 +595,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; dev_dbg(&icd->dev, "Setting gain %d\n", data); - data = reg_write(icd, MT9T031_GLOBAL_GAIN, data); + data = reg_write(client, MT9T031_GLOBAL_GAIN, data); if (data < 0) return -EIO; } else { @@ -609,8 +615,8 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60; dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n", - reg_read(icd, MT9T031_GLOBAL_GAIN), data); - data = reg_write(icd, MT9T031_GLOBAL_GAIN, data); + reg_read(client, MT9T031_GLOBAL_GAIN), data); + data = reg_write(client, MT9T031_GLOBAL_GAIN, data); if (data < 0) return -EIO; } @@ -628,10 +634,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro range / 2) / range + 1; u32 old; - get_shutter(icd, &old); + get_shutter(client, &old); dev_dbg(&icd->dev, "Setting shutter width from %u to %u\n", old, shutter); - if (set_shutter(icd, shutter) < 0) + if (set_shutter(client, shutter) < 0) return -EIO; icd->exposure = ctrl->value; mt9t031->autoexposure = 0; @@ -641,7 +647,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro if (ctrl->value) { const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; - if (set_shutter(icd, icd->height + + if (set_shutter(client, icd->height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); @@ -661,6 +667,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro * this wasn't our capture interface, so, we wait for the right one */ static int mt9t031_video_probe(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); s32 data; int ret; @@ -672,11 +679,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) return -ENODEV; /* Enable the chip */ - data = reg_write(icd, MT9T031_CHIP_ENABLE, 1); + data = reg_write(client, MT9T031_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); /* Read out the chip version register */ - data = reg_read(icd, MT9T031_CHIP_VERSION); + data = reg_read(client, MT9T031_CHIP_VERSION); switch (data) { case 0x1621: diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 3bee30caa..016bcdfcf 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -91,51 +91,49 @@ struct mt9v022 { u16 chip_control; }; -static int reg_read(struct soc_camera_device *icd, const u8 reg) +static int reg_read(struct i2c_client *client, const u8 reg) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct i2c_client *client = mt9v022->client; s32 data = i2c_smbus_read_word_data(client, reg); return data < 0 ? data : swab16(data); } -static int reg_write(struct soc_camera_device *icd, const u8 reg, +static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data)); + return i2c_smbus_write_word_data(client, reg, swab16(data)); } -static int reg_set(struct soc_camera_device *icd, const u8 reg, +static int reg_set(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret | data); + return reg_write(client, reg, ret | data); } -static int reg_clear(struct soc_camera_device *icd, const u8 reg, +static int reg_clear(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret & ~data); + return reg_write(client, reg, ret & ~data); } static int mt9v022_init(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; int ret; if (icl->power) { - ret = icl->power(&mt9v022->client->dev, 1); + ret = icl->power(&client->dev, 1); if (ret < 0) { dev_err(icd->vdev->parent, "Platform failed to power-on the camera.\n"); @@ -148,27 +146,27 @@ static int mt9v022_init(struct soc_camera_device *icd) * if available. Soft reset is done in video_probe(). */ if (icl->reset) - icl->reset(&mt9v022->client->dev); + icl->reset(&client->dev); /* Almost the default mode: master, parallel, simultaneous, and an * undocumented bit 0x200, which is present in table 7, but not in 8, * plus snapshot mode to disable scan for now */ mt9v022->chip_control |= 0x10; - ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control); if (!ret) - ret = reg_write(icd, MT9V022_READ_MODE, 0x300); + ret = reg_write(client, MT9V022_READ_MODE, 0x300); /* All defaults */ if (!ret) /* AEC, AGC on */ - ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); + ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3); if (!ret) - ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); + ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); if (!ret) /* default - auto */ - ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); + ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); if (!ret) - ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); + ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0); return ret; } @@ -186,10 +184,11 @@ static int mt9v022_release(struct soc_camera_device *icd) static int mt9v022_start_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); /* Switch to master "normal" mode */ mt9v022->chip_control &= ~0x10; - if (reg_write(icd, MT9V022_CHIP_CONTROL, + if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) return -EIO; return 0; @@ -197,10 +196,11 @@ static int mt9v022_start_capture(struct soc_camera_device *icd) static int mt9v022_stop_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); /* Switch to snapshot mode */ mt9v022->chip_control |= 0x10; - if (reg_write(icd, MT9V022_CHIP_CONTROL, + if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) return -EIO; return 0; @@ -209,8 +209,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd) static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; u16 pixclk = 0; @@ -243,14 +244,14 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH)) pixclk |= 0x2; - ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); + ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk); if (ret < 0) return ret; if (!(flags & SOCAM_MASTER)) mt9v022->chip_control &= ~0x8; - ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control); if (ret < 0) return ret; @@ -282,35 +283,36 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) static int mt9v022_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { + struct i2c_client *client = to_i2c_client(icd->control); int ret; /* Like in example app. Contradicts the datasheet though */ - ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + ret = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (ret >= 0) { if (ret & 1) /* Autoexposure */ - ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, + ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, rect->height + icd->y_skip_top + 43); else - ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, rect->height + icd->y_skip_top + 43); } /* Setup frame format: defaults apart from width and height */ if (!ret) - ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); + ret = reg_write(client, MT9V022_COLUMN_START, rect->left); if (!ret) - ret = reg_write(icd, MT9V022_ROW_START, rect->top); + ret = reg_write(client, MT9V022_ROW_START, rect->top); if (!ret) /* Default 94, Phytec driver says: * "width + horizontal blank >= 660" */ - ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, + ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, rect->width > 660 - 43 ? 43 : 660 - rect->width); if (!ret) - ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); + ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45); if (!ret) - ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); + ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect->width); if (!ret) - ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, + ret = reg_write(client, MT9V022_WINDOW_HEIGHT, rect->height + icd->y_skip_top); if (ret < 0) @@ -396,16 +398,16 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, static int mt9v022_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9v022->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; reg->size = 2; - reg->val = reg_read(icd, reg->reg); + reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) return -EIO; @@ -416,15 +418,15 @@ static int mt9v022_get_register(struct soc_camera_device *icd, static int mt9v022_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9v022->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - if (reg_write(icd, reg->reg, reg->val) < 0) + if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; return 0; @@ -517,29 +519,30 @@ static struct soc_camera_ops mt9v022_ops = { static int mt9v022_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); int data; switch (ctrl->id) { case V4L2_CID_VFLIP: - data = reg_read(icd, MT9V022_READ_MODE); + data = reg_read(client, MT9V022_READ_MODE); if (data < 0) return -EIO; ctrl->value = !!(data & 0x10); break; case V4L2_CID_HFLIP: - data = reg_read(icd, MT9V022_READ_MODE); + data = reg_read(client, MT9V022_READ_MODE); if (data < 0) return -EIO; ctrl->value = !!(data & 0x20); break; case V4L2_CID_EXPOSURE_AUTO: - data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + data = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (data < 0) return -EIO; ctrl->value = !!(data & 0x1); break; case V4L2_CID_AUTOGAIN: - data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + data = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (data < 0) return -EIO; ctrl->value = !!(data & 0x2); @@ -552,6 +555,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { int data; + struct i2c_client *client = to_i2c_client(icd->control); const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); @@ -562,17 +566,17 @@ static int mt9v022_set_control(struct soc_camera_device *icd, switch (ctrl->id) { case V4L2_CID_VFLIP: if (ctrl->value) - data = reg_set(icd, MT9V022_READ_MODE, 0x10); + data = reg_set(client, MT9V022_READ_MODE, 0x10); else - data = reg_clear(icd, MT9V022_READ_MODE, 0x10); + data = reg_clear(client, MT9V022_READ_MODE, 0x10); if (data < 0) return -EIO; break; case V4L2_CID_HFLIP: if (ctrl->value) - data = reg_set(icd, MT9V022_READ_MODE, 0x20); + data = reg_set(client, MT9V022_READ_MODE, 0x20); else - data = reg_clear(icd, MT9V022_READ_MODE, 0x20); + data = reg_clear(client, MT9V022_READ_MODE, 0x20); if (data < 0) return -EIO; break; @@ -593,12 +597,12 @@ static int mt9v022_set_control(struct soc_camera_device *icd, /* The user wants to set gain manually, hope, she * knows, what she's doing... Switch AGC off. */ - if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) + if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) return -EIO; dev_info(&icd->dev, "Setting gain from %d to %lu\n", - reg_read(icd, MT9V022_ANALOG_GAIN), gain); - if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0) + reg_read(client, MT9V022_ANALOG_GAIN), gain); + if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0) return -EIO; icd->gain = ctrl->value; } @@ -614,13 +618,13 @@ static int mt9v022_set_control(struct soc_camera_device *icd, /* The user wants to set shutter width manually, hope, * she knows, what she's doing... Switch AEC off. */ - if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) + if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) return -EIO; dev_dbg(&icd->dev, "Shutter width from %d to %lu\n", - reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH), + reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH), shutter); - if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, shutter) < 0) return -EIO; icd->exposure = ctrl->value; @@ -628,17 +632,17 @@ static int mt9v022_set_control(struct soc_camera_device *icd, break; case V4L2_CID_AUTOGAIN: if (ctrl->value) - data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2); else - data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2); if (data < 0) return -EIO; break; case V4L2_CID_EXPOSURE_AUTO: if (ctrl->value) - data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1); else - data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1); if (data < 0) return -EIO; break; @@ -650,8 +654,9 @@ static int mt9v022_set_control(struct soc_camera_device *icd, * this wasn't our capture interface, so, we wait for the right one */ static int mt9v022_video_probe(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; s32 data; int ret; unsigned long flags; @@ -661,7 +666,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) return -ENODEV; /* Read out the chip version register */ - data = reg_read(icd, MT9V022_CHIP_VERSION); + data = reg_read(client, MT9V022_CHIP_VERSION); /* must be 0x1311 or 0x1313 */ if (data != 0x1311 && data != 0x1313) { @@ -672,12 +677,12 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) } /* Soft reset */ - ret = reg_write(icd, MT9V022_RESET, 1); + ret = reg_write(client, MT9V022_RESET, 1); if (ret < 0) goto ei2c; /* 15 clock cycles */ udelay(200); - if (reg_read(icd, MT9V022_RESET)) { + if (reg_read(client, MT9V022_RESET)) { dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); goto ei2c; } @@ -685,11 +690,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) /* Set monochrome or colour sensor type */ if (sensor_type && (!strcmp("colour", sensor_type) || !strcmp("color", sensor_type))) { - ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); + ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; icd->formats = mt9v022_colour_formats; } else { - ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); + ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; icd->formats = mt9v022_monochrome_formats; } @@ -735,10 +740,13 @@ ei2c: static void mt9v022_video_remove(struct soc_camera_device *icd) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, icd->dev.parent, icd->vdev); soc_camera_video_stop(icd); + if (icl->free_bus) + icl->free_bus(icl); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 86fab56c5..2d075205b 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -102,10 +102,10 @@ struct mx1_buffer { * Interface. If anyone ever builds hardware to enable more than * one camera, they will have to modify this driver too */ struct mx1_camera_dev { + struct soc_camera_host soc_host; struct soc_camera_device *icd; struct mx1_camera_pdata *pdata; struct mx1_buffer *active; - struct device *dev; struct resource *res; struct clk *clk; struct list_head capture; @@ -219,7 +219,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) int ret; if (unlikely(!pcdev->active)) { - dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n"); + dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n"); return -EFAULT; } @@ -229,7 +229,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) vbuf->size, pcdev->res->start + CSIRXR, DMA_MODE_READ); if (unlikely(ret)) - dev_err(pcdev->dev, "Failed to setup DMA sg list\n"); + dev_err(pcdev->soc_host.dev, "Failed to setup DMA sg list\n"); return ret; } @@ -338,14 +338,14 @@ static void mx1_camera_dma_irq(int channel, void *data) imx_dma_disable(channel); if (unlikely(!pcdev->active)) { - dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n"); + dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n"); goto out; } vb = &pcdev->active->vb; buf = container_of(vb, struct mx1_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(pcdev->soc_host.dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); mx1_camera_wakeup(pcdev, vb, buf); @@ -366,7 +366,7 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx1_camera_dev *pcdev = ici->priv; - videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, pcdev->dev, + videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, ici->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, @@ -385,7 +385,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) * they get a nice Oops */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; - dev_dbg(pcdev->dev, "System clock %lukHz, target freq %dkHz, " + dev_dbg(pcdev->soc_host.dev, "System clock %lukHz, target freq %dkHz, " "divisor %lu\n", lcdclk / 1000, mclk / 1000, div); return div; @@ -395,7 +395,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) { unsigned int csicr1 = CSICR1_EN; - dev_dbg(pcdev->dev, "Activate device\n"); + dev_dbg(pcdev->soc_host.dev, "Activate device\n"); clk_enable(pcdev->clk); @@ -411,7 +411,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) { - dev_dbg(pcdev->dev, "Deactivate device\n"); + dev_dbg(pcdev->soc_host.dev, "Deactivate device\n"); /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); @@ -550,7 +550,7 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -633,12 +633,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = { .querycap = mx1_camera_querycap, }; -/* Should be allocated dynamically too, but we have only one. */ -static struct soc_camera_host mx1_soc_camera_host = { - .drv_name = DRIVER_NAME, - .ops = &mx1_soc_camera_host_ops, -}; - static struct fiq_handler fh = { .name = "csi_sof" }; @@ -673,7 +667,6 @@ static int __init mx1_camera_probe(struct platform_device *pdev) goto exit_put_clk; } - dev_set_drvdata(&pdev->dev, pcdev); pcdev->res = res; pcdev->clk = clk; @@ -707,16 +700,15 @@ static int __init mx1_camera_probe(struct platform_device *pdev) } pcdev->irq = irq; pcdev->base = base; - pcdev->dev = &pdev->dev; /* request dma */ pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH); if (pcdev->dma_chan < 0) { - dev_err(pcdev->dev, "Can't request DMA for MX1 CSI\n"); + dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n"); err = -EBUSY; goto exit_iounmap; } - dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan); + dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan); imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL, pcdev); @@ -729,7 +721,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) /* request irq */ err = claim_fiq(&fh); if (err) { - dev_err(pcdev->dev, "Camera interrupt register failed \n"); + dev_err(&pdev->dev, "Camera interrupt register failed \n"); goto exit_free_dma; } @@ -746,10 +738,12 @@ static int __init mx1_camera_probe(struct platform_device *pdev) mxc_set_irq_fiq(irq, 1); enable_fiq(irq); - mx1_soc_camera_host.priv = pcdev; - mx1_soc_camera_host.dev.parent = &pdev->dev; - mx1_soc_camera_host.nr = pdev->id; - err = soc_camera_host_register(&mx1_soc_camera_host); + pcdev->soc_host.drv_name = DRIVER_NAME; + pcdev->soc_host.ops = &mx1_soc_camera_host_ops; + pcdev->soc_host.priv = pcdev; + pcdev->soc_host.dev = &pdev->dev; + pcdev->soc_host.nr = pdev->id; + err = soc_camera_host_register(&pcdev->soc_host); if (err) goto exit_free_irq; @@ -777,7 +771,9 @@ exit: static int __exit mx1_camera_remove(struct platform_device *pdev) { - struct mx1_camera_dev *pcdev = platform_get_drvdata(pdev); + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct mx1_camera_dev *pcdev = container_of(soc_host, + struct mx1_camera_dev, soc_host); struct resource *res; imx_dma_free(pcdev->dma_chan); @@ -787,7 +783,7 @@ static int __exit mx1_camera_remove(struct platform_device *pdev) clk_put(pcdev->clk); - soc_camera_host_unregister(&mx1_soc_camera_host); + soc_camera_host_unregister(soc_host); iounmap(pcdev->base); diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index c462b811e..4d47eeb14 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -87,7 +87,6 @@ struct mx3_camera_buffer { * @soc_host: embedded soc_host object */ struct mx3_camera_dev { - struct device *dev; /* * i.MX3x is only supposed to handle one camera on its Camera Sensor * Interface. If anyone ever builds hardware to enable more than one @@ -431,7 +430,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev, + videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, ici->dev, &mx3_cam->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, @@ -599,7 +598,8 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, *flags |= SOCAM_DATAWIDTH_4; break; default: - dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth); + dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n", + buswidth); return -EINVAL; } @@ -614,7 +614,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); - dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret); + dev_dbg(ici->dev, "requested bus width %d bit: %d\n", depth, ret); if (ret < 0) return ret; @@ -637,7 +637,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg) if (!rq) return false; - pdata = rq->mx3_cam->dev->platform_data; + pdata = rq->mx3_cam->soc_host.dev->platform_data; return rq->id == chan->chan_id && pdata->dma_dev == chan->device->dev; @@ -697,7 +697,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->dev, "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -709,7 +709,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->dev, "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -722,7 +722,7 @@ passthrough: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, + dev_dbg(ici->dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -829,7 +829,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -866,7 +866,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (pixfmt && !xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -933,11 +933,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } - dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", + dev_dbg(ici->dev, "requested bus width %d bit: %d\n", icd->buswidth, ret); if (ret < 0) @@ -947,7 +947,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); if (!common_flags) { - dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n", + dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n", camera_flags, bus_flags); return -EINVAL; } @@ -1054,7 +1054,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); - dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw); + dev_dbg(ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw); return 0; } @@ -1063,10 +1063,6 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx3_camera_add_device, .remove = mx3_camera_remove_device, -#ifdef CONFIG_PM - .suspend = mx3_camera_suspend, - .resume = mx3_camera_resume, -#endif .set_crop = mx3_camera_set_crop, .set_fmt = mx3_camera_set_fmt, .try_fmt = mx3_camera_try_fmt, @@ -1106,8 +1102,6 @@ static int mx3_camera_probe(struct platform_device *pdev) goto eclkget; } - dev_set_drvdata(&pdev->dev, mx3_cam); - mx3_cam->pdata = pdev->dev.platform_data; mx3_cam->platform_flags = mx3_cam->pdata->flags; if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 | @@ -1139,14 +1133,14 @@ static int mx3_camera_probe(struct platform_device *pdev) } mx3_cam->base = base; - mx3_cam->dev = &pdev->dev; soc_host = &mx3_cam->soc_host; soc_host->drv_name = MX3_CAM_DRV_NAME; soc_host->ops = &mx3_soc_camera_host_ops; soc_host->priv = mx3_cam; - soc_host->dev.parent = &pdev->dev; + soc_host->dev = &pdev->dev; soc_host->nr = pdev->id; + err = soc_camera_host_register(soc_host); if (err) goto ecamhostreg; @@ -1169,11 +1163,13 @@ egetres: static int __devexit mx3_camera_remove(struct platform_device *pdev) { - struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev); + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct mx3_camera_dev *mx3_cam = container_of(soc_host, + struct mx3_camera_dev, soc_host); clk_put(mx3_cam->clk); - soc_camera_host_unregister(&mx3_cam->soc_host); + soc_camera_host_unregister(soc_host); iounmap(mx3_cam->base); diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 4a50c0e95..411efcd34 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -457,7 +457,7 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); - if (i->index < 0 || i->index >= MXB_INPUTS) + if (i->index >= MXB_INPUTS) return -EINVAL; memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); return 0; @@ -620,7 +620,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; - if (a->index < 0 || a->index > MXB_INPUTS) { + if (a->index > MXB_INPUTS) { DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index)); return -EINVAL; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 1cb6a260e..341af4355 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -71,6 +71,7 @@ static const struct pvr2_device_desc pvr2_device_29xxx = { .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, + .ir_scheme = PVR2_IR_SCHEME_29XXX, }; @@ -284,6 +285,9 @@ static struct tda10048_config hauppauge_tda10048_config = { .output_mode = TDA10048_PARALLEL_OUTPUT, .fwbulkwritelen = TDA10048_BULKWRITE_50, .inversion = TDA10048_INVERSION_ON, + .if_freq_khz = TDA10048_IF_4300, + .clk_freq_khz = TDA10048_CLK_16000, + .disable_gate_access = 1, }; static struct tda829x_config tda829x_no_probe = { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 3e553389c..ea04ecf8a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -69,6 +69,7 @@ struct pvr2_string_table { #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0 #define PVR2_ROUTING_SCHEME_GOTVIEW 1 #define PVR2_ROUTING_SCHEME_ONAIR 2 +#define PVR2_ROUTING_SCHEME_AV400 3 #define PVR2_DIGITAL_SCHEME_NONE 0 #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 @@ -78,8 +79,10 @@ struct pvr2_string_table { #define PVR2_LED_SCHEME_HAUPPAUGE 1 #define PVR2_IR_SCHEME_NONE 0 -#define PVR2_IR_SCHEME_24XXX 1 -#define PVR2_IR_SCHEME_ZILOG 2 +#define PVR2_IR_SCHEME_24XXX 1 /* FX2-controlled IR */ +#define PVR2_IR_SCHEME_ZILOG 2 /* HVR-1950 style (must be taken out of reset) */ +#define PVR2_IR_SCHEME_24XXX_MCE 3 /* 24xxx MCE device */ +#define PVR2_IR_SCHEME_29XXX 4 /* Original 29xxx device */ /* This describes a particular hardware type (except for the USB device ID which must live in a separate structure due to environmental @@ -162,19 +165,9 @@ struct pvr2_device_desc { ensure that it is found. */ unsigned int flag_has_wm8775:1; - /* Indicate any specialized IR scheme that might need to be - supported by this driver. If not set, then it is assumed that - IR can work without help from the driver (which is frequently - the case). This is otherwise set to one of - PVR2_IR_SCHEME_xxxx. For "xxxx", the value "24XXX" indicates a - Hauppauge 24xxx class device which has an FPGA-hosted IR - receiver that can only be reached via FX2 command codes. In - that case the pvrusb2 driver will emulate the behavior of the - older 29xxx device's IR receiver (a "virtual" I2C chip) in terms - of those command codes. For the value "ZILOG", we're dealing - with an IR chip that must be taken out of reset via another FX2 - command code (which is the case for HVR-1950 devices). */ - unsigned int ir_scheme:2; + /* Indicate IR scheme of hardware. If not set, then it is assumed + that IR can work without any help from the driver. */ + unsigned int ir_scheme:3; /* These bits define which kinds of sources the device can handle. Note: Digital tuner presence is inferred by the diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 5d75eb521..5b152ff20 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -200,6 +200,9 @@ struct pvr2_hdw { int i2c_cx25840_hack_state; int i2c_linked; + /* IR related */ + unsigned int ir_scheme_active; /* IR scheme as seen from the outside */ + /* Frequency table */ unsigned int freqTable[FREQTABLE_SIZE]; unsigned int freqProgSlot; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f3d9db69e..3411cb36a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -143,6 +143,15 @@ static const unsigned char *module_i2c_addresses[] = { }; +static const char *ir_scheme_names[] = { + [PVR2_IR_SCHEME_NONE] = "none", + [PVR2_IR_SCHEME_29XXX] = "29xxx", + [PVR2_IR_SCHEME_24XXX] = "24xxx (29xxx emulation)", + [PVR2_IR_SCHEME_24XXX_MCE] = "24xxx (MCE device)", + [PVR2_IR_SCHEME_ZILOG] = "Zilog", +}; + + /* Define the list of additional controls we'll dynamically construct based on query of the cx2341x module. */ struct pvr2_mpeg_ids { @@ -1471,7 +1480,6 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) return ret; } - usb_settoggle(hdw->usb_dev, 0 & 0xf, !(0 & USB_DIR_IN), 0); usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f)); pipe = usb_sndctrlpipe(hdw->usb_dev, 0); @@ -2188,7 +2196,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } /* Take the IR chip out of reset, if appropriate */ - if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_ZILOG) { + if (hdw->ir_scheme_active == PVR2_IR_SCHEME_ZILOG) { pvr2_issue_simple_cmd(hdw, FX2CMD_HCW_ZILOG_RESET | (1 << 8) | @@ -2469,6 +2477,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, GFP_KERNEL); if (!hdw->controls) goto fail; hdw->hdw_desc = hdw_desc; + hdw->ir_scheme_active = hdw->hdw_desc->ir_scheme; for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; cptr->hdw = hdw; @@ -4904,6 +4913,12 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, stats.buffers_processed, stats.buffers_failed); } + case 6: { + unsigned int id = hdw->ir_scheme_active; + return scnprintf(buf, acnt, "ir scheme: id=%d %s", id, + (id >= ARRAY_SIZE(ir_scheme_names) ? + "?" : ir_scheme_names[id])); + } default: break; } return 0; @@ -4920,65 +4935,35 @@ static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw, unsigned int tcnt = 0; unsigned int ccnt; struct i2c_client *client; - struct list_head *item; - void *cd; const char *p; unsigned int id; - ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:"); + ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers and I2C clients:\n"); tcnt += ccnt; v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { id = sd->grp_id; p = NULL; if (id < ARRAY_SIZE(module_names)) p = module_names[id]; if (p) { - ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p); + ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s:", p); tcnt += ccnt; } else { ccnt = scnprintf(buf + tcnt, acnt - tcnt, - " (unknown id=%u)", id); + " (unknown id=%u):", id); tcnt += ccnt; } - } - ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); - tcnt += ccnt; - - ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n"); - tcnt += ccnt; - - mutex_lock(&hdw->i2c_adap.clist_lock); - list_for_each(item, &hdw->i2c_adap.clients) { - client = list_entry(item, struct i2c_client, list); - ccnt = scnprintf(buf + tcnt, acnt - tcnt, - " %s: i2c=%02x", client->name, client->addr); - tcnt += ccnt; - cd = i2c_get_clientdata(client); - v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { - if (cd == sd) { - id = sd->grp_id; - p = NULL; - if (id < ARRAY_SIZE(module_names)) { - p = module_names[id]; - } - if (p) { - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " subdev=%s", p); - tcnt += ccnt; - } else { - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " subdev= id %u)", - id); - tcnt += ccnt; - } - break; - } + client = v4l2_get_subdevdata(sd); + if (client) { + ccnt = scnprintf(buf + tcnt, acnt - tcnt, + " %s @ %02x\n", client->name, + client->addr); + tcnt += ccnt; + } else { + ccnt = scnprintf(buf + tcnt, acnt - tcnt, + " no i2c client\n"); + tcnt += ccnt; } - ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); - tcnt += ccnt; } - mutex_unlock(&hdw->i2c_adap.clist_lock); return tcnt; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 919a4f4e1..28463489a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -43,6 +43,18 @@ static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 }; module_param_array(ir_mode, int, NULL, 0444); MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); +static int pvr2_disable_ir_video = 1; +module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video, + int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(disable_autoload_ir_video, + "1=do not try to autoload ir_video IR receiver"); + +/* Mapping of IR schemes to known I2C addresses - if any */ +static const unsigned char ir_video_addresses[] = { + [PVR2_IR_SCHEME_29XXX] = 0x18, + [PVR2_IR_SCHEME_24XXX] = 0x18, +}; + static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ u8 i2c_addr, /* I2C address we're talking to */ u8 *data, /* Data to write */ @@ -637,6 +649,31 @@ static void do_i2c_scan(struct pvr2_hdw *hdw) printk(KERN_INFO "%s: i2c scan done.\n", hdw->name); } +static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) +{ + struct i2c_board_info info; + unsigned char addr = 0; + if (pvr2_disable_ir_video) { + pvr2_trace(PVR2_TRACE_INFO, + "Automatic binding of ir_video has been disabled."); + return; + } + if (hdw->ir_scheme_active < ARRAY_SIZE(ir_video_addresses)) { + addr = ir_video_addresses[hdw->ir_scheme_active]; + } + if (!addr) { + /* The device either doesn't support I2C-based IR or we + don't know (yet) how to operate IR on the device. */ + return; + } + pvr2_trace(PVR2_TRACE_INFO, + "Binding ir_video to i2c address 0x%02x.", addr); + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + info.addr = addr; + i2c_new_device(&hdw->i2c_adap, &info); +} + void pvr2_i2c_core_init(struct pvr2_hdw *hdw) { unsigned int idx; @@ -652,7 +689,9 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) printk(KERN_INFO "%s: IR disabled\n",hdw->name); hdw->i2c_func[0x18] = i2c_black_hole; } else if (ir_mode[hdw->unit_number] == 1) { - if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) { + if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) { + /* Set up translation so that our IR looks like a + 29xxx device */ hdw->i2c_func[0x18] = i2c_24xxx_ir; } } @@ -675,15 +714,23 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) i2c_add_adapter(&hdw->i2c_adap); if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { /* Probe for a different type of IR receiver on this - device. If present, disable the emulated IR receiver. */ + device. This is really the only way to differentiate + older 24xxx devices from 24xxx variants that include an + IR blaster. If the IR blaster is present, the IR + receiver is part of that chip and thus we must disable + the emulated IR receiver. */ if (do_i2c_probe(hdw, 0x71)) { pvr2_trace(PVR2_TRACE_INFO, "Device has newer IR hardware;" " disabling unneeded virtual IR device"); hdw->i2c_func[0x18] = NULL; + /* Remember that this is a different device... */ + hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE; } } if (i2c_scan) do_i2c_scan(hdw); + + pvr2_i2c_register_ir(hdw); } void pvr2_i2c_core_done(struct pvr2_hdw *hdw) diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 7ed3b8453..d8ad83df3 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -548,7 +548,7 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) &sfp->attr_unit_number); } pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); - sfp->class_dev->driver_data = NULL; + dev_set_drvdata(sfp->class_dev, NULL); device_unregister(sfp->class_dev); sfp->class_dev = NULL; } @@ -558,7 +558,7 @@ static ssize_t v4l_minor_number_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, @@ -570,7 +570,7 @@ static ssize_t bus_info_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_bus_info(sfp->channel.hdw)); @@ -581,7 +581,7 @@ static ssize_t hdw_name_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_type(sfp->channel.hdw)); @@ -592,7 +592,7 @@ static ssize_t hdw_desc_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_desc(sfp->channel.hdw)); @@ -604,7 +604,7 @@ static ssize_t v4l_radio_minor_number_show(struct device *class_dev, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, @@ -616,7 +616,7 @@ static ssize_t unit_number_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_get_unit_number(sfp->channel.hdw)); @@ -644,7 +644,7 @@ static void class_dev_create(struct pvr2_sysfs *sfp, class_dev->parent = &usb_dev->dev; sfp->class_dev = class_dev; - class_dev->driver_data = sfp; + dev_set_drvdata(class_dev, sfp); ret = device_register(class_dev); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, @@ -817,7 +817,7 @@ static ssize_t debuginfo_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; pvr2_hdw_trigger_module_log(sfp->channel.hdw); return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); @@ -828,7 +828,7 @@ static ssize_t debugcmd_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); } @@ -841,7 +841,7 @@ static ssize_t debugcmd_store(struct device *class_dev, struct pvr2_sysfs *sfp; int ret; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index c7fc605f8..a19ad36e5 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -91,7 +91,7 @@ static struct v4l2_capability pvr_capability ={ .driver = "pvrusb2", .card = "Hauppauge WinTV pvr-usb2", .bus_info = "usb", - .version = KERNEL_VERSION(0,8,0), + .version = KERNEL_VERSION(0, 9, 0), .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | V4L2_CAP_READWRITE), @@ -268,7 +268,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&tmp,0,sizeof(tmp)); tmp.index = vi->index; ret = 0; - if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { + if (vi->index >= fh->input_cnt) { ret = -EINVAL; break; } @@ -332,7 +332,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_S_INPUT: { struct v4l2_input *vi = (struct v4l2_input *)arg; - if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { + if (vi->index >= fh->input_cnt) { ret = -ERANGE; break; } diff --git a/linux/drivers/media/video/pwc/pwc-ctrl.c b/linux/drivers/media/video/pwc/pwc-ctrl.c index f9fbe02e0..50b415e07 100644 --- a/linux/drivers/media/video/pwc/pwc-ctrl.c +++ b/linux/drivers/media/video/pwc/pwc-ctrl.c @@ -159,35 +159,67 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev); /****************************************************************************/ +static int _send_control_msg(struct pwc_device *pdev, + u8 request, u16 value, int index, void *buf, int buflen, int timeout) +{ + int rc; + void *kbuf = NULL; + + if (buflen) { + kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */ + if (kbuf == NULL) + return -ENOMEM; + memcpy(kbuf, buf, buflen); + } -#define SendControlMsg(request, value, buflen) \ - usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \ - request, \ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ - value, \ - pdev->vcinterface, \ - &buf, buflen, 500) + rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), + request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + index, + kbuf, buflen, timeout); -#define RecvControlMsg(request, value, buflen) \ - usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \ - request, \ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ - value, \ - pdev->vcinterface, \ - &buf, buflen, 500) + kfree(kbuf); + return rc; +} +static int recv_control_msg(struct pwc_device *pdev, + u8 request, u16 value, void *buf, int buflen) +{ + int rc; + void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */ + + if (kbuf == NULL) + return -ENOMEM; + + rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), + request, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + pdev->vcinterface, + kbuf, buflen, 500); + memcpy(buf, kbuf, buflen); + kfree(kbuf); + return rc; +} -static int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) +static inline int send_video_command(struct pwc_device *pdev, + int index, void *buf, int buflen) { - return usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), + return _send_control_msg(pdev, SET_EP_STREAM_CTL, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VIDEO_OUTPUT_CONTROL_FORMATTER, index, buf, buflen, 1000); } +static inline int send_control_msg(struct pwc_device *pdev, + u8 request, u16 value, void *buf, int buflen) +{ + return _send_control_msg(pdev, + request, value, pdev->vcinterface, buf, buflen, 500); +} + static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) @@ -224,7 +256,7 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) return -EINVAL; memcpy(buf, pEntry->mode, 3); - ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); + ret = send_video_command(pdev, pdev->vendpoint, buf, 3); if (ret < 0) { PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret); return ret; @@ -285,7 +317,7 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i memcpy(buf, pChoose->mode, 13); if (snapshot) buf[0] |= 0x80; - ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13); + ret = send_video_command(pdev, pdev->vendpoint, buf, 13); if (ret < 0) return ret; @@ -358,7 +390,7 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i buf[0] |= 0x80; /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ - ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12); + ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12); if (ret < 0) return ret; @@ -530,7 +562,8 @@ int pwc_get_brightness(struct pwc_device *pdev) char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; return buf; @@ -545,7 +578,8 @@ int pwc_set_brightness(struct pwc_device *pdev, int value) if (value > 0xffff) value = 0xffff; buf = (value >> 9) & 0x7f; - return SendControlMsg(SET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf)); } /* CONTRAST */ @@ -555,7 +589,8 @@ int pwc_get_contrast(struct pwc_device *pdev) char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; return buf; @@ -570,7 +605,8 @@ int pwc_set_contrast(struct pwc_device *pdev, int value) if (value > 0xffff) value = 0xffff; buf = (value >> 10) & 0x3f; - return SendControlMsg(SET_LUM_CTL, CONTRAST_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf)); } /* GAMMA */ @@ -580,7 +616,8 @@ int pwc_get_gamma(struct pwc_device *pdev) char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; return buf; @@ -595,7 +632,8 @@ int pwc_set_gamma(struct pwc_device *pdev, int value) if (value > 0xffff) value = 0xffff; buf = (value >> 11) & 0x1f; - return SendControlMsg(SET_LUM_CTL, GAMMA_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf)); } @@ -613,7 +651,8 @@ int pwc_get_saturation(struct pwc_device *pdev, int *value) saturation_register = SATURATION_MODE_FORMATTER2; else saturation_register = SATURATION_MODE_FORMATTER1; - ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, saturation_register, &buf, sizeof(buf)); if (ret < 0) return ret; *value = (signed)buf; @@ -636,7 +675,8 @@ int pwc_set_saturation(struct pwc_device *pdev, int value) saturation_register = SATURATION_MODE_FORMATTER2; else saturation_register = SATURATION_MODE_FORMATTER1; - return SendControlMsg(SET_CHROM_CTL, saturation_register, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, saturation_register, &buf, sizeof(buf)); } /* AGC */ @@ -651,7 +691,8 @@ int pwc_set_agc(struct pwc_device *pdev, int mode, int value) else buf = 0xff; /* fixed */ - ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf)); if (!mode && ret >= 0) { if (value < 0) @@ -659,7 +700,8 @@ int pwc_set_agc(struct pwc_device *pdev, int mode, int value) if (value > 0xffff) value = 0xffff; buf = (value >> 10) & 0x3F; - ret = SendControlMsg(SET_LUM_CTL, PRESET_AGC_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf)); } if (ret < 0) return ret; @@ -671,12 +713,14 @@ int pwc_get_agc(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; if (buf != 0) { /* fixed */ - ret = RecvControlMsg(GET_LUM_CTL, PRESET_AGC_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; if (buf > 0x3F) @@ -684,7 +728,8 @@ int pwc_get_agc(struct pwc_device *pdev, int *value) *value = (buf << 10); } else { /* auto */ - ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, READ_AGC_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; /* Gah... this value ranges from 0x00 ... 0x9F */ @@ -707,7 +752,8 @@ int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) else buf[0] = 0xff; /* fixed */ - ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, sizeof(buf)); if (!mode && ret >= 0) { if (value < 0) @@ -726,7 +772,9 @@ int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) buf[0] = value >> 8; } - ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); + ret = send_control_msg(pdev, + SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, + &buf, sizeof(buf)); } return ret; } @@ -737,7 +785,8 @@ int pwc_get_shutter_speed(struct pwc_device *pdev, int *value) unsigned char buf[2]; int ret; - ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, READ_SHUTTER_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf[0] + (buf[1] << 8); @@ -764,7 +813,9 @@ int pwc_camera_power(struct pwc_device *pdev, int power) buf = 0x00; /* active */ else buf = 0xFF; /* power save */ - return SendControlMsg(SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, 1); + return send_control_msg(pdev, + SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, + &buf, sizeof(buf)); } @@ -773,20 +824,20 @@ int pwc_camera_power(struct pwc_device *pdev, int power) int pwc_restore_user(struct pwc_device *pdev) { - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0); + return send_control_msg(pdev, + SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, NULL, 0); } int pwc_save_user(struct pwc_device *pdev) { - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0); + return send_control_msg(pdev, + SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, NULL, 0); } int pwc_restore_factory(struct pwc_device *pdev) { - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0); + return send_control_msg(pdev, + SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, NULL, 0); } /* ************************************************* */ @@ -814,7 +865,8 @@ int pwc_set_awb(struct pwc_device *pdev, int mode) buf = mode & 0x07; /* just the lowest three bits */ - ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; @@ -826,7 +878,8 @@ int pwc_get_awb(struct pwc_device *pdev) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; @@ -843,7 +896,9 @@ int pwc_set_red_gain(struct pwc_device *pdev, int value) value = 0xffff; /* only the msb is considered */ buf = value >> 8; - return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, + &buf, sizeof(buf)); } int pwc_get_red_gain(struct pwc_device *pdev, int *value) @@ -851,7 +906,9 @@ int pwc_get_red_gain(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 8; @@ -869,7 +926,9 @@ int pwc_set_blue_gain(struct pwc_device *pdev, int value) value = 0xffff; /* only the msb is considered */ buf = value >> 8; - return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, + &buf, sizeof(buf)); } int pwc_get_blue_gain(struct pwc_device *pdev, int *value) @@ -877,7 +936,9 @@ int pwc_get_blue_gain(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 8; @@ -894,7 +955,8 @@ static int pwc_read_red_gain(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 8; @@ -906,7 +968,8 @@ static int pwc_read_blue_gain(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 8; @@ -920,7 +983,8 @@ static int pwc_set_wb_speed(struct pwc_device *pdev, int speed) /* useful range is 0x01..0x20 */ buf = speed / 0x7f0; - return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf)); } static int pwc_get_wb_speed(struct pwc_device *pdev, int *value) @@ -928,7 +992,8 @@ static int pwc_get_wb_speed(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf * 0x7f0; @@ -942,7 +1007,8 @@ static int pwc_set_wb_delay(struct pwc_device *pdev, int delay) /* useful range is 0x01..0x3F */ buf = (delay >> 10); - return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf)); } static int pwc_get_wb_delay(struct pwc_device *pdev, int *value) @@ -950,7 +1016,8 @@ static int pwc_get_wb_delay(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 10; @@ -978,7 +1045,8 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) buf[0] = on_value; buf[1] = off_value; - return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); + return send_control_msg(pdev, + SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf)); } static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) @@ -992,7 +1060,8 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) return 0; } - ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *on_value = buf[0] * 100; @@ -1009,7 +1078,8 @@ int pwc_set_contour(struct pwc_device *pdev, int contour) buf = 0xff; /* auto contour on */ else buf = 0x0; /* auto contour off */ - ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; @@ -1019,7 +1089,8 @@ int pwc_set_contour(struct pwc_device *pdev, int contour) contour = 0xffff; buf = (contour >> 10); /* contour preset is [0..3f] */ - ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; return 0; @@ -1030,13 +1101,16 @@ int pwc_get_contour(struct pwc_device *pdev, int *contour) unsigned char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; if (buf == 0) { /* auto mode off, query current preset value */ - ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *contour = buf << 10; @@ -1055,7 +1129,9 @@ int pwc_set_backlight(struct pwc_device *pdev, int backlight) buf = 0xff; else buf = 0x0; - return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, + &buf, sizeof(buf)); } int pwc_get_backlight(struct pwc_device *pdev, int *backlight) @@ -1063,7 +1139,9 @@ int pwc_get_backlight(struct pwc_device *pdev, int *backlight) int ret; unsigned char buf; - ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *backlight = !!buf; @@ -1078,7 +1156,8 @@ int pwc_set_colour_mode(struct pwc_device *pdev, int colour) buf = 0xff; else buf = 0x0; - return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf)); } int pwc_get_colour_mode(struct pwc_device *pdev, int *colour) @@ -1086,7 +1165,8 @@ int pwc_get_colour_mode(struct pwc_device *pdev, int *colour) int ret; unsigned char buf; - ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *colour = !!buf; @@ -1102,7 +1182,8 @@ int pwc_set_flicker(struct pwc_device *pdev, int flicker) buf = 0xff; else buf = 0x0; - return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf)); } int pwc_get_flicker(struct pwc_device *pdev, int *flicker) @@ -1110,7 +1191,8 @@ int pwc_get_flicker(struct pwc_device *pdev, int *flicker) int ret; unsigned char buf; - ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *flicker = !!buf; @@ -1126,7 +1208,9 @@ int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) if (noise > 3) noise = 3; buf = noise; - return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, + &buf, sizeof(buf)); } int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) @@ -1134,7 +1218,9 @@ int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) int ret; unsigned char buf; - ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *noise = buf; @@ -1146,7 +1232,8 @@ static int _pwc_mpt_reset(struct pwc_device *pdev, int flags) unsigned char buf; buf = flags & 0x03; // only lower two bits are currently used - return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); + return send_control_msg(pdev, + SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf)); } int pwc_mpt_reset(struct pwc_device *pdev, int flags) @@ -1175,7 +1262,8 @@ static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) buf[1] = (pan >> 8) & 0xFF; buf[2] = tilt & 0xFF; buf[3] = (tilt >> 8) & 0xFF; - return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4); + return send_control_msg(pdev, + SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf)); } int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) @@ -1211,7 +1299,8 @@ static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *st int ret; unsigned char buf[5]; - ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5); + ret = recv_control_msg(pdev, + GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; status->status = buf[0] & 0x7; // 3 bits are used for reporting @@ -1233,7 +1322,8 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) else request = SENSOR_TYPE_FORMATTER2; - ret = RecvControlMsg(GET_STATUS_CTL, request, 1); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, request, &buf, sizeof(buf)); if (ret < 0) return ret; if (pdev->type < 675) diff --git a/linux/drivers/media/video/pwc/pwc-v4l.c b/linux/drivers/media/video/pwc/pwc-v4l.c index bc0a46429..2876ce084 100644 --- a/linux/drivers/media/video/pwc/pwc-v4l.c +++ b/linux/drivers/media/video/pwc/pwc-v4l.c @@ -1107,7 +1107,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) return -EINVAL; if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if (buf->index < 0 || buf->index >= pwc_mbufs) + if (buf->index >= pwc_mbufs) return -EINVAL; buf->flags |= V4L2_BUF_FLAG_QUEUED; diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index cb4491338..35642c430 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -214,7 +214,7 @@ struct pxa_buffer { }; struct pxa_camera_dev { - struct device *dev; + struct soc_camera_host soc_host; /* PXA27x is only supposed to handle one camera on its Quick Capture * interface. If anyone ever builds hardware to enable more than * one camera, they will have to modify this driver too */ @@ -273,7 +273,6 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct pxa_camera_dev *pcdev = ici->priv; struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); int i; @@ -290,7 +289,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { if (buf->dmas[i].sg_cpu) - dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size, + dma_free_coherent(ici->dev, buf->dmas[i].sg_size, buf->dmas[i].sg_cpu, buf->dmas[i].sg_dma); buf->dmas[i].sg_cpu = NULL; @@ -350,14 +349,14 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, int dma_len = 0, xfer_len = 0; if (pxa_dma->sg_cpu) - dma_free_coherent(pcdev->dev, pxa_dma->sg_size, + dma_free_coherent(pcdev->soc_host.dev, pxa_dma->sg_size, pxa_dma->sg_cpu, pxa_dma->sg_dma); sglen = calculate_dma_sglen(*sg_first, dma->sglen, *sg_first_ofs, size); pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc); - pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size, + pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->soc_host.dev, pxa_dma->sg_size, &pxa_dma->sg_dma, GFP_KERNEL); if (!pxa_dma->sg_cpu) return -ENOMEM; @@ -365,7 +364,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sglen = sglen; offset = *sg_first_ofs; - dev_dbg(pcdev->dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", + dev_dbg(pcdev->soc_host.dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", *sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma); @@ -388,7 +387,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sg_cpu[i].ddadr = pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); - dev_vdbg(pcdev->dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", + dev_vdbg(pcdev->soc_host.dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc), sg_dma_address(sg) + offset, xfer_len); offset = 0; @@ -500,7 +499,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, &sg, &next_ofs); if (ret) { - dev_err(pcdev->dev, + dev_err(pcdev->soc_host.dev, "DMA initialization for Y/RGB failed\n"); goto fail; } @@ -510,7 +509,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1, size_u, &sg, &next_ofs); if (ret) { - dev_err(pcdev->dev, + dev_err(pcdev->soc_host.dev, "DMA initialization for U failed\n"); goto fail_u; } @@ -520,7 +519,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2, size_v, &sg, &next_ofs); if (ret) { - dev_err(pcdev->dev, + dev_err(pcdev->soc_host.dev, "DMA initialization for V failed\n"); goto fail_v; } @@ -534,10 +533,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, return 0; fail_v: - dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size, + dma_free_coherent(pcdev->soc_host.dev, buf->dmas[1].sg_size, buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma); fail_u: - dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size, + dma_free_coherent(pcdev->soc_host.dev, buf->dmas[0].sg_size, buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma); fail: free_buffer(vq, buf); @@ -561,7 +560,7 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) active = pcdev->active; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->dev, "%s (channel=%d) ddadr=%08x\n", __func__, + dev_dbg(pcdev->soc_host.dev, "%s (channel=%d) ddadr=%08x\n", __func__, i, active->dmas[i].sg_dma); DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; DCSR(pcdev->dma_chans[i]) = DCSR_RUN; @@ -573,7 +572,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) int i; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->dev, "%s (channel=%d)\n", __func__, i); + dev_dbg(pcdev->soc_host.dev, "%s (channel=%d)\n", __func__, i); DCSR(pcdev->dma_chans[i]) = 0; } } @@ -609,7 +608,7 @@ static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) { unsigned long cicr0, cifr; - dev_dbg(pcdev->dev, "%s\n", __func__); + dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); /* Reset the FIFOs */ cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; __raw_writel(cifr, pcdev->base + CIFR); @@ -629,7 +628,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) __raw_writel(cicr0, pcdev->base + CICR0); pcdev->active = NULL; - dev_dbg(pcdev->dev, "%s\n", __func__); + dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); } static void pxa_videobuf_queue(struct videobuf_queue *vq, @@ -698,7 +697,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); - dev_dbg(pcdev->dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb); + dev_dbg(pcdev->soc_host.dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb); if (list_empty(&pcdev->capture)) { pxa_camera_stop_capture(pcdev); @@ -734,7 +733,7 @@ static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) for (i = 0; i < pcdev->channels; i++) if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP) is_dma_stopped = 0; - dev_dbg(pcdev->dev, "%s : top queued buffer=%p, dma_stopped=%d\n", + dev_dbg(pcdev->soc_host.dev, "%s : top queued buffer=%p, dma_stopped=%d\n", __func__, pcdev->active, is_dma_stopped); if (pcdev->active && is_dma_stopped) pxa_camera_start_capture(pcdev); @@ -759,12 +758,12 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, overrun |= CISR_IFO_1 | CISR_IFO_2; if (status & DCSR_BUSERR) { - dev_err(pcdev->dev, "DMA Bus Error IRQ!\n"); + dev_err(pcdev->soc_host.dev, "DMA Bus Error IRQ!\n"); goto out; } if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) { - dev_err(pcdev->dev, "Unknown DMA IRQ source, " + dev_err(pcdev->soc_host.dev, "Unknown DMA IRQ source, " "status: 0x%08x\n", status); goto out; } @@ -788,7 +787,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, buf = container_of(vb, struct pxa_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", + dev_dbg(pcdev->soc_host.dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", __func__, channel, status & DCSR_STARTINTR ? "SOF " : "", status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); @@ -799,7 +798,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, */ if (camera_status & overrun && !list_is_last(pcdev->capture.next, &pcdev->capture)) { - dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", + dev_dbg(pcdev->soc_host.dev, "FIFO overrun! CISR: %x\n", camera_status); pxa_camera_stop_capture(pcdev); pxa_camera_start_capture(pcdev); @@ -866,7 +865,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) /* mclk <= ciclk / 4 (27.4.2) */ if (mclk > lcdclk / 4) { mclk = lcdclk / 4; - dev_warn(pcdev->dev, "Limiting master clock to %lu\n", mclk); + dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk); } /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ @@ -876,7 +875,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) pcdev->mclk = lcdclk / (2 * (div + 1)); - dev_dbg(pcdev->dev, "LCD clock %luHz, target freq %luHz, " + dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, " "divisor %u\n", lcdclk, mclk, div); return div; @@ -896,12 +895,12 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) struct pxacamera_platform_data *pdata = pcdev->pdata; u32 cicr4 = 0; - dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n", + dev_dbg(pcdev->soc_host.dev, "Registered platform device at %p data %p\n", pcdev, pdata); if (pdata && pdata->init) { - dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__); - pdata->init(pcdev->dev); + dev_dbg(pcdev->soc_host.dev, "%s: Init gpios\n", __func__); + pdata->init(pcdev->soc_host.dev); } /* disable all interrupts */ @@ -943,7 +942,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) struct videobuf_buffer *vb; status = __raw_readl(pcdev->base + CISR); - dev_dbg(pcdev->dev, "Camera interrupt status 0x%lx\n", status); + dev_dbg(pcdev->soc_host.dev, "Camera interrupt status 0x%lx\n", status); if (!status) return IRQ_NONE; @@ -1271,7 +1270,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->dev, "Providing format %s using %s\n", pxa_camera_formats[0].name, icd->formats[idx].name); } @@ -1286,7 +1285,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, "Providing format %s packed\n", + dev_dbg(ici->dev, "Providing format %s packed\n", icd->formats[idx].name); } break; @@ -1298,7 +1297,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(&ici->dev, + dev_dbg(ici->dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -1327,11 +1326,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n", + dev_warn(ici->dev, "Failed to crop to %ux%u@%u:%u\n", rect->width, rect->height, rect->left, rect->top); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(&ici->dev, + dev_err(ici->dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1359,7 +1358,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -1375,11 +1374,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(&ici->dev, "Failed to configure for format %x\n", + dev_warn(ici->dev, "Failed to configure for format %x\n", pix->pixelformat); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(&ici->dev, + dev_err(ici->dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1407,7 +1406,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -1564,12 +1563,6 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .set_bus_param = pxa_camera_set_bus_param, }; -/* Should be allocated dynamically too, but we have only one. */ -static struct soc_camera_host pxa_soc_camera_host = { - .drv_name = PXA_CAM_DRV_NAME, - .ops = &pxa_soc_camera_host_ops, -}; - static int pxa_camera_probe(struct platform_device *pdev) { struct pxa_camera_dev *pcdev; @@ -1598,7 +1591,6 @@ static int pxa_camera_probe(struct platform_device *pdev) goto exit_kfree; } - dev_set_drvdata(&pdev->dev, pcdev); pcdev->res = res; pcdev->pdata = pdev->dev.platform_data; @@ -1619,7 +1611,6 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->mclk = 20000000; } - pcdev->dev = &pdev->dev; pcdev->mclk_divisor = mclk_get_divisor(pcdev); INIT_LIST_HEAD(&pcdev->capture); @@ -1628,13 +1619,13 @@ static int pxa_camera_probe(struct platform_device *pdev) /* * Request the regions. */ - if (!request_mem_region(res->start, res->end - res->start + 1, + if (!request_mem_region(res->start, resource_size(res), PXA_CAM_DRV_NAME)) { err = -EBUSY; goto exit_clk; } - base = ioremap(res->start, res->end - res->start + 1); + base = ioremap(res->start, resource_size(res)); if (!base) { err = -ENOMEM; goto exit_release; @@ -1646,29 +1637,29 @@ static int pxa_camera_probe(struct platform_device *pdev) err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, pxa_camera_dma_irq_y, pcdev); if (err < 0) { - dev_err(pcdev->dev, "Can't request DMA for Y\n"); + dev_err(&pdev->dev, "Can't request DMA for Y\n"); goto exit_iounmap; } pcdev->dma_chans[0] = err; - dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); + dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); err = pxa_request_dma("CI_U", DMA_PRIO_HIGH, pxa_camera_dma_irq_u, pcdev); if (err < 0) { - dev_err(pcdev->dev, "Can't request DMA for U\n"); + dev_err(&pdev->dev, "Can't request DMA for U\n"); goto exit_free_dma_y; } pcdev->dma_chans[1] = err; - dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); + dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); err = pxa_request_dma("CI_V", DMA_PRIO_HIGH, pxa_camera_dma_irq_v, pcdev); if (err < 0) { - dev_err(pcdev->dev, "Can't request DMA for V\n"); + dev_err(&pdev->dev, "Can't request DMA for V\n"); goto exit_free_dma_u; } pcdev->dma_chans[2] = err; - dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); + dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD; @@ -1678,14 +1669,17 @@ static int pxa_camera_probe(struct platform_device *pdev) err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME, pcdev); if (err) { - dev_err(pcdev->dev, "Camera interrupt register failed \n"); + dev_err(&pdev->dev, "Camera interrupt register failed \n"); goto exit_free_dma; } - pxa_soc_camera_host.priv = pcdev; - pxa_soc_camera_host.dev.parent = &pdev->dev; - pxa_soc_camera_host.nr = pdev->id; - err = soc_camera_host_register(&pxa_soc_camera_host); + pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; + pcdev->soc_host.ops = &pxa_soc_camera_host_ops; + pcdev->soc_host.priv = pcdev; + pcdev->soc_host.dev = &pdev->dev; + pcdev->soc_host.nr = pdev->id; + + err = soc_camera_host_register(&pcdev->soc_host); if (err) goto exit_free_irq; @@ -1702,7 +1696,7 @@ exit_free_dma_y: exit_iounmap: iounmap(base); exit_release: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); exit_clk: clk_put(pcdev->clk); exit_kfree: @@ -1713,7 +1707,9 @@ exit: static int __devexit pxa_camera_remove(struct platform_device *pdev) { - struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct pxa_camera_dev *pcdev = container_of(soc_host, + struct pxa_camera_dev, soc_host); struct resource *res; clk_put(pcdev->clk); @@ -1723,12 +1719,12 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev) pxa_free_dma(pcdev->dma_chans[2]); free_irq(pcdev->irq, pcdev); - soc_camera_host_unregister(&pxa_soc_camera_host); + soc_camera_host_unregister(soc_host); iounmap(pcdev->base); res = pcdev->res; - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); kfree(pcdev); diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index c13aa2cc8..8a939387a 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -78,6 +78,8 @@ #define MAX_CHANNELS 4 #define S2255_MARKER_FRAME 0x2255DA4AL #define S2255_MARKER_RESPONSE 0x2255ACACL +#define S2255_RESPONSE_SETMODE 0x01 +#define S2255_RESPONSE_FW 0x10 #define S2255_USB_XFER_SIZE (16 * 1024) #define MAX_CHANNELS 4 #define MAX_PIPE_BUFFERS 1 @@ -179,9 +181,6 @@ struct s2255_bufferi { struct s2255_dmaqueue { struct list_head active; - /* thread for acquisition */ - struct task_struct *kthread; - int frame; struct s2255_dev *dev; int channel; }; @@ -211,16 +210,11 @@ struct s2255_pipeinfo { u32 max_transfer_size; u32 cur_transfer_size; u8 *transfer_buffer; - u32 transfer_flags;; u32 state; - u32 prev_state; - u32 urb_size; void *stream_urb; void *dev; /* back pointer to s2255_dev struct*/ u32 err_count; - u32 buf_index; u32 idx; - u32 priority_set; }; struct s2255_fmt; /*forward declaration */ @@ -240,8 +234,6 @@ struct s2255_dev { struct list_head s2255_devlist; struct timer_list timer; struct s2255_fw *fw_data; - int board_num; - int is_open; struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; struct s2255_bufferi buffer[MAX_CHANNELS]; struct s2255_mode mode[MAX_CHANNELS]; @@ -298,9 +290,10 @@ struct s2255_fh { int resources[MAX_CHANNELS]; }; -#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */ +/* current cypress EEPROM firmware version */ +#define S2255_CUR_USB_FWVER ((3 << 8) | 6) #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 13 +#define S2255_MINOR_VERSION 14 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ @@ -1238,6 +1231,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, buffer[1] = (u32) chn_rev; buffer[2] = CMD_SET_MODE; memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode)); + dev->setmode_ready[chn] = 0; res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); if (debug) dump_verify_mode(dev, mode); @@ -1246,7 +1240,6 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, /* wait at least 3 frames before continuing */ if (mode->restart) { - dev->setmode_ready[chn] = 0; wait_event_timeout(dev->wait_setmode[chn], (dev->setmode_ready[chn] != 0), msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); @@ -1819,7 +1812,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev) INIT_LIST_HEAD(&dev->vidq[i].active); dev->vidq[i].dev = dev; dev->vidq[i].channel = i; - dev->vidq[i].kthread = NULL; /* register 4 video devices */ dev->vdev[i] = video_device_alloc(); memcpy(dev->vdev[i], &template, sizeof(struct video_device)); @@ -1840,7 +1832,9 @@ static int s2255_probe_v4l(struct s2255_dev *dev) return ret; } } - printk(KERN_INFO "Sensoray 2255 V4L driver\n"); + printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n", + S2255_MAJOR_VERSION, + S2255_MINOR_VERSION); return ret; } @@ -1930,14 +1924,14 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) if (!(cc >= 0 && cc < MAX_CHANNELS)) break; switch (pdword[2]) { - case 0x01: + case S2255_RESPONSE_SETMODE: /* check if channel valid */ /* set mode ready */ dev->setmode_ready[cc] = 1; wake_up(&dev->wait_setmode[cc]); dprintk(5, "setmode ready %d\n", cc); break; - case 0x10: + case S2255_RESPONSE_FW: dev->chn_ready |= (1 << cc); if ((dev->chn_ready & 0x0f) != 0x0f) @@ -2173,10 +2167,15 @@ static int s2255_board_init(struct s2255_dev *dev) /* query the firmware */ fw_ver = s2255_get_fx2fw(dev); - printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver); - if (fw_ver < CUR_USB_FWVER) + printk(KERN_INFO "2255 usb firmware version %d.%d\n", + (fw_ver >> 8) & 0xff, + fw_ver & 0xff); + + if (fw_ver < S2255_CUR_USB_FWVER) dev_err(&dev->udev->dev, - "usb firmware not up to date %d\n", fw_ver); + "usb firmware not up to date %d.%d\n", + (fw_ver >> 8) & 0xff, + fw_ver & 0xff); for (j = 0; j < MAX_CHANNELS; j++) { dev->b_acquire[j] = 0; @@ -2241,8 +2240,10 @@ static void read_pipe_completion(struct urb *purb) return; } status = purb->status; - if (status != 0) { - dprintk(2, "read_pipe_completion: err\n"); + /* if shutting down, do not resubmit, exit immediately */ + if (status == -ESHUTDOWN) { + dprintk(2, "read_pipe_completion: err shutdown\n"); + pipe_info->err_count++; return; } @@ -2251,9 +2252,13 @@ static void read_pipe_completion(struct urb *purb) return; } - s2255_read_video_callback(dev, pipe_info); + if (status == 0) + s2255_read_video_callback(dev, pipe_info); + else { + pipe_info->err_count++; + dprintk(1, "s2255drv: failed URB %d\n", status); + } - pipe_info->err_count = 0; pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); /* reuse urb */ usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev, @@ -2265,7 +2270,6 @@ static void read_pipe_completion(struct urb *purb) if (pipe_info->state != 0) { if (usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL)) { dev_err(&dev->udev->dev, "error submitting urb\n"); - usb_free_urb(pipe_info->stream_urb); } } else { dprintk(2, "read pipe complete state 0\n"); @@ -2284,8 +2288,7 @@ static int s2255_start_readpipe(struct s2255_dev *dev) for (i = 0; i < MAX_PIPE_BUFFERS; i++) { pipe_info->state = 1; - pipe_info->buf_index = (u32) i; - pipe_info->priority_set = 0; + pipe_info->err_count = 0; pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); if (!pipe_info->stream_urb) { dev_err(&dev->udev->dev, @@ -2299,7 +2302,6 @@ static int s2255_start_readpipe(struct s2255_dev *dev) pipe_info->cur_transfer_size, read_pipe_completion, pipe_info); - pipe_info->urb_size = sizeof(pipe_info->stream_urb); dprintk(4, "submitting URB %p\n", pipe_info->stream_urb); retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); if (retval) { @@ -2404,8 +2406,6 @@ static void s2255_stop_readpipe(struct s2255_dev *dev) if (pipe_info->state == 0) continue; pipe_info->state = 0; - pipe_info->prev_state = 1; - } } @@ -2543,7 +2543,9 @@ static int s2255_probe(struct usb_interface *interface, s2255_probe_v4l(dev); usb_reset_device(dev->udev); /* load 2255 board specific */ - s2255_board_init(dev); + retval = s2255_board_init(dev); + if (retval) + goto error; dprintk(4, "before probe done %p\n", dev); spin_lock_init(&dev->slock); diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 2849b7f54..a4e3deac2 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1669,6 +1669,39 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_AVERMEDIA_CARDBUS_501] = { + /* Oldrich Jedlicka <oldium.pro@seznam.cz> */ + .name = "AVerMedia Cardbus TV/Radio (E501R)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_ALPS_TSBE5_PAL, + .radio_type = TUNER_TEA5767, + .tuner_addr = 0x61, + .radio_addr = 0x60, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x08000000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x08000000, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x08000000, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x08000000, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x00000000, + }, + }, [SAA7134_BOARD_CINERGY400_CARDBUS] = { .name = "Terratec Cinergy 400 mobile", .audio_clock = 0x187de7, @@ -4045,7 +4078,7 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_BEHOLD_505FM] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov <d.belimov@gmail.com> */ - .name = "Beholder BeholdTV 505 FM/RDS", + .name = "Beholder BeholdTV 505 FM", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, @@ -4058,6 +4091,40 @@ struct saa7134_board saa7134_boards[] = { .vmux = 3, .amux = LINE2, .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .mute = { + .name = name_mute, + .amux = LINE1, + }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_505RDS] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov <d.belimov@gmail.com> */ + .name = "Beholder BeholdTV 505 RDS", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, },{ .name = name_comp1, .vmux = 1, @@ -4079,7 +4146,7 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_BEHOLD_507_9FM] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov <d.belimov@gmail.com> */ - .name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM", + .name = "Beholder BeholdTV 507 FM / BeholdTV 509 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, @@ -4106,6 +4173,66 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }, }, + [SAA7134_BOARD_BEHOLD_507RDS_MK5] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov <d.belimov@gmail.com> */ + .name = "Beholder BeholdTV 507 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_507RDS_MK3] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov <d.belimov@gmail.com> */ + .name = "Beholder BeholdTV 507 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov <d.belimov@gmail.com> */ @@ -4140,9 +4267,9 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x000A8000, }, }, - [SAA7134_BOARD_BEHOLD_607_9FM] = { + [SAA7134_BOARD_BEHOLD_607FM_MK3] = { /* Andrey Melnikoff <temnota@kmv.ru> */ - .name = "Beholder BeholdTV 607 / BeholdTV 609", + .name = "Beholder BeholdTV 607 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, @@ -4154,6 +4281,202 @@ struct saa7134_board saa7134_boards[] = { .vmux = 3, .amux = TV, .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_609FM_MK3] = { + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV 609 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_607FM_MK5] = { + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV 607 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_609FM_MK5] = { + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV 609 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_607RDS_MK3] = { + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV 607 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_609RDS_MK3] = { + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV 609 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_607RDS_MK5] = { + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV 607 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_609RDS_MK5] = { + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV 609 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, },{ .name = name_comp1, .vmux = 1, @@ -4248,8 +4571,7 @@ struct saa7134_board saa7134_boards[] = { /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */ .name = "Beholder BeholdTV M6 Extra", .audio_clock = 0x00187de7, - /* FIXME: Must be PHILIPS_FM1216ME_MK5*/ - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -4504,7 +4826,6 @@ 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 = 3, @@ -5104,6 +5425,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0xd6ee, .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS, },{ + /* AVerMedia CardBus */ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xb7e9, + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_501, + }, { /* TransGear 3000TV */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, @@ -5730,14 +6058,8 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x0000, - .subdevice = 0x5051, - .driver_data = SAA7134_BOARD_BEHOLD_505FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x0000, .subdevice = 0x505B, - .driver_data = SAA7134_BOARD_BEHOLD_505FM, + .driver_data = SAA7134_BOARD_BEHOLD_505RDS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, @@ -5749,13 +6071,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0000, .subdevice = 0x5071, - .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0000, .subdevice = 0x507B, - .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -5779,49 +6101,49 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5ace, .subdevice = 0x6070, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5ace, .subdevice = 0x6071, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5ace, .subdevice = 0x6072, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5ace, .subdevice = 0x6073, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5ace, .subdevice = 0x6090, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5ace, .subdevice = 0x6091, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5ace, .subdevice = 0x6092, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5ace, .subdevice = 0x6093, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -6257,7 +6579,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: - case SAA7134_BOARD_VIDEOMATE_T750: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: @@ -6285,7 +6606,10 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_407FM: case SAA7134_BOARD_BEHOLD_409: case SAA7134_BOARD_BEHOLD_505FM: + case SAA7134_BOARD_BEHOLD_505RDS: case SAA7134_BOARD_BEHOLD_507_9FM: + case SAA7134_BOARD_BEHOLD_507RDS_MK3: + case SAA7134_BOARD_BEHOLD_507RDS_MK5: case SAA7134_BOARD_GENIUS_TVGO_A11MCE: case SAA7134_BOARD_REAL_ANGEL_220: case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: @@ -6341,6 +6665,16 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); msleep(10); break; + case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: + /* power-down tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08400000, 0x08400000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0); + msleep(10); + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08400000, 0x08400000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0x08400000); + msleep(10); + dev->has_remote = SAA7134_REMOTE_I2C; + break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: saa7134_set_gpio(dev, 23, 0); msleep(10); @@ -6400,7 +6734,14 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_UPMOST_PURPLE_TV: case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: case SAA7134_BOARD_HAUPPAUGE_HVR1110: - case SAA7134_BOARD_BEHOLD_607_9FM: + case SAA7134_BOARD_BEHOLD_607FM_MK3: + case SAA7134_BOARD_BEHOLD_607FM_MK5: + case SAA7134_BOARD_BEHOLD_609FM_MK3: + case SAA7134_BOARD_BEHOLD_609FM_MK5: + case SAA7134_BOARD_BEHOLD_607RDS_MK3: + case SAA7134_BOARD_BEHOLD_607RDS_MK5: + case SAA7134_BOARD_BEHOLD_609RDS_MK3: + case SAA7134_BOARD_BEHOLD_609RDS_MK5: case SAA7134_BOARD_BEHOLD_M6: case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: @@ -6782,6 +7123,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: { struct v4l2_priv_tun_config tea5767_cfg; struct tea5767_ctrl ctl; diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index bab6b56c8..dd22a5215 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -499,11 +499,8 @@ static void empress_signal_update(struct work_struct *work) if (dev->nosignal) { dprintk("no video signal\n"); - ts_reset_encoder(dev); } else { dprintk("video signal acquired\n"); - if (atomic_read(&dev->empress_users)) - ts_init_encoder(dev); } } diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 87dc1b9bb..80a4cc23d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -507,7 +507,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_407FM: case SAA7134_BOARD_BEHOLD_409: case SAA7134_BOARD_BEHOLD_505FM: + case SAA7134_BOARD_BEHOLD_505RDS: case SAA7134_BOARD_BEHOLD_507_9FM: + case SAA7134_BOARD_BEHOLD_507RDS_MK3: + case SAA7134_BOARD_BEHOLD_507RDS_MK5: ir_codes = ir_codes_manli; mask_keycode = 0x003f00; mask_keyup = 0x004000; @@ -718,7 +721,14 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) ir->get_key = get_key_hvr1110; ir->ir_codes = ir_codes_hauppauge_new; break; - case SAA7134_BOARD_BEHOLD_607_9FM: + case SAA7134_BOARD_BEHOLD_607FM_MK3: + case SAA7134_BOARD_BEHOLD_607FM_MK5: + case SAA7134_BOARD_BEHOLD_609FM_MK3: + case SAA7134_BOARD_BEHOLD_609FM_MK5: + case SAA7134_BOARD_BEHOLD_607RDS_MK3: + case SAA7134_BOARD_BEHOLD_607RDS_MK5: + case SAA7134_BOARD_BEHOLD_609RDS_MK3: + case SAA7134_BOARD_BEHOLD_609RDS_MK5: case SAA7134_BOARD_BEHOLD_M6: case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: diff --git a/linux/drivers/media/video/saa7134/saa7134-ts.c b/linux/drivers/media/video/saa7134/saa7134-ts.c index cc8b923af..b8ff459d0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-ts.c +++ b/linux/drivers/media/video/saa7134/saa7134-ts.c @@ -65,7 +65,7 @@ static int buffer_activate(struct saa7134_dev *dev, /* start DMA */ saa7134_set_dmabits(dev); - mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT); + mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT); if (dev->ts_state == SAA7134_TS_BUFF_DONE) { /* Clear TS cache */ diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 46d12fc27..ae7ba8923 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -253,7 +253,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_505FM 126 #define SAA7134_BOARD_BEHOLD_507_9FM 127 #define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128 -#define SAA7134_BOARD_BEHOLD_607_9FM 129 +#define SAA7134_BOARD_BEHOLD_607FM_MK3 129 #define SAA7134_BOARD_BEHOLD_M6 130 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 #define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 @@ -282,6 +282,17 @@ struct saa7134_format { #define SAA7134_BOARD_HAUPPAUGE_HVR1120 155 #define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 +#define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 +#define SAA7134_BOARD_BEHOLD_505RDS 159 +#define SAA7134_BOARD_BEHOLD_507RDS_MK3 160 +#define SAA7134_BOARD_BEHOLD_507RDS_MK5 161 +#define SAA7134_BOARD_BEHOLD_607FM_MK5 162 +#define SAA7134_BOARD_BEHOLD_609FM_MK3 163 +#define SAA7134_BOARD_BEHOLD_609FM_MK5 164 +#define SAA7134_BOARD_BEHOLD_607RDS_MK3 165 +#define SAA7134_BOARD_BEHOLD_607RDS_MK5 166 +#define SAA7134_BOARD_BEHOLD_609RDS_MK3 167 +#define SAA7134_BOARD_BEHOLD_609RDS_MK5 168 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 @@ -366,6 +377,7 @@ struct saa7134_board { #define INTERLACE_OFF 2 #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ +#define TS_BUFFER_TIMEOUT msecs_to_jiffies(1000) /* 1 second */ struct saa7134_dev; struct saa7134_dma; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index cd796b33f..bf0b176f9 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -82,7 +82,6 @@ struct sh_mobile_ceu_buffer { }; struct sh_mobile_ceu_dev { - struct device *dev; struct soc_camera_host ici; struct soc_camera_device *icd; @@ -618,7 +617,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(&ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->dev, "Providing format %s using %s\n", sh_mobile_ceu_formats[k].name, icd->formats[idx].name); } @@ -631,7 +630,7 @@ add_single_format: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(&ici->dev, + dev_dbg(ici->dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -658,7 +657,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -685,7 +684,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -783,7 +782,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &sh_mobile_ceu_videobuf_ops, - &ici->dev, &pcdev->lock, + ici->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, pcdev->is_interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, @@ -830,7 +829,6 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit; } - platform_set_drvdata(pdev, pcdev); INIT_LIST_HEAD(&pcdev->capture); spin_lock_init(&pcdev->lock); @@ -841,7 +839,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_kfree; } - base = ioremap_nocache(res->start, res->end - res->start + 1); + base = ioremap_nocache(res->start, resource_size(res)); if (!base) { err = -ENXIO; dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n"); @@ -851,13 +849,12 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) pcdev->irq = irq; pcdev->base = base; pcdev->video_limit = 0; /* only enabled if second resource exists */ - pcdev->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res) { err = dma_declare_coherent_memory(&pdev->dev, res->start, res->start, - (res->end - res->start) + 1, + resource_size(res), DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE); if (!err) { @@ -866,7 +863,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_iounmap; } - pcdev->video_limit = (res->end - res->start) + 1; + pcdev->video_limit = resource_size(res); } /* request irq */ @@ -886,7 +883,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) } pcdev->ici.priv = pcdev; - pcdev->ici.dev.parent = &pdev->dev; + pcdev->ici.dev = &pdev->dev; pcdev->ici.nr = pdev->id; pcdev->ici.drv_name = dev_name(&pdev->dev); pcdev->ici.ops = &sh_mobile_ceu_host_ops; @@ -914,9 +911,11 @@ exit: static int sh_mobile_ceu_remove(struct platform_device *pdev) { - struct sh_mobile_ceu_dev *pcdev = platform_get_drvdata(pdev); + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct sh_mobile_ceu_dev *pcdev = container_of(soc_host, + struct sh_mobile_ceu_dev, ici); - soc_camera_host_unregister(&pcdev->ici); + soc_camera_host_unregister(soc_host); clk_put(pcdev->clk); free_irq(pcdev->irq, pcdev); if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 9e432d390..822052b25 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -16,19 +16,21 @@ * published by the Free Software Foundation. */ -#include <linux/module.h> -#include <linux/init.h> #include <linux/device.h> -#include <linux/list.h> #include <linux/err.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/module.h> #include <linux/mutex.h> +#include <linux/platform_device.h> #include <linux/vmalloc.h> +#include <media/soc_camera.h> #include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> #include <media/v4l2-dev.h> +#include <media/v4l2-ioctl.h> #include <media/videobuf-core.h> -#include <media/soc_camera.h> #include "compat.h" /* Default to VGA resolution */ @@ -280,7 +282,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return ret; } else if (!icd->current_fmt || icd->current_fmt->fourcc != pix->pixelformat) { - dev_err(&ici->dev, + dev_err(ici->dev, "Host driver hasn't set up current format correctly!\n"); return -EINVAL; } @@ -795,7 +797,7 @@ static void scan_add_host(struct soc_camera_host *ici) list_for_each_entry(icd, &devices, list) { if (icd->iface == ici->nr) { - icd->dev.parent = &ici->dev; + icd->dev.parent = ici->dev; device_register_link(icd); } } @@ -819,7 +821,7 @@ static int scan_add_device(struct soc_camera_device *icd) list_for_each_entry(ici, &hosts, list) { if (icd->iface == ici->nr) { ret = 1; - icd->dev.parent = &ici->dev; + icd->dev.parent = ici->dev; break; } } @@ -953,7 +955,6 @@ static void dummy_release(struct device *dev) int soc_camera_host_register(struct soc_camera_host *ici) { - int ret; struct soc_camera_host *ix; if (!ici || !ici->ops || @@ -966,12 +967,10 @@ int soc_camera_host_register(struct soc_camera_host *ici) !ici->ops->reqbufs || !ici->ops->add || !ici->ops->remove || - !ici->ops->poll) + !ici->ops->poll || + !ici->dev) return -EINVAL; - /* Number might be equal to the platform device ID */ - dev_set_name(&ici->dev, "camera_host%d", ici->nr); - mutex_lock(&list_lock); list_for_each_entry(ix, &hosts, list) { if (ix->nr == ici->nr) { @@ -980,26 +979,14 @@ int soc_camera_host_register(struct soc_camera_host *ici) } } + dev_set_drvdata(ici->dev, ici); + list_add_tail(&ici->list, &hosts); mutex_unlock(&list_lock); - ici->dev.release = dummy_release; - - ret = device_register(&ici->dev); - - if (ret) - goto edevr; - scan_add_host(ici); return 0; - -edevr: - mutex_lock(&list_lock); - list_del(&ici->list); - mutex_unlock(&list_lock); - - return ret; } EXPORT_SYMBOL(soc_camera_host_register); @@ -1013,7 +1000,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) list_del(&ici->list); list_for_each_entry(icd, &devices, list) { - if (icd->dev.parent == &ici->dev) { + if (icd->dev.parent == ici->dev) { device_unregister(&icd->dev); /* Not before device_unregister(), .remove * needs parent to call ici->ops->remove() */ @@ -1024,7 +1011,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) mutex_unlock(&list_lock); - device_unregister(&ici->dev); + dev_set_drvdata(ici->dev, NULL); } EXPORT_SYMBOL(soc_camera_host_unregister); @@ -1131,7 +1118,7 @@ int soc_camera_video_start(struct soc_camera_device *icd) vdev = video_device_alloc(); if (!vdev) goto evidallocd; - dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); + dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); @@ -1175,6 +1162,57 @@ void soc_camera_video_stop(struct soc_camera_device *icd) } EXPORT_SYMBOL(soc_camera_video_stop); +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) +{ + struct soc_camera_link *icl = pdev->dev.platform_data; + struct i2c_adapter *adap; + struct i2c_client *client; + + if (!icl) + return -EINVAL; + + adap = i2c_get_adapter(icl->i2c_adapter_id); + if (!adap) { + dev_warn(&pdev->dev, "Cannot get adapter #%d. No driver?\n", + icl->i2c_adapter_id); + /* -ENODEV and -ENXIO do not produce an error on probe()... */ + return -ENOENT; + } + + icl->board_info->platform_data = icl; + client = i2c_new_device(adap, icl->board_info); + if (!client) { + i2c_put_adapter(adap); + return -ENOMEM; + } + + platform_set_drvdata(pdev, client); + + return 0; +} + +static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) +{ + struct i2c_client *client = platform_get_drvdata(pdev); + + if (!client) + return -ENODEV; + + i2c_unregister_device(client); + i2c_put_adapter(client->adapter); + + return 0; +} + +static struct platform_driver __refdata soc_camera_pdrv = { + .probe = soc_camera_pdrv_probe, + .remove = __exit_p(soc_camera_pdrv_remove), + .driver = { + .name = "soc-camera-pdrv", + .owner = THIS_MODULE, + }, +}; + static int __init soc_camera_init(void) { int ret = bus_register(&soc_camera_bus_type); @@ -1184,8 +1222,14 @@ static int __init soc_camera_init(void) if (ret) goto edrvr; + ret = platform_driver_register(&soc_camera_pdrv); + if (ret) + goto epdr; + return 0; +epdr: + driver_unregister(&ic_drv); edrvr: bus_unregister(&soc_camera_bus_type); return ret; @@ -1193,6 +1237,7 @@ edrvr: static void __exit soc_camera_exit(void) { + platform_driver_unregister(&soc_camera_pdrv); driver_unregister(&ic_drv); bus_unregister(&soc_camera_bus_type); } @@ -1203,3 +1248,4 @@ module_exit(soc_camera_exit); MODULE_DESCRIPTION("Image capture bus driver"); MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:soc-camera-pdrv"); diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 7cbc4f736..886caf736 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1138,7 +1138,7 @@ static int stk_vidioc_querybuf(struct file *filp, struct stk_camera *dev = priv; struct stk_sio_buffer *sbuf; - if (buf->index < 0 || buf->index >= dev->n_sbufs) + if (buf->index >= dev->n_sbufs) return -EINVAL; sbuf = dev->sio_bufs + buf->index; *buf = sbuf->v4lbuf; @@ -1155,7 +1155,7 @@ static int stk_vidioc_qbuf(struct file *filp, if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if (buf->index < 0 || buf->index >= dev->n_sbufs) + if (buf->index >= dev->n_sbufs) return -EINVAL; sbuf = dev->sio_bufs + buf->index; if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 749539cb8..a1416084b 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -20,20 +20,6 @@ * loudness - set between 0 and 15 for varying degrees of loudness effect * * maxvol - set maximium volume to +20db (1), default is 0db(0) - * - * - * Revision: 0.7 - maxvol module parm to set maximium volume 0db or +20db - * store if muted so we can return it - * change balance only if flaged to - * Revision: 0.6 - added tone controls - * Revision: 0.5 - Fixed odd balance problem - * Revision: 0.4 - added muting - * Revision: 0.3 - Fixed silly reversed volume controls. :) - * Revision: 0.2 - Cleaned up #defines - * fixed volume control - * Added I2C_DRIVERID_TDA7432 - * added loudness insmod control - * Revision: 0.1 - initial version */ #include <linux/module.h> diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index de866798b..910e156f4 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -147,7 +147,6 @@ static const struct v4l2_subdev_ops tea6415c_ops = { .video = &tea6415c_video_ops, }; -/* this function is called by i2c_probe */ static int tea6415c_probe(struct i2c_client *client, const struct i2c_device_id *id) { diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index 90054dfbe..0e7bb8d6a 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -118,7 +118,6 @@ static const struct v4l2_subdev_ops tea6420_ops = { .audio = &tea6420_audio_ops, }; -/* this function is called by i2c_probe */ static int tea6420_probe(struct i2c_client *client, const struct i2c_device_id *id) { diff --git a/linux/drivers/media/video/ths7303.c b/linux/drivers/media/video/ths7303.c new file mode 100644 index 000000000..21781f8a0 --- /dev/null +++ b/linux/drivers/media/video/ths7303.c @@ -0,0 +1,151 @@ +/* + * ths7303- THS7303 Video Amplifier driver + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/ctype.h> +#include <linux/i2c.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/uaccess.h> +#include <linux/videodev2.h> + +#include <media/v4l2-device.h> +#include <media/v4l2-subdev.h> +#include <media/v4l2-chip-ident.h> + +MODULE_DESCRIPTION("TI THS7303 video amplifier driver"); +MODULE_AUTHOR("Chaithrika U S"); +MODULE_LICENSE("GPL"); + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level 0-1"); + +/* following function is used to set ths7303 */ +static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std) +{ + int err = 0; + u8 val; + struct i2c_client *client; + + client = v4l2_get_subdevdata(sd); + + if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) { + val = 0x02; + v4l2_dbg(1, debug, sd, "setting value for SDTV format\n"); + } else { + val = 0x00; + v4l2_dbg(1, debug, sd, "disabling all channels\n"); + } + + err |= i2c_smbus_write_byte_data(client, 0x01, val); + err |= i2c_smbus_write_byte_data(client, 0x02, val); + err |= i2c_smbus_write_byte_data(client, 0x03, val); + + if (err) + v4l2_err(sd, "write failed\n"); + + return err; +} + +static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) +{ + return ths7303_setvalue(sd, norm); +} + +static int ths7303_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_THS7303, 0); +} + +static const struct v4l2_subdev_video_ops ths7303_video_ops = { + .s_std_output = ths7303_s_std_output, +}; + +static const struct v4l2_subdev_core_ops ths7303_core_ops = { + .g_chip_ident = ths7303_g_chip_ident, +}; + +static const struct v4l2_subdev_ops ths7303_ops = { + .core = &ths7303_core_ops, + .video = &ths7303_video_ops, +}; + +static int ths7303_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct v4l2_subdev *sd; + v4l2_std_id std_id = V4L2_STD_NTSC; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + + sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + + v4l2_i2c_subdev_init(sd, client, &ths7303_ops); + + return ths7303_setvalue(sd, std_id); +} + +static int ths7303_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); + + return 0; +} + +static const struct i2c_device_id ths7303_id[] = { + {"ths7303", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, ths7303_id); + +static struct i2c_driver ths7303_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "ths7303", + }, + .probe = ths7303_probe, + .remove = ths7303_remove, + .id_table = ths7303_id, +}; + +static int __init ths7303_init(void) +{ + return i2c_add_driver(&ths7303_driver); +} + +static void __exit ths7303_exit(void) +{ + i2c_del_driver(&ths7303_driver); +} + +module_init(ths7303_init); +module_exit(ths7303_exit); + diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 9f763535e..cb715f143 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -109,8 +109,7 @@ static unsigned short normal_i2c[] = { 0x10, #endif 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x60, 0x61, 0x62, 0x63, 0x64, I2C_CLIENT_END }; @@ -324,32 +323,6 @@ static void set_freq(struct i2c_client *c, unsigned long freq) } } -static void tuner_i2c_address_check(struct tuner *t) -{ - if ((t->type == UNSET || t->type == TUNER_ABSENT) || - ((t->i2c->addr < 0x64) || (t->i2c->addr > 0x6f))) - return; - - /* We already know that the XC5000 can only be located at - * i2c address 0x61, 0x62, 0x63 or 0x64 */ - if ((t->type == TUNER_XC5000) && - ((t->i2c->addr <= 0x64)) && (t->i2c->addr >= 0x61)) - return; - - tuner_warn("====================== WARNING! ======================\n"); - tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n"); - tuner_warn("will soon be dropped. This message indicates that your\n"); - tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n", - t->name, t->i2c->addr); - tuner_warn("To ensure continued support for your device, please\n"); - tuner_warn("send a copy of this message, along with full dmesg\n"); - tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); - tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); - tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", - t->i2c->adapter->name, t->i2c->addr, t->type, t->name); - tuner_warn("====================== WARNING! ======================\n"); -} - static struct xc5000_config xc5000_cfg; static void set_type(struct i2c_client *c, unsigned int type, @@ -461,10 +434,6 @@ 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; - - xc_tuner_ops = &t->fe.ops.tuner_ops; - if (xc_tuner_ops->init) - xc_tuner_ops->init(&t->fe); break; } default: @@ -505,7 +474,6 @@ static void set_type(struct i2c_client *c, unsigned int type, tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n", c->adapter->name, c->driver->driver.name, c->addr << 1, type, t->mode_mask); - tuner_i2c_address_check(t); return; attach_failed: @@ -1213,28 +1181,6 @@ static int tuner_legacy_probe(struct i2c_adapter *adap) if ((adap->class & I2C_CLASS_TV_ANALOG) == 0) return 0; - - /* HACK: Ignore 0x6b and 0x6f on cx88 boards. - * FusionHDTV5 RT Gold has an ir receiver at 0x6b - * and an RTC at 0x6f which can get corrupted if probed. - */ - if ((adap->id == I2C_HW_B_CX2388x) || - (adap->id == I2C_HW_B_CX23885)) { - unsigned int i = 0; - - while (i < I2C_CLIENT_MAX_OPTS && ignore[i] != I2C_CLIENT_END) - i += 2; - if (i + 4 < I2C_CLIENT_MAX_OPTS) { - ignore[i+0] = adap->nr; - ignore[i+1] = 0x6b; - ignore[i+2] = adap->nr; - ignore[i+3] = 0x6f; - ignore[i+4] = I2C_CLIENT_END; - } else - printk(KERN_WARNING "tuner: " - "too many options specified " - "in i2c probe ignore list!\n"); - } return 1; } #else diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index cdea91aae..7d6459dd2 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -211,7 +211,7 @@ hauppauge_tuner[] = { TUNER_TEA5767, "Philips TEA5768HL FM Radio"}, { TUNER_ABSENT, "Panasonic ENV57H12D5"}, { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05-4"}, - { TUNER_ABSENT, "TCL MNM05-4"}, + { TUNER_PHILIPS_FM1236_MK3, "TCL MNM05-4"}, { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"}, { TUNER_ABSENT, "TCL MQNM05-4"}, { TUNER_ABSENT, "LG TAPC-W701D"}, diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index d7056a5b7..d03e5922d 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -541,7 +541,7 @@ static int vidioc_enum_input (struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); int chan; - if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) + if (vi->index >= usbvision->video_inputs) return -EINVAL; if (usbvision->have_tuner) { chan = vi->index; diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 177d149a5..8d193376c 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1707,14 +1707,17 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) static int __uvc_resume(struct usb_interface *intf, int reset) { struct uvc_device *dev = usb_get_intfdata(intf); - int ret; uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", intf->cur_altsetting->desc.bInterfaceNumber); if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { - if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0) - return ret; + if (reset) { + int ret = uvc_ctrl_resume_device(dev); + + if (ret < 0) + return ret; + } return uvc_status_resume(dev); } diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index d75d89c88..8f2db1250 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -774,6 +774,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, const struct v4l2_subdev_ops *ops) { v4l2_subdev_init(sd, ops); + sd->flags |= V4L2_SUBDEV_FL_IS_I2C; /* the owner is the same as the i2c_client's driver owner */ sd->owner = client->driver->driver.owner; /* i2c_client and v4l2_subdev point to one another */ @@ -978,8 +979,7 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) }; static const unsigned short tv_addrs[] = { 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x60, 0x61, 0x62, 0x63, 0x64, I2C_CLIENT_END }; diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index 2cb81c210..b962862fe 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -50,6 +50,22 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) } EXPORT_SYMBOL_GPL(v4l2_device_register); +int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename, + atomic_t *instance) +{ + int num = atomic_inc_return(instance) - 1; + int len = strlen(basename); + + if (basename[len - 1] >= '0' && basename[len - 1] <= '9') + snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), + "%s-%d", basename, num); + else + snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), + "%s%d", basename, num); + return num; +} +EXPORT_SYMBOL_GPL(v4l2_device_set_name); + void v4l2_device_disconnect(struct v4l2_device *v4l2_dev) { if (v4l2_dev->dev) { @@ -68,8 +84,21 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) v4l2_device_disconnect(v4l2_dev); /* Unregister subdevs */ - list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) + list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) { v4l2_device_unregister_subdev(sd); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + + /* We need to unregister the i2c client explicitly. + We cannot rely on i2c_del_adapter to always + unregister clients for us, since if the i2c bus + is a platform bus, then it is never deleted. */ + if (client) + i2c_unregister_device(client); + } +#endif + } } EXPORT_SYMBOL_GPL(v4l2_device_unregister); diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 885e6f557..22b380dfd 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -43,6 +43,12 @@ printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\ } while (0) +/* Zero out the end of the struct pointed to by p. Everthing after, but + * not including, the specified field is cleared. */ +#define CLEAR_AFTER_FIELD(p, field) \ + memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \ + 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field)) + struct std_descr { v4l2_std_id std; const char *descr; @@ -545,39 +551,39 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (ops->vidioc_try_fmt_vid_cap) + if (ops->vidioc_g_fmt_vid_cap) return 0; break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (ops->vidioc_try_fmt_vid_overlay) + if (ops->vidioc_g_fmt_vid_overlay) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (ops->vidioc_try_fmt_vid_out) + if (ops->vidioc_g_fmt_vid_out) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (ops->vidioc_try_fmt_vid_out_overlay) + if (ops->vidioc_g_fmt_vid_out_overlay) return 0; break; case V4L2_BUF_TYPE_VBI_CAPTURE: - if (ops->vidioc_try_fmt_vbi_cap) + if (ops->vidioc_g_fmt_vbi_cap) return 0; break; case V4L2_BUF_TYPE_VBI_OUTPUT: - if (ops->vidioc_try_fmt_vbi_out) + if (ops->vidioc_g_fmt_vbi_out) return 0; break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (ops->vidioc_try_fmt_sliced_vbi_cap) + if (ops->vidioc_g_fmt_sliced_vbi_cap) return 0; break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (ops->vidioc_try_fmt_sliced_vbi_out) + if (ops->vidioc_g_fmt_sliced_vbi_out) return 0; break; case V4L2_BUF_TYPE_PRIVATE: - if (ops->vidioc_try_fmt_type_private) + if (ops->vidioc_g_fmt_type_private) return 0; break; } @@ -783,44 +789,53 @@ static long __video_do_ioctl(struct file *file, switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.pix); v4l_print_pix_fmt(vfd, &f->fmt.pix); if (ops->vidioc_s_fmt_vid_cap) ret = ops->vidioc_s_fmt_vid_cap(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_s_fmt_vid_overlay) ret = ops->vidioc_s_fmt_vid_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.pix); v4l_print_pix_fmt(vfd, &f->fmt.pix); if (ops->vidioc_s_fmt_vid_out) ret = ops->vidioc_s_fmt_vid_out(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_s_fmt_vid_out_overlay) ret = ops->vidioc_s_fmt_vid_out_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_s_fmt_vbi_cap) ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_s_fmt_vbi_out) ret = ops->vidioc_s_fmt_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_s_fmt_sliced_vbi_cap) ret = ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_s_fmt_sliced_vbi_out) ret = ops->vidioc_s_fmt_sliced_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_PRIVATE: + /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ if (ops->vidioc_s_fmt_type_private) ret = ops->vidioc_s_fmt_type_private(file, fh, f); @@ -837,46 +852,55 @@ static long __video_do_ioctl(struct file *file, v4l2_type_names)); switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.pix); if (ops->vidioc_try_fmt_vid_cap) ret = ops->vidioc_try_fmt_vid_cap(file, fh, f); if (!ret) v4l_print_pix_fmt(vfd, &f->fmt.pix); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_try_fmt_vid_overlay) ret = ops->vidioc_try_fmt_vid_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.pix); if (ops->vidioc_try_fmt_vid_out) ret = ops->vidioc_try_fmt_vid_out(file, fh, f); if (!ret) v4l_print_pix_fmt(vfd, &f->fmt.pix); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_try_fmt_vid_out_overlay) ret = ops->vidioc_try_fmt_vid_out_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_try_fmt_vbi_cap) ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_try_fmt_vbi_out) ret = ops->vidioc_try_fmt_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_try_fmt_sliced_vbi_cap) ret = ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_try_fmt_sliced_vbi_out) ret = ops->vidioc_try_fmt_sliced_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_PRIVATE: + /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ if (ops->vidioc_try_fmt_type_private) ret = ops->vidioc_try_fmt_type_private(file, fh, f); @@ -899,6 +923,9 @@ static long __video_do_ioctl(struct file *file, if (ret) break; + if (p->type < V4L2_BUF_TYPE_PRIVATE) + CLEAR_AFTER_FIELD(p, memory); + ret = ops->vidioc_reqbufs(file, fh, p); dbgarg(cmd, "count=%d, type=%s, memory=%s\n", p->count, diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c index b104cd593..e9696385d 100644 --- a/linux/drivers/media/video/videobuf-core.c +++ b/linux/drivers/media/video/videobuf-core.c @@ -440,6 +440,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, } req->count = retval; + retval = 0; done: mutex_unlock(&q->vb_lock); @@ -455,7 +456,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) dprintk(1, "querybuf: Wrong type.\n"); goto done; } - if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) { + if (unlikely(b->index >= VIDEO_MAX_FRAME)) { dprintk(1, "querybuf: index out of range.\n"); goto done; } @@ -496,7 +497,7 @@ int videobuf_qbuf(struct videobuf_queue *q, dprintk(1, "qbuf: Wrong type.\n"); goto done; } - if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) { + if (b->index >= VIDEO_MAX_FRAME) { dprintk(1, "qbuf: index out of range.\n"); goto done; } diff --git a/linux/drivers/media/video/videobuf-dma-contig.c b/linux/drivers/media/video/videobuf-dma-contig.c index 6db1398fd..633a124cf 100644 --- a/linux/drivers/media/video/videobuf-dma-contig.c +++ b/linux/drivers/media/video/videobuf-dma-contig.c @@ -183,19 +183,6 @@ static int __videobuf_iolock(struct videobuf_queue *q, return 0; } -static int __videobuf_sync(struct videobuf_queue *q, - struct videobuf_buffer *buf) -{ - struct videobuf_dma_contig_memory *mem = buf->priv; - - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - dma_sync_single_for_cpu(q->dev, mem->dma_handle, mem->size, - DMA_FROM_DEVICE); - return 0; -} - static int __videobuf_mmap_free(struct videobuf_queue *q) { unsigned int i; @@ -357,7 +344,6 @@ static struct videobuf_qtype_ops qops = { .alloc = __videobuf_alloc, .iolock = __videobuf_iolock, - .sync = __videobuf_sync, .mmap_free = __videobuf_mmap_free, .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 733db7690..67ab10878 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1023,7 +1023,7 @@ zr36057_init (struct zoran *zr) zr->vbuf_bytesperline = 0; /* Avoid nonsense settings from user for default input/norm */ - if (default_norm < 0 && default_norm > 2) + if (default_norm < 0 || default_norm > 2) default_norm = 0; if (default_norm == 0) { zr->norm = V4L2_STD_PAL; diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 047902eb0..793395074 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1871,22 +1871,20 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag) { - int num = -1, i; - - for (i = 0; i < NUM_FORMATS; i++) { - if (zoran_formats[i].flags & flag) - num++; - if (num == fmt->index) - break; + unsigned int num, i; + + for (num = i = 0; i < NUM_FORMATS; i++) { + if (zoran_formats[i].flags & flag && num++ == fmt->index) { + strncpy(fmt->description, zoran_formats[i].name, + sizeof(fmt->description) - 1); + /* fmt struct pre-zeroed, so adding '\0' not neeed */ + fmt->pixelformat = zoran_formats[i].fourcc; + if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) + fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; + return 0; + } } - if (fmt->index < 0 /* late, but not too late */ || i == NUM_FORMATS) - return -EINVAL; - - strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); - fmt->pixelformat = zoran_formats[i].fourcc; - if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) - fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; - return 0; + return -EINVAL; } static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh, diff --git a/linux/include/media/adv7343.h b/linux/include/media/adv7343.h new file mode 100644 index 000000000..d6f8a4e1a --- /dev/null +++ b/linux/include/media/adv7343.h @@ -0,0 +1,23 @@ +/* + * ADV7343 header file + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef ADV7343_H +#define ADV7343_H + +#define ADV7343_COMPOSITE_ID (0) +#define ADV7343_COMPONENT_ID (1) +#define ADV7343_SVIDEO_ID (2) + +#endif /* End of #ifndef ADV7343_H */ diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 37013688a..23ecead35 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -60,7 +60,7 @@ struct soc_camera_file { struct soc_camera_host { struct list_head list; - struct device dev; + struct device *dev; unsigned char nr; /* Host number */ void *priv; const char *drv_name; @@ -92,11 +92,16 @@ struct soc_camera_host_ops { #define SOCAM_SENSOR_INVERT_VSYNC (1 << 3) #define SOCAM_SENSOR_INVERT_DATA (1 << 4) +struct i2c_board_info; + struct soc_camera_link { /* Camera bus id, used to match a camera and a bus */ int bus_id; /* Per camera SOCAM_SENSOR_* bus flags */ unsigned long flags; + int i2c_adapter_id; + struct i2c_board_info *board_info; + const char *module_name; /* Optional callbacks to power on or off and reset the sensor */ int (*power)(struct device *, int); int (*reset)(struct device *); @@ -107,6 +112,7 @@ struct soc_camera_link { */ int (*set_bus_param)(struct soc_camera_link *, unsigned long flags); unsigned long (*query_bus_param)(struct soc_camera_link *); + void (*free_bus)(struct soc_camera_link *); }; static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) @@ -116,7 +122,7 @@ static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) { - return container_of(dev, struct soc_camera_host, dev); + return dev_get_drvdata(dev); } extern int soc_camera_host_register(struct soc_camera_host *ici); diff --git a/linux/include/media/tuner.h b/linux/include/media/tuner.h index 7d4e2db78..735a2a941 100644 --- a/linux/include/media/tuner.h +++ b/linux/include/media/tuner.h @@ -124,6 +124,7 @@ #define TUNER_XC5000 76 /* Xceive Silicon Tuner */ #define TUNER_TCL_MF02GIP_5N 77 /* TCL MF02GIP_5N */ #define TUNER_PHILIPS_FMD1216MEX_MK3 78 +#define TUNER_PHILIPS_FM1216MK5 79 /* tv card specific */ #define TDA9887_PRESENT (1<<0) diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index 1be461a29..4d7e2272c 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -137,6 +137,12 @@ enum { /* module saa7191: just ident 7191 */ V4L2_IDENT_SAA7191 = 7191, + /* module ths7303: just ident 7303 */ + V4L2_IDENT_THS7303 = 7303, + + /* module adv7343: just ident 7343 */ + V4L2_IDENT_ADV7343 = 7343, + /* module wm8739: just ident 8739 */ V4L2_IDENT_WM8739 = 8739, diff --git a/linux/include/media/v4l2-device.h b/linux/include/media/v4l2-device.h index 9afd39fb2..5d5d550e6 100644 --- a/linux/include/media/v4l2-device.h +++ b/linux/include/media/v4l2-device.h @@ -53,10 +53,31 @@ struct v4l2_device { dev may be NULL in rare cases (ISA devices). In that case you must fill in the v4l2_dev->name field before calling this function. */ int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); + +/* Optional function to initialize the name field of struct v4l2_device using + the driver name and a driver-global atomic_t instance. + This function will increment the instance counter and returns the instance + value used in the name. + + Example: + + static atomic_t drv_instance = ATOMIC_INIT(0); + + ... + + instance = v4l2_device_set_name(&v4l2_dev, "foo", &drv_instance); + + The first time this is called the name field will be set to foo0 and + this function returns 0. If the name ends with a digit (e.g. cx18), + then the name will be set to cx18-0 since cx180 looks really odd. */ +int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename, + atomic_t *instance); + /* Set v4l2_dev->dev to NULL. Call when the USB parent disconnects. Since the parent disappears this ensures that v4l2_dev doesn't have an invalid parent pointer. */ void v4l2_device_disconnect(struct v4l2_device *v4l2_dev); + /* Unregister all sub-devices and any other resources related to v4l2_dev. */ void v4l2_device_unregister(struct v4l2_device *v4l2_dev); diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h index 17856081c..a503e1cee 100644 --- a/linux/include/media/v4l2-subdev.h +++ b/linux/include/media/v4l2-subdev.h @@ -230,12 +230,16 @@ struct v4l2_subdev_ops { #define V4L2_SUBDEV_NAME_SIZE 32 +/* Set this flag if this subdev is a i2c device. */ +#define V4L2_SUBDEV_FL_IS_I2C (1U << 0) + /* Each instance of a subdev driver should create this struct, either stand-alone or embedded in a larger struct. */ struct v4l2_subdev { struct list_head list; struct module *owner; + u32 flags; struct v4l2_device *v4l2_dev; const struct v4l2_subdev_ops *ops; /* name must be unique */ @@ -264,6 +268,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd, BUG_ON(!ops || !ops->core); sd->ops = ops; sd->v4l2_dev = NULL; + sd->flags = 0; sd->name[0] = '\0'; sd->grp_id = 0; sd->priv = NULL; |