aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/dvb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/b2c2/flexcop-common.h8
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c790
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c20
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c8
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c121
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c14
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c42
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.h4
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c10
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig3
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c94
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c31
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c7
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h4
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c325
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.h1
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c8
-rw-r--r--drivers/media/dvb/firewire/firedtv-1394.c4
-rw-r--r--drivers/media/dvb/firewire/firedtv-dvb.c2
-rw-r--r--drivers/media/dvb/firewire/firedtv-rc.c4
-rw-r--r--drivers/media/dvb/frontends/Kconfig22
-rw-r--r--drivers/media/dvb/frontends/Makefile4
-rw-r--r--drivers/media/dvb/frontends/af9013.c2
-rw-r--r--drivers/media/dvb/frontends/au8522_dig.c98
-rw-r--r--drivers/media/dvb/frontends/cx24116.c2
-rw-r--r--drivers/media/dvb/frontends/drx397xD.c4
-rw-r--r--drivers/media/dvb/frontends/isl6423.c308
-rw-r--r--drivers/media/dvb/frontends/isl6423.h63
-rw-r--r--drivers/media/dvb/frontends/lgdt3305.c17
-rw-r--r--drivers/media/dvb/frontends/lgs8gxx.c10
-rw-r--r--drivers/media/dvb/frontends/lnbp21.c2
-rw-r--r--drivers/media/dvb/frontends/mt312.c2
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c6
-rw-r--r--drivers/media/dvb/frontends/or51132.c2
-rw-r--r--drivers/media/dvb/frontends/stv0900.h7
-rw-r--r--drivers/media/dvb/frontends/stv0900_core.c100
-rw-r--r--drivers/media/dvb/frontends/stv0900_priv.h4
-rw-r--r--drivers/media/dvb/frontends/stv090x.c4302
-rw-r--r--drivers/media/dvb/frontends/stv090x.h106
-rw-r--r--drivers/media/dvb/frontends/stv090x_priv.h269
-rw-r--r--drivers/media/dvb/frontends/stv090x_reg.h2373
-rw-r--r--drivers/media/dvb/frontends/stv6110x.c373
-rw-r--r--drivers/media/dvb/frontends/stv6110x.h71
-rw-r--r--drivers/media/dvb/frontends/stv6110x_priv.h75
-rw-r--r--drivers/media/dvb/frontends/stv6110x_reg.h82
-rw-r--r--drivers/media/dvb/frontends/tda10048.c313
-rw-r--r--drivers/media/dvb/frontends/tda10048.h21
-rw-r--r--drivers/media/dvb/siano/Makefile2
-rw-r--r--drivers/media/dvb/siano/sms-cards.c188
-rw-r--r--drivers/media/dvb/siano/sms-cards.h64
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c468
-rw-r--r--drivers/media/dvb/siano/smscoreapi.h488
-rw-r--r--drivers/media/dvb/siano/smsdvb.c372
-rw-r--r--drivers/media/dvb/siano/smsendian.c102
-rw-r--r--drivers/media/dvb/siano/smsendian.h32
-rw-r--r--drivers/media/dvb/siano/smsir.c301
-rw-r--r--drivers/media/dvb/siano/smsir.h93
-rw-r--r--drivers/media/dvb/siano/smssdio.c357
-rw-r--r--drivers/media/dvb/siano/smsusb.c75
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c124
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c2
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c2
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c2
-rw-r--r--drivers/media/dvb/ttpci/budget.c85
67 files changed, 11940 insertions, 967 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 3e1c472092a..9e2148a1996 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/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/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index f7afab5944c..efb4a6c2b57 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/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 int 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;
+ return 1;
+ }
+ return 0;
+}
+#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,155 @@ 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 int skystar2_rev26_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ 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;
+ return 1;
+ }
+ return 0;
+}
+#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 int skystar2_rev27_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ flexcop_ibi_value r108;
+ 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)
+ goto fail;
+
+ i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
+ if (!i2c_tuner)
+ goto fail;
+
+ fc->fe_sleep = fc->fe->ops.sleep;
+ fc->fe->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)) {
+ err("ISL6421 could NOT be attached");
+ goto fail_isl;
+ }
+ 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 (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
+ &skystar2_rev2_7_itd1000_config)) {
+ err("ITD1000 could NOT be attached");
+ /* Should i2c clock be restored? */
+ goto fail_isl;
+ }
+ info("ITD1000 successfully attached");
+
+ return 1;
+
+fail_isl:
+ fc->fc_i2c_adap[2].no_base_addr = 0;
+fail:
+ /* for the next devices we need it again */
+ fc->fc_i2c_adap[0].no_base_addr = 0;
+ return 0;
+}
+#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 int skystar2_rev28_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ struct i2c_adapter *i2c_tuner;
+
+ fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
+ i2c);
+ if (!fc->fe)
+ return 0;
+
+ i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);;
+ if (!i2c_tuner)
+ return 0;
+
+ if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
+ i2c_tuner)) {
+ err("CX24113 could NOT be attached");
+ return 0;
+ }
+ 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)) {
+ err("ISL6421 could NOT be attached");
+ fc->fc_i2c_adap[2].no_base_addr = 0;
+ return 0;
+ }
+ 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 ??? */
+ return 1;
+}
+#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_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 +463,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 +485,95 @@ 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 int 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;
+ return 1;
+ }
+ return 0;
+}
+#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 int 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;
+ fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
+ return fc->fe != NULL;
+}
+#endif
- buf[0] = (div >> 8) & 0x7f;
- buf[1] = (div >> 0) & 0xff;
- buf[2] = 0x84 | ((div >> 10) & 0x60);
- buf[3] = 0x80;
+/* AirStar ATSC 2nd generation */
+#if defined(CONFIG_DVB_NXT200X_MODULE)
+static struct nxt200x_config samsung_tbmv_config = {
+ .demod_address = 0x0a,
+};
- if (params->frequency < 1550000)
- buf[3] |= 0x02;
+static int airstar_atsc2_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
+ if (!fc->fe)
+ return 0;
- 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;
+ return !!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 int 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)
+ return 0;
+
+ return !!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 +586,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 +599,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,182 +683,73 @@ 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 int 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;
+ if (!fc->fe) {
+ /* Reset for next frontend to try */
+ fc->fc_i2c_adap[0].no_base_addr = 0;
+ return 0;
}
- 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;
+ fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
+ return 1;
+}
+#endif
+
+static struct {
+ flexcop_device_type_t type;
+ int (*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;
+ if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
+ goto fe_found;
+ /* Clean up partially attached frontend */
+ if (fc->fe) {
+ dvb_frontend_detach(fc->fe);
+ fc->fe = NULL;
+ }
}
-
+ fc->dev_type = FC_UNK;
err("no frontend driver found for this B2C2/FlexCop adapter");
return -ENODEV;
@@ -664,9 +757,7 @@ fe_found:
info("found '%s' .", fc->fe->ops.info.name);
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
err("frontend registration failed!");
- ops = &fc->fe->ops;
- if (ops->release != NULL)
- ops->release(fc->fe);
+ dvb_frontend_detach(fc->fe);
fc->fe = NULL;
return -EINVAL;
}
@@ -680,6 +771,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/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index e2bed507648..fd1df235276 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/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/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index e56627d2f0f..f06f3a9070f 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -46,16 +46,16 @@ static const char *flexcop_revision_names[] = {
};
static const char *flexcop_device_names[] = {
- "Unknown device",
- "Air2PC/AirStar 2 DVB-T",
- "Air2PC/AirStar 2 ATSC 1st generation",
- "Air2PC/AirStar 2 ATSC 2nd generation",
- "Sky2PC/SkyStar 2 DVB-S",
- "Sky2PC/SkyStar 2 DVB-S (old version)",
- "Cable2PC/CableStar 2 DVB-C",
- "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
- "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
- "Sky2PC/SkyStar 2 DVB-S rev 2.8",
+ [FC_UNK] = "Unknown device",
+ [FC_CABLE] = "Cable2PC/CableStar 2 DVB-C",
+ [FC_AIR_DVBT] = "Air2PC/AirStar 2 DVB-T",
+ [FC_AIR_ATSC1] = "Air2PC/AirStar 2 ATSC 1st generation",
+ [FC_AIR_ATSC2] = "Air2PC/AirStar 2 ATSC 2nd generation",
+ [FC_AIR_ATSC3] = "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
+ [FC_SKY_REV23] = "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)",
+ [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6",
+ [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
+ [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8",
};
static const char *flexcop_bus_names[] = {
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 56d8fab688b..a24c125331f 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -508,12 +508,6 @@ static int __devinit bt878_probe(struct pci_dev *dev,
pci_set_master(dev);
pci_set_drvdata(dev, bt);
-/* if(init_bt878(btv) < 0) {
- bt878_remove(dev);
- return -EIO;
- }
-*/
-
if ((result = bt878_mem_alloc(bt))) {
printk(KERN_ERR "bt878: failed to allocate memory!\n");
goto fail2;
@@ -579,7 +573,7 @@ static struct pci_driver bt878_pci_driver = {
.name = "bt878",
.id_table = bt878_pci_tbl,
.probe = bt878_probe,
- .remove = bt878_remove,
+ .remove = __devexit_p(bt878_remove),
};
static int bt878_pci_driver_registered;
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index 971a8b18f6d..4dbd7d4185a 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -51,6 +51,9 @@
#ifndef PCI_VENDOR_ID_TRIGEM
#define PCI_VENDOR_ID_TRIGEM 0x109f
#endif
+#ifndef PCI_VENDOR_ID_AXESS
+#define PCI_VENDOR_ID_AXESS 0x195d
+#endif
#ifndef PCI_DEVICE_ID_DM1105
#define PCI_DEVICE_ID_DM1105 0x036f
#endif
@@ -60,6 +63,9 @@
#ifndef PCI_DEVICE_ID_DW2004
#define PCI_DEVICE_ID_DW2004 0x2004
#endif
+#ifndef PCI_DEVICE_ID_DM05
+#define PCI_DEVICE_ID_DM05 0x1105
+#endif
/* ----------------------------------------------- */
/* sdmc dm1105 registers */
@@ -150,6 +156,11 @@
#define DM1105_LNB_13V 0x00010100
#define DM1105_LNB_18V 0x00000100
+/* GPIO's for LNB power control for Axess DM05 */
+#define DM05_LNB_MASK 0x00000000
+#define DM05_LNB_13V 0x00020000
+#define DM05_LNB_18V 0x00030000
+
static int ir_debug;
module_param(ir_debug, int, 0644);
MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
@@ -188,6 +199,8 @@ struct dm1105dvb {
/* irq */
struct work_struct work;
+ struct workqueue_struct *wq;
+ char wqn[16];
/* dma */
dma_addr_t dma_addr;
@@ -313,15 +326,25 @@ static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe)
static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
+ u32 lnb_mask, lnb_13v, lnb_18v;
- if (voltage == SEC_VOLTAGE_18) {
- outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
- outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL));
- } else {
- /*LNB ON-13V by default!*/
- outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
- outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL));
- }
+ switch (dm1105dvb->pdev->subsystem_device) {
+ case PCI_DEVICE_ID_DM05:
+ lnb_mask = DM05_LNB_MASK;
+ lnb_13v = DM05_LNB_13V;
+ lnb_18v = DM05_LNB_18V;
+ break;
+ default:
+ lnb_mask = DM1105_LNB_MASK;
+ lnb_13v = DM1105_LNB_13V;
+ lnb_18v = DM1105_LNB_18V;
+ }
+
+ outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR));
+ if (voltage == SEC_VOLTAGE_18)
+ outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL));
+ else
+ outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL));
return 0;
}
@@ -440,7 +463,7 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
case (INTSTS_TSIRQ | INTSTS_IR):
dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
inl(dm_io_mem(DM1105_STADR));
- schedule_work(&dm1105dvb->work);
+ queue_work(dm1105dvb->wq, &dm1105dvb->work);
break;
case INTSTS_IR:
dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
@@ -567,46 +590,44 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
int ret;
switch (dm1105dvb->pdev->subsystem_device) {
- case PCI_DEVICE_ID_DW2002:
+ case PCI_DEVICE_ID_DW2004:
dm1105dvb->fe = dvb_attach(
- stv0299_attach, &sharp_z0194a_config,
+ cx24116_attach, &serit_sp2633_config,
&dm1105dvb->i2c_adap);
+ if (dm1105dvb->fe)
+ dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
+ break;
+ default:
+ dm1105dvb->fe = dvb_attach(
+ stv0299_attach, &sharp_z0194a_config,
+ &dm1105dvb->i2c_adap);
if (dm1105dvb->fe) {
dm1105dvb->fe->ops.set_voltage =
dm1105dvb_set_voltage;
dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
&dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
+ break;
}
- if (!dm1105dvb->fe) {
- dm1105dvb->fe = dvb_attach(
- stv0288_attach, &earda_config,
- &dm1105dvb->i2c_adap);
- if (dm1105dvb->fe) {
- dm1105dvb->fe->ops.set_voltage =
- dm1105dvb_set_voltage;
- dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
- &dm1105dvb->i2c_adap);
- }
+ dm1105dvb->fe = dvb_attach(
+ stv0288_attach, &earda_config,
+ &dm1105dvb->i2c_adap);
+ if (dm1105dvb->fe) {
+ dm1105dvb->fe->ops.set_voltage =
+ dm1105dvb_set_voltage;
+ dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
+ &dm1105dvb->i2c_adap);
+ break;
}
- if (!dm1105dvb->fe) {
- dm1105dvb->fe = dvb_attach(
- si21xx_attach, &serit_config,
- &dm1105dvb->i2c_adap);
- if (dm1105dvb->fe)
- dm1105dvb->fe->ops.set_voltage =
- dm1105dvb_set_voltage;
- }
- break;
- case PCI_DEVICE_ID_DW2004:
dm1105dvb->fe = dvb_attach(
- cx24116_attach, &serit_sp2633_config,
+ si21xx_attach, &serit_config,
&dm1105dvb->i2c_adap);
if (dm1105dvb->fe)
- dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
- break;
+ dm1105dvb->fe->ops.set_voltage =
+ dm1105dvb_set_voltage;
+
}
if (!dm1105dvb->fe) {
@@ -630,10 +651,17 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
static u8 command[1] = { 0x28 };
struct i2c_msg msg[] = {
- { .addr = IIC_24C01_addr >> 1, .flags = 0,
- .buf = command, .len = 1 },
- { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD,
- .buf = mac, .len = 6 },
+ {
+ .addr = IIC_24C01_addr >> 1,
+ .flags = 0,
+ .buf = command,
+ .len = 1
+ }, {
+ .addr = IIC_24C01_addr >> 1,
+ .flags = I2C_M_RD,
+ .buf = mac,
+ .len = 6
+ },
};
dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
@@ -752,14 +780,22 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
dm1105_ir_init(dm1105dvb);
INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
+ sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
+ dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn);
+ if (!dm1105dvb->wq)
+ goto err_dvb_net;
ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
DRIVER_NAME, dm1105dvb);
if (ret < 0)
- goto err_free_irq;
+ goto err_workqueue;
return 0;
+err_workqueue:
+ destroy_workqueue(dm1105dvb->wq);
+err_dvb_net:
+ dvb_net_release(&dm1105dvb->dvbnet);
err_disconnect_frontend:
dmx->disconnect_frontend(dmx);
err_remove_mem_frontend:
@@ -776,8 +812,6 @@ err_i2c_del_adapter:
i2c_del_adapter(&dm1105dvb->i2c_adap);
err_dm1105dvb_hw_exit:
dm1105dvb_hw_exit(dm1105dvb);
-err_free_irq:
- free_irq(pdev->irq, dm1105dvb);
err_pci_iounmap:
pci_iounmap(pdev, dm1105dvb->io_mem);
err_pci_release_regions:
@@ -834,6 +868,11 @@ static struct pci_device_id dm1105_id_table[] __devinitdata = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_DEVICE_ID_DW2004,
}, {
+ .vendor = PCI_VENDOR_ID_AXESS,
+ .device = PCI_DEVICE_ID_DM05,
+ .subvendor = PCI_VENDOR_ID_AXESS,
+ .subdevice = PCI_DEVICE_ID_DM05,
+ }, {
/* empty */
},
};
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index c35fbb8d8f4..6d6121eb5d5 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -244,19 +244,13 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
{
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
- int ret;
- if (dmxdev->exit) {
- mutex_unlock(&dmxdev->mutex);
+ if (dmxdev->exit)
return -ENODEV;
- }
- //mutex_lock(&dmxdev->mutex);
- ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
- file->f_flags & O_NONBLOCK,
- buf, count, ppos);
- //mutex_unlock(&dmxdev->mutex);
- return ret;
+ return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
+ file->f_flags & O_NONBLOCK,
+ buf, count, ppos);
}
static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index e2eca0b1fe7..cfe2768d24a 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -38,6 +38,16 @@
*/
// #define DVB_DEMUX_SECTION_LOSS_LOG
+static int dvb_demux_tscheck;
+module_param(dvb_demux_tscheck, int, 0644);
+MODULE_PARM_DESC(dvb_demux_tscheck,
+ "enable transport stream continuity and TEI check");
+
+#define dprintk_tscheck(x...) do { \
+ if (dvb_demux_tscheck && printk_ratelimit()) \
+ printk(x); \
+ } while (0)
+
/******************************************************************************
* static inlined helper functions
******************************************************************************/
@@ -376,6 +386,36 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
u16 pid = ts_pid(buf);
int dvr_done = 0;
+ if (dvb_demux_tscheck) {
+ if (!demux->cnt_storage)
+ demux->cnt_storage = vmalloc(MAX_PID + 1);
+
+ if (!demux->cnt_storage) {
+ printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
+ dvb_demux_tscheck = 0;
+ goto no_dvb_demux_tscheck;
+ }
+
+ /* check pkt counter */
+ if (pid < MAX_PID) {
+ if (buf[1] & 0x80)
+ dprintk_tscheck("TEI detected. "
+ "PID=0x%x data1=0x%x\n",
+ pid, buf[1]);
+
+ if ((buf[3] & 0xf) != demux->cnt_storage[pid])
+ dprintk_tscheck("TS packet counter mismatch. "
+ "PID=0x%x expected 0x%x "
+ "got 0x%x\n",
+ pid, demux->cnt_storage[pid],
+ buf[3] & 0xf);
+
+ demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
+ };
+ /* end check */
+ };
+no_dvb_demux_tscheck:
+
list_for_each_entry(feed, &demux->feed_list, list_head) {
if ((feed->pid != pid) && (feed->pid != 0x2000))
continue;
@@ -1160,6 +1200,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
int i;
struct dmx_demux *dmx = &dvbdemux->dmx;
+ dvbdemux->cnt_storage = NULL;
dvbdemux->users = 0;
dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
@@ -1226,6 +1267,7 @@ EXPORT_SYMBOL(dvb_dmx_init);
void dvb_dmx_release(struct dvb_demux *dvbdemux)
{
+ vfree(dvbdemux->cnt_storage);
vfree(dvbdemux->filter);
vfree(dvbdemux->feed);
}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 2c5f915329c..2fe05d03240 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -42,6 +42,8 @@
#define DVB_DEMUX_MASK_MAX 18
+#define MAX_PID 0x1fff
+
struct dvb_demux_filter {
struct dmx_section_filter filter;
u8 maskandmode[DMX_MAX_FILTER_SIZE];
@@ -127,6 +129,8 @@ struct dvb_demux {
struct mutex mutex;
spinlock_t lock;
+
+ uint8_t *cnt_storage; /* for TS continuity check */
};
int dvb_dmx_init(struct dvb_demux *dvbdemux);
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index ebc78157b9b..f50ca7292a7 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -543,6 +543,7 @@ restart:
if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */
+ fepriv->exit = 1;
break;
}
@@ -656,6 +657,7 @@ restart:
}
fepriv->thread = NULL;
+ fepriv->exit = 0;
mb();
dvb_frontend_wakeup(fe);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index a454ee8f1e4..479dd05762a 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -447,6 +447,15 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
+static char *dvb_nodename(struct device *dev)
+{
+ struct dvb_device *dvbdev = dev_get_drvdata(dev);
+
+ return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
+ dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
+}
+
+
static int __init init_dvbdev(void)
{
int retval;
@@ -469,6 +478,7 @@ static int __init init_dvbdev(void)
goto error;
}
dvb_class->dev_uevent = dvb_uevent;
+ dvb_class->nodename = dvb_nodename;
return 0;
error:
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 60955a70d88..496c1a37034 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -216,7 +216,7 @@ config DVB_USB_TTUSB2
help
Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
firmware protocol used by this module is similar to the one used by the
- old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko.
+ old ttusb-driver - that's why the module is called dvb-usb-ttusb2.
config DVB_USB_DTT200U
tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
@@ -261,6 +261,7 @@ config DVB_USB_DW2102
select DVB_STB6000 if !DVB_FE_CUSTOMISE
select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_SI21XX if !DVB_FE_CUSTOMISE
+ select DVB_TDA10021 if !DVB_FE_CUSTOMISE
help
Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
and the TeVii S650.
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 53bfc8e42fb..4cb31e7c13c 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -40,7 +40,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static DEFINE_MUTEX(af9015_usb_mutex);
static struct af9015_config af9015_config;
-static struct dvb_usb_device_properties af9015_properties[2];
+static struct dvb_usb_device_properties af9015_properties[3];
static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
static struct af9013_config af9015_af9013_config[] = {
@@ -538,7 +538,7 @@ exit:
/* dump eeprom */
static int af9015_eeprom_dump(struct dvb_usb_device *d)
{
- char buf[52], buf2[4];
+ char buf[4+3*16+1], buf2[4];
u8 reg, val;
for (reg = 0; ; reg++) {
@@ -1261,7 +1261,11 @@ static struct usb_device_id af9015_usb_table[] = {
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
{USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
+/* 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)},
+ {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
{0},
};
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1321,7 +1325,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo,
- .num_device_descs = 9,
+ .num_device_descs = 9, /* max 9 */
.devices = {
{
.name = "Afatech AF9015 DVB-T USB2.0 stick",
@@ -1426,7 +1430,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo,
- .num_device_descs = 9,
+ .num_device_descs = 9, /* max 9 */
.devices = {
{
.name = "Xtensions XD-380",
@@ -1478,7 +1482,85 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.warm_ids = {NULL},
},
}
- }
+ }, {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .download_firmware = af9015_download_firmware,
+ .firmware = "dvb-usb-af9015.fw",
+ .no_reconnect = 1,
+
+ .size_of_priv = sizeof(struct af9015_state), \
+
+ .num_adapters = 2,
+ .adapter = {
+ {
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+ .pid_filter_count = 32,
+ .pid_filter = af9015_pid_filter,
+ .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
+ .frontend_attach =
+ af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ },
+ },
+ {
+ .frontend_attach =
+ af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x85,
+ .u = {
+ .bulk = {
+ .buffersize =
+ TS_USB20_MAX_PACKET_SIZE,
+ }
+ }
+ },
+ }
+ },
+
+ .identify_state = af9015_identify_state,
+
+ .rc_query = af9015_rc_query,
+ .rc_interval = 150,
+
+ .i2c_algo = &af9015_i2c_algo,
+
+ .num_device_descs = 4, /* max 9 */
+ .devices = {
+ {
+ .name = "AverMedia AVerTV Volar GPS 805 (A805)",
+ .cold_ids = {&af9015_usb_table[21], NULL},
+ .warm_ids = {NULL},
+ },
+ {
+ .name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
+ "V3.0",
+ .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},
+ },
+ {
+ .name = "Genius TVGo DVB-T03",
+ .cold_ids = {&af9015_usb_table[24], NULL},
+ .warm_ids = {NULL},
+ },
+ }
+ },
};
static int af9015_usb_probe(struct usb_interface *intf,
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 8ddbadf6219..818b2ab584b 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/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;
@@ -1493,6 +1493,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);
@@ -1692,7 +1696,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 },
@@ -1726,8 +1730,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",
@@ -1738,6 +1743,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,
@@ -1784,8 +1793,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",
@@ -1812,7 +1822,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 },
@@ -1842,6 +1852,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/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 8ee6cd4da9e..8dbad1ec53c 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/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/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index f506c74119f..9593b728999 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -80,6 +80,7 @@
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
#define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80
+#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
#define USB_PID_CONEXANT_D680_DMB 0x86d6
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
@@ -97,6 +98,7 @@
#define USB_PID_DPOSH_M9206_COLD 0x9206
#define USB_PID_DPOSH_M9206_WARM 0xa090
#define USB_PID_UNIWILL_STK7700P 0x6003
+#define USB_PID_GENIUS_TVGO_DVB_T03 0x4012
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_INTEL_CE9500 0x9500
@@ -104,6 +106,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
@@ -171,6 +174,7 @@
#define USB_PID_AVERMEDIA_A309 0xa309
#define USB_PID_AVERMEDIA_A310 0xa310
#define USB_PID_AVERMEDIA_A850 0x850a
+#define USB_PID_AVERMEDIA_A805 0xa805
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
@@ -178,6 +182,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
@@ -222,6 +228,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
@@ -251,5 +258,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/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 2d5352e54dc..e441d274e6c 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -196,7 +196,7 @@ struct dvb_usb_device_properties {
#define CYPRESS_FX2 3
int usb_ctrl;
int (*download_firmware) (struct usb_device *, const struct firmware *);
- const char firmware[FIRMWARE_NAME_MAX];
+ const char *firmware;
int no_reconnect;
int size_of_priv;
@@ -223,7 +223,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/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index c65f273ff31..75de49c0d94 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -1,7 +1,7 @@
/* DVB USB framework compliant Linux driver for the
-* DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card
-*
-* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
+* TeVii S600, S650 Cards
+* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -17,6 +17,7 @@
#include "stb6000.h"
#include "eds1547.h"
#include "cx24116.h"
+#include "tda1002x.h"
#ifndef USB_PID_DW2102
#define USB_PID_DW2102 0x2102
@@ -26,10 +27,18 @@
#define USB_PID_DW2104 0x2104
#endif
+#ifndef USB_PID_DW3101
+#define USB_PID_DW3101 0x3101
+#endif
+
#ifndef USB_PID_CINERGY_S
#define USB_PID_CINERGY_S 0x0064
#endif
+#ifndef USB_PID_TEVII_S650
+#define USB_PID_TEVII_S650 0xd650
+#endif
+
#define DW210X_READ_MSG 0
#define DW210X_WRITE_MSG 1
@@ -40,18 +49,21 @@
#define DW2102_VOLTAGE_CTRL (0x1800)
#define DW2102_RC_QUERY (0x1a00)
-struct dw210x_state {
- u32 last_key_pressed;
-};
-struct dw210x_rc_keys {
- u32 keycode;
- u32 event;
+struct dvb_usb_rc_keys_table {
+ struct dvb_usb_rc_key *rc_keys;
+ int rc_keys_size;
};
/* debug */
static int dvb_usb_dw2102_debug;
module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS);
+MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
+ DVB_USB_DEBUG_STATUS);
+
+/* keymaps */
+static int ir_keymap;
+module_param_named(keymap, ir_keymap, int, 0644);
+MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ...");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@@ -79,7 +91,7 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
-struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0, ret = 0;
u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
u16 value;
@@ -205,6 +217,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
mutex_unlock(&d->i2c_mutex);
return num;
}
+
static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
@@ -219,7 +232,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
case 2: {
/* read */
/* first write first register number */
- u8 ibuf [msg[1].len + 2], obuf[3];
+ u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = 0xd0;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
@@ -293,7 +306,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
case 2: {
/* read */
/* first write first register number */
- u8 ibuf [msg[1].len + 2], obuf[3];
+ u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = 0xaa;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
@@ -360,6 +373,69 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
return num;
}
+static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret = 0, i;
+
+ if (!d)
+ return -ENODEV;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ switch (num) {
+ case 2: {
+ /* read */
+ /* first write first register number */
+ u8 ibuf[msg[1].len + 2], obuf[3];
+ obuf[0] = msg[0].addr << 1;
+ obuf[1] = msg[0].len;
+ obuf[2] = msg[0].buf[0];
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+ /* second read registers */
+ ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
+ ibuf, msg[1].len + 2, DW210X_READ_MSG);
+ memcpy(msg[1].buf, ibuf + 2, msg[1].len);
+
+ break;
+ }
+ case 1:
+ switch (msg[0].addr) {
+ case 0x60:
+ case 0x0c: {
+ /* write to register */
+ u8 obuf[msg[0].len + 2];
+ obuf[0] = msg[0].addr << 1;
+ obuf[1] = msg[0].len;
+ memcpy(obuf + 2, msg[0].buf, msg[0].len);
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+ break;
+ }
+ case(DW2102_RC_QUERY): {
+ u8 ibuf[2];
+ ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ ibuf, 2, DW210X_READ_MSG);
+ memcpy(msg[0].buf, ibuf , 2);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ for (i = 0; i < num; i++) {
+ deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
+ msg[i].flags == 0 ? ">>>" : "<<<");
+ debug_dump(msg[i].buf, msg[i].len, deb_xfer);
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return num;
+}
+
static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
@@ -385,6 +461,11 @@ static struct i2c_algorithm dw2104_i2c_algo = {
.functionality = dw210x_i2c_func,
};
+static struct i2c_algorithm dw3101_i2c_algo = {
+ .master_xfer = dw3101_i2c_transfer,
+ .functionality = dw210x_i2c_func,
+};
+
static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i;
@@ -404,6 +485,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
debug_dump(eepromline, 16, deb_xfer);
}
}
+
memcpy(mac, eeprom + 8, 6);
return 0;
};
@@ -448,6 +530,11 @@ static struct si21xx_config serit_sp1511lhb_config = {
};
+static struct tda10023_config dw3101_tda10023_config = {
+ .demod_address = 0x0c,
+ .invert = 1,
+};
+
static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
{
if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
@@ -460,6 +547,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
}
static struct dvb_usb_device_properties dw2102_properties;
+static struct dvb_usb_device_properties dw2104_properties;
static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
{
@@ -497,6 +585,17 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
return -EIO;
}
+static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
+{
+ d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
+ &d->dev->i2c_adap, 0x48);
+ if (d->fe != NULL) {
+ info("Attached tda10023!\n");
+ return 0;
+ }
+ return -EIO;
+}
+
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -512,6 +611,14 @@ static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ &adap->dev->i2c_adap, DVB_PLL_TUA6034);
+
+ return 0;
+}
+
static struct dvb_usb_rc_key dw210x_rc_keys[] = {
{ 0xf8, 0x0a, KEY_Q }, /*power*/
{ 0xf8, 0x0c, KEY_M }, /*mute*/
@@ -544,44 +651,147 @@ static struct dvb_usb_rc_key dw210x_rc_keys[] = {
{ 0xf8, 0x40, KEY_F }, /*full*/
{ 0xf8, 0x1e, KEY_W }, /*tvmode*/
{ 0xf8, 0x1b, KEY_B }, /*recall*/
+};
+static struct dvb_usb_rc_key tevii_rc_keys[] = {
+ { 0xf8, 0x0a, KEY_POWER },
+ { 0xf8, 0x0c, KEY_MUTE },
+ { 0xf8, 0x11, KEY_1 },
+ { 0xf8, 0x12, KEY_2 },
+ { 0xf8, 0x13, KEY_3 },
+ { 0xf8, 0x14, KEY_4 },
+ { 0xf8, 0x15, KEY_5 },
+ { 0xf8, 0x16, KEY_6 },
+ { 0xf8, 0x17, KEY_7 },
+ { 0xf8, 0x18, KEY_8 },
+ { 0xf8, 0x19, KEY_9 },
+ { 0xf8, 0x10, KEY_0 },
+ { 0xf8, 0x1c, KEY_MENU },
+ { 0xf8, 0x0f, KEY_VOLUMEDOWN },
+ { 0xf8, 0x1a, KEY_LAST },
+ { 0xf8, 0x0e, KEY_OPEN },
+ { 0xf8, 0x04, KEY_RECORD },
+ { 0xf8, 0x09, KEY_VOLUMEUP },
+ { 0xf8, 0x08, KEY_CHANNELUP },
+ { 0xf8, 0x07, KEY_PVR },
+ { 0xf8, 0x0b, KEY_TIME },
+ { 0xf8, 0x02, KEY_RIGHT },
+ { 0xf8, 0x03, KEY_LEFT },
+ { 0xf8, 0x00, KEY_UP },
+ { 0xf8, 0x1f, KEY_OK },
+ { 0xf8, 0x01, KEY_DOWN },
+ { 0xf8, 0x05, KEY_TUNER },
+ { 0xf8, 0x06, KEY_CHANNELDOWN },
+ { 0xf8, 0x40, KEY_PLAYPAUSE },
+ { 0xf8, 0x1e, KEY_REWIND },
+ { 0xf8, 0x1b, KEY_FAVORITES },
+ { 0xf8, 0x1d, KEY_BACK },
+ { 0xf8, 0x4d, KEY_FASTFORWARD },
+ { 0xf8, 0x44, KEY_EPG },
+ { 0xf8, 0x4c, KEY_INFO },
+ { 0xf8, 0x41, KEY_AB },
+ { 0xf8, 0x43, KEY_AUDIO },
+ { 0xf8, 0x45, KEY_SUBTITLE },
+ { 0xf8, 0x4a, KEY_LIST },
+ { 0xf8, 0x46, KEY_F1 },
+ { 0xf8, 0x47, KEY_F2 },
+ { 0xf8, 0x5e, KEY_F3 },
+ { 0xf8, 0x5c, KEY_F4 },
+ { 0xf8, 0x52, KEY_F5 },
+ { 0xf8, 0x5a, KEY_F6 },
+ { 0xf8, 0x56, KEY_MODE },
+ { 0xf8, 0x58, KEY_SWITCHVIDEOMODE },
};
+static struct dvb_usb_rc_key tbs_rc_keys[] = {
+ { 0xf8, 0x84, KEY_POWER },
+ { 0xf8, 0x94, KEY_MUTE },
+ { 0xf8, 0x87, KEY_1 },
+ { 0xf8, 0x86, KEY_2 },
+ { 0xf8, 0x85, KEY_3 },
+ { 0xf8, 0x8b, KEY_4 },
+ { 0xf8, 0x8a, KEY_5 },
+ { 0xf8, 0x89, KEY_6 },
+ { 0xf8, 0x8f, KEY_7 },
+ { 0xf8, 0x8e, KEY_8 },
+ { 0xf8, 0x8d, KEY_9 },
+ { 0xf8, 0x92, KEY_0 },
+ { 0xf8, 0x96, KEY_CHANNELUP },
+ { 0xf8, 0x91, KEY_CHANNELDOWN },
+ { 0xf8, 0x93, KEY_VOLUMEUP },
+ { 0xf8, 0x8c, KEY_VOLUMEDOWN },
+ { 0xf8, 0x83, KEY_RECORD },
+ { 0xf8, 0x98, KEY_PAUSE },
+ { 0xf8, 0x99, KEY_OK },
+ { 0xf8, 0x9a, KEY_SHUFFLE },
+ { 0xf8, 0x81, KEY_UP },
+ { 0xf8, 0x90, KEY_LEFT },
+ { 0xf8, 0x82, KEY_RIGHT },
+ { 0xf8, 0x88, KEY_DOWN },
+ { 0xf8, 0x95, KEY_FAVORITES },
+ { 0xf8, 0x97, KEY_SUBTITLE },
+ { 0xf8, 0x9d, KEY_ZOOM },
+ { 0xf8, 0x9f, KEY_EXIT },
+ { 0xf8, 0x9e, KEY_MENU },
+ { 0xf8, 0x9c, KEY_EPG },
+ { 0xf8, 0x80, KEY_PREVIOUS },
+ { 0xf8, 0x9b, KEY_MODE }
+};
+static struct dvb_usb_rc_keys_table keys_tables[] = {
+ { dw210x_rc_keys, ARRAY_SIZE(dw210x_rc_keys) },
+ { tevii_rc_keys, ARRAY_SIZE(tevii_rc_keys) },
+ { tbs_rc_keys, ARRAY_SIZE(tbs_rc_keys) },
+};
static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
- struct dw210x_state *st = d->priv;
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ int keymap_size = d->props.rc_key_map_size;
u8 key[2];
- struct i2c_msg msg[] = {
- {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
- .len = 2},
+ struct i2c_msg msg = {
+ .addr = DW2102_RC_QUERY,
+ .flags = I2C_M_RD,
+ .buf = key,
+ .len = 2
};
int i;
+ /* override keymap */
+ if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {
+ keymap = keys_tables[ir_keymap - 1].rc_keys ;
+ keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;
+ }
*state = REMOTE_NO_KEY_PRESSED;
- if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
- for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) {
- if (dw210x_rc_keys[i].data == msg[0].buf[0]) {
+ if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) {
+ for (i = 0; i < keymap_size ; i++) {
+ if (keymap[i].data == msg.buf[0]) {
*state = REMOTE_KEY_PRESSED;
- *event = dw210x_rc_keys[i].event;
- st->last_key_pressed =
- dw210x_rc_keys[i].event;
+ *event = keymap[i].event;
break;
}
- st->last_key_pressed = 0;
+
}
+
+ if ((*state) == REMOTE_KEY_PRESSED)
+ deb_rc("%s: found rc key: %x, %x, event: %x\n",
+ __func__, key[0], key[1], (*event));
+ else if (key[0] != 0xff)
+ deb_rc("%s: unknown rc key: %x, %x\n",
+ __func__, key[0], key[1]);
+
}
- /* info("key: %x %x\n",key[0],key[1]); */
+
return 0;
}
static struct usb_device_id dw2102_table[] = {
{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
{USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
- {USB_DEVICE(USB_VID_CYPRESS, 0x2104)},
- {USB_DEVICE(0x9022, 0xd650)},
+ {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
+ {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
{USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
+ {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
{ }
};
@@ -642,11 +852,16 @@ static int dw2102_load_firmware(struct usb_device *dev,
}
/* init registers */
switch (dev->descriptor.idProduct) {
+ case USB_PID_TEVII_S650:
+ dw2104_properties.rc_key_map = tevii_rc_keys;
+ dw2104_properties.rc_key_map_size =
+ ARRAY_SIZE(tevii_rc_keys);
case USB_PID_DW2104:
- case 0xd650:
reset = 1;
dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
DW210X_WRITE_MSG);
+ /* break omitted intentionally */
+ case USB_PID_DW3101:
reset = 0;
dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
DW210X_WRITE_MSG);
@@ -690,6 +905,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
DW210X_READ_MSG);
break;
}
+
msleep(100);
kfree(p);
}
@@ -700,7 +916,6 @@ static struct dvb_usb_device_properties dw2102_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-dw2102.fw",
- .size_of_priv = sizeof(struct dw210x_state),
.no_reconnect = 1,
.i2c_algo = &dw2102_serit_i2c_algo,
@@ -714,7 +929,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
.num_adapters = 1,
.download_firmware = dw2102_load_firmware,
.read_mac_address = dw210x_read_mac_address,
- .adapter = {
+ .adapter = {
{
.frontend_attach = dw2102_frontend_attach,
.streaming_ctrl = NULL,
@@ -752,7 +967,6 @@ static struct dvb_usb_device_properties dw2104_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-dw2104.fw",
- .size_of_priv = sizeof(struct dw210x_state),
.no_reconnect = 1,
.i2c_algo = &dw2104_i2c_algo,
@@ -796,12 +1010,57 @@ static struct dvb_usb_device_properties dw2104_properties = {
}
};
+static struct dvb_usb_device_properties dw3101_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-dw3101.fw",
+ .no_reconnect = 1,
+
+ .i2c_algo = &dw3101_i2c_algo,
+ .rc_key_map = dw210x_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
+ .rc_interval = 150,
+ .rc_query = dw2102_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x81,
+ /* parameter for the MPEG2-data transfer */
+ .num_adapters = 1,
+ .download_firmware = dw2102_load_firmware,
+ .read_mac_address = dw210x_read_mac_address,
+ .adapter = {
+ {
+ .frontend_attach = dw3101_frontend_attach,
+ .streaming_ctrl = NULL,
+ .tuner_attach = dw3101_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ }
+ },
+ .num_device_descs = 1,
+ .devices = {
+ { "DVBWorld DVB-C 3101 USB2.0",
+ {&dw2102_table[5], NULL},
+ {NULL},
+ },
+ }
+};
+
static int dw2102_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &dw2104_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &dw3101_properties,
THIS_MODULE, NULL, adapter_nr)) {
return 0;
}
@@ -833,6 +1092,8 @@ module_init(dw2102_module_init);
module_exit(dw2102_module_exit);
MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
-MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
+ " DVB-C 3101 USB2.0,"
+ " TeVii S600, S650 USB2.0 devices");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h
index e3370734e95..5cd0b0eb6ce 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.h
+++ b/drivers/media/dvb/dvb-usb/dw2102.h
@@ -5,4 +5,5 @@
#include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
+#define deb_rc(args...) dprintk(dvb_usb_dw2102_debug, 0x04, args)
#endif
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index 3dd6843864e..afb444db43a 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/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,6 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.cold_ids = { NULL },
.warm_ids = { &gp8psk_usb_table[3], NULL },
},
- { .name = "Genpix SkyWalker-CW3K DVB-S receiver",
- .cold_ids = { NULL },
- .warm_ids = { &gp8psk_usb_table[4], NULL },
- },
{ NULL },
}
};
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c
index 4e207658c5d..2b6eeeab5b2 100644
--- a/drivers/media/dvb/firewire/firedtv-1394.c
+++ b/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/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c
index 9d308dd32a5..5742fde79d9 100644
--- a/drivers/media/dvb/firewire/firedtv-dvb.c
+++ b/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/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c
index 46a6324d7b7..27bca2e283d 100644
--- a/drivers/media/dvb/firewire/firedtv-rc.c
+++ b/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/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 23e4cffeba3..be967ac09a3 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/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/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index bc2b00abd10..832473c1e51 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/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/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c
index b2b50fb4cfd..136c5863d81 100644
--- a/drivers/media/dvb/frontends/af9013.c
+++ b/drivers/media/dvb/frontends/af9013.c
@@ -1455,7 +1455,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/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c
index 35731258bb0..956b80f4979 100644
--- a/drivers/media/dvb/frontends/au8522_dig.c
+++ b/drivers/media/dvb/frontends/au8522_dig.c
@@ -367,11 +367,90 @@ static struct {
{ 0x8231, 0x13 },
};
-/* QAM Modulation table */
+/* QAM64 Modulation table */
static struct {
u16 reg;
u16 data;
-} QAM_mod_tab[] = {
+} QAM64_mod_tab[] = {
+ { 0x00a3, 0x09 },
+ { 0x00a4, 0x00 },
+ { 0x0081, 0xc4 },
+ { 0x00a5, 0x40 },
+ { 0x00aa, 0x77 },
+ { 0x00ad, 0x77 },
+ { 0x00a6, 0x67 },
+ { 0x0262, 0x20 },
+ { 0x021c, 0x30 },
+ { 0x00b8, 0x3e },
+ { 0x00b9, 0xf0 },
+ { 0x00ba, 0x01 },
+ { 0x00bb, 0x18 },
+ { 0x00bc, 0x50 },
+ { 0x00bd, 0x00 },
+ { 0x00be, 0xea },
+ { 0x00bf, 0xef },
+ { 0x00c0, 0xfc },
+ { 0x00c1, 0xbd },
+ { 0x00c2, 0x1f },
+ { 0x00c3, 0xfc },
+ { 0x00c4, 0xdd },
+ { 0x00c5, 0xaf },
+ { 0x00c6, 0x00 },
+ { 0x00c7, 0x38 },
+ { 0x00c8, 0x30 },
+ { 0x00c9, 0x05 },
+ { 0x00ca, 0x4a },
+ { 0x00cb, 0xd0 },
+ { 0x00cc, 0x01 },
+ { 0x00cd, 0xd9 },
+ { 0x00ce, 0x6f },
+ { 0x00cf, 0xf9 },
+ { 0x00d0, 0x70 },
+ { 0x00d1, 0xdf },
+ { 0x00d2, 0xf7 },
+ { 0x00d3, 0xc2 },
+ { 0x00d4, 0xdf },
+ { 0x00d5, 0x02 },
+ { 0x00d6, 0x9a },
+ { 0x00d7, 0xd0 },
+ { 0x0250, 0x0d },
+ { 0x0251, 0xcd },
+ { 0x0252, 0xe0 },
+ { 0x0253, 0x05 },
+ { 0x0254, 0xa7 },
+ { 0x0255, 0xff },
+ { 0x0256, 0xed },
+ { 0x0257, 0x5b },
+ { 0x0258, 0xae },
+ { 0x0259, 0xe6 },
+ { 0x025a, 0x3d },
+ { 0x025b, 0x0f },
+ { 0x025c, 0x0d },
+ { 0x025d, 0xea },
+ { 0x025e, 0xf2 },
+ { 0x025f, 0x51 },
+ { 0x0260, 0xf5 },
+ { 0x0261, 0x06 },
+ { 0x021a, 0x00 },
+ { 0x0546, 0x40 },
+ { 0x0210, 0xc7 },
+ { 0x0211, 0xaa },
+ { 0x0212, 0xab },
+ { 0x0213, 0x02 },
+ { 0x0502, 0x00 },
+ { 0x0121, 0x04 },
+ { 0x0122, 0x04 },
+ { 0x052e, 0x10 },
+ { 0x00a4, 0xca },
+ { 0x00a7, 0x40 },
+ { 0x0526, 0x01 },
+};
+
+/* QAM256 Modulation table */
+static struct {
+ u16 reg;
+ u16 data;
+} QAM256_mod_tab[] = {
{ 0x80a3, 0x09 },
{ 0x80a4, 0x00 },
{ 0x8081, 0xc4 },
@@ -464,12 +543,19 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
au8522_set_if(fe, state->config->vsb_if);
break;
case QAM_64:
+ dprintk("%s() QAM 64\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(QAM64_mod_tab); i++)
+ au8522_writereg(state,
+ QAM64_mod_tab[i].reg,
+ QAM64_mod_tab[i].data);
+ au8522_set_if(fe, state->config->qam_if);
+ break;
case QAM_256:
- dprintk("%s() QAM 64/256\n", __func__);
- for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
+ dprintk("%s() QAM 256\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
au8522_writereg(state,
- QAM_mod_tab[i].reg,
- QAM_mod_tab[i].data);
+ QAM256_mod_tab[i].reg,
+ QAM256_mod_tab[i].data);
au8522_set_if(fe, state->config->qam_if);
break;
default:
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
index 9b9f57264ce..2410d8b59b6 100644
--- a/drivers/media/dvb/frontends/cx24116.c
+++ b/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/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c
index 172f1f928f0..01007553522 100644
--- a/drivers/media/dvb/frontends/drx397xD.c
+++ b/drivers/media/dvb/frontends/drx397xD.c
@@ -123,10 +123,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/drivers/media/dvb/frontends/isl6423.c b/drivers/media/dvb/frontends/isl6423.c
new file mode 100644
index 00000000000..dca5bebfeeb
--- /dev/null
+++ b/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 = &reg, .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/drivers/media/dvb/frontends/isl6423.h b/drivers/media/dvb/frontends/isl6423.h
new file mode 100644
index 00000000000..e1a37fba01c
--- /dev/null
+++ b/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/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb/frontends/lgdt3305.c
index d92d0557a80..fde8c59700f 100644
--- a/drivers/media/dvb/frontends/lgdt3305.c
+++ b/drivers/media/dvb/frontends/lgdt3305.c
@@ -19,6 +19,7 @@
*
*/
+#include <asm/div64.h>
#include <linux/dvb/frontend.h>
#include "dvb_math.h"
#include "lgdt3305.h"
@@ -496,27 +497,15 @@ static int lgdt3305_set_if(struct lgdt3305_state *state,
nco = if_freq_khz / 10;
-#define LGDT3305_64BIT_DIVISION_ENABLED 0
- /* FIXME: 64bit division disabled to avoid linking error:
- * WARNING: "__udivdi3" [lgdt3305.ko] undefined!
- */
switch (param->u.vsb.modulation) {
case VSB_8:
-#if LGDT3305_64BIT_DIVISION_ENABLED
nco <<= 24;
- nco /= 625;
-#else
- nco *= ((1 << 24) / 625);
-#endif
+ do_div(nco, 625);
break;
case QAM_64:
case QAM_256:
-#if LGDT3305_64BIT_DIVISION_ENABLED
nco <<= 28;
- nco /= 625;
-#else
- nco *= ((1 << 28) / 625);
-#endif
+ do_div(nco, 625);
break;
default:
return -EINVAL;
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c
index f9785dfe735..fde27645bbe 100644
--- a/drivers/media/dvb/frontends/lgs8gxx.c
+++ b/drivers/media/dvb/frontends/lgs8gxx.c
@@ -37,14 +37,14 @@
} while (0)
static int debug;
-static int fake_signal_str;
+static int fake_signal_str = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
module_param(fake_signal_str, int, 0644);
MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
-"Signal strength calculation is slow.(default:off).");
+"Signal strength calculation is slow.(default:on).");
/* LGS8GXX internal helper functions */
@@ -610,7 +610,7 @@ static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
else
cat = 0;
- *signal = cat;
+ *signal = cat * 65535 / 5;
return 0;
}
@@ -630,8 +630,8 @@ static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
if (fake_signal_str) {
if ((t & 0xC0) == 0xC0) {
- dprintk("Fake signal strength as 50\n");
- *signal = 0x32;
+ dprintk("Fake signal strength\n");
+ *signal = 0x7FFF;
} else
*signal = 0;
return 0;
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
index 1dcc56f32bf..71f607fe8fc 100644
--- a/drivers/media/dvb/frontends/lnbp21.c
+++ b/drivers/media/dvb/frontends/lnbp21.c
@@ -133,7 +133,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe,
/* override frontend ops */
fe->ops.set_voltage = lnbp21_set_voltage;
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
- printk(KERN_INFO "LNBx2x attached on addr=%x", lnbp21->i2c_addr);
+ printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
return fe;
}
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index 5ac9b15920f..a621f727935 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/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/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index a8429ebfa8a..eac20650499 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -879,7 +879,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");
@@ -943,7 +944,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/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index 5ed32544de3..8133ea3cddd 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/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/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h
index 8a1332c2031..bf4e9b63304 100644
--- a/drivers/media/dvb/frontends/stv0900.h
+++ b/drivers/media/dvb/frontends/stv0900.h
@@ -29,6 +29,11 @@
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
+struct stv0900_reg {
+ u16 addr;
+ u8 val;
+};
+
struct stv0900_config {
u8 demod_address;
u32 xtal;
@@ -38,7 +43,7 @@ struct stv0900_config {
u8 path1_mode;
u8 path2_mode;
-
+ struct stv0900_reg *ts_config_regs;
u8 tun1_maddress;/* 0, 1, 2, 3 for 0xc0, 0xc2, 0xc4, 0xc6 */
u8 tun2_maddress;
u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c
index 8499bcf7f25..1da045fbb4e 100644
--- a/drivers/media/dvb/frontends/stv0900_core.c
+++ b/drivers/media/dvb/frontends/stv0900_core.c
@@ -149,31 +149,31 @@ void stv0900_write_reg(struct stv0900_internal *i_params, u16 reg_addr,
dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
}
-u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg_addr)
+u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg)
{
- u8 data[2];
int ret;
- struct i2c_msg i2cmsg = {
- .addr = i_params->i2c_addr,
- .flags = 0,
- .len = 2,
- .buf = data,
+ u8 b0[] = { MSB(reg), LSB(reg) };
+ u8 buf = 0;
+ struct i2c_msg msg[] = {
+ {
+ .addr = i_params->i2c_addr,
+ .flags = 0,
+ .buf = b0,
+ .len = 2,
+ }, {
+ .addr = i_params->i2c_addr,
+ .flags = I2C_M_RD,
+ .buf = &buf,
+ .len = 1,
+ },
};
- data[0] = MSB(reg_addr);
- data[1] = LSB(reg_addr);
-
- ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
- if (ret != 1)
- dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
-
- i2cmsg.flags = I2C_M_RD;
- i2cmsg.len = 1;
- ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
- if (ret != 1)
- dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
+ ret = i2c_transfer(i_params->i2c_adap, msg, 2);
+ if (ret != 2)
+ dprintk(KERN_ERR "%s: i2c error %d, reg[0x%02x]\n",
+ __func__, ret, reg);
- return data[0];
+ return buf;
}
void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
@@ -712,6 +712,44 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe,
return c_n;
}
+static int stv0900_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
+{
+ struct stv0900_state *state = fe->demodulator_priv;
+ struct stv0900_internal *i_params = state->internal;
+ enum fe_stv0900_demod_num demod = state->demod;
+ u8 err_val1, err_val0;
+ s32 err_field1, err_field0;
+ u32 header_err_val = 0;
+
+ *ucblocks = 0x0;
+ if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) {
+ /* DVB-S2 delineator errors count */
+
+ /* retreiving number for errnous headers */
+ dmd_reg(err_field0, R0900_P1_BBFCRCKO0,
+ R0900_P2_BBFCRCKO0);
+ dmd_reg(err_field1, R0900_P1_BBFCRCKO1,
+ R0900_P2_BBFCRCKO1);
+
+ err_val1 = stv0900_read_reg(i_params, err_field1);
+ err_val0 = stv0900_read_reg(i_params, err_field0);
+ header_err_val = (err_val1<<8) | err_val0;
+
+ /* retreiving number for errnous packets */
+ dmd_reg(err_field0, R0900_P1_UPCRCKO0,
+ R0900_P2_UPCRCKO0);
+ dmd_reg(err_field1, R0900_P1_UPCRCKO1,
+ R0900_P2_UPCRCKO1);
+
+ err_val1 = stv0900_read_reg(i_params, err_field1);
+ err_val0 = stv0900_read_reg(i_params, err_field0);
+ *ucblocks = (err_val1<<8) | err_val0;
+ *ucblocks += header_err_val;
+ }
+
+ return 0;
+}
+
static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr)
{
*snr = stv0900_carr_get_quality(fe,
@@ -1355,7 +1393,7 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
struct stv0900_state *state = fe->demodulator_priv;
enum fe_stv0900_error error = STV0900_NO_ERROR;
enum fe_stv0900_error demodError = STV0900_NO_ERROR;
- int selosci;
+ int selosci, i;
struct stv0900_inode *temp_int = find_inode(state->i2c_adap,
state->config->demod_address);
@@ -1402,7 +1440,23 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
stv0900_write_bits(state->internal, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff);
stv0900_write_bits(state->internal, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff);
- stv0900_set_ts_parallel_serial(state->internal, p_init->path1_ts_clock, p_init->path2_ts_clock);
+ state->internal->ts_config = p_init->ts_config;
+ if (state->internal->ts_config == NULL)
+ stv0900_set_ts_parallel_serial(state->internal,
+ p_init->path1_ts_clock,
+ p_init->path2_ts_clock);
+ else {
+ for (i = 0; state->internal->ts_config[i].addr != 0xffff; i++)
+ stv0900_write_reg(state->internal,
+ state->internal->ts_config[i].addr,
+ state->internal->ts_config[i].val);
+
+ stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 1);
+ stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 0);
+ stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 1);
+ stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 0);
+ }
+
stv0900_write_bits(state->internal, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress);
switch (p_init->tuner1_adc) {
case 1:
@@ -1882,6 +1936,7 @@ static struct dvb_frontend_ops stv0900_ops = {
.read_ber = stv0900_read_ber,
.read_signal_strength = stv0900_read_signal_strength,
.read_snr = stv0900_read_snr,
+ .read_ucblocks = stv0900_read_ucblocks,
};
struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
@@ -1915,6 +1970,7 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
init_params.tun1_iq_inversion = STV0900_IQ_NORMAL;
init_params.tuner1_adc = config->tun1_adc;
init_params.path2_ts_clock = config->path2_mode;
+ init_params.ts_config = config->ts_config_regs;
init_params.tun2_maddress = config->tun2_maddress;
init_params.tuner2_adc = config->tun2_adc;
init_params.tun2_iq_inversion = STV0900_IQ_SWAPPED;
diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h
index 762d5af62d7..5ed7a145c7d 100644
--- a/drivers/media/dvb/frontends/stv0900_priv.h
+++ b/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...) \
@@ -273,6 +271,7 @@ struct stv0900_init_params{
/* IQ from the tuner2 to the demod */
enum stv0900_iq_inversion tun2_iq_inversion;
+ struct stv0900_reg *ts_config;
};
struct stv0900_search_params {
@@ -365,6 +364,7 @@ struct stv0900_internal{
u8 i2c_addr;
u8 clkmode;/* 0 for CLKI, 2 for XTALI */
u8 chip_id;
+ struct stv0900_reg *ts_config;
enum fe_stv0900_error errs;
int dmds_used;
};
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
new file mode 100644
index 00000000000..488bdfb34fb
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -0,0 +1,4302 @@
+/*
+ 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 */
+};
+
+
+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 },
+ { STV090x_P2_DMDCFGMD, 0xF9 },
+ { STV090x_P2_DEMOD, 0x08 },
+ { STV090x_P2_DMDCFG3, 0xc4 },
+ { STV090x_P2_CARFREQ, 0xed },
+ { 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 },
+ { STV090x_P1_DMDCFGMD, 0xf9 },
+ { STV090x_P1_DEMOD, 0x08 },
+ { STV090x_P1_DMDCFG3, 0xc4 },
+ { STV090x_P1_DMDTOM, 0x20 },
+ { STV090x_P1_CARFREQ, 0xed },
+ { 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 },
+ { STV090x_P1_DMDCFGMD, 0xF9 },
+ { STV090x_P1_DEMOD, 0x08 },
+ { STV090x_P1_DMDCFG3, 0xc4 },
+ { STV090x_P1_CARFREQ, 0xed },
+ { STV090x_P1_TNRCFG2, 0x82 },
+ { 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, &reg) < 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, &reg) < 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 = NULL;
+ 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) {
+ /* Cut 3.0 and up */
+ short_crl = stv090x_s2_short_crl_cut30;
+ } else {
+ /* Cut 2.0 and up: we don't support cuts older than 2.0 */
+ short_crl = stv090x_s2_short_crl_cut20;
+ }
+
+ 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;
+ 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;
+}
+
+
+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, &reg) < 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);
+ }
+
+ /* 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/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h
new file mode 100644
index 00000000000..e968c98bb70
--- /dev/null
+++ b/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/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h
new file mode 100644
index 00000000000..5a4a01740d8
--- /dev/null
+++ b/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/drivers/media/dvb/frontends/stv090x_reg.h b/drivers/media/dvb/frontends/stv090x_reg.h
new file mode 100644
index 00000000000..57b6abbbd32
--- /dev/null
+++ b/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/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c
new file mode 100644
index 00000000000..3d8a2e01c9c
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv6110x.c
@@ -0,0 +1,373 @@
+/*
+ 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;
+}
+
+
+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,
+ .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/drivers/media/dvb/frontends/stv6110x.h b/drivers/media/dvb/frontends/stv6110x.h
new file mode 100644
index 00000000000..a38257080e0
--- /dev/null
+++ b/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/drivers/media/dvb/frontends/stv6110x_priv.h b/drivers/media/dvb/frontends/stv6110x_priv.h
new file mode 100644
index 00000000000..7260da633d4
--- /dev/null
+++ b/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/drivers/media/dvb/frontends/stv6110x_reg.h b/drivers/media/dvb/frontends/stv6110x_reg.h
new file mode 100644
index 00000000000..93e5c70e5fd
--- /dev/null
+++ b/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/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 2a8bbcd44cd..cc8862ce4aa 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -1,7 +1,7 @@
/*
NXP TDA10048HN DVB OFDM demodulator driver
- Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
+ Copyright (C) 2009 Steven Toth <stoth@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
@@ -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"
@@ -138,11 +139,20 @@ struct tda10048_state {
struct i2c_adapter *i2c;
- /* configuration settings */
- const struct tda10048_config *config;
+ /* We'll cache and update the attach config settings */
+ struct tda10048_config config;
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 {
@@ -192,12 +202,27 @@ static struct init_tab {
{ TDA10048_CONF_C4_2, 0x04 },
};
+static struct pll_tab {
+ u32 clk_freq_khz;
+ u32 if_freq_khz;
+ u8 m, n, p;
+} pll_tab[] = {
+ { TDA10048_CLK_4000, TDA10048_IF_36130, 10, 0, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_3300, 10, 3, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_3500, 10, 3, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_3800, 10, 3, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 },
+};
+
static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
{
+ struct tda10048_config *config = &state->config;
int ret;
u8 buf[] = { reg, data };
struct i2c_msg msg = {
- .addr = state->config->demod_address,
+ .addr = config->demod_address,
.flags = 0, .buf = buf, .len = 2 };
dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
@@ -212,13 +237,14 @@ static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
{
+ struct tda10048_config *config = &state->config;
int ret;
u8 b0[] = { reg };
u8 b1[] = { 0 };
struct i2c_msg msg[] = {
- { .addr = state->config->demod_address,
+ { .addr = config->demod_address,
.flags = 0, .buf = b0, .len = 1 },
- { .addr = state->config->demod_address,
+ { .addr = config->demod_address,
.flags = I2C_M_RD, .buf = b1, .len = 1 } };
dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
@@ -235,6 +261,7 @@ static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
const u8 *data, u16 len)
{
+ struct tda10048_config *config = &state->config;
int ret = -EREMOTEIO;
struct i2c_msg msg;
u8 *buf;
@@ -250,7 +277,7 @@ static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
*buf = reg;
memcpy(buf + 1, data, len);
- msg.addr = state->config->demod_address;
+ msg.addr = config->demod_address;
msg.flags = 0;
msg.buf = buf;
msg.len = len + 1;
@@ -271,14 +298,206 @@ 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_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ struct tda10048_config *config = &state->config;
+ int i;
+ u32 if_freq_khz;
+
+ dprintk(1, "%s(bw = %d)\n", __func__, bw);
+
+ /* based on target bandwidth and clk we calculate pll factors */
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ if_freq_khz = config->dtv6_if_freq_khz;
+ break;
+ case BANDWIDTH_7_MHZ:
+ if_freq_khz = config->dtv7_if_freq_khz;
+ break;
+ case BANDWIDTH_8_MHZ:
+ if_freq_khz = config->dtv8_if_freq_khz;
+ break;
+ default:
+ printk(KERN_ERR "%s() no default\n", __func__);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pll_tab); i++) {
+ if ((pll_tab[i].clk_freq_khz == config->clk_freq_khz) &&
+ (pll_tab[i].if_freq_khz == if_freq_khz)) {
+
+ state->freq_if_hz = pll_tab[i].if_freq_khz * 1000;
+ state->xtal_hz = pll_tab[i].clk_freq_khz * 1000;
+ state->pll_mfactor = pll_tab[i].m;
+ state->pll_nfactor = pll_tab[i].n;
+ state->pll_pfactor = pll_tab[i].p;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(pll_tab)) {
+ printk(KERN_ERR "%s() Incorrect attach settings\n",
+ __func__);
+ return -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);
+
+ /* Update the I/F */
+ tda10048_set_phy2(fe, state->sample_freq, state->freq_if_hz);
+
+ return 0;
+}
+
static int tda10048_firmware_upload(struct dvb_frontend *fe)
{
struct tda10048_state *state = fe->demodulator_priv;
+ struct tda10048_config *config = &state->config;
const struct firmware *fw;
int ret;
int pos = 0;
int cnt;
- u8 wlen = state->config->fwbulkwritelen;
+ u8 wlen = config->fwbulkwritelen;
if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
wlen = TDA10048_BULKWRITE_200;
@@ -289,7 +508,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__);
@@ -484,8 +703,12 @@ static int tda10048_get_tps(struct tda10048_state *state,
static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct tda10048_state *state = fe->demodulator_priv;
+ struct tda10048_config *config = &state->config;
dprintk(1, "%s(%d)\n", __func__, enable);
+ if (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 +746,12 @@ static int tda10048_set_frontend(struct dvb_frontend *fe,
dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
+ /* Update the I/F pll's if the bandwidth changes */
+ if (p->u.ofdm.bandwidth != state->bandwidth) {
+ tda10048_set_if(fe, p->u.ofdm.bandwidth);
+ tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth);
+ }
+
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
@@ -544,6 +773,7 @@ static int tda10048_set_frontend(struct dvb_frontend *fe,
static int tda10048_init(struct dvb_frontend *fe)
{
struct tda10048_state *state = fe->demodulator_priv;
+ struct tda10048_config *config = &state->config;
int ret = 0, i;
dprintk(1, "%s()\n", __func__);
@@ -556,10 +786,14 @@ static int tda10048_init(struct dvb_frontend *fe)
ret = tda10048_firmware_upload(fe);
/* Set either serial or parallel */
- tda10048_output_mode(fe, state->config->output_mode);
+ tda10048_output_mode(fe, config->output_mode);
+
+ /* Set inversion */
+ tda10048_set_inversion(fe, config->inversion);
- /* set inversion */
- tda10048_set_inversion(fe, state->config->inversion);
+ /* Establish default RF values */
+ tda10048_set_if(fe, BANDWIDTH_8_MHZ);
+ tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ);
/* Ensure we leave the gate closed */
tda10048_i2c_gate_ctrl(fe, 0);
@@ -812,6 +1046,45 @@ static void tda10048_release(struct dvb_frontend *fe)
kfree(state);
}
+static void tda10048_establish_defaults(struct dvb_frontend *fe)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ struct tda10048_config *config = &state->config;
+
+ /* Validate/default the config */
+ if (config->dtv6_if_freq_khz == 0) {
+ config->dtv6_if_freq_khz = TDA10048_IF_4300;
+ printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz "
+ "is not set (defaulting to %d)\n",
+ __func__,
+ config->dtv6_if_freq_khz);
+ }
+
+ if (config->dtv7_if_freq_khz == 0) {
+ config->dtv7_if_freq_khz = TDA10048_IF_4300;
+ printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz "
+ "is not set (defaulting to %d)\n",
+ __func__,
+ config->dtv7_if_freq_khz);
+ }
+
+ if (config->dtv8_if_freq_khz == 0) {
+ config->dtv8_if_freq_khz = TDA10048_IF_4300;
+ printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz "
+ "is not set (defaulting to %d)\n",
+ __func__,
+ config->dtv8_if_freq_khz);
+ }
+
+ if (config->clk_freq_khz == 0) {
+ config->clk_freq_khz = TDA10048_CLK_16000;
+ printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz "
+ "is not set (defaulting to %d)\n",
+ __func__,
+ config->clk_freq_khz);
+ }
+}
+
static struct dvb_frontend_ops tda10048_ops;
struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
@@ -826,10 +1099,11 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
if (state == NULL)
goto error;
- /* setup the state */
- state->config = config;
+ /* setup the state and clone the config */
+ memcpy(&state->config, config, sizeof(*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)
@@ -840,6 +1114,17 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
+ /* Establish any defaults the the user didn't pass */
+ tda10048_establish_defaults(&state->frontend);
+
+ /* Set the xtal and freq defaults */
+ if (tda10048_set_if(&state->frontend, BANDWIDTH_8_MHZ) != 0)
+ goto error;
+
+ /* Default bandwidth */
+ if (tda10048_set_bandwidth(&state->frontend, BANDWIDTH_8_MHZ) != 0)
+ goto error;
+
/* Leave the gate closed */
tda10048_i2c_gate_ctrl(&state->frontend, 0);
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
index 0457b24601f..8828ceaf74b 100644
--- a/drivers/media/dvb/frontends/tda10048.h
+++ b/drivers/media/dvb/frontends/tda10048.h
@@ -1,7 +1,7 @@
/*
NXP TDA10048HN DVB OFDM demodulator driver
- Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
+ Copyright (C) 2009 Steven Toth <stoth@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
@@ -43,6 +43,25 @@ 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 dtv6_if_freq_khz;
+ u16 dtv7_if_freq_khz;
+ u16 dtv8_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/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
index bcf93f4828b..c6644d90943 100644
--- a/drivers/media/dvb/siano/Makefile
+++ b/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/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index 63e4d0ec658..d8b15d583bd 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/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",
@@ -82,6 +85,16 @@ static struct sms_board sms_boards[] = {
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
.lna_ctrl = -1,
},
+ [SMS1XXX_BOARD_SIANO_NICE] = {
+ /* 11 */
+ .name = "Siano Nice Digital Receiver",
+ .type = SMS_NOVA_B0,
+ },
+ [SMS1XXX_BOARD_SIANO_VENICE] = {
+ /* 12 */
+ .name = "Siano Venice Digital Receiver",
+ .type = SMS_VEGA,
+ },
};
struct sms_board *sms_get_board(int id)
@@ -91,12 +104,179 @@ struct sms_board *sms_get_board(int id)
return &sms_boards[id];
}
EXPORT_SYMBOL_GPL(sms_get_board);
+static inline void sms_gpio_assign_11xx_default_led_config(
+ struct smscore_gpio_config *pGpioConfig) {
+ pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT;
+ pGpioConfig->InputCharacteristics =
+ SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL;
+ pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA;
+ pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
+ pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE;
+}
+
+int sms_board_event(struct smscore_device_t *coredev,
+ enum SMS_BOARD_EVENTS gevent) {
+ int board_id = smscore_get_board_id(coredev);
+ struct sms_board *board = sms_get_board(board_id);
+ struct smscore_gpio_config MyGpioConfig;
+
+ sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
+
+ switch (gevent) {
+ case BOARD_EVENT_POWER_INIT: /* including hotplug */
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ /* set I/O and turn off all LEDs */
+ smscore_gpio_configure(coredev,
+ board->board_cfg.leds_power,
+ &MyGpioConfig);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.leds_power, 0);
+ smscore_gpio_configure(coredev, board->board_cfg.led0,
+ &MyGpioConfig);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led0, 0);
+ smscore_gpio_configure(coredev, board->board_cfg.led1,
+ &MyGpioConfig);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+ /* set I/O and turn off LNA */
+ smscore_gpio_configure(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ &MyGpioConfig);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ 0);
+ break;
+ }
+ break; /* BOARD_EVENT_BIND */
+
+ case BOARD_EVENT_POWER_SUSPEND:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.leds_power, 0);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led0, 0);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ 0);
+ break;
+ }
+ break; /* BOARD_EVENT_POWER_SUSPEND */
+
+ case BOARD_EVENT_POWER_RESUME:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.leds_power, 1);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led0, 1);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ 1);
+ break;
+ }
+ break; /* BOARD_EVENT_POWER_RESUME */
+
+ case BOARD_EVENT_BIND:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.leds_power, 1);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led0, 1);
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+ case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.foreign_lna0_ctrl,
+ 1);
+ break;
+ }
+ break; /* BOARD_EVENT_BIND */
+
+ case BOARD_EVENT_SCAN_PROG:
+ break; /* BOARD_EVENT_SCAN_PROG */
+ case BOARD_EVENT_SCAN_COMP:
+ break; /* BOARD_EVENT_SCAN_COMP */
+ case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL:
+ break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */
+ case BOARD_EVENT_FE_LOCK:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 1);
+ break;
+ }
+ break; /* BOARD_EVENT_FE_LOCK */
+ case BOARD_EVENT_FE_UNLOCK:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ }
+ break; /* BOARD_EVENT_FE_UNLOCK */
+ case BOARD_EVENT_DEMOD_LOCK:
+ break; /* BOARD_EVENT_DEMOD_LOCK */
+ case BOARD_EVENT_DEMOD_UNLOCK:
+ break; /* BOARD_EVENT_DEMOD_UNLOCK */
+ case BOARD_EVENT_RECEPTION_MAX_4:
+ break; /* BOARD_EVENT_RECEPTION_MAX_4 */
+ case BOARD_EVENT_RECEPTION_3:
+ break; /* BOARD_EVENT_RECEPTION_3 */
+ case BOARD_EVENT_RECEPTION_2:
+ break; /* BOARD_EVENT_RECEPTION_2 */
+ case BOARD_EVENT_RECEPTION_1:
+ break; /* BOARD_EVENT_RECEPTION_1 */
+ case BOARD_EVENT_RECEPTION_LOST_0:
+ break; /* BOARD_EVENT_RECEPTION_LOST_0 */
+ case BOARD_EVENT_MULTIPLEX_OK:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 1);
+ break;
+ }
+ break; /* BOARD_EVENT_MULTIPLEX_OK */
+ case BOARD_EVENT_MULTIPLEX_ERRORS:
+ switch (board_id) {
+ case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+ smscore_gpio_set_level(coredev,
+ board->board_cfg.led1, 0);
+ break;
+ }
+ break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
+
+ default:
+ sms_err("Unknown SMS board event");
+ break;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sms_board_event);
static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
{
int lvl, ret;
u32 gpio;
- struct smscore_gpio_config gpioconfig = {
+ struct smscore_config_gpio gpioconfig = {
.direction = SMS_GPIO_DIRECTION_OUTPUT,
.pullupdown = SMS_GPIO_PULLUPDOWN_NONE,
.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h
index 64d74c59c33..38f062f6ad6 100644
--- a/drivers/media/dvb/siano/sms-cards.h
+++ b/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
@@ -34,10 +35,47 @@
#define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9
#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
+#define SMS1XXX_BOARD_SIANO_NICE 11
+#define SMS1XXX_BOARD_SIANO_VENICE 12
+
+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 +83,32 @@ struct sms_board {
struct sms_board *sms_get_board(int id);
+extern struct smscore_device_t *coredev;
+
+enum SMS_BOARD_EVENTS {
+ BOARD_EVENT_POWER_INIT,
+ BOARD_EVENT_POWER_SUSPEND,
+ BOARD_EVENT_POWER_RESUME,
+ BOARD_EVENT_BIND,
+ BOARD_EVENT_SCAN_PROG,
+ BOARD_EVENT_SCAN_COMP,
+ BOARD_EVENT_EMERGENCY_WARNING_SIGNAL,
+ BOARD_EVENT_FE_LOCK,
+ BOARD_EVENT_FE_UNLOCK,
+ BOARD_EVENT_DEMOD_LOCK,
+ BOARD_EVENT_DEMOD_UNLOCK,
+ BOARD_EVENT_RECEPTION_MAX_4,
+ BOARD_EVENT_RECEPTION_3,
+ BOARD_EVENT_RECEPTION_2,
+ BOARD_EVENT_RECEPTION_1,
+ BOARD_EVENT_RECEPTION_LOST_0,
+ BOARD_EVENT_MULTIPLEX_OK,
+ BOARD_EVENT_MULTIPLEX_ERRORS
+};
+
+int sms_board_event(struct smscore_device_t *coredev,
+ enum SMS_BOARD_EVENTS gevent);
+
int sms_board_setup(struct smscore_device_t *coredev);
#define SMS_LED_OFF 0
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index 7bd4d1dee2b..a246903c334 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/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);
@@ -58,42 +62,6 @@ struct smscore_client_t {
onremove_t onremove_handler;
};
-struct smscore_device_t {
- struct list_head entry;
-
- struct list_head clients;
- struct list_head subclients;
- spinlock_t clientslock;
-
- struct list_head buffers;
- spinlock_t bufferslock;
- int num_buffers;
-
- void *common_buffer;
- int common_buffer_size;
- dma_addr_t common_buffer_phys;
-
- void *context;
- struct device *device;
-
- char devpath[32];
- unsigned long device_flags;
-
- setmode_t setmode_handler;
- detectmode_t detectmode_handler;
- sendrequest_t sendrequest_handler;
- preload_t preload_handler;
- postload_t postload_handler;
-
- int mode, modes_supported;
-
- struct completion version_ex_done, data_download_done, trigger_done;
- struct completion init_device_done, reload_start_done, resume_done;
-
- int board_id;
- int led_state;
-};
-
void smscore_set_board_id(struct smscore_device_t *core, int id)
{
core->board_id = id;
@@ -384,6 +352,13 @@ 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->gpio_configuration_done);
+ init_completion(&dev->gpio_set_level_done);
+ init_completion(&dev->gpio_get_level_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;
@@ -439,6 +414,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
*
@@ -459,6 +499,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);
@@ -468,29 +509,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);
@@ -657,6 +688,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);
@@ -664,7 +698,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++;
}
@@ -685,8 +721,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);
@@ -746,7 +784,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*/
@@ -870,7 +908,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;
}
@@ -940,14 +978,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;
-
static unsigned long last_sample_time; /* = 0; */
static int data_total; /* = 0; */
unsigned long time_now = jiffies_to_msecs(jiffies);
@@ -965,6 +1000,16 @@ void smscore_onresponse(struct smscore_device_t *coredev,
}
data_total += cb->size;
+ /* 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)
@@ -1009,6 +1054,35 @@ void smscore_onresponse(struct smscore_device_t *coredev,
case MSG_SMS_SLEEP_RESUME_COMP_IND:
complete(&coredev->resume_done);
break;
+ case MSG_SMS_GPIO_CONFIG_EX_RES:
+ sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
+ complete(&coredev->gpio_configuration_done);
+ break;
+ case MSG_SMS_GPIO_SET_LEVEL_RES:
+ sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
+ complete(&coredev->gpio_set_level_done);
+ break;
+ case MSG_SMS_GPIO_GET_LEVEL_RES:
+ {
+ u32 *msgdata = (u32 *) phdr;
+ coredev->gpio_get_res = msgdata[1];
+ sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
+ coredev->gpio_get_res);
+ complete(&coredev->gpio_get_level_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:
break;
}
@@ -1030,12 +1104,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);
@@ -1052,8 +1138,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);
@@ -1210,8 +1296,9 @@ int smsclient_sendrequest(struct smscore_client_t *client,
EXPORT_SYMBOL_GPL(smsclient_sendrequest);
+/* old GPIO managments implementation */
int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
- struct smscore_gpio_config *pinconfig)
+ struct smscore_config_gpio *pinconfig)
{
struct {
struct SmsMsgHdr_ST hdr;
@@ -1280,35 +1367,254 @@ int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
&msg, sizeof(msg));
}
-static int __init smscore_module_init(void)
-{
- int rc = 0;
+/* new GPIO managment implementation */
+static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
+ u32 *pGroupNum, u32 *pGroupCfg) {
+
+ *pGroupCfg = 1;
+
+ if (PinNum >= 0 && PinNum <= 1) {
+ *pTranslatedPinNum = 0;
+ *pGroupNum = 9;
+ *pGroupCfg = 2;
+ } else if (PinNum >= 2 && PinNum <= 6) {
+ *pTranslatedPinNum = 2;
+ *pGroupNum = 0;
+ *pGroupCfg = 2;
+ } else if (PinNum >= 7 && PinNum <= 11) {
+ *pTranslatedPinNum = 7;
+ *pGroupNum = 1;
+ } else if (PinNum >= 12 && PinNum <= 15) {
+ *pTranslatedPinNum = 12;
+ *pGroupNum = 2;
+ *pGroupCfg = 3;
+ } else if (PinNum == 16) {
+ *pTranslatedPinNum = 16;
+ *pGroupNum = 23;
+ } else if (PinNum >= 17 && PinNum <= 24) {
+ *pTranslatedPinNum = 17;
+ *pGroupNum = 3;
+ } else if (PinNum == 25) {
+ *pTranslatedPinNum = 25;
+ *pGroupNum = 6;
+ } else if (PinNum >= 26 && PinNum <= 28) {
+ *pTranslatedPinNum = 26;
+ *pGroupNum = 4;
+ } else if (PinNum == 29) {
+ *pTranslatedPinNum = 29;
+ *pGroupNum = 5;
+ *pGroupCfg = 2;
+ } else if (PinNum == 30) {
+ *pTranslatedPinNum = 30;
+ *pGroupNum = 8;
+ } else if (PinNum == 31) {
+ *pTranslatedPinNum = 31;
+ *pGroupNum = 17;
+ } else
+ return -1;
- INIT_LIST_HEAD(&g_smscore_notifyees);
- INIT_LIST_HEAD(&g_smscore_devices);
- kmutex_init(&g_smscore_deviceslock);
+ *pGroupCfg <<= 24;
- INIT_LIST_HEAD(&g_smscore_registry);
- kmutex_init(&g_smscore_registrylock);
+ return 0;
+}
+
+int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+ struct smscore_gpio_config *pGpioConfig) {
+
+ u32 totalLen;
+ u32 TranslatedPinNum = 0;
+ u32 GroupNum = 0;
+ u32 ElectricChar;
+ u32 groupCfg;
+ void *buffer;
+ int rc;
+
+ struct SetGpioMsg {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[6];
+ } *pMsg;
+
+
+ if (PinNum > MAX_GPIO_PIN_NUMBER)
+ return -EINVAL;
+
+ if (pGpioConfig == NULL)
+ return -EINVAL;
+
+ totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
+
+ buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+ GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+
+ pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+ pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ pMsg->xMsgHeader.msgDstId = HIF_TASK;
+ pMsg->xMsgHeader.msgFlags = 0;
+ pMsg->xMsgHeader.msgLength = (u16) totalLen;
+ pMsg->msgData[0] = PinNum;
+
+ if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
+ pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
+ if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
+ &groupCfg) != 0)
+ return -EINVAL;
+
+ pMsg->msgData[1] = TranslatedPinNum;
+ pMsg->msgData[2] = GroupNum;
+ ElectricChar = (pGpioConfig->PullUpDown)
+ | (pGpioConfig->InputCharacteristics << 2)
+ | (pGpioConfig->OutputSlewRate << 3)
+ | (pGpioConfig->OutputDriving << 4);
+ pMsg->msgData[3] = ElectricChar;
+ pMsg->msgData[4] = pGpioConfig->Direction;
+ pMsg->msgData[5] = groupCfg;
+ } else {
+ pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
+ pMsg->msgData[1] = pGpioConfig->PullUpDown;
+ pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
+ pMsg->msgData[3] = pGpioConfig->OutputDriving;
+ pMsg->msgData[4] = pGpioConfig->Direction;
+ pMsg->msgData[5] = 0;
+ }
+
+ smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+ rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+ &coredev->gpio_configuration_done);
+
+ if (rc != 0) {
+ if (rc == -ETIME)
+ sms_err("smscore_gpio_configure timeout");
+ else
+ sms_err("smscore_gpio_configure error");
+ }
+ kfree(buffer);
+
+ return rc;
+}
+
+int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+ u8 NewLevel) {
+
+ u32 totalLen;
+ int rc;
+ void *buffer;
+
+ struct SetGpioMsg {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[3]; /* keep it 3 ! */
+ } *pMsg;
+
+ if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) ||
+ (PinNum > MAX_GPIO_PIN_NUMBER))
+ return -EINVAL;
+ totalLen = sizeof(struct SmsMsgHdr_ST) +
+ (3 * sizeof(u32)); /* keep it 3 ! */
+ buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+ GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+ pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+ pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ pMsg->xMsgHeader.msgDstId = HIF_TASK;
+ pMsg->xMsgHeader.msgFlags = 0;
+ pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
+ pMsg->xMsgHeader.msgLength = (u16) totalLen;
+ pMsg->msgData[0] = PinNum;
+ pMsg->msgData[1] = NewLevel;
+ /* Send message to SMS */
+ smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+ rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+ &coredev->gpio_set_level_done);
+
+ if (rc != 0) {
+ if (rc == -ETIME)
+ sms_err("smscore_gpio_set_level timeout");
+ else
+ sms_err("smscore_gpio_set_level error");
+ }
+ kfree(buffer);
return rc;
- sms_debug("rc %d", rc);
+}
+
+int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+ u8 *level) {
+
+ u32 totalLen;
+ int rc;
+ void *buffer;
+
+ struct SetGpioMsg {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[2];
+ } *pMsg;
+
+
+ if (PinNum > MAX_GPIO_PIN_NUMBER)
+ return -EINVAL;
+
+ totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
+
+ buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+ GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+
+ pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+ pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ pMsg->xMsgHeader.msgDstId = HIF_TASK;
+ pMsg->xMsgHeader.msgFlags = 0;
+ pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
+ pMsg->xMsgHeader.msgLength = (u16) totalLen;
+ pMsg->msgData[0] = PinNum;
+ pMsg->msgData[1] = 0;
+
+ /* Send message to SMS */
+ smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+ rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+ &coredev->gpio_get_level_done);
+
+ if (rc != 0) {
+ if (rc == -ETIME)
+ sms_err("smscore_gpio_get_level timeout");
+ else
+ sms_err("smscore_gpio_get_level error");
+ }
+ kfree(buffer);
+
+ /* Its a race between other gpio_get_level() and the copy of the single
+ * global 'coredev->gpio_get_res' to the function's variable 'level'
+ */
+ *level = coredev->gpio_get_res;
return rc;
}
-static void __exit smscore_module_exit(void)
+static int __init smscore_module_init(void)
{
+ int rc = 0;
+ INIT_LIST_HEAD(&g_smscore_notifyees);
+ INIT_LIST_HEAD(&g_smscore_devices);
+ kmutex_init(&g_smscore_deviceslock);
+ INIT_LIST_HEAD(&g_smscore_registry);
+ kmutex_init(&g_smscore_registrylock);
+ return rc;
+}
-
+static void __exit smscore_module_exit(void)
+{
kmutex_lock(&g_smscore_deviceslock);
while (!list_empty(&g_smscore_notifyees)) {
struct smscore_device_notifyee_t *notifyee =
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
index 548de9056e8..f1108c64e89 100644
--- a/drivers/media/dvb/siano/smscoreapi.h
+++ b/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,14 +28,13 @@
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/types.h>
-#include <asm/page.h>
#include <linux/mutex.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 "smsir.h"
#define kmutex_init(_p_) mutex_init(_p_)
#define kmutex_lock(_p_) mutex_lock(_p_)
@@ -46,13 +45,14 @@
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
-#define SMS_ALLOC_ALIGNMENT 128
-#define SMS_DMA_ALIGNMENT 16
+#define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS (10000)
+#define SMS_ALLOC_ALIGNMENT 128
+#define SMS_DMA_ALIGNMENT 16
#define SMS_ALIGN_ADDRESS(addr) \
((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
-#define SMS_DEVICE_FAMILY2 1
-#define SMS_ROM_NO_RESPONSE 2
+#define SMS_DEVICE_FAMILY2 1
+#define SMS_ROM_NO_RESPONSE 2
#define SMS_DEVICE_NOT_READY 0x8000000
enum sms_device_type_st {
@@ -83,13 +83,13 @@ typedef void (*onremove_t)(void *context);
struct smscore_buffer_t {
/* public members, once passed to clients can be changed freely */
struct list_head entry;
- int size;
- int offset;
+ int size;
+ int offset;
/* private members, read-only for clients */
- void *p;
- dma_addr_t phys;
- unsigned long offset_in_common;
+ void *p;
+ dma_addr_t phys;
+ unsigned long offset_in_common;
};
struct smsdevice_params_t {
@@ -116,10 +116,63 @@ struct smsclient_params_t {
int data_type;
onresponse_t onresponse_handler;
onremove_t onremove_handler;
-
void *context;
};
+struct smscore_device_t {
+ struct list_head entry;
+
+ struct list_head clients;
+ struct list_head subclients;
+ spinlock_t clientslock;
+
+ struct list_head buffers;
+ spinlock_t bufferslock;
+ int num_buffers;
+
+ void *common_buffer;
+ int common_buffer_size;
+ dma_addr_t common_buffer_phys;
+
+ void *context;
+ struct device *device;
+
+ char devpath[32];
+ unsigned long device_flags;
+
+ setmode_t setmode_handler;
+ detectmode_t detectmode_handler;
+ sendrequest_t sendrequest_handler;
+ preload_t preload_handler;
+ postload_t postload_handler;
+
+ int mode, modes_supported;
+
+ /* host <--> device messages */
+ struct completion version_ex_done, data_download_done, trigger_done;
+ struct completion init_device_done, reload_start_done, resume_done;
+ struct completion gpio_configuration_done, gpio_set_level_done;
+ struct completion gpio_get_level_done, ir_init_done;
+
+ /* Buffer management */
+ wait_queue_head_t buffer_mng_waitq;
+
+ /* GPIO */
+ int gpio_get_res;
+
+ /* Target hardware board */
+ int board_id;
+
+ /* Firmware */
+ u8 *fw_buf;
+ u32 fw_buf_size;
+
+ /* Infrared (IR) */
+ struct ir_t ir;
+
+ int led_state;
+};
+
/* GPIO definitions for antenna frequency domain control (SMS8021) */
#define SMS_ANTENNA_GPIO_0 1
#define SMS_ANTENNA_GPIO_1 0
@@ -154,18 +207,15 @@ struct smsclient_params_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_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_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_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
@@ -190,14 +240,31 @@ struct smsclient_params_t {
#define MSG_SMS_GPIO_CONFIG_EX_RES 713
#define MSG_SMS_ISDBT_TUNE_REQ 776
#define MSG_SMS_ISDBT_TUNE_RES 777
+#define MSG_SMS_TRANSMISSION_IND 782
+#define MSG_SMS_START_IR_REQ 800
+#define MSG_SMS_START_IR_RES 801
+#define MSG_SMS_IR_SAMPLES_IND 802
+#define MSG_SMS_SIGNAL_DETECTED_IND 827
+#define MSG_SMS_NO_SIGNAL_IND 828
#define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
(ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
(ptr)->msgLength = len; (ptr)->msgFlags = 0; \
} while (0)
+
#define SMS_INIT_MSG(ptr, type, len) \
SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
+enum SMS_DVB3_EVENTS {
+ DVB3_EVENT_INIT = 0,
+ DVB3_EVENT_SLEEP,
+ DVB3_EVENT_HOTPLUG,
+ DVB3_EVENT_FE_LOCK,
+ DVB3_EVENT_FE_UNLOCK,
+ DVB3_EVENT_UNC_OK,
+ DVB3_EVENT_UNC_ERR
+};
+
enum SMS_DEVICE_MODE {
DEVICE_MODE_NONE = -1,
DEVICE_MODE_DVBT = 0,
@@ -221,8 +288,13 @@ struct SmsMsgHdr_ST {
};
struct SmsMsgData_ST {
- struct SmsMsgHdr_ST xMsgHeader;
- u32 msgData[1];
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[1];
+};
+
+struct SmsMsgData_ST2 {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[2];
};
struct SmsDataDownload_ST {
@@ -238,11 +310,12 @@ struct SmsVersionRes_ST {
u8 Step; /* 0 - Step A */
u8 MetalFix; /* 0 - Metal 0 */
- u8 FirmwareId; /* 0xFF � ROM, otherwise the
- * value indicated by
- * SMSHOSTLIB_DEVICE_MODES_E */
- u8 SupportedProtocols; /* Bitwise OR combination of
+ /* FirmwareId 0xFF if ROM, otherwise the
+ * value indicated by SMSHOSTLIB_DEVICE_MODES_E */
+ u8 FirmwareId;
+ /* SupportedProtocols Bitwise OR combination of
* supported protocols */
+ u8 SupportedProtocols;
u8 VersionMajor;
u8 VersionMinor;
@@ -264,86 +337,219 @@ 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 */
- 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 */
-
- /* Transmission parameters, valid only for DVB-T/H */
- u32 Frequency; /* Frequency in Hz */
- u32 Bandwidth; /* Bandwidth in MHz */
- u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4,
- * for DVB-T/H FFT mode carriers in Kilos */
- 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 */
+
+ /* 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 */
- 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 */
-
+ 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 */
+ u32 NumMPEReceived; /* DVB-H, Num MPE section received */
+
+ u32 ReservedFields[10]; /* Reserved */
};
-struct SmsMsgStatisticsInfo_ST {
- u32 RequestResult;
+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_ST Stat;
+struct PID_DATA_S {
+ u32 pid;
+ u32 num_rows;
+ struct PID_STATISTICS_DATA_S pid_statistics;
+};
- /* Split the calc of the SNR in DAB */
- u32 Signal; /* dB */
- u32 Noise; /* dB */
+#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 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 */
+};
-struct smscore_gpio_config {
+
+/* 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 */
+ struct TRANSMISSION_STATISTICS_S TransmissionData;
+
+ /* Burst parameters, valid only for DVB-H */
+#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 {
+ u32 DeviceAddress; /* I2c device address */
+ u32 WriteCount; /* number of bytes to write */
+ u32 ReadCount; /* number of bytes to read */
+ u8 Data[1];
+};
+
+struct SMSHOSTLIB_I2C_RES_ST {
+ u32 Status; /* non-zero value in case of failure */
+ u32 ReadCount; /* number of bytes read */
+ u8 Data[1];
+};
+
+
+struct smscore_config_gpio {
#define SMS_GPIO_DIRECTION_INPUT 0
#define SMS_GPIO_DIRECTION_OUTPUT 1
u8 direction;
@@ -369,6 +575,47 @@ struct smscore_gpio_config {
u8 outputdriving;
};
+struct smscore_gpio_config {
+#define SMS_GPIO_DIRECTION_INPUT 0
+#define SMS_GPIO_DIRECTION_OUTPUT 1
+ u8 Direction;
+
+#define SMS_GPIO_PULL_UP_DOWN_NONE 0
+#define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1
+#define SMS_GPIO_PULL_UP_DOWN_PULLUP 2
+#define SMS_GPIO_PULL_UP_DOWN_KEEPER 3
+ u8 PullUpDown;
+
+#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL 0
+#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
+ u8 InputCharacteristics;
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW 1 /* 10xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST 0 /* 10xx */
+
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS 0 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS 1 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS 2 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS 3 /* 11xx */
+ u8 OutputSlewRate;
+
+#define SMS_GPIO_OUTPUT_DRIVING_S_4mA 0 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_8mA 1 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_12mA 2 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_16mA 3 /* 10xx */
+
+#define SMS_GPIO_OUTPUT_DRIVING_1_5mA 0 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_2_8mA 1 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_4mA 2 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_7mA 3 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_10mA 4 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_11mA 5 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_14mA 6 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_16mA 7 /* 11xx */
+ u8 OutputDriving;
+};
+
extern void smscore_registry_setmode(char *devpath, int mode);
extern int smscore_registry_getmode(char *devpath);
@@ -410,10 +657,19 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
extern void smscore_putbuffer(struct smscore_device_t *coredev,
struct smscore_buffer_t *cb);
+/* old GPIO managment */
int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
- struct smscore_gpio_config *pinconfig);
+ struct smscore_config_gpio *pinconfig);
int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
+/* new GPIO managment */
+extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+ struct smscore_gpio_config *pGpioConfig);
+extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+ u8 NewLevel);
+extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+ u8 *level);
+
void smscore_set_board_id(struct smscore_device_t *core, int id);
int smscore_get_board_id(struct smscore_device_t *core);
@@ -442,4 +698,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/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
index ba080b95bef..3ee1c3902c5 100644
--- a/drivers/media/dvb/siano/smsdvb.c
+++ b/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,69 @@ 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) {
+
+ struct smscore_device_t *coredev = client->coredev;
+ switch (event) {
+ case DVB3_EVENT_INIT:
+ sms_debug("DVB3_EVENT_INIT");
+ sms_board_event(coredev, BOARD_EVENT_BIND);
+ break;
+ case DVB3_EVENT_SLEEP:
+ sms_debug("DVB3_EVENT_SLEEP");
+ sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
+ break;
+ case DVB3_EVENT_HOTPLUG:
+ sms_debug("DVB3_EVENT_HOTPLUG");
+ sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
+ break;
+ case DVB3_EVENT_FE_LOCK:
+ if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
+ client->event_fe_state = DVB3_EVENT_FE_LOCK;
+ sms_debug("DVB3_EVENT_FE_LOCK");
+ sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
+ }
+ break;
+ case DVB3_EVENT_FE_UNLOCK:
+ if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
+ client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
+ sms_debug("DVB3_EVENT_FE_UNLOCK");
+ sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
+ }
+ break;
+ case DVB3_EVENT_UNC_OK:
+ if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
+ client->event_unc_state = DVB3_EVENT_UNC_OK;
+ sms_debug("DVB3_EVENT_UNC_OK");
+ sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
+ }
+ break;
+ case DVB3_EVENT_UNC_ERR:
+ if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
+ client->event_unc_state = DVB3_EVENT_UNC_ERR;
+ sms_debug("DVB3_EVENT_UNC_ERR");
+ sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
+ }
+ break;
+
+ default:
+ sms_err("Unknown dvb3 api event");
+ break;
+ }
+}
+
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 +137,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 +283,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 +304,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 +313,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 +325,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 +403,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;
@@ -307,24 +427,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);
}
@@ -349,8 +451,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;
}
@@ -359,8 +460,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;
}
@@ -485,7 +585,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);
@@ -493,8 +592,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;
@@ -547,5 +649,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/drivers/media/dvb/siano/smsendian.c b/drivers/media/dvb/siano/smsendian.c
new file mode 100644
index 00000000000..457b6d02ef8
--- /dev/null
+++ b/drivers/media/dvb/siano/smsendian.c
@@ -0,0 +1,102 @@
+/****************************************************************
+
+ Siano Mobile Silicon, Inc.
+ MDTV receiver kernel modules.
+ Copyright (C) 2006-2009, 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 <asm/byteorder.h>
+
+#include "smsendian.h"
+#include "smscoreapi.h"
+
+void smsendian_handle_tx_message(void *buffer)
+{
+#ifdef __BIG_ENDIAN
+ struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+ int i;
+ int msgWords;
+
+ switch (msg->xMsgHeader.msgType) {
+ case MSG_SMS_DATA_DOWNLOAD_REQ:
+ {
+ msg->msgData[0] = le32_to_cpu(msg->msgData[0]);
+ break;
+ }
+
+ default:
+ msgWords = (msg->xMsgHeader.msgLength -
+ sizeof(struct SmsMsgHdr_ST))/4;
+
+ for (i = 0; i < msgWords; i++)
+ msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+
+ break;
+ }
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_tx_message);
+
+void smsendian_handle_rx_message(void *buffer)
+{
+#ifdef __BIG_ENDIAN
+ struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+ int i;
+ int msgWords;
+
+ switch (msg->xMsgHeader.msgType) {
+ case MSG_SMS_GET_VERSION_EX_RES:
+ {
+ struct SmsVersionRes_ST *ver =
+ (struct SmsVersionRes_ST *) msg;
+ ver->ChipModel = le16_to_cpu(ver->ChipModel);
+ break;
+ }
+
+ case MSG_SMS_DVBT_BDA_DATA:
+ case MSG_SMS_DAB_CHANNEL:
+ case MSG_SMS_DATA_MSG:
+ {
+ break;
+ }
+
+ default:
+ {
+ msgWords = (msg->xMsgHeader.msgLength -
+ sizeof(struct SmsMsgHdr_ST))/4;
+
+ for (i = 0; i < msgWords; i++)
+ msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+
+ break;
+ }
+ }
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_rx_message);
+
+void smsendian_handle_message_header(void *msg)
+{
+#ifdef __BIG_ENDIAN
+ struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg;
+
+ phdr->msgType = le16_to_cpu(phdr->msgType);
+ phdr->msgLength = le16_to_cpu(phdr->msgLength);
+ phdr->msgFlags = le16_to_cpu(phdr->msgFlags);
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_message_header);
diff --git a/drivers/media/dvb/siano/smsendian.h b/drivers/media/dvb/siano/smsendian.h
new file mode 100644
index 00000000000..1624d6fd367
--- /dev/null
+++ b/drivers/media/dvb/siano/smsendian.h
@@ -0,0 +1,32 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2009, 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/>.
+
+****************************************************************/
+
+#ifndef __SMS_ENDIAN_H__
+#define __SMS_ENDIAN_H__
+
+#include <asm/byteorder.h>
+
+extern void smsendian_handle_tx_message(void *buffer);
+extern void smsendian_handle_rx_message(void *buffer);
+extern void smsendian_handle_message_header(void *msg);
+
+#endif /* __SMS_ENDIAN_H__ */
+
diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c
new file mode 100644
index 00000000000..e3d776feeac
--- /dev/null
+++ b/drivers/media/dvb/siano/smsir.c
@@ -0,0 +1,301 @@
+/****************************************************************
+
+ Siano Mobile Silicon, Inc.
+ MDTV receiver kernel modules.
+ Copyright (C) 2006-2009, 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/types.h>
+#include <linux/input.h>
+
+#include "smscoreapi.h"
+#include "smsir.h"
+#include "sms-cards.h"
+
+/* In order to add new IR remote control -
+ * 1) Add it to the <enum ir_kb_type> @ smsir,h,
+ * 2) Add its map to keyboard_layout_maps below
+ * 3) Set your board (sms-cards sub-module) to use it
+ */
+
+static struct keyboard_layout_map_t keyboard_layout_maps[] = {
+ [SMS_IR_KB_DEFAULT_TV] = {
+ .ir_protocol = IR_RC5,
+ .rc5_kbd_address = KEYBOARD_ADDRESS_TV1,
+ .keyboard_layout_map = {
+ KEY_0, KEY_1, KEY_2,
+ KEY_3, KEY_4, KEY_5,
+ KEY_6, KEY_7, KEY_8,
+ KEY_9, 0, 0, KEY_POWER,
+ KEY_MUTE, 0, 0,
+ KEY_VOLUMEUP, KEY_VOLUMEDOWN,
+ KEY_BRIGHTNESSUP,
+ KEY_BRIGHTNESSDOWN, KEY_CHANNELUP,
+ KEY_CHANNELDOWN,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ }
+ },
+ [SMS_IR_KB_HCW_SILVER] = {
+ .ir_protocol = IR_RC5,
+ .rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1,
+ .keyboard_layout_map = {
+ KEY_0, KEY_1, KEY_2,
+ KEY_3, KEY_4, KEY_5,
+ KEY_6, KEY_7, KEY_8,
+ KEY_9, KEY_TEXT, KEY_RED,
+ KEY_RADIO, KEY_MENU,
+ KEY_SUBTITLE,
+ KEY_MUTE, KEY_VOLUMEUP,
+ KEY_VOLUMEDOWN, KEY_PREVIOUS, 0,
+ KEY_UP, KEY_DOWN, KEY_LEFT,
+ KEY_RIGHT, KEY_VIDEO, KEY_AUDIO,
+ KEY_MHP, KEY_EPG, KEY_TV,
+ 0, KEY_NEXTSONG, KEY_EXIT,
+ KEY_CHANNELUP, KEY_CHANNELDOWN,
+ KEY_CHANNEL, 0,
+ KEY_PREVIOUSSONG, KEY_ENTER,
+ KEY_SLEEP, 0, 0, KEY_BLUE,
+ 0, 0, 0, 0, KEY_GREEN, 0,
+ KEY_PAUSE, 0, KEY_REWIND,
+ 0, KEY_FASTFORWARD, KEY_PLAY,
+ KEY_STOP, KEY_RECORD,
+ KEY_YELLOW, 0, 0, KEY_SELECT,
+ KEY_ZOOM, KEY_POWER, 0, 0
+ }
+ },
+ { } /* Terminating entry */
+};
+
+u32 ir_pos;
+u32 ir_word;
+u32 ir_toggle;
+
+#define RC5_PUSH_BIT(dst, bit, pos) \
+ { dst <<= 1; dst |= bit; pos++; }
+
+
+static void sms_ir_rc5_event(struct smscore_device_t *coredev,
+ u32 toggle, u32 addr, u32 cmd)
+{
+ bool toggle_changed;
+ u16 keycode;
+
+ sms_log("IR RC5 word: address %d, command %d, toggle %d",
+ addr, cmd, toggle);
+
+ toggle_changed = ir_toggle != toggle;
+ /* keep toggle */
+ ir_toggle = toggle;
+
+ if (addr !=
+ keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address)
+ return; /* Check for valid address */
+
+ keycode =
+ keyboard_layout_maps
+ [coredev->ir.ir_kb_type].keyboard_layout_map[cmd];
+
+ if (!toggle_changed &&
+ (keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN))
+ return; /* accept only repeated volume, reject other keys */
+
+ sms_log("kernel input keycode (from ir) %d", keycode);
+ input_report_key(coredev->ir.input_dev, keycode, 1);
+ input_sync(coredev->ir.input_dev);
+
+}
+
+/* decode raw bit pattern to RC5 code */
+/* taken from ir-functions.c */
+static u32 ir_rc5_decode(unsigned int code)
+{
+/* unsigned int org_code = code;*/
+ unsigned int pair;
+ unsigned int rc5 = 0;
+ int i;
+
+ for (i = 0; i < 14; ++i) {
+ pair = code & 0x3;
+ code >>= 2;
+
+ rc5 <<= 1;
+ switch (pair) {
+ case 0:
+ case 2:
+ break;
+ case 1:
+ rc5 |= 1;
+ break;
+ case 3:
+/* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/
+ sms_log("bad code");
+ return 0;
+ }
+ }
+/*
+ dprintk(1, "ir-common: code=%x, rc5=%x, start=%x,
+ toggle=%x, address=%x, "
+ "instr=%x\n", rc5, org_code, RC5_START(rc5),
+ RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
+*/
+ return rc5;
+}
+
+static void sms_rc5_parse_word(struct smscore_device_t *coredev)
+{
+ #define RC5_START(x) (((x)>>12)&3)
+ #define RC5_TOGGLE(x) (((x)>>11)&1)
+ #define RC5_ADDR(x) (((x)>>6)&0x1F)
+ #define RC5_INSTR(x) ((x)&0x3F)
+
+ int i, j;
+ u32 rc5_word = 0;
+
+ /* Reverse the IR word direction */
+ for (i = 0 ; i < 28 ; i++)
+ RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j)
+
+ rc5_word = ir_rc5_decode(rc5_word);
+ /* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */
+
+ sms_ir_rc5_event(coredev,
+ RC5_TOGGLE(rc5_word),
+ RC5_ADDR(rc5_word),
+ RC5_INSTR(rc5_word));
+}
+
+
+static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev,
+ s32 ir_sample)
+{
+ #define RC5_TIME_GRANULARITY 200
+ #define RC5_DEF_BIT_TIME 889
+ #define RC5_MAX_SAME_BIT_CONT 4
+ #define RC5_WORD_LEN 27 /* 28 bit */
+
+ u32 i, j;
+ s32 delta_time;
+ u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample);
+ u32 level = (ir_sample < 0) ? 0 : 1;
+
+ for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) {
+ delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY;
+ if (delta_time < 0)
+ continue; /* not so many consecutive bits */
+ if (delta_time > (2 * RC5_TIME_GRANULARITY)) {
+ /* timeout */
+ if (ir_pos == (RC5_WORD_LEN-1))
+ /* complete last bit */
+ RC5_PUSH_BIT(ir_word, level, ir_pos)
+
+ if (ir_pos == RC5_WORD_LEN)
+ sms_rc5_parse_word(coredev);
+ else if (ir_pos) /* timeout within a word */
+ sms_log("IR error parsing a word");
+
+ ir_pos = 0;
+ ir_word = 0;
+ /* sms_log("timeout %d", time); */
+ break;
+ }
+ /* The time is within the range of this number of bits */
+ for (j = 0 ; j < i ; j++)
+ RC5_PUSH_BIT(ir_word, level, ir_pos)
+
+ break;
+ }
+}
+
+void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
+{
+ #define IR_DATA_RECEIVE_MAX_LEN 520 /* 128*4 + 4 + 4 */
+ u32 i;
+ enum ir_protocol ir_protocol =
+ keyboard_layout_maps[coredev->ir.ir_kb_type]
+ .ir_protocol;
+ s32 *samples;
+ int count = len>>2;
+
+ samples = (s32 *)buf;
+/* sms_log("IR buffer received, length = %d", count);*/
+
+ for (i = 0; i < count; i++)
+ if (ir_protocol == IR_RC5)
+ sms_rc5_accumulate_bits(coredev, samples[i]);
+ /* IR_RCMM not implemented */
+}
+
+int sms_ir_init(struct smscore_device_t *coredev)
+{
+ struct input_dev *input_dev;
+
+ sms_log("Allocating input device");
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ sms_err("Not enough memory");
+ return -ENOMEM;
+ }
+
+ coredev->ir.input_dev = input_dev;
+ coredev->ir.ir_kb_type =
+ sms_get_board(smscore_get_board_id(coredev))->ir_kb_type;
+ coredev->ir.keyboard_layout_map =
+ keyboard_layout_maps[coredev->ir.ir_kb_type].
+ keyboard_layout_map;
+ 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_log("IR port %d, timeout %d ms",
+ coredev->ir.controller, coredev->ir.timeout);
+
+ snprintf(coredev->ir.name,
+ IR_DEV_NAME_MAX_LEN,
+ "SMS IR w/kbd type %d",
+ coredev->ir.ir_kb_type);
+ input_dev->name = coredev->ir.name;
+ input_dev->phys = coredev->ir.name;
+ input_dev->dev.parent = coredev->device;
+
+ /* Key press events only */
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
+ input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+
+ 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");
+ input_free_device(input_dev);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+void sms_ir_exit(struct smscore_device_t *coredev)
+{
+ if (coredev->ir.input_dev)
+ input_unregister_device(coredev->ir.input_dev);
+
+ sms_log("");
+}
+
diff --git a/drivers/media/dvb/siano/smsir.h b/drivers/media/dvb/siano/smsir.h
new file mode 100644
index 00000000000..b7d703e2d33
--- /dev/null
+++ b/drivers/media/dvb/siano/smsir.h
@@ -0,0 +1,93 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2009, 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/>.
+
+****************************************************************/
+
+#ifndef __SMS_IR_H__
+#define __SMS_IR_H__
+
+#include <linux/input.h>
+
+#define IR_DEV_NAME_MAX_LEN 23 /* "SMS IR kbd type nn\0" */
+#define IR_KEYBOARD_LAYOUT_SIZE 64
+#define IR_DEFAULT_TIMEOUT 100
+
+enum ir_kb_type {
+ SMS_IR_KB_DEFAULT_TV,
+ SMS_IR_KB_HCW_SILVER
+};
+
+enum rc5_keyboard_address {
+ KEYBOARD_ADDRESS_TV1 = 0,
+ KEYBOARD_ADDRESS_TV2 = 1,
+ KEYBOARD_ADDRESS_TELETEXT = 2,
+ KEYBOARD_ADDRESS_VIDEO = 3,
+ KEYBOARD_ADDRESS_LV1 = 4,
+ KEYBOARD_ADDRESS_VCR1 = 5,
+ KEYBOARD_ADDRESS_VCR2 = 6,
+ KEYBOARD_ADDRESS_EXPERIMENTAL = 7,
+ KEYBOARD_ADDRESS_SAT1 = 8,
+ KEYBOARD_ADDRESS_CAMERA = 9,
+ KEYBOARD_ADDRESS_SAT2 = 10,
+ KEYBOARD_ADDRESS_CDV = 12,
+ KEYBOARD_ADDRESS_CAMCORDER = 13,
+ KEYBOARD_ADDRESS_PRE_AMP = 16,
+ KEYBOARD_ADDRESS_TUNER = 17,
+ KEYBOARD_ADDRESS_RECORDER1 = 18,
+ KEYBOARD_ADDRESS_PRE_AMP1 = 19,
+ KEYBOARD_ADDRESS_CD_PLAYER = 20,
+ KEYBOARD_ADDRESS_PHONO = 21,
+ KEYBOARD_ADDRESS_SATA = 22,
+ KEYBOARD_ADDRESS_RECORDER2 = 23,
+ KEYBOARD_ADDRESS_CDR = 26,
+ KEYBOARD_ADDRESS_LIGHTING = 29,
+ KEYBOARD_ADDRESS_LIGHTING1 = 30, /* KEYBOARD_ADDRESS_HCW_SILVER */
+ KEYBOARD_ADDRESS_PHONE = 31,
+ KEYBOARD_ADDRESS_NOT_RC5 = 0xFFFF
+};
+
+enum ir_protocol {
+ IR_RC5,
+ IR_RCMM
+};
+
+struct keyboard_layout_map_t {
+ enum ir_protocol ir_protocol;
+ enum rc5_keyboard_address rc5_kbd_address;
+ u16 keyboard_layout_map[IR_KEYBOARD_LAYOUT_SIZE];
+};
+
+struct smscore_device_t;
+
+struct ir_t {
+ struct input_dev *input_dev;
+ enum ir_kb_type ir_kb_type;
+ char name[IR_DEV_NAME_MAX_LEN+1];
+ u16 *keyboard_layout_map;
+ u32 timeout;
+ u32 controller;
+};
+
+int sms_ir_init(struct smscore_device_t *coredev);
+void sms_ir_exit(struct smscore_device_t *coredev);
+void sms_ir_event(struct smscore_device_t *coredev,
+ const char *buf, int len);
+
+#endif /* __SMS_IR_H__ */
+
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c
new file mode 100644
index 00000000000..dfaa49a53f3
--- /dev/null
+++ b/drivers/media/dvb/siano/smssdio.c
@@ -0,0 +1,357 @@
+/*
+ * smssdio.c - Siano 1xxx SDIO interface driver
+ *
+ * Copyright 2008 Pierre Ossman
+ *
+ * Based on code by Siano Mobile Silicon, Inc.,
+ * 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 hardware is a bit odd in that all transfers should be done
+ * to/from the SMSSDIO_DATA register, yet the "increase address" bit
+ * always needs to be set.
+ *
+ * Also, buffers from the card are always aligned to 128 byte
+ * boundaries.
+ */
+
+/*
+ * General cleanup notes:
+ *
+ * - only typedefs should be name *_t
+ *
+ * - use ERR_PTR and friends for smscore_register_device()
+ *
+ * - smscore_getbuffer should zero fields
+ *
+ * Fix stop command
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+/* Registers */
+
+#define SMSSDIO_DATA 0x00
+#define SMSSDIO_INT 0x04
+
+static const struct sdio_device_id smssdio_ids[] = {
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
+ .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
+ .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0),
+ .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0),
+ .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE),
+ .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+ { /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(sdio, smssdio_ids);
+
+struct smssdio_device {
+ struct sdio_func *func;
+
+ struct smscore_device_t *coredev;
+
+ struct smscore_buffer_t *split_cb;
+};
+
+/*******************************************************************/
+/* Siano core callbacks */
+/*******************************************************************/
+
+static int smssdio_sendrequest(void *context, void *buffer, size_t size)
+{
+ int ret;
+ struct smssdio_device *smsdev;
+
+ smsdev = context;
+
+ sdio_claim_host(smsdev->func);
+
+ while (size >= smsdev->func->cur_blksize) {
+ ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1);
+ if (ret)
+ goto out;
+
+ buffer += smsdev->func->cur_blksize;
+ size -= smsdev->func->cur_blksize;
+ }
+
+ if (size) {
+ ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA,
+ buffer, size);
+ }
+
+out:
+ sdio_release_host(smsdev->func);
+
+ return ret;
+}
+
+/*******************************************************************/
+/* SDIO callbacks */
+/*******************************************************************/
+
+static void smssdio_interrupt(struct sdio_func *func)
+{
+ int ret, isr;
+
+ struct smssdio_device *smsdev;
+ struct smscore_buffer_t *cb;
+ struct SmsMsgHdr_ST *hdr;
+ size_t size;
+
+ smsdev = sdio_get_drvdata(func);
+
+ /*
+ * The interrupt register has no defined meaning. It is just
+ * a way of turning of the level triggered interrupt.
+ */
+ isr = sdio_readb(func, SMSSDIO_INT, &ret);
+ if (ret) {
+ dev_err(&smsdev->func->dev,
+ "Unable to read interrupt register!\n");
+ return;
+ }
+
+ if (smsdev->split_cb == NULL) {
+ cb = smscore_getbuffer(smsdev->coredev);
+ if (!cb) {
+ dev_err(&smsdev->func->dev,
+ "Unable to allocate data buffer!\n");
+ return;
+ }
+
+ ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1);
+ if (ret) {
+ dev_err(&smsdev->func->dev,
+ "Error %d reading initial block!\n", ret);
+ return;
+ }
+
+ hdr = cb->p;
+
+ if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) {
+ smsdev->split_cb = cb;
+ return;
+ }
+
+ size = hdr->msgLength - smsdev->func->cur_blksize;
+ } else {
+ cb = smsdev->split_cb;
+ hdr = cb->p;
+
+ size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST);
+
+ smsdev->split_cb = NULL;
+ }
+
+ if (hdr->msgLength > smsdev->func->cur_blksize) {
+ void *buffer;
+
+ size = ALIGN(size, 128);
+ buffer = cb->p + hdr->msgLength;
+
+ BUG_ON(smsdev->func->cur_blksize != 128);
+
+ /*
+ * First attempt to transfer all of it in one go...
+ */
+ ret = sdio_read_blocks(smsdev->func, buffer,
+ SMSSDIO_DATA, size / 128);
+ if (ret && ret != -EINVAL) {
+ smscore_putbuffer(smsdev->coredev, cb);
+ dev_err(&smsdev->func->dev,
+ "Error %d reading data from card!\n", ret);
+ return;
+ }
+
+ /*
+ * ..then fall back to one block at a time if that is
+ * not possible...
+ *
+ * (we have to do this manually because of the
+ * problem with the "increase address" bit)
+ */
+ if (ret == -EINVAL) {
+ while (size) {
+ ret = sdio_read_blocks(smsdev->func,
+ buffer, SMSSDIO_DATA, 1);
+ if (ret) {
+ smscore_putbuffer(smsdev->coredev, cb);
+ dev_err(&smsdev->func->dev,
+ "Error %d reading "
+ "data from card!\n", ret);
+ return;
+ }
+
+ buffer += smsdev->func->cur_blksize;
+ if (size > smsdev->func->cur_blksize)
+ size -= smsdev->func->cur_blksize;
+ else
+ size = 0;
+ }
+ }
+ }
+
+ cb->size = hdr->msgLength;
+ cb->offset = 0;
+
+ smscore_onresponse(smsdev->coredev, cb);
+}
+
+static int smssdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ int ret;
+
+ int board_id;
+ struct smssdio_device *smsdev;
+ struct smsdevice_params_t params;
+
+ board_id = id->driver_data;
+
+ smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL);
+ if (!smsdev)
+ return -ENOMEM;
+
+ smsdev->func = func;
+
+ memset(&params, 0, sizeof(struct smsdevice_params_t));
+
+ params.device = &func->dev;
+ params.buffer_size = 0x5000; /* ?? */
+ params.num_buffers = 22; /* ?? */
+ params.context = smsdev;
+
+ snprintf(params.devpath, sizeof(params.devpath),
+ "sdio\\%s", sdio_func_id(func));
+
+ params.sendrequest_handler = smssdio_sendrequest;
+
+ params.device_type = sms_get_board(board_id)->type;
+
+ if (params.device_type != SMS_STELLAR)
+ params.flags |= SMS_DEVICE_FAMILY2;
+ else {
+ /*
+ * FIXME: Stellar needs special handling...
+ */
+ ret = -ENODEV;
+ goto free;
+ }
+
+ ret = smscore_register_device(&params, &smsdev->coredev);
+ if (ret < 0)
+ goto free;
+
+ smscore_set_board_id(smsdev->coredev, board_id);
+
+ sdio_claim_host(func);
+
+ ret = sdio_enable_func(func);
+ if (ret)
+ goto release;
+
+ ret = sdio_set_block_size(func, 128);
+ if (ret)
+ goto disable;
+
+ ret = sdio_claim_irq(func, smssdio_interrupt);
+ if (ret)
+ goto disable;
+
+ sdio_set_drvdata(func, smsdev);
+
+ sdio_release_host(func);
+
+ ret = smscore_start_device(smsdev->coredev);
+ if (ret < 0)
+ goto reclaim;
+
+ return 0;
+
+reclaim:
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+disable:
+ sdio_disable_func(func);
+release:
+ sdio_release_host(func);
+ smscore_unregister_device(smsdev->coredev);
+free:
+ kfree(smsdev);
+
+ return ret;
+}
+
+static void smssdio_remove(struct sdio_func *func)
+{
+ struct smssdio_device *smsdev;
+
+ smsdev = sdio_get_drvdata(func);
+
+ /* FIXME: racy! */
+ if (smsdev->split_cb)
+ smscore_putbuffer(smsdev->coredev, smsdev->split_cb);
+
+ smscore_unregister_device(smsdev->coredev);
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+
+ kfree(smsdev);
+}
+
+static struct sdio_driver smssdio_driver = {
+ .name = "smssdio",
+ .id_table = smssdio_ids,
+ .probe = smssdio_probe,
+ .remove = smssdio_remove,
+};
+
+/*******************************************************************/
+/* Module functions */
+/*******************************************************************/
+
+int smssdio_module_init(void)
+{
+ int ret = 0;
+
+ printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n");
+ printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n");
+
+ ret = sdio_register_driver(&smssdio_driver);
+
+ return ret;
+}
+
+void smssdio_module_exit(void)
+{
+ sdio_unregister_driver(&smssdio_driver);
+}
+
+module_init(smssdio_module_init);
+module_exit(smssdio_module_exit);
+
+MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
+MODULE_AUTHOR("Pierre Ossman");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index 71c65f544c0..cb8a358b731 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/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);
@@ -64,15 +65,16 @@ static void smsusb_onresponse(struct urb *urb)
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;
@@ -109,7 +111,10 @@ static void smsusb_onresponse(struct urb *urb)
"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);
@@ -176,6 +181,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);
}
@@ -333,8 +339,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;
@@ -479,7 +485,6 @@ static int smsusb_resume(struct usb_interface *intf)
}
struct usb_device_id smsusb_id_table[] = {
-#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
{ USB_DEVICE(0x187f, 0x0010),
.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
{ USB_DEVICE(0x187f, 0x0100),
@@ -490,7 +495,6 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
{ USB_DEVICE(0x187f, 0x0300),
.driver_info = SMS1XXX_BOARD_SIANO_VEGA },
-#endif
{ USB_DEVICE(0x2040, 0x1700),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
{ USB_DEVICE(0x2040, 0x1800),
@@ -521,8 +525,13 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5590),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
- { } /* Terminating entry */
-};
+ { USB_DEVICE(0x187f, 0x0202),
+ .driver_info = SMS1XXX_BOARD_SIANO_NICE },
+ { USB_DEVICE(0x187f, 0x0301),
+ .driver_info = SMS1XXX_BOARD_SIANO_VENICE },
+ { } /* Terminating entry */
+ };
+
MODULE_DEVICE_TABLE(usb, smsusb_id_table);
static struct usb_driver smsusb_driver = {
@@ -548,14 +557,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/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index e4d0900d512..53884814161 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/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/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 5e3f88911a1..e162691b515 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/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/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index 2210cff738e..ce64c6214cc 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/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/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 855fe74b640..8ea91522767 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/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/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 83e9e7750c8..e48380c4899 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/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),