diff options
Diffstat (limited to 'drivers/media/dvb-frontends')
70 files changed, 4113 insertions, 1665 deletions
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index 6f809a7..0e2ec6f 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -210,7 +210,7 @@ config DVB_SI21XX config DVB_TS2020 tristate "Montage Tehnology TS2020 based tuners" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S/S2 silicon tuner. Say Y when you want to support this tuner. diff --git a/drivers/media/dvb-frontends/a8293.h b/drivers/media/dvb-frontends/a8293.h index ed29e55..b6ef642 100644 --- a/drivers/media/dvb-frontends/a8293.h +++ b/drivers/media/dvb-frontends/a8293.h @@ -21,12 +21,13 @@ #ifndef A8293_H #define A8293_H +#include <linux/kconfig.h> + struct a8293_config { u8 i2c_addr; }; -#if defined(CONFIG_DVB_A8293) || \ - (defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_A8293) extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct a8293_config *cfg); #else diff --git a/drivers/media/dvb-frontends/af9013.h b/drivers/media/dvb-frontends/af9013.h index dc837d9..09273b2 100644 --- a/drivers/media/dvb-frontends/af9013.h +++ b/drivers/media/dvb-frontends/af9013.h @@ -25,6 +25,7 @@ #ifndef AF9013_H #define AF9013_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> /* AF9013/5 GPIOs (mostly guessed) @@ -102,8 +103,7 @@ struct af9013_config { u8 gpio[4]; }; -#if defined(CONFIG_DVB_AF9013) || \ - (defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_AF9013) extern struct dvb_frontend *af9013_attach(const struct af9013_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index c9cad989..a777b4b 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -156,6 +156,37 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, return 0; } +/* write reg val table using reg addr auto increment */ +static int af9033_wr_reg_val_tab(struct af9033_state *state, + const struct reg_val *tab, int tab_len) +{ + int ret, i, j; + u8 buf[tab_len]; + + dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); + + for (i = 0, j = 0; i < tab_len; i++) { + buf[j] = tab[i].val; + + if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) { + ret = af9033_wr_regs(state, tab[i].reg - j, buf, j + 1); + if (ret < 0) + goto err; + + j = 0; + } else { + j++; + } + } + + return 0; + +err: + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + + return ret; +} + static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x) { u32 r = 0, c = 0, i; @@ -223,6 +254,7 @@ static int af9033_init(struct dvb_frontend *fe) { 0x80f986, state->ts_mode_parallel, 0x01 }, { 0x00d827, 0x00, 0xff }, { 0x00d829, 0x00, 0xff }, + { 0x800045, state->cfg.adc_multiplier, 0xff }, }; /* program clock control */ @@ -286,14 +318,29 @@ static int af9033_init(struct dvb_frontend *fe) /* load OFSM settings */ dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__); - len = ARRAY_SIZE(ofsm_init); - init = ofsm_init; - for (i = 0; i < len; i++) { - ret = af9033_wr_reg(state, init[i].reg, init[i].val); - if (ret < 0) - goto err; + switch (state->cfg.tuner) { + case AF9033_TUNER_IT9135_38: + case AF9033_TUNER_IT9135_51: + case AF9033_TUNER_IT9135_52: + len = ARRAY_SIZE(ofsm_init_it9135_v1); + init = ofsm_init_it9135_v1; + break; + case AF9033_TUNER_IT9135_60: + case AF9033_TUNER_IT9135_61: + case AF9033_TUNER_IT9135_62: + len = ARRAY_SIZE(ofsm_init_it9135_v2); + init = ofsm_init_it9135_v2; + break; + default: + len = ARRAY_SIZE(ofsm_init); + init = ofsm_init; + break; } + ret = af9033_wr_reg_val_tab(state, init, len); + if (ret < 0) + goto err; + /* load tuner specific settings */ dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n", __func__); @@ -322,6 +369,30 @@ static int af9033_init(struct dvb_frontend *fe) len = ARRAY_SIZE(tuner_init_fc0012); init = tuner_init_fc0012; break; + case AF9033_TUNER_IT9135_38: + len = ARRAY_SIZE(tuner_init_it9135_38); + init = tuner_init_it9135_38; + break; + case AF9033_TUNER_IT9135_51: + len = ARRAY_SIZE(tuner_init_it9135_51); + init = tuner_init_it9135_51; + break; + case AF9033_TUNER_IT9135_52: + len = ARRAY_SIZE(tuner_init_it9135_52); + init = tuner_init_it9135_52; + break; + case AF9033_TUNER_IT9135_60: + len = ARRAY_SIZE(tuner_init_it9135_60); + init = tuner_init_it9135_60; + break; + case AF9033_TUNER_IT9135_61: + len = ARRAY_SIZE(tuner_init_it9135_61); + init = tuner_init_it9135_61; + break; + case AF9033_TUNER_IT9135_62: + len = ARRAY_SIZE(tuner_init_it9135_62); + init = tuner_init_it9135_62; + break; default: dev_dbg(&state->i2c->dev, "%s: unsupported tuner ID=%d\n", __func__, state->cfg.tuner); @@ -329,11 +400,9 @@ static int af9033_init(struct dvb_frontend *fe) goto err; } - for (i = 0; i < len; i++) { - ret = af9033_wr_reg(state, init[i].reg, init[i].val); - if (ret < 0) - goto err; - } + ret = af9033_wr_reg_val_tab(state, init, len); + if (ret < 0) + goto err; if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { ret = af9033_wr_reg_mask(state, 0x00d91c, 0x01, 0x01); @@ -349,6 +418,15 @@ static int af9033_init(struct dvb_frontend *fe) goto err; } + switch (state->cfg.tuner) { + case AF9033_TUNER_IT9135_60: + case AF9033_TUNER_IT9135_61: + case AF9033_TUNER_IT9135_62: + ret = af9033_wr_reg(state, 0x800000, 0x01); + if (ret < 0) + goto err; + } + state->bandwidth_hz = 0; /* force to program all parameters */ return 0; @@ -415,7 +493,8 @@ err: static int af9033_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *fesettings) { - fesettings->min_delay_ms = 800; + /* 800 => 2000 because IT9135 v2 is slow to gain lock */ + fesettings->min_delay_ms = 2000; fesettings->step_size = 0; fesettings->max_drift = 0; @@ -498,17 +577,17 @@ static int af9033_set_frontend(struct dvb_frontend *fe) if (spec_inv == -1) freq_cw = 0x800000 - freq_cw; - /* get adc multiplies */ - ret = af9033_rd_reg(state, 0x800045, &tmp); - if (ret < 0) - goto err; - - if (tmp == 1) + if (state->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X) freq_cw /= 2; buf[0] = (freq_cw >> 0) & 0xff; buf[1] = (freq_cw >> 8) & 0xff; buf[2] = (freq_cw >> 16) & 0x7f; + + /* FIXME: there seems to be calculation error here... */ + if (if_frequency == 0) + buf[2] = 0; + ret = af9033_wr_regs(state, 0x800029, buf, 3); if (ret < 0) goto err; @@ -934,13 +1013,24 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config, buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); /* sleep */ - ret = af9033_wr_reg(state, 0x80004c, 1); - if (ret < 0) - goto err; + switch (state->cfg.tuner) { + case AF9033_TUNER_IT9135_38: + case AF9033_TUNER_IT9135_51: + case AF9033_TUNER_IT9135_52: + case AF9033_TUNER_IT9135_60: + case AF9033_TUNER_IT9135_61: + case AF9033_TUNER_IT9135_62: + /* IT9135 did not like to sleep at that early */ + break; + default: + ret = af9033_wr_reg(state, 0x80004c, 1); + if (ret < 0) + goto err; - ret = af9033_wr_reg(state, 0x800000, 0); - if (ret < 0) - goto err; + ret = af9033_wr_reg(state, 0x800000, 0); + if (ret < 0) + goto err; + } /* configure internal TS mode */ switch (state->cfg.ts_mode) { diff --git a/drivers/media/dvb-frontends/af9033.h b/drivers/media/dvb-frontends/af9033.h index 82bd8c1..c286e8f 100644 --- a/drivers/media/dvb-frontends/af9033.h +++ b/drivers/media/dvb-frontends/af9033.h @@ -22,6 +22,8 @@ #ifndef AF9033_H #define AF9033_H +#include <linux/kconfig.h> + struct af9033_config { /* * I2C address @@ -36,6 +38,13 @@ struct af9033_config { u32 clock; /* + * ADC multiplier + */ +#define AF9033_ADC_MULTIPLIER_1X 0 +#define AF9033_ADC_MULTIPLIER_2X 1 + u8 adc_multiplier; + + /* * tuner */ #define AF9033_TUNER_TUA9001 0x27 /* Infineon TUA 9001 */ @@ -44,6 +53,14 @@ struct af9033_config { #define AF9033_TUNER_MXL5007T 0xa0 /* MaxLinear MxL5007T */ #define AF9033_TUNER_TDA18218 0xa1 /* NXP TDA 18218HN */ #define AF9033_TUNER_FC2580 0x32 /* FCI FC2580 */ +/* 50-5f Omega */ +#define AF9033_TUNER_IT9135_38 0x38 /* Omega */ +#define AF9033_TUNER_IT9135_51 0x51 /* Omega LNA config 1 */ +#define AF9033_TUNER_IT9135_52 0x52 /* Omega LNA config 2 */ +/* 60-6f Omega v2 */ +#define AF9033_TUNER_IT9135_60 0x60 /* Omega v2 */ +#define AF9033_TUNER_IT9135_61 0x61 /* Omega v2 LNA config 1 */ +#define AF9033_TUNER_IT9135_62 0x62 /* Omega v2 LNA config 2 */ u8 tuner; /* @@ -61,8 +78,7 @@ struct af9033_config { }; -#if defined(CONFIG_DVB_AF9033) || \ - (defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_AF9033) extern struct dvb_frontend *af9033_attach(const struct af9033_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/af9033_priv.h b/drivers/media/dvb-frontends/af9033_priv.h index e9bd782..fc2ad58 100644 --- a/drivers/media/dvb-frontends/af9033_priv.h +++ b/drivers/media/dvb-frontends/af9033_priv.h @@ -547,5 +547,1509 @@ static const struct reg_val tuner_init_fc2580[] = { { 0x80f1e6, 0x01 }, }; -#endif /* AF9033_PRIV_H */ +static const struct reg_val ofsm_init_it9135_v1[] = { + { 0x800051, 0x01 }, + { 0x800070, 0x0a }, + { 0x80007e, 0x04 }, + { 0x800081, 0x0a }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800099, 0x01 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000c2, 0x05 }, + { 0x8000c6, 0x19 }, + { 0x80f000, 0x0f }, + { 0x80f016, 0x10 }, + { 0x80f017, 0x04 }, + { 0x80f018, 0x05 }, + { 0x80f019, 0x04 }, + { 0x80f01a, 0x05 }, + { 0x80f021, 0x03 }, + { 0x80f022, 0x0a }, + { 0x80f023, 0x0a }, + { 0x80f02b, 0x00 }, + { 0x80f02c, 0x01 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f078, 0x00 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5df, 0xfb }, + { 0x80f5e0, 0x00 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f5f8, 0x01 }, + { 0x80f5fd, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; + +/* ITE Tech IT9135 Omega tuner init + AF9033_TUNER_IT9135_38 = 0x38 */ +static const struct reg_val tuner_init_it9135_38[] = { + { 0x800043, 0x00 }, + { 0x800046, 0x38 }, + { 0x800051, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800068, 0x0a }, + { 0x800070, 0x0a }, + { 0x800071, 0x05 }, + { 0x800072, 0x02 }, + { 0x800075, 0x8c }, + { 0x800076, 0x8c }, + { 0x800077, 0x8c }, + { 0x800078, 0xc8 }, + { 0x800079, 0x01 }, + { 0x80007e, 0x04 }, + { 0x80007f, 0x00 }, + { 0x800081, 0x0a }, + { 0x800082, 0x12 }, + { 0x800083, 0x02 }, + { 0x800084, 0x0a }, + { 0x800085, 0x03 }, + { 0x800086, 0xc8 }, + { 0x800087, 0xb8 }, + { 0x800088, 0xd0 }, + { 0x800089, 0xc3 }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x00 }, + { 0x800099, 0x01 }, + { 0x80009b, 0x3c }, + { 0x80009c, 0x28 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a4, 0x5a }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000b3, 0x02 }, + { 0x8000b4, 0x32 }, + { 0x8000b6, 0x14 }, + { 0x8000c0, 0x11 }, + { 0x8000c1, 0x00 }, + { 0x8000c2, 0x05 }, + { 0x8000c4, 0x00 }, + { 0x8000c6, 0x19 }, + { 0x8000c7, 0x00 }, + { 0x8000cc, 0x2e }, + { 0x8000cd, 0x51 }, + { 0x8000ce, 0x33 }, + { 0x8000f3, 0x05 }, + { 0x8000f4, 0x8c }, + { 0x8000f5, 0x8c }, + { 0x8000f8, 0x03 }, + { 0x8000f9, 0x06 }, + { 0x8000fa, 0x06 }, + { 0x8000fc, 0x02 }, + { 0x8000fd, 0x02 }, + { 0x8000fe, 0x02 }, + { 0x8000ff, 0x09 }, + { 0x800100, 0x50 }, + { 0x800101, 0x7b }, + { 0x800102, 0x77 }, + { 0x800103, 0x00 }, + { 0x800104, 0x02 }, + { 0x800105, 0xc8 }, + { 0x800106, 0x05 }, + { 0x800107, 0x7b }, + { 0x800109, 0x02 }, + { 0x800115, 0x0a }, + { 0x800116, 0x03 }, + { 0x800117, 0x02 }, + { 0x800118, 0x80 }, + { 0x80011a, 0xc8 }, + { 0x80011b, 0x7b }, + { 0x80011c, 0x8a }, + { 0x80011d, 0xa0 }, + { 0x800122, 0x02 }, + { 0x800123, 0x18 }, + { 0x800124, 0xc3 }, + { 0x800127, 0x00 }, + { 0x800128, 0x07 }, + { 0x80012a, 0x53 }, + { 0x80012b, 0x51 }, + { 0x80012c, 0x4e }, + { 0x80012d, 0x43 }, + { 0x800137, 0x01 }, + { 0x800138, 0x00 }, + { 0x800139, 0x07 }, + { 0x80013a, 0x00 }, + { 0x80013b, 0x06 }, + { 0x80013d, 0x00 }, + { 0x80013e, 0x01 }, + { 0x80013f, 0x5b }, + { 0x800140, 0xc8 }, + { 0x800141, 0x59 }, + { 0x80f000, 0x0f }, + { 0x80f016, 0x10 }, + { 0x80f017, 0x04 }, + { 0x80f018, 0x05 }, + { 0x80f019, 0x04 }, + { 0x80f01a, 0x05 }, + { 0x80f01f, 0x8c }, + { 0x80f020, 0x00 }, + { 0x80f021, 0x03 }, + { 0x80f022, 0x0a }, + { 0x80f023, 0x0a }, + { 0x80f029, 0x8c }, + { 0x80f02a, 0x00 }, + { 0x80f02b, 0x00 }, + { 0x80f02c, 0x01 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f077, 0x01 }, + { 0x80f078, 0x00 }, + { 0x80f085, 0x00 }, + { 0x80f086, 0x02 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f24c, 0x88 }, + { 0x80f24d, 0x95 }, + { 0x80f24e, 0x9a }, + { 0x80f24f, 0x90 }, + { 0x80f25a, 0x07 }, + { 0x80f25b, 0xe8 }, + { 0x80f25c, 0x03 }, + { 0x80f25d, 0xb0 }, + { 0x80f25e, 0x04 }, + { 0x80f270, 0x01 }, + { 0x80f271, 0x02 }, + { 0x80f272, 0x01 }, + { 0x80f273, 0x02 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5df, 0xfb }, + { 0x80f5e0, 0x00 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f5f8, 0x01 }, + { 0x80f5fd, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; + +/* ITE Tech IT9135 Omega LNA config 1 tuner init + AF9033_TUNER_IT9135_51 = 0x51 */ +static const struct reg_val tuner_init_it9135_51[] = { + { 0x800043, 0x00 }, + { 0x800046, 0x51 }, + { 0x800051, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800068, 0x0a }, + { 0x800070, 0x0a }, + { 0x800071, 0x06 }, + { 0x800072, 0x02 }, + { 0x800075, 0x8c }, + { 0x800076, 0x8c }, + { 0x800077, 0x8c }, + { 0x800078, 0xc8 }, + { 0x800079, 0x01 }, + { 0x80007e, 0x04 }, + { 0x80007f, 0x00 }, + { 0x800081, 0x0a }, + { 0x800082, 0x12 }, + { 0x800083, 0x02 }, + { 0x800084, 0x0a }, + { 0x800085, 0x03 }, + { 0x800086, 0xc0 }, + { 0x800087, 0x96 }, + { 0x800088, 0xcf }, + { 0x800089, 0xc3 }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x00 }, + { 0x800099, 0x01 }, + { 0x80009b, 0x3c }, + { 0x80009c, 0x28 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a4, 0x5a }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000b3, 0x02 }, + { 0x8000b4, 0x3c }, + { 0x8000b6, 0x14 }, + { 0x8000c0, 0x11 }, + { 0x8000c1, 0x00 }, + { 0x8000c2, 0x05 }, + { 0x8000c4, 0x00 }, + { 0x8000c6, 0x19 }, + { 0x8000c7, 0x00 }, + { 0x8000cc, 0x2e }, + { 0x8000cd, 0x51 }, + { 0x8000ce, 0x33 }, + { 0x8000f3, 0x05 }, + { 0x8000f4, 0x8c }, + { 0x8000f5, 0x8c }, + { 0x8000f8, 0x03 }, + { 0x8000f9, 0x06 }, + { 0x8000fa, 0x06 }, + { 0x8000fc, 0x03 }, + { 0x8000fd, 0x02 }, + { 0x8000fe, 0x02 }, + { 0x8000ff, 0x09 }, + { 0x800100, 0x50 }, + { 0x800101, 0x7a }, + { 0x800102, 0x77 }, + { 0x800103, 0x01 }, + { 0x800104, 0x02 }, + { 0x800105, 0xb0 }, + { 0x800106, 0x02 }, + { 0x800107, 0x7a }, + { 0x800109, 0x02 }, + { 0x800115, 0x0a }, + { 0x800116, 0x03 }, + { 0x800117, 0x02 }, + { 0x800118, 0x80 }, + { 0x80011a, 0xc0 }, + { 0x80011b, 0x7a }, + { 0x80011c, 0xac }, + { 0x80011d, 0x8c }, + { 0x800122, 0x02 }, + { 0x800123, 0x70 }, + { 0x800124, 0xa4 }, + { 0x800127, 0x00 }, + { 0x800128, 0x07 }, + { 0x80012a, 0x53 }, + { 0x80012b, 0x51 }, + { 0x80012c, 0x4e }, + { 0x80012d, 0x43 }, + { 0x800137, 0x01 }, + { 0x800138, 0x00 }, + { 0x800139, 0x07 }, + { 0x80013a, 0x00 }, + { 0x80013b, 0x06 }, + { 0x80013d, 0x00 }, + { 0x80013e, 0x01 }, + { 0x80013f, 0x5b }, + { 0x800140, 0xc0 }, + { 0x800141, 0x59 }, + { 0x80f000, 0x0f }, + { 0x80f016, 0x10 }, + { 0x80f017, 0x04 }, + { 0x80f018, 0x05 }, + { 0x80f019, 0x04 }, + { 0x80f01a, 0x05 }, + { 0x80f01f, 0x8c }, + { 0x80f020, 0x00 }, + { 0x80f021, 0x03 }, + { 0x80f022, 0x0a }, + { 0x80f023, 0x0a }, + { 0x80f029, 0x8c }, + { 0x80f02a, 0x00 }, + { 0x80f02b, 0x00 }, + { 0x80f02c, 0x01 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f077, 0x01 }, + { 0x80f078, 0x00 }, + { 0x80f085, 0xc0 }, + { 0x80f086, 0x01 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f24c, 0x88 }, + { 0x80f24d, 0x95 }, + { 0x80f24e, 0x9a }, + { 0x80f24f, 0x90 }, + { 0x80f25a, 0x07 }, + { 0x80f25b, 0xe8 }, + { 0x80f25c, 0x03 }, + { 0x80f25d, 0xb0 }, + { 0x80f25e, 0x04 }, + { 0x80f270, 0x01 }, + { 0x80f271, 0x02 }, + { 0x80f272, 0x01 }, + { 0x80f273, 0x02 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5df, 0xfb }, + { 0x80f5e0, 0x00 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f5f8, 0x01 }, + { 0x80f5fd, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; + +/* ITE Tech IT9135 Omega LNA config 2 tuner init + AF9033_TUNER_IT9135_52 = 0x52 */ +static const struct reg_val tuner_init_it9135_52[] = { + { 0x800043, 0x00 }, + { 0x800046, 0x52 }, + { 0x800051, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800068, 0x10 }, + { 0x800070, 0x0a }, + { 0x800071, 0x05 }, + { 0x800072, 0x02 }, + { 0x800075, 0x8c }, + { 0x800076, 0x8c }, + { 0x800077, 0x8c }, + { 0x800078, 0xa0 }, + { 0x800079, 0x01 }, + { 0x80007e, 0x04 }, + { 0x80007f, 0x00 }, + { 0x800081, 0x0a }, + { 0x800082, 0x17 }, + { 0x800083, 0x03 }, + { 0x800084, 0x0a }, + { 0x800085, 0x03 }, + { 0x800086, 0xb3 }, + { 0x800087, 0x97 }, + { 0x800088, 0xc0 }, + { 0x800089, 0x9e }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x00 }, + { 0x800099, 0x01 }, + { 0x80009b, 0x3c }, + { 0x80009c, 0x28 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a4, 0x5c }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000b3, 0x02 }, + { 0x8000b4, 0x3c }, + { 0x8000b6, 0x14 }, + { 0x8000c0, 0x11 }, + { 0x8000c1, 0x00 }, + { 0x8000c2, 0x05 }, + { 0x8000c4, 0x00 }, + { 0x8000c6, 0x19 }, + { 0x8000c7, 0x00 }, + { 0x8000cc, 0x2e }, + { 0x8000cd, 0x51 }, + { 0x8000ce, 0x33 }, + { 0x8000f3, 0x05 }, + { 0x8000f4, 0x91 }, + { 0x8000f5, 0x8c }, + { 0x8000f8, 0x03 }, + { 0x8000f9, 0x06 }, + { 0x8000fa, 0x06 }, + { 0x8000fc, 0x03 }, + { 0x8000fd, 0x02 }, + { 0x8000fe, 0x02 }, + { 0x8000ff, 0x09 }, + { 0x800100, 0x50 }, + { 0x800101, 0x74 }, + { 0x800102, 0x77 }, + { 0x800103, 0x02 }, + { 0x800104, 0x02 }, + { 0x800105, 0xa4 }, + { 0x800106, 0x02 }, + { 0x800107, 0x6e }, + { 0x800109, 0x02 }, + { 0x800115, 0x0a }, + { 0x800116, 0x03 }, + { 0x800117, 0x02 }, + { 0x800118, 0x80 }, + { 0x80011a, 0xcd }, + { 0x80011b, 0x62 }, + { 0x80011c, 0xa4 }, + { 0x80011d, 0x8c }, + { 0x800122, 0x03 }, + { 0x800123, 0x18 }, + { 0x800124, 0x9e }, + { 0x800127, 0x00 }, + { 0x800128, 0x07 }, + { 0x80012a, 0x53 }, + { 0x80012b, 0x51 }, + { 0x80012c, 0x4e }, + { 0x80012d, 0x43 }, + { 0x800137, 0x00 }, + { 0x800138, 0x00 }, + { 0x800139, 0x07 }, + { 0x80013a, 0x00 }, + { 0x80013b, 0x06 }, + { 0x80013d, 0x00 }, + { 0x80013e, 0x01 }, + { 0x80013f, 0x5b }, + { 0x800140, 0xb6 }, + { 0x800141, 0x59 }, + { 0x80f000, 0x0f }, + { 0x80f016, 0x10 }, + { 0x80f017, 0x04 }, + { 0x80f018, 0x05 }, + { 0x80f019, 0x04 }, + { 0x80f01a, 0x05 }, + { 0x80f01f, 0x8c }, + { 0x80f020, 0x00 }, + { 0x80f021, 0x03 }, + { 0x80f022, 0x0a }, + { 0x80f023, 0x0a }, + { 0x80f029, 0x8c }, + { 0x80f02a, 0x00 }, + { 0x80f02b, 0x00 }, + { 0x80f02c, 0x01 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f077, 0x01 }, + { 0x80f078, 0x00 }, + { 0x80f085, 0xc0 }, + { 0x80f086, 0x01 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f24c, 0x88 }, + { 0x80f24d, 0x95 }, + { 0x80f24e, 0x9a }, + { 0x80f24f, 0x90 }, + { 0x80f25a, 0x07 }, + { 0x80f25b, 0xe8 }, + { 0x80f25c, 0x03 }, + { 0x80f25d, 0xb0 }, + { 0x80f25e, 0x04 }, + { 0x80f270, 0x01 }, + { 0x80f271, 0x02 }, + { 0x80f272, 0x01 }, + { 0x80f273, 0x02 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5df, 0xfb }, + { 0x80f5e0, 0x00 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f5f8, 0x01 }, + { 0x80f5fd, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; + +static const struct reg_val ofsm_init_it9135_v2[] = { + { 0x800051, 0x01 }, + { 0x800070, 0x0a }, + { 0x80007e, 0x04 }, + { 0x800081, 0x0a }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800099, 0x01 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000c2, 0x05 }, + { 0x8000c6, 0x19 }, + { 0x80f000, 0x0f }, + { 0x80f02b, 0x00 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f078, 0x00 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; + +/* ITE Tech IT9135 Omega v2 tuner init + AF9033_TUNER_IT9135_60 = 0x60 */ +static const struct reg_val tuner_init_it9135_60[] = { + { 0x800043, 0x00 }, + { 0x800046, 0x60 }, + { 0x800051, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800068, 0x0a }, + { 0x80006a, 0x03 }, + { 0x800070, 0x0a }, + { 0x800071, 0x05 }, + { 0x800072, 0x02 }, + { 0x800075, 0x8c }, + { 0x800076, 0x8c }, + { 0x800077, 0x8c }, + { 0x800078, 0x8c }, + { 0x800079, 0x01 }, + { 0x80007e, 0x04 }, + { 0x800081, 0x0a }, + { 0x800082, 0x18 }, + { 0x800084, 0x0a }, + { 0x800085, 0x33 }, + { 0x800086, 0xbe }, + { 0x800087, 0xa0 }, + { 0x800088, 0xc6 }, + { 0x800089, 0xb6 }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x00 }, + { 0x800099, 0x01 }, + { 0x80009b, 0x3c }, + { 0x80009c, 0x28 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a4, 0x5a }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000b3, 0x02 }, + { 0x8000b4, 0x3a }, + { 0x8000b6, 0x14 }, + { 0x8000c0, 0x11 }, + { 0x8000c1, 0x00 }, + { 0x8000c2, 0x05 }, + { 0x8000c3, 0x01 }, + { 0x8000c4, 0x00 }, + { 0x8000c6, 0x19 }, + { 0x8000c7, 0x00 }, + { 0x8000cb, 0x32 }, + { 0x8000cc, 0x2c }, + { 0x8000cd, 0x4f }, + { 0x8000ce, 0x30 }, + { 0x8000f3, 0x05 }, + { 0x8000f4, 0xa0 }, + { 0x8000f5, 0x8c }, + { 0x8000f8, 0x03 }, + { 0x8000f9, 0x06 }, + { 0x8000fa, 0x06 }, + { 0x8000fc, 0x03 }, + { 0x8000fd, 0x03 }, + { 0x8000fe, 0x02 }, + { 0x8000ff, 0x0a }, + { 0x800100, 0x50 }, + { 0x800101, 0x7b }, + { 0x800102, 0x8c }, + { 0x800103, 0x00 }, + { 0x800104, 0x02 }, + { 0x800105, 0xbe }, + { 0x800106, 0x00 }, + { 0x800109, 0x02 }, + { 0x800115, 0x0a }, + { 0x800116, 0x03 }, + { 0x80011a, 0xbe }, + { 0x800124, 0xae }, + { 0x800127, 0x00 }, + { 0x80012a, 0x56 }, + { 0x80012b, 0x50 }, + { 0x80012c, 0x47 }, + { 0x80012d, 0x42 }, + { 0x800137, 0x00 }, + { 0x80013b, 0x08 }, + { 0x80013f, 0x5b }, + { 0x800141, 0x59 }, + { 0x800142, 0xf9 }, + { 0x800143, 0x19 }, + { 0x800144, 0x00 }, + { 0x800145, 0x8c }, + { 0x800146, 0x8c }, + { 0x800147, 0x8c }, + { 0x800148, 0x6e }, + { 0x800149, 0x8c }, + { 0x80014a, 0x50 }, + { 0x80014b, 0x8c }, + { 0x80014d, 0xac }, + { 0x80014e, 0xc6 }, + { 0x80014f, 0x03 }, + { 0x800151, 0x1e }, + { 0x800153, 0xbc }, + { 0x800178, 0x09 }, + { 0x800181, 0x94 }, + { 0x800182, 0x6e }, + { 0x800185, 0x24 }, + { 0x800189, 0xbe }, + { 0x80018c, 0x03 }, + { 0x80018d, 0x5f }, + { 0x80018f, 0xa0 }, + { 0x800190, 0x5a }, + { 0x80ed02, 0xff }, + { 0x80ee42, 0xff }, + { 0x80ee82, 0xff }, + { 0x80f000, 0x0f }, + { 0x80f01f, 0x8c }, + { 0x80f020, 0x00 }, + { 0x80f029, 0x8c }, + { 0x80f02a, 0x00 }, + { 0x80f02b, 0x00 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f077, 0x01 }, + { 0x80f078, 0x00 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f24c, 0x88 }, + { 0x80f24d, 0x95 }, + { 0x80f24e, 0x9a }, + { 0x80f24f, 0x90 }, + { 0x80f25a, 0x07 }, + { 0x80f25b, 0xe8 }, + { 0x80f25c, 0x03 }, + { 0x80f25d, 0xb0 }, + { 0x80f25e, 0x04 }, + { 0x80f270, 0x01 }, + { 0x80f271, 0x02 }, + { 0x80f272, 0x01 }, + { 0x80f273, 0x02 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; +/* ITE Tech IT9135 Omega v2 LNA config 1 tuner init + AF9033_TUNER_IT9135_61 = 0x61 */ +static const struct reg_val tuner_init_it9135_61[] = { + { 0x800043, 0x00 }, + { 0x800046, 0x61 }, + { 0x800051, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800068, 0x06 }, + { 0x80006a, 0x03 }, + { 0x800070, 0x0a }, + { 0x800071, 0x05 }, + { 0x800072, 0x02 }, + { 0x800075, 0x8c }, + { 0x800076, 0x8c }, + { 0x800077, 0x8c }, + { 0x800078, 0x90 }, + { 0x800079, 0x01 }, + { 0x80007e, 0x04 }, + { 0x800081, 0x0a }, + { 0x800082, 0x12 }, + { 0x800084, 0x0a }, + { 0x800085, 0x33 }, + { 0x800086, 0xbc }, + { 0x800087, 0x9c }, + { 0x800088, 0xcc }, + { 0x800089, 0xa8 }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x00 }, + { 0x800099, 0x01 }, + { 0x80009b, 0x3c }, + { 0x80009c, 0x28 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a4, 0x5c }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000b3, 0x02 }, + { 0x8000b4, 0x3a }, + { 0x8000b6, 0x14 }, + { 0x8000c0, 0x11 }, + { 0x8000c1, 0x00 }, + { 0x8000c2, 0x05 }, + { 0x8000c3, 0x01 }, + { 0x8000c4, 0x00 }, + { 0x8000c6, 0x19 }, + { 0x8000c7, 0x00 }, + { 0x8000cb, 0x32 }, + { 0x8000cc, 0x2c }, + { 0x8000cd, 0x4f }, + { 0x8000ce, 0x30 }, + { 0x8000f3, 0x05 }, + { 0x8000f4, 0xa0 }, + { 0x8000f5, 0x8c }, + { 0x8000f8, 0x03 }, + { 0x8000f9, 0x06 }, + { 0x8000fa, 0x06 }, + { 0x8000fc, 0x03 }, + { 0x8000fd, 0x03 }, + { 0x8000fe, 0x02 }, + { 0x8000ff, 0x08 }, + { 0x800100, 0x50 }, + { 0x800101, 0x7b }, + { 0x800102, 0x8c }, + { 0x800103, 0x01 }, + { 0x800104, 0x02 }, + { 0x800105, 0xc8 }, + { 0x800106, 0x00 }, + { 0x800109, 0x02 }, + { 0x800115, 0x0a }, + { 0x800116, 0x03 }, + { 0x80011a, 0xc6 }, + { 0x800124, 0xa8 }, + { 0x800127, 0x00 }, + { 0x80012a, 0x59 }, + { 0x80012b, 0x50 }, + { 0x80012c, 0x47 }, + { 0x80012d, 0x42 }, + { 0x800137, 0x00 }, + { 0x80013b, 0x05 }, + { 0x80013f, 0x5b }, + { 0x800141, 0x59 }, + { 0x800142, 0xf9 }, + { 0x800143, 0x59 }, + { 0x800144, 0x01 }, + { 0x800145, 0x8c }, + { 0x800146, 0x8c }, + { 0x800147, 0x8c }, + { 0x800148, 0x7b }, + { 0x800149, 0x8c }, + { 0x80014a, 0x50 }, + { 0x80014b, 0x8c }, + { 0x80014d, 0xa8 }, + { 0x80014e, 0xc6 }, + { 0x80014f, 0x03 }, + { 0x800151, 0x28 }, + { 0x800153, 0xcc }, + { 0x800178, 0x09 }, + { 0x800181, 0x9c }, + { 0x800182, 0x76 }, + { 0x800185, 0x28 }, + { 0x800189, 0xaa }, + { 0x80018c, 0x03 }, + { 0x80018d, 0x5f }, + { 0x80018f, 0xfb }, + { 0x800190, 0x5c }, + { 0x80ed02, 0xff }, + { 0x80ee42, 0xff }, + { 0x80ee82, 0xff }, + { 0x80f000, 0x0f }, + { 0x80f01f, 0x8c }, + { 0x80f020, 0x00 }, + { 0x80f029, 0x8c }, + { 0x80f02a, 0x00 }, + { 0x80f02b, 0x00 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f077, 0x01 }, + { 0x80f078, 0x00 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f24c, 0x88 }, + { 0x80f24d, 0x95 }, + { 0x80f24e, 0x9a }, + { 0x80f24f, 0x90 }, + { 0x80f25a, 0x07 }, + { 0x80f25b, 0xe8 }, + { 0x80f25c, 0x03 }, + { 0x80f25d, 0xb0 }, + { 0x80f25e, 0x04 }, + { 0x80f270, 0x01 }, + { 0x80f271, 0x02 }, + { 0x80f272, 0x01 }, + { 0x80f273, 0x02 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; + +/* ITE Tech IT9135 Omega v2 LNA config 2 tuner init + AF9033_TUNER_IT9135_62 = 0x62 */ +static const struct reg_val tuner_init_it9135_62[] = { + { 0x800043, 0x00 }, + { 0x800046, 0x62 }, + { 0x800051, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800068, 0x0a }, + { 0x80006a, 0x03 }, + { 0x800070, 0x0a }, + { 0x800071, 0x05 }, + { 0x800072, 0x02 }, + { 0x800075, 0x8c }, + { 0x800076, 0x8c }, + { 0x800077, 0x8c }, + { 0x800078, 0x8c }, + { 0x800079, 0x01 }, + { 0x80007e, 0x04 }, + { 0x800081, 0x0a }, + { 0x800082, 0x12 }, + { 0x800084, 0x0a }, + { 0x800085, 0x33 }, + { 0x800086, 0xb8 }, + { 0x800087, 0x9c }, + { 0x800088, 0xb2 }, + { 0x800089, 0xa6 }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x00 }, + { 0x800099, 0x01 }, + { 0x80009b, 0x3c }, + { 0x80009c, 0x28 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a4, 0x5a }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000b3, 0x02 }, + { 0x8000b4, 0x3a }, + { 0x8000b6, 0x14 }, + { 0x8000c0, 0x11 }, + { 0x8000c1, 0x00 }, + { 0x8000c2, 0x05 }, + { 0x8000c3, 0x01 }, + { 0x8000c4, 0x00 }, + { 0x8000c6, 0x19 }, + { 0x8000c7, 0x00 }, + { 0x8000cb, 0x32 }, + { 0x8000cc, 0x2c }, + { 0x8000cd, 0x4f }, + { 0x8000ce, 0x30 }, + { 0x8000f3, 0x05 }, + { 0x8000f4, 0x8c }, + { 0x8000f5, 0x8c }, + { 0x8000f8, 0x03 }, + { 0x8000f9, 0x06 }, + { 0x8000fa, 0x06 }, + { 0x8000fc, 0x02 }, + { 0x8000fd, 0x03 }, + { 0x8000fe, 0x02 }, + { 0x8000ff, 0x09 }, + { 0x800100, 0x50 }, + { 0x800101, 0x6e }, + { 0x800102, 0x8c }, + { 0x800103, 0x02 }, + { 0x800104, 0x02 }, + { 0x800105, 0xc2 }, + { 0x800106, 0x00 }, + { 0x800109, 0x02 }, + { 0x800115, 0x0a }, + { 0x800116, 0x03 }, + { 0x80011a, 0xb8 }, + { 0x800124, 0xa8 }, + { 0x800127, 0x00 }, + { 0x80012a, 0x53 }, + { 0x80012b, 0x51 }, + { 0x80012c, 0x4e }, + { 0x80012d, 0x43 }, + { 0x800137, 0x00 }, + { 0x80013b, 0x05 }, + { 0x80013f, 0x5b }, + { 0x800141, 0x59 }, + { 0x800142, 0xf9 }, + { 0x800143, 0x59 }, + { 0x800144, 0x00 }, + { 0x800145, 0x8c }, + { 0x800146, 0x8c }, + { 0x800147, 0x8c }, + { 0x800148, 0x7b }, + { 0x800149, 0x8c }, + { 0x80014a, 0x50 }, + { 0x80014b, 0x70 }, + { 0x80014d, 0x96 }, + { 0x80014e, 0xd0 }, + { 0x80014f, 0x03 }, + { 0x800151, 0x28 }, + { 0x800153, 0xb2 }, + { 0x800178, 0x09 }, + { 0x800181, 0x9c }, + { 0x800182, 0x6e }, + { 0x800185, 0x24 }, + { 0x800189, 0xb8 }, + { 0x80018c, 0x03 }, + { 0x80018d, 0x5f }, + { 0x80018f, 0xfb }, + { 0x800190, 0x5a }, + { 0x80ed02, 0xff }, + { 0x80ee42, 0xff }, + { 0x80ee82, 0xff }, + { 0x80f000, 0x0f }, + { 0x80f01f, 0x8c }, + { 0x80f020, 0x00 }, + { 0x80f029, 0x8c }, + { 0x80f02a, 0x00 }, + { 0x80f02b, 0x00 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f077, 0x01 }, + { 0x80f078, 0x00 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f24c, 0x88 }, + { 0x80f24d, 0x95 }, + { 0x80f24e, 0x9a }, + { 0x80f24f, 0x90 }, + { 0x80f25a, 0x07 }, + { 0x80f25b, 0xe8 }, + { 0x80f25c, 0x03 }, + { 0x80f25d, 0xb0 }, + { 0x80f25e, 0x04 }, + { 0x80f270, 0x01 }, + { 0x80f271, 0x02 }, + { 0x80f272, 0x01 }, + { 0x80f273, 0x02 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; + +#endif /* AF9033_PRIV_H */ diff --git a/drivers/media/dvb-frontends/atbm8830.h b/drivers/media/dvb-frontends/atbm8830.h index 0242733..8e0ac98 100644 --- a/drivers/media/dvb-frontends/atbm8830.h +++ b/drivers/media/dvb-frontends/atbm8830.h @@ -22,6 +22,7 @@ #ifndef __ATBM8830_H__ #define __ATBM8830_H__ +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include <linux/i2c.h> @@ -60,8 +61,7 @@ struct atbm8830_config { u8 agc_hold_loop; }; -#if defined(CONFIG_DVB_ATBM8830) || \ - (defined(CONFIG_DVB_ATBM8830_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_ATBM8830) extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h index 565dcf3..83fe9a6 100644 --- a/drivers/media/dvb-frontends/au8522.h +++ b/drivers/media/dvb-frontends/au8522.h @@ -22,6 +22,7 @@ #ifndef __AU8522_H__ #define __AU8522_H__ +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> enum au8522_if_freq { @@ -60,8 +61,7 @@ struct au8522_config { enum au8522_if_freq qam_if; }; -#if defined(CONFIG_DVB_AU8522) || \ - (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_AU8522_DTV) extern struct dvb_frontend *au8522_attach(const struct au8522_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 5243ba6..2099f21 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -229,15 +229,11 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode) /* Provide reasonable defaults for picture tuning values */ au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07); au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed); - state->brightness = 0xed - 128; au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79); - state->contrast = 0x79; au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80); au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80); - state->saturation = 0x80; au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00); au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00); - state->hue = 0x00; /* Other decoder registers */ au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00); @@ -489,75 +485,32 @@ static void set_audio_input(struct au8522_state *state, int aud_input) /* ----------------------------------------------------------------------- */ -static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +static int au8522_s_ctrl(struct v4l2_ctrl *ctrl) { - struct au8522_state *state = to_state(sd); + struct au8522_state *state = + container_of(ctrl->handler, struct au8522_state, hdl); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - state->brightness = ctrl->value; au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, - ctrl->value - 128); + ctrl->val - 128); break; case V4L2_CID_CONTRAST: - state->contrast = ctrl->value; au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, - ctrl->value); + ctrl->val); break; case V4L2_CID_SATURATION: - state->saturation = ctrl->value; au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, - ctrl->value); + ctrl->val); au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, - ctrl->value); + ctrl->val); break; case V4L2_CID_HUE: - state->hue = ctrl->value; au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, - ctrl->value >> 8); + ctrl->val >> 8); au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, - ctrl->value & 0xFF); - break; - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_MUTE: - /* Not yet implemented */ - default: - return -EINVAL; - } - - return 0; -} - -static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct au8522_state *state = to_state(sd); - - /* Note that we are using values cached in the state structure instead - of reading the registers due to issues with i2c reads not working - properly/consistently yet on the HVR-950q */ - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = state->brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = state->contrast; + ctrl->val & 0xFF); break; - case V4L2_CID_SATURATION: - ctrl->value = state->saturation; - break; - case V4L2_CID_HUE: - ctrl->value = state->hue; - break; - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_MUTE: - /* Not yet supported */ default: return -EINVAL; } @@ -583,7 +536,7 @@ static int au8522_g_register(struct v4l2_subdev *sd, } static int au8522_s_register(struct v4l2_subdev *sd, - struct v4l2_dbg_register *reg) + const struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct au8522_state *state = to_state(sd); @@ -616,26 +569,6 @@ static int au8522_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) -{ - switch (qc->id) { - case V4L2_CID_CONTRAST: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, - AU8522_TVDEC_CONTRAST_REG00BH_CVBS); - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109); - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0); - default: - break; - } - - qc->type = 0; - return -EINVAL; -} - static int au8522_reset(struct v4l2_subdev *sd, u32 val) { struct au8522_state *state = to_state(sd); @@ -712,20 +645,11 @@ static int au8522_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); } -static int au8522_log_status(struct v4l2_subdev *sd) -{ - /* FIXME: Add some status info here */ - return 0; -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops au8522_core_ops = { - .log_status = au8522_log_status, + .log_status = v4l2_ctrl_subdev_log_status, .g_chip_ident = au8522_g_chip_ident, - .g_ctrl = au8522_g_ctrl, - .s_ctrl = au8522_s_ctrl, - .queryctrl = au8522_queryctrl, .reset = au8522_reset, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = au8522_g_register, @@ -753,12 +677,17 @@ static const struct v4l2_subdev_ops au8522_ops = { .video = &au8522_video_ops, }; +static const struct v4l2_ctrl_ops au8522_ctrl_ops = { + .s_ctrl = au8522_s_ctrl, +}; + /* ----------------------------------------------------------------------- */ static int au8522_probe(struct i2c_client *client, const struct i2c_device_id *did) { struct au8522_state *state; + struct v4l2_ctrl_handler *hdl; struct v4l2_subdev *sd; int instance; struct au8522_config *demod_config; @@ -799,6 +728,27 @@ static int au8522_probe(struct i2c_client *client, sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &au8522_ops); + hdl = &state->hdl; + v4l2_ctrl_handler_init(hdl, 4); + v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 255, 1, 109); + v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, + AU8522_TVDEC_CONTRAST_REG00BH_CVBS); + v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 128); + v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops, + V4L2_CID_HUE, -32768, 32767, 1, 0); + sd->ctrl_handler = hdl; + if (hdl->error) { + int err = hdl->error; + + v4l2_ctrl_handler_free(hdl); + kfree(demod_config); + kfree(state); + return err; + } + state->c = client; state->vid_input = AU8522_COMPOSITE_CH1; state->aud_input = AU8522_AUDIO_NONE; @@ -815,6 +765,7 @@ static int au8522_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(sd->ctrl_handler); au8522_release_state(to_state(sd)); return 0; } diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h index 0529699..aa0f16d 100644 --- a/drivers/media/dvb-frontends/au8522_priv.h +++ b/drivers/media/dvb-frontends/au8522_priv.h @@ -29,6 +29,7 @@ #include <linux/delay.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> #include <linux/i2c.h> #include "dvb_frontend.h" #include "au8522.h" @@ -65,10 +66,7 @@ struct au8522_state { int aud_input; u32 id; u32 rev; - u8 brightness; - u8 contrast; - u8 saturation; - s16 hue; + struct v4l2_ctrl_handler hdl; }; /* These are routines shared by both the VSB/QAM demodulator and the analog diff --git a/drivers/media/dvb-frontends/cx22702.h b/drivers/media/dvb-frontends/cx22702.h index f154e1f..0b1a6c2 100644 --- a/drivers/media/dvb-frontends/cx22702.h +++ b/drivers/media/dvb-frontends/cx22702.h @@ -28,6 +28,7 @@ #ifndef CX22702_H #define CX22702_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct cx22702_config { @@ -40,8 +41,7 @@ struct cx22702_config { u8 output_mode; }; -#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_CX22702) extern struct dvb_frontend *cx22702_attach( const struct cx22702_config *config, struct i2c_adapter *i2c); diff --git a/drivers/media/dvb-frontends/cx24113.h b/drivers/media/dvb-frontends/cx24113.h index 01eb7b9..782711ba 100644 --- a/drivers/media/dvb-frontends/cx24113.h +++ b/drivers/media/dvb-frontends/cx24113.h @@ -22,6 +22,8 @@ #ifndef CX24113_H #define CX24113_H +#include <linux/kconfig.h> + struct dvb_frontend; struct cx24113_config { @@ -30,8 +32,7 @@ struct cx24113_config { u32 xtal_khz; }; -#if defined(CONFIG_DVB_TUNER_CX24113) || \ - (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_TUNER_CX24113) extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *, const struct cx24113_config *config, struct i2c_adapter *i2c); diff --git a/drivers/media/dvb-frontends/cx24116.h b/drivers/media/dvb-frontends/cx24116.h index 7d90ab9..2ec84fa 100644 --- a/drivers/media/dvb-frontends/cx24116.h +++ b/drivers/media/dvb-frontends/cx24116.h @@ -21,6 +21,7 @@ #ifndef CX24116_H #define CX24116_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct cx24116_config { @@ -40,8 +41,7 @@ struct cx24116_config { u16 i2c_wr_max; }; -#if defined(CONFIG_DVB_CX24116) || \ - (defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_CX24116) extern struct dvb_frontend *cx24116_attach( const struct cx24116_config *config, struct i2c_adapter *i2c); diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c index 68c88ab..a771da3 100644 --- a/drivers/media/dvb-frontends/cx24123.c +++ b/drivers/media/dvb-frontends/cx24123.c @@ -26,6 +26,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <asm/div64.h> #include "dvb_frontend.h" #include "cx24123.h" @@ -452,7 +453,8 @@ static u32 cx24123_int_log2(u32 a, u32 b) static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate) { - u32 tmp, sample_rate, ratio, sample_gain; + u64 tmp; + u32 sample_rate, ratio, sample_gain; u8 pll_mult; /* check if symbol rate is within limits */ @@ -482,27 +484,11 @@ static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate) sample_rate = pll_mult * XTAL; - /* - SYSSymbolRate[21:0] = (srate << 23) / sample_rate - - We have to use 32 bit unsigned arithmetic without precision loss. - The maximum srate is 45000000 or 0x02AEA540. This number has - only 6 clear bits on top, hence we can shift it left only 6 bits - at a time. Borrowed from cx24110.c - */ - - tmp = srate << 6; - ratio = tmp / sample_rate; - - tmp = (tmp % sample_rate) << 6; - ratio = (ratio << 6) + (tmp / sample_rate); - - tmp = (tmp % sample_rate) << 6; - ratio = (ratio << 6) + (tmp / sample_rate); - - tmp = (tmp % sample_rate) << 5; - ratio = (ratio << 5) + (tmp / sample_rate); + /* SYSSymbolRate[21:0] = (srate << 23) / sample_rate */ + tmp = ((u64)srate) << 23; + do_div(tmp, sample_rate); + ratio = (u32) tmp; cx24123_writereg(state, 0x01, pll_mult * 6); diff --git a/drivers/media/dvb-frontends/cx24123.h b/drivers/media/dvb-frontends/cx24123.h index 51ae866..102e70d 100644 --- a/drivers/media/dvb-frontends/cx24123.h +++ b/drivers/media/dvb-frontends/cx24123.h @@ -21,6 +21,7 @@ #ifndef CX24123_H #define CX24123_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct cx24123_config { @@ -38,8 +39,7 @@ struct cx24123_config { void (*agc_callback) (struct dvb_frontend *); }; -#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_CX24123) extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config, struct i2c_adapter *i2c); extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *); diff --git a/drivers/media/dvb-frontends/cxd2820r.h b/drivers/media/dvb-frontends/cxd2820r.h index 6acc21c..82b3d93 100644 --- a/drivers/media/dvb-frontends/cxd2820r.h +++ b/drivers/media/dvb-frontends/cxd2820r.h @@ -22,6 +22,7 @@ #ifndef CXD2820R_H #define CXD2820R_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #define CXD2820R_GPIO_D (0 << 0) /* disable */ @@ -65,8 +66,7 @@ struct cxd2820r_config { }; -#if defined(CONFIG_DVB_CXD2820R) || \ - (defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_CXD2820R) extern struct dvb_frontend *cxd2820r_attach( const struct cxd2820r_config *config, struct i2c_adapter *i2c, diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 9b658c1..7ca5c69 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -660,7 +660,8 @@ static const struct dvb_frontend_ops cxd2820r_ops = { FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | FE_CAN_MUTE_TS | - FE_CAN_2G_MODULATION + FE_CAN_2G_MODULATION | + FE_CAN_MULTISTREAM }, .release = cxd2820r_release, diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index e82d82a..2ba130e 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -124,6 +124,23 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) buf[1] = ((if_ctl >> 8) & 0xff); buf[2] = ((if_ctl >> 0) & 0xff); + /* PLP filtering */ + if (c->stream_id > 255) { + dev_dbg(&priv->i2c->dev, "%s: Disable PLP filtering\n", __func__); + ret = cxd2820r_wr_reg(priv, 0x023ad , 0); + if (ret) + goto error; + } else { + dev_dbg(&priv->i2c->dev, "%s: Enable PLP filtering = %d\n", __func__, + c->stream_id); + ret = cxd2820r_wr_reg(priv, 0x023af , c->stream_id & 0xFF); + if (ret) + goto error; + ret = cxd2820r_wr_reg(priv, 0x023ad , 1); + if (ret) + goto error; + } + ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3); if (ret) goto error; diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c index d9fe60b..3ee22ff 100644 --- a/drivers/media/dvb-frontends/dib0090.c +++ b/drivers/media/dvb-frontends/dib0090.c @@ -528,20 +528,19 @@ static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_ u16 PllCfg, i, v; HARD_RESET(state); - dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL); - dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */ + if (cfg->in_soc) + return; - if (!cfg->in_soc) { - /* adcClkOutRatio=8->7, release reset */ - dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0); - if (cfg->clkoutdrive != 0) - dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8) - | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0)); - else - dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8) - | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0)); - } + dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */ + /* adcClkOutRatio=8->7, release reset */ + dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0); + if (cfg->clkoutdrive != 0) + dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8) + | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0)); + else + dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8) + | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0)); /* Read Pll current config * */ PllCfg = dib0090_read_reg(state, 0x21); @@ -694,192 +693,174 @@ void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) EXPORT_SYMBOL(dib0090_dcc_freq); static const u16 bb_ramp_pwm_normal_socs[] = { - 550, /* max BB gain in 10th of dB */ - (1 << 9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */ + 550, /* max BB gain in 10th of dB */ + (1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */ 440, - (4 << 9) | 0, /* BB_RAMP3 = 26dB */ - (0 << 9) | 208, /* BB_RAMP4 */ - (4 << 9) | 208, /* BB_RAMP5 = 29dB */ - (0 << 9) | 440, /* BB_RAMP6 */ + (4 << 9) | 0, /* BB_RAMP3 = 26dB */ + (0 << 9) | 208, /* BB_RAMP4 */ + (4 << 9) | 208, /* BB_RAMP5 = 29dB */ + (0 << 9) | 440, /* BB_RAMP6 */ }; -static const u16 rf_ramp_pwm_cband_7090[] = { - 280, /* max RF gain in 10th of dB */ - 18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ - 504, /* ramp_max = maximum X used on the ramp */ - (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */ - (0 << 10) | 504, /* RF_RAMP6, LNA 1 */ - (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */ - (0 << 10) | 364, /* RF_RAMP8, LNA 2 */ - (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */ - (0 << 10) | 228, /* GAIN_4_2, LNA 3 */ - (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ - (0 << 10) | 109, /* RF_RAMP4, LNA 4 */ +static const u16 rf_ramp_pwm_cband_7090p[] = { + 280, /* max RF gain in 10th of dB */ + 18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 504, /* ramp_max = maximum X used on the ramp */ + (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */ + (0 << 10) | 504, /* RF_RAMP6, LNA 1 */ + (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */ + (0 << 10) | 364, /* RF_RAMP8, LNA 2 */ + (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */ + (0 << 10) | 228, /* GAIN_4_2, LNA 3 */ + (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ + (0 << 10) | 109, /* RF_RAMP4, LNA 4 */ }; -static const uint16_t rf_ramp_pwm_cband_7090e_sensitivity[] = { - 186, - 40, - 746, - (10 << 10) | 345, - (0 << 10) | 746, - (0 << 10) | 0, - (0 << 10) | 0, - (28 << 10) | 200, - (0 << 10) | 345, - (20 << 10) | 0, - (0 << 10) | 200, +static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = { + 186, /* max RF gain in 10th of dB */ + 40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 746, /* ramp_max = maximum X used on the ramp */ + (10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */ + (0 << 10) | 746, /* RF_RAMP6, LNA 1 */ + (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */ + (0 << 10) | 0, /* RF_RAMP8, LNA 2 */ + (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */ + (0 << 10) | 345, /* GAIN_4_2, LNA 3 */ + (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */ + (0 << 10) | 200, /* RF_RAMP4, LNA 4 */ }; -static const uint16_t rf_ramp_pwm_cband_7090e_aci[] = { - 86, - 40, - 345, - (0 << 10) | 0, - (0 << 10) | 0, - (0 << 10) | 0, - (0 << 10) | 0, - (28 << 10) | 200, - (0 << 10) | 345, - (20 << 10) | 0, - (0 << 10) | 200, +static const u16 rf_ramp_pwm_cband_7090e_aci[] = { + 86, /* max RF gain in 10th of dB */ + 40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 345, /* ramp_max = maximum X used on the ramp */ + (0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */ + (0 << 10) | 0, /* RF_RAMP6, LNA 1 */ + (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */ + (0 << 10) | 0, /* RF_RAMP8, LNA 2 */ + (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */ + (0 << 10) | 345, /* GAIN_4_2, LNA 3 */ + (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */ + (0 << 10) | 200, /* RF_RAMP4, LNA 4 */ }; static const u16 rf_ramp_pwm_cband_8090[] = { - 345, /* max RF gain in 10th of dB */ - 29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ - 1000, /* ramp_max = maximum X used on the ramp */ - (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */ - (0 << 10) | 1000, /* RF_RAMP4, LNA 1 */ - (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */ - (0 << 10) | 772, /* RF_RAMP6, LNA 2 */ - (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */ - (0 << 10) | 496, /* RF_RAMP8, LNA 3 */ - (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */ - (0 << 10) | 200, /* GAIN_4_2, LNA 4 */ + 345, /* max RF gain in 10th of dB */ + 29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 1000, /* ramp_max = maximum X used on the ramp */ + (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */ + (0 << 10) | 1000, /* RF_RAMP4, LNA 1 */ + (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */ + (0 << 10) | 772, /* RF_RAMP6, LNA 2 */ + (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */ + (0 << 10) | 496, /* RF_RAMP8, LNA 3 */ + (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */ + (0 << 10) | 200, /* GAIN_4_2, LNA 4 */ }; static const u16 rf_ramp_pwm_uhf_7090[] = { - 407, /* max RF gain in 10th of dB */ - 13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ - 529, /* ramp_max = maximum X used on the ramp */ - (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */ - (0 << 10) | 176, /* RF_RAMP4, LNA 1 */ - (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */ - (0 << 10) | 529, /* RF_RAMP6, LNA 2 */ - (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */ - (0 << 10) | 400, /* RF_RAMP8, LNA 3 */ - (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */ - (0 << 10) | 316, /* GAIN_4_2, LNA 4 */ + 407, /* max RF gain in 10th of dB */ + 13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 529, /* ramp_max = maximum X used on the ramp */ + (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */ + (0 << 10) | 176, /* RF_RAMP4, LNA 1 */ + (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */ + (0 << 10) | 529, /* RF_RAMP6, LNA 2 */ + (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */ + (0 << 10) | 400, /* RF_RAMP8, LNA 3 */ + (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */ + (0 << 10) | 316, /* GAIN_4_2, LNA 4 */ }; static const u16 rf_ramp_pwm_uhf_8090[] = { - 388, /* max RF gain in 10th of dB */ - 26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ - 1008, /* ramp_max = maximum X used on the ramp */ - (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */ - (0 << 10) | 369, /* RF_RAMP4, LNA 1 */ - (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */ - (0 << 10) | 1008, /* RF_RAMP6, LNA 2 */ - (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */ - (0 << 10) | 809, /* RF_RAMP8, LNA 3 */ - (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */ - (0 << 10) | 659, /* GAIN_4_2, LNA 4 */ + 388, /* max RF gain in 10th of dB */ + 26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 1008, /* ramp_max = maximum X used on the ramp */ + (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */ + (0 << 10) | 369, /* RF_RAMP4, LNA 1 */ + (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */ + (0 << 10) | 1008, /* RF_RAMP6, LNA 2 */ + (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */ + (0 << 10) | 809, /* RF_RAMP8, LNA 3 */ + (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */ + (0 << 10) | 659, /* GAIN_4_2, LNA 4 */ }; -static const u16 rf_ramp_pwm_cband[] = { - 0, /* max RF gain in 10th of dB */ - 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ - 0, /* ramp_max = maximum X used on the ramp */ - (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */ - (0 << 10) | 0, /* 0x2d, LNA 1 */ - (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */ - (0 << 10) | 0, /* 0x2f, LNA 2 */ - (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */ - (0 << 10) | 0, /* 0x31, LNA 3 */ - (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */ - (0 << 10) | 0, /* GAIN_4_2, LNA 4 */ -}; - -static const u16 rf_ramp_vhf[] = { - 412, /* max RF gain in 10th of dB */ - 132, 307, 127, /* LNA1, 13.2dB */ - 105, 412, 255, /* LNA2, 10.5dB */ - 50, 50, 127, /* LNA3, 5dB */ - 125, 175, 127, /* LNA4, 12.5dB */ - 0, 0, 127, /* CBAND, 0dB */ -}; - -static const u16 rf_ramp_uhf[] = { - 412, /* max RF gain in 10th of dB */ - 132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */ - 105, 412, 255, /* LNA2 : 10.5 dB */ - 50, 50, 127, /* LNA3 : 5.0 dB */ - 125, 175, 127, /* LNA4 : 12.5 dB */ - 0, 0, 127, /* CBAND : 0.0 dB */ +/* GENERAL PWM ramp definition for all other Krosus */ +static const u16 bb_ramp_pwm_normal[] = { + 500, /* max BB gain in 10th of dB */ + 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */ + 400, + (2 << 9) | 0, /* BB_RAMP3 = 21dB */ + (0 << 9) | 168, /* BB_RAMP4 */ + (2 << 9) | 168, /* BB_RAMP5 = 29dB */ + (0 << 9) | 400, /* BB_RAMP6 */ }; -static const u16 rf_ramp_cband_broadmatching[] = /* for p1G only */ -{ - 314, /* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */ - 84, 314, 127, /* LNA1 */ - 80, 230, 255, /* LNA2 */ - 80, 150, 127, /* LNA3 It was measured 12dB, do not lock if 120 */ - 70, 70, 127, /* LNA4 */ - 0, 0, 127, /* CBAND */ +static const u16 bb_ramp_pwm_boost[] = { + 550, /* max BB gain in 10th of dB */ + 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */ + 440, + (2 << 9) | 0, /* BB_RAMP3 = 26dB */ + (0 << 9) | 208, /* BB_RAMP4 */ + (2 << 9) | 208, /* BB_RAMP5 = 29dB */ + (0 << 9) | 440, /* BB_RAMP6 */ }; -static const u16 rf_ramp_cband[] = { - 332, /* max RF gain in 10th of dB */ - 132, 252, 127, /* LNA1, dB */ - 80, 332, 255, /* LNA2, dB */ - 0, 0, 127, /* LNA3, dB */ - 0, 0, 127, /* LNA4, dB */ - 120, 120, 127, /* LT1 CBAND */ +static const u16 rf_ramp_pwm_cband[] = { + 314, /* max RF gain in 10th of dB */ + 33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 1023, /* ramp_max = maximum X used on the ramp */ + (8 << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */ + (0 << 10) | 1023, /* RF_RAMP4, LNA 1 */ + (15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */ + (0 << 10) | 742, /* RF_RAMP6, LNA 2 */ + (9 << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */ + (0 << 10) | 468, /* RF_RAMP8, LNA 3 */ + (9 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */ + (0 << 10) | 233, /* GAIN_4_2, LNA 4 */ }; static const u16 rf_ramp_pwm_vhf[] = { - 404, /* max RF gain in 10th of dB */ - 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ - 1011, /* ramp_max = maximum X used on the ramp */ - (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */ - (0 << 10) | 756, /* 0x2d, LNA 1 */ - (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */ - (0 << 10) | 1011, /* 0x2f, LNA 2 */ - (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */ - (0 << 10) | 417, /* 0x31, LNA 3 */ - (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */ - (0 << 10) | 290, /* GAIN_4_2, LNA 4 */ + 398, /* max RF gain in 10th of dB */ + 24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 954, /* ramp_max = maximum X used on the ramp */ + (7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */ + (0 << 10) | 290, /* RF_RAMP4, LNA 1 */ + (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */ + (0 << 10) | 954, /* RF_RAMP6, LNA 2 */ + (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */ + (0 << 10) | 699, /* RF_RAMP8, LNA 3 */ + (7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */ + (0 << 10) | 580, /* GAIN_4_2, LNA 4 */ }; static const u16 rf_ramp_pwm_uhf[] = { - 404, /* max RF gain in 10th of dB */ - 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ - 1011, /* ramp_max = maximum X used on the ramp */ - (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */ - (0 << 10) | 756, /* 0x2d, LNA 1 */ - (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */ - (0 << 10) | 1011, /* 0x2f, LNA 2 */ - (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */ - (0 << 10) | 127, /* 0x31, LNA 3 */ - (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */ - (0 << 10) | 417, /* GAIN_4_2, LNA 4 */ + 398, /* max RF gain in 10th of dB */ + 24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 954, /* ramp_max = maximum X used on the ramp */ + (7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */ + (0 << 10) | 290, /* RF_RAMP4, LNA 1 */ + (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */ + (0 << 10) | 954, /* RF_RAMP6, LNA 2 */ + (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */ + (0 << 10) | 699, /* RF_RAMP8, LNA 3 */ + (7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */ + (0 << 10) | 580, /* GAIN_4_2, LNA 4 */ }; -static const u16 bb_ramp_boost[] = { - 550, /* max BB gain in 10th of dB */ - 260, 260, 26, /* BB1, 26dB */ - 290, 550, 29, /* BB2, 29dB */ -}; - -static const u16 bb_ramp_pwm_normal[] = { - 500, /* max RF gain in 10th of dB */ - 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */ - 400, - (2 << 9) | 0, /* 0x35 = 21dB */ - (0 << 9) | 168, /* 0x36 */ - (2 << 9) | 168, /* 0x37 = 29dB */ - (0 << 9) | 400, /* 0x38 */ +static const u16 rf_ramp_pwm_sband[] = { + 253, /* max RF gain in 10th of dB */ + 38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ + 961, + (4 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */ + (0 << 10) | 508, /* RF_RAMP4, LNA 1 */ + (9 << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */ + (0 << 10) | 961, /* RF_RAMP6, LNA 2 */ + (0 << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */ + (0 << 10) | 0, /* RF_RAMP8, LNA 3 */ + (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */ + (0 << 10) | 0, /* GAIN_4_2, LNA 4 */ }; struct slope { @@ -1089,70 +1070,69 @@ static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg) void dib0090_pwm_gain_reset(struct dvb_frontend *fe) { struct dib0090_state *state = fe->tuner_priv; - /* reset the AGC */ + u16 *bb_ramp = (u16 *)&bb_ramp_pwm_normal; /* default baseband config */ + u16 *rf_ramp = NULL; + u8 en_pwm_rf_mux = 1; + /* reset the AGC */ if (state->config->use_pwm_agc) { -#ifdef CONFIG_BAND_SBAND - if (state->current_band == BAND_SBAND) { - dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband); - dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost); - } else -#endif -#ifdef CONFIG_BAND_CBAND if (state->current_band == BAND_CBAND) { if (state->identity.in_soc) { - dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs); + bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs; if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1) - dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090); - else if (state->identity.version == SOC_7090_P1G_11R1 - || state->identity.version == SOC_7090_P1G_21R1) { + rf_ramp = (u16 *)&rf_ramp_pwm_cband_8090; + else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) { if (state->config->is_dib7090e) { if (state->rf_ramp == NULL) - dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090e_sensitivity); + rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090e_sensitivity; else - dib0090_set_rframp_pwm(state, state->rf_ramp); + rf_ramp = (u16 *)state->rf_ramp; } else - dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090); + rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090p; } - } else { - dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband); - dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); - } + } else + rf_ramp = (u16 *)&rf_ramp_pwm_cband; } else -#endif -#ifdef CONFIG_BAND_VHF - if (state->current_band == BAND_VHF) { - if (state->identity.in_soc) { - dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs); - } else { - dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf); - dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); + + if (state->current_band == BAND_VHF) { + if (state->identity.in_soc) { + bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs; + /* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */ + } else + rf_ramp = (u16 *)&rf_ramp_pwm_vhf; + } else if (state->current_band == BAND_UHF) { + if (state->identity.in_soc) { + bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs; + if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1) + rf_ramp = (u16 *)&rf_ramp_pwm_uhf_8090; + else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) + rf_ramp = (u16 *)&rf_ramp_pwm_uhf_7090; + } else + rf_ramp = (u16 *)&rf_ramp_pwm_uhf; } + if (rf_ramp) + dib0090_set_rframp_pwm(state, rf_ramp); + dib0090_set_bbramp_pwm(state, bb_ramp); + + /* activate the ramp generator using PWM control */ + dprintk("ramp RF gain = %d BAND = %s version = %d", state->rf_ramp[0], (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", state->identity.version & 0x1f); + + if ((state->rf_ramp[0] == 0) || (state->current_band == BAND_CBAND && (state->identity.version & 0x1f) <= P1D_E_F)) { + dprintk("DE-Engage mux for direct gain reg control"); + en_pwm_rf_mux = 0; } else -#endif - { - if (state->identity.in_soc) { - if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1) - dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090); - else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) - dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090); - dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs); - } else { - dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf); - dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); - } - } + dprintk("Engage mux for PWM control"); - if (state->rf_ramp[0] != 0) - dib0090_write_reg(state, 0x32, (3 << 11)); - else - dib0090_write_reg(state, 0x32, (0 << 11)); + dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11)); - dib0090_write_reg(state, 0x04, 0x03); - dib0090_write_reg(state, 0x39, (1 << 10)); + /* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/ + if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) + dib0090_write_reg(state, 0x04, 3); + else + dib0090_write_reg(state, 0x04, 1); + dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */ } } - EXPORT_SYMBOL(dib0090_pwm_gain_reset); void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff) @@ -1193,22 +1173,22 @@ int dib0090_gain_control(struct dvb_frontend *fe) #endif #ifdef CONFIG_BAND_VHF if (state->current_band == BAND_VHF && !state->identity.p1g) { - dib0090_set_rframp(state, rf_ramp_vhf); - dib0090_set_bbramp(state, bb_ramp_boost); + dib0090_set_rframp(state, rf_ramp_pwm_vhf); + dib0090_set_bbramp(state, bb_ramp_pwm_normal); } else #endif #ifdef CONFIG_BAND_CBAND if (state->current_band == BAND_CBAND && !state->identity.p1g) { - dib0090_set_rframp(state, rf_ramp_cband); - dib0090_set_bbramp(state, bb_ramp_boost); + dib0090_set_rframp(state, rf_ramp_pwm_cband); + dib0090_set_bbramp(state, bb_ramp_pwm_normal); } else #endif if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) { - dib0090_set_rframp(state, rf_ramp_cband_broadmatching); - dib0090_set_bbramp(state, bb_ramp_boost); + dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p); + dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs); } else { - dib0090_set_rframp(state, rf_ramp_uhf); - dib0090_set_bbramp(state, bb_ramp_boost); + dib0090_set_rframp(state, rf_ramp_pwm_uhf); + dib0090_set_bbramp(state, bb_ramp_pwm_normal); } dib0090_write_reg(state, 0x32, 0); @@ -1553,14 +1533,16 @@ static void dib0090_set_EFUSE(struct dib0090_state *state) if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN)) c = 32; + else + c += 14; if ((h >= HR_MAX) || (h <= HR_MIN)) h = 34; if ((n >= POLY_MAX) || (n <= POLY_MIN)) n = 3; - dib0090_write_reg(state, 0x13, (h << 10)) ; - e2 = (n<<11) | ((h>>2)<<6) | (c); - dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */ + dib0090_write_reg(state, 0x13, (h << 10)); + e2 = (n << 11) | ((h >> 2)<<6) | c; + dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */ } } diff --git a/drivers/media/dvb-frontends/dib3000mc.h b/drivers/media/dvb-frontends/dib3000mc.h index d75ffad..129d142 100644 --- a/drivers/media/dvb-frontends/dib3000mc.h +++ b/drivers/media/dvb-frontends/dib3000mc.h @@ -13,6 +13,8 @@ #ifndef DIB3000MC_H #define DIB3000MC_H +#include <linux/kconfig.h> + #include "dibx000_common.h" struct dib3000mc_config { @@ -39,8 +41,7 @@ struct dib3000mc_config { #define DEFAULT_DIB3000MC_I2C_ADDRESS 16 #define DEFAULT_DIB3000P_I2C_ADDRESS 24 -#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && \ - defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_DIB3000MC) extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg); diff --git a/drivers/media/dvb-frontends/dib7000m.h b/drivers/media/dvb-frontends/dib7000m.h index 81fcf22..b585413 100644 --- a/drivers/media/dvb-frontends/dib7000m.h +++ b/drivers/media/dvb-frontends/dib7000m.h @@ -1,6 +1,8 @@ #ifndef DIB7000M_H #define DIB7000M_H +#include <linux/kconfig.h> + #include "dibx000_common.h" struct dib7000m_config { @@ -38,8 +40,7 @@ struct dib7000m_config { #define DEFAULT_DIB7000M_I2C_ADDRESS 18 -#if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \ - defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_DIB7000M) extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 3e1eefa..effb87f 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -429,6 +429,13 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe, } EXPORT_SYMBOL(dib7000p_get_agc_values); +int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v) +{ + struct dib7000p_state *state = fe->demodulator_priv; + return dib7000p_write_word(state, 108, v); +} +EXPORT_SYMBOL(dib7000p_set_agc1_min); + static void dib7000p_reset_pll(struct dib7000p_state *state) { struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; @@ -821,6 +828,7 @@ static int dib7000p_agc_startup(struct dvb_frontend *demod) u8 agc_split; u16 reg; u32 upd_demod_gain_period = 0x1000; + s32 frequency_offset = 0; switch (state->agc_state) { case 0: @@ -841,7 +849,14 @@ static int dib7000p_agc_startup(struct dvb_frontend *demod) if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0) return -1; - dib7000p_set_dds(state, 0); + if (demod->ops.tuner_ops.get_frequency) { + u32 frequency_tuner; + + demod->ops.tuner_ops.get_frequency(demod, &frequency_tuner); + frequency_offset = (s32)frequency_tuner / 1000 - ch->frequency / 1000; + } + + dib7000p_set_dds(state, frequency_offset); ret = 7; (*agc_state)++; break; diff --git a/drivers/media/dvb-frontends/dib7000p.h b/drivers/media/dvb-frontends/dib7000p.h index b61b03a..d08cdff 100644 --- a/drivers/media/dvb-frontends/dib7000p.h +++ b/drivers/media/dvb-frontends/dib7000p.h @@ -1,6 +1,8 @@ #ifndef DIB7000P_H #define DIB7000P_H +#include <linux/kconfig.h> + #include "dibx000_common.h" struct dib7000p_config { @@ -44,8 +46,7 @@ struct dib7000p_config { #define DEFAULT_DIB7000P_I2C_ADDRESS 18 -#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && \ - defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_DIB7000P) extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]); @@ -62,6 +63,7 @@ extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe); extern int dib7090_slave_reset(struct dvb_frontend *fe); extern int dib7000p_get_agc_values(struct dvb_frontend *fe, u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd); +extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v); #else static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) { @@ -153,6 +155,12 @@ static inline int dib7000p_get_agc_values(struct dvb_frontend *fe, printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } + +static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} #endif #endif diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 1f3bcb5..a54182d 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -23,8 +23,8 @@ #define LAYER_B 2 #define LAYER_C 3 -#define FE_CALLBACK_TIME_NEVER 0xffffffff #define MAX_NUMBER_OF_FRONTENDS 6 +/* #define DIB8000_AGC_FREEZE */ static int debug; module_param(debug, int, 0644); @@ -32,8 +32,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) -#define FE_STATUS_TUNE_FAILED 0 - struct i2c_device { struct i2c_adapter *adap; u8 addr; @@ -42,6 +40,23 @@ struct i2c_device { struct mutex *i2c_buffer_lock; }; +enum param_loop_step { + LOOP_TUNE_1, + LOOP_TUNE_2 +}; + +enum dib8000_autosearch_step { + AS_START = 0, + AS_SEARCHING_FFT, + AS_SEARCHING_GUARD, + AS_DONE = 100, +}; + +enum timeout_mode { + SYMBOL_DEPENDENT_OFF = 0, + SYMBOL_DEPENDENT_ON, +}; + struct dib8000_state { struct dib8000_config cfg; @@ -72,7 +87,7 @@ struct dib8000_state { u16 revision; u8 isdbt_cfg_loaded; enum frontend_tune_state tune_state; - u32 status; + s32 status; struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; @@ -85,6 +100,30 @@ struct dib8000_state { u16 tuner_enable; struct i2c_adapter dib8096p_tuner_adap; + u16 current_demod_bw; + + u16 seg_mask; + u16 seg_diff_mask; + u16 mode; + u8 layer_b_nb_seg; + u8 layer_c_nb_seg; + + u8 channel_parameters_set; + u16 autosearch_state; + u16 found_nfft; + u16 found_guard; + u8 subchannel; + u8 symbol_duration; + u32 timeout; + u8 longest_intlv_layer; + u16 output_mode; + +#ifdef DIB8000_AGC_FREEZE + u16 agc1_max; + u16 agc1_min; + u16 agc2_max; + u16 agc2_min; +#endif }; enum dib8000_power_mode { @@ -338,9 +377,9 @@ static void dib8000_set_acquisition_mode(struct dib8000_state *state) static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) { struct dib8000_state *state = fe->demodulator_priv; - u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */ + state->output_mode = mode; outreg = 0; fifo_threshold = 1792; smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); @@ -399,8 +438,9 @@ static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) { struct dib8000_state *state = fe->demodulator_priv; - u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0; + u16 tmp, sync_wait = dib8000_read_word(state, 273) & 0xfff0; + dprintk("set diversity input to %i", onoff); if (!state->differential_constellation) { dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1 dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2 @@ -424,6 +464,13 @@ static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) dib8000_write_word(state, 271, 1); break; } + + if (state->revision == 0x8002) { + tmp = dib8000_read_word(state, 903); + dib8000_write_word(state, 903, tmp & ~(1 << 3)); + msleep(30); + dib8000_write_word(state, 903, tmp | (1 << 3)); + } return 0; } @@ -468,27 +515,6 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow dib8000_write_word(state, 1280, reg_1280); } -static int dib8000_init_sdram(struct dib8000_state *state) -{ - u16 reg = 0; - dprintk("Init sdram"); - - reg = dib8000_read_word(state, 274)&0xfff0; - /* P_dintlv_delay_ram = 7 because of MobileSdram */ - dib8000_write_word(state, 274, reg | 0x7); - - dib8000_write_word(state, 1803, (7<<2)); - - reg = dib8000_read_word(state, 1280); - /* force restart P_restart_sdram */ - dib8000_write_word(state, 1280, reg | (1<<2)); - - /* release restart P_restart_sdram */ - dib8000_write_word(state, 1280, reg); - - return 0; -} - static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no) { int ret = 0; @@ -584,18 +610,23 @@ static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw) static int dib8000_sad_calib(struct dib8000_state *state) { + u8 sad_sel = 3; + if (state->revision == 0x8090) { - dprintk("%s: the sad calibration is not needed for the dib8096P", - __func__); - return 0; - } - /* internal */ - dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); - dib8000_write_word(state, 924, 776); // 0.625*3.3 / 4096 + dib8000_write_word(state, 922, (sad_sel << 2)); + dib8000_write_word(state, 923, 2048); + + dib8000_write_word(state, 922, (sad_sel << 2) | 0x1); + dib8000_write_word(state, 922, (sad_sel << 2)); + } else { + /* internal */ + dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); + dib8000_write_word(state, 924, 776); - /* do the calibration */ - dib8000_write_word(state, 923, (1 << 0)); - dib8000_write_word(state, 923, (0 << 0)); + /* do the calibration */ + dib8000_write_word(state, 923, (1 << 0)); + dib8000_write_word(state, 923, (0 << 0)); + } msleep(1); return 0; @@ -609,8 +640,8 @@ int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) state->wbd_ref = value; return dib8000_write_word(state, 106, value); } - EXPORT_SYMBOL(dib8000_set_wbd_ref); + static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) { dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25); @@ -685,20 +716,23 @@ static void dib8000_reset_pll(struct dib8000_state *state) } int dib8000_update_pll(struct dvb_frontend *fe, - struct dibx000_bandwidth_config *pll) + struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio) { struct dib8000_state *state = fe->demodulator_priv; u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856); - u8 loopdiv, prediv; + u8 loopdiv, prediv, oldprediv = state->cfg.pll->pll_prediv ; u32 internal, xtal; /* get back old values */ prediv = reg_1856 & 0x3f; loopdiv = (reg_1856 >> 6) & 0x3f; - if ((pll != NULL) && (pll->pll_prediv != prediv || - pll->pll_ratio != loopdiv)) { - dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio); + if ((pll == NULL) || (pll->pll_prediv == prediv && + pll->pll_ratio == loopdiv)) + return -EINVAL; + + dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio); + if (state->revision == 0x8090) { reg_1856 &= 0xf000; reg_1857 = dib8000_read_word(state, 1857); /* disable PLL */ @@ -729,10 +763,33 @@ int dib8000_update_pll(struct dvb_frontend *fe, reg_1856 = dib8000_read_word(state, 1856); dprintk("PLL Updated with prediv = %d and loopdiv = %d", reg_1856&0x3f, (reg_1856>>6)&0x3f); + } else { + if (bw != state->current_demod_bw) { + /** Bandwidth change => force PLL update **/ + dprintk("PLL: Bandwidth Change %d MHz -> %d MHz (prediv: %d->%d)", state->current_demod_bw / 1000, bw / 1000, oldprediv, state->cfg.pll->pll_prediv); + + if (state->cfg.pll->pll_prediv != oldprediv) { + /** Full PLL change only if prediv is changed **/ + + /** full update => bypass and reconfigure **/ + dprintk("PLL: New Setting for %d MHz Bandwidth (prediv: %d, ratio: %d)", bw/1000, state->cfg.pll->pll_prediv, state->cfg.pll->pll_ratio); + dib8000_write_word(state, 902, dib8000_read_word(state, 902) | (1<<3)); /* bypass PLL */ + dib8000_reset_pll(state); + dib8000_write_word(state, 898, 0x0004); /* sad */ + } else + ratio = state->cfg.pll->pll_ratio; - return 0; - } - return -EINVAL; + state->current_demod_bw = bw; + } + + if (ratio != 0) { + /** ratio update => only change ratio **/ + dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio); + dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */ + } +} + + return 0; } EXPORT_SYMBOL(dib8000_update_pll); @@ -928,7 +985,7 @@ static int dib8000_reset(struct dvb_frontend *fe) dib8000_set_power_mode(state, DIB8000_POWER_ALL); /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ - dib8000_set_adc_state(state, DIBX000_VBG_ENABLE); + dib8000_set_adc_state(state, DIBX000_ADC_OFF); /* restart all parts */ dib8000_write_word(state, 770, 0xffff); @@ -992,12 +1049,11 @@ static int dib8000_reset(struct dvb_frontend *fe) l = *n++; } } - if (state->revision != 0x8090) - dib8000_write_word(state, 903, (0 << 4) | 2); + state->isdbt_cfg_loaded = 0; //div_cfg override for special configs - if (state->cfg.div_cfg != 0) + if ((state->revision != 8090) && (state->cfg.div_cfg != 0)) dib8000_write_word(state, 903, state->cfg.div_cfg); /* unforce divstr regardless whether i2c enumeration was done or not */ @@ -1006,10 +1062,12 @@ static int dib8000_reset(struct dvb_frontend *fe) dib8000_set_bandwidth(fe, 6000); dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); - if (state->revision != 0x8090) { - dib8000_sad_calib(state); + dib8000_sad_calib(state); + if (state->revision != 0x8090) dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); - } + + /* ber_rs_len = 3 */ + dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); @@ -1441,6 +1499,7 @@ static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode) u8 prefer_mpeg_mux_use = 1; int ret = 0; + state->output_mode = mode; dib8096p_host_bus_drive(state, 1); fifo_threshold = 1792; @@ -1879,782 +1938,643 @@ static const u16 adc_target_16dB[11] = { }; static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; -static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching) +static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation) { - u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0; - u8 guard, crate, constellation, timeI; - u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled - const s16 *ncoeff = NULL, *ana_fe; - u16 tmcc_pow = 0; - u16 coff_pow = 0x2800; - u16 init_prbs = 0xfff; - u16 ana_gain = 0; - - if (state->revision == 0x8090) - dib8000_init_sdram(state); + u8 cr, constellation, time_intlv; + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; - if (state->ber_monitored_layer != LAYER_ALL) - dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer); - else - dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); - - i = dib8000_read_word(state, 26) & 1; // P_dds_invspec - dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion^i); - - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { - //compute new dds_freq for the seg and adjust prbs - int seg_offset = - state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx - - (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) - - (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2); - int clk = state->cfg.pll->internal; - u32 segtodds = ((u32) (430 << 23) / clk) << 3; // segtodds = SegBW / Fclk * pow(2,26) - int dds_offset = seg_offset * segtodds; - int new_dds, sub_channel; - if ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) - dds_offset -= (int)(segtodds / 2); - - if (state->cfg.pll->ifreq == 0) { - if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) { - dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1); - new_dds = dds_offset; - } else - new_dds = dds_offset; - - // We shift tuning frequency if the wanted segment is : - // - the segment of center frequency with an odd total number of segments - // - the segment to the left of center frequency with an even total number of segments - // - the segment to the right of center frequency with an even total number of segments - if ((state->fe[0]->dtv_property_cache.delivery_system == SYS_ISDBT) - && (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) - && (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) - && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == - ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) - || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) - && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2))) - || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) - && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == - ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) - )) { - new_dds -= ((u32) (850 << 22) / clk) << 4; // new_dds = 850 (freq shift in KHz) / Fclk * pow(2,26) - } - } else { - if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) - new_dds = state->cfg.pll->ifreq - dds_offset; - else - new_dds = state->cfg.pll->ifreq + dds_offset; - } - dib8000_write_word(state, 27, (u16) ((new_dds >> 16) & 0x01ff)); - dib8000_write_word(state, 28, (u16) (new_dds & 0xffff)); - if (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) - sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3; - else - sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3; - sub_channel -= 6; - - if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K - || state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) { - dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); //adp_pass =1 - dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); //pha3_force_pha_shift = 1 - } else { - dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); //adp_pass =0 - dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); //pha3_force_pha_shift = 0 - } - - switch (state->fe[0]->dtv_property_cache.transmission_mode) { - case TRANSMISSION_MODE_2K: - switch (sub_channel) { - case -6: - init_prbs = 0x0; - break; // 41, 0, 1 - case -5: - init_prbs = 0x423; - break; // 02~04 - case -4: - init_prbs = 0x9; - break; // 05~07 - case -3: - init_prbs = 0x5C7; - break; // 08~10 - case -2: - init_prbs = 0x7A6; - break; // 11~13 - case -1: - init_prbs = 0x3D8; - break; // 14~16 - case 0: - init_prbs = 0x527; - break; // 17~19 - case 1: - init_prbs = 0x7FF; - break; // 20~22 - case 2: - init_prbs = 0x79B; - break; // 23~25 - case 3: - init_prbs = 0x3D6; - break; // 26~28 - case 4: - init_prbs = 0x3A2; - break; // 29~31 - case 5: - init_prbs = 0x53B; - break; // 32~34 - case 6: - init_prbs = 0x2F4; - break; // 35~37 - default: - case 7: - init_prbs = 0x213; - break; // 38~40 - } - break; - - case TRANSMISSION_MODE_4K: - switch (sub_channel) { - case -6: - init_prbs = 0x0; - break; // 41, 0, 1 - case -5: - init_prbs = 0x208; - break; // 02~04 - case -4: - init_prbs = 0xC3; - break; // 05~07 - case -3: - init_prbs = 0x7B9; - break; // 08~10 - case -2: - init_prbs = 0x423; - break; // 11~13 - case -1: - init_prbs = 0x5C7; - break; // 14~16 - case 0: - init_prbs = 0x3D8; - break; // 17~19 - case 1: - init_prbs = 0x7FF; - break; // 20~22 - case 2: - init_prbs = 0x3D6; - break; // 23~25 - case 3: - init_prbs = 0x53B; - break; // 26~28 - case 4: - init_prbs = 0x213; - break; // 29~31 - case 5: - init_prbs = 0x29; - break; // 32~34 - case 6: - init_prbs = 0xD0; - break; // 35~37 - default: - case 7: - init_prbs = 0x48E; - break; // 38~40 - } - break; - - default: - case TRANSMISSION_MODE_8K: - switch (sub_channel) { - case -6: - init_prbs = 0x0; - break; // 41, 0, 1 - case -5: - init_prbs = 0x740; - break; // 02~04 - case -4: - init_prbs = 0x069; - break; // 05~07 - case -3: - init_prbs = 0x7DD; - break; // 08~10 - case -2: - init_prbs = 0x208; - break; // 11~13 - case -1: - init_prbs = 0x7B9; - break; // 14~16 - case 0: - init_prbs = 0x5C7; - break; // 17~19 - case 1: - init_prbs = 0x7FF; - break; // 20~22 - case 2: - init_prbs = 0x53B; - break; // 23~25 - case 3: - init_prbs = 0x29; - break; // 26~28 - case 4: - init_prbs = 0x48E; - break; // 29~31 - case 5: - init_prbs = 0x4C4; - break; // 32~34 - case 6: - init_prbs = 0x367; - break; // 33~37 - default: - case 7: - init_prbs = 0x684; - break; // 38~40 - } - break; - } - } else { - dib8000_write_word(state, 27, (u16) ((state->cfg.pll->ifreq >> 16) & 0x01ff)); - dib8000_write_word(state, 28, (u16) (state->cfg.pll->ifreq & 0xffff)); - dib8000_write_word(state, 26, (u16) ((state->cfg.pll->ifreq >> 25) & 0x0003)); - } - /*P_mode == ?? */ - dib8000_write_word(state, 10, (seq << 4)); - // dib8000_write_word(state, 287, (dib8000_read_word(state, 287) & 0xe000) | 0x1000); - - switch (state->fe[0]->dtv_property_cache.guard_interval) { - case GUARD_INTERVAL_1_32: - guard = 0; - break; - case GUARD_INTERVAL_1_16: - guard = 1; - break; - case GUARD_INTERVAL_1_8: - guard = 2; - break; - case GUARD_INTERVAL_1_4: - default: - guard = 3; - break; - } - - dib8000_write_word(state, 1, (init_prbs << 2) | (guard & 0x3)); // ADDR 1 - - max_constellation = DQPSK; - for (i = 0; i < 3; i++) { - switch (state->fe[0]->dtv_property_cache.layer[i].modulation) { - case DQPSK: + switch (c->layer[layer_index].modulation) { + case DQPSK: constellation = 0; break; - case QPSK: + case QPSK: constellation = 1; break; - case QAM_16: + case QAM_16: constellation = 2; break; - case QAM_64: - default: + case QAM_64: + default: constellation = 3; break; - } + } - switch (state->fe[0]->dtv_property_cache.layer[i].fec) { - case FEC_1_2: - crate = 1; + switch (c->layer[layer_index].fec) { + case FEC_1_2: + cr = 1; break; - case FEC_2_3: - crate = 2; + case FEC_2_3: + cr = 2; break; - case FEC_3_4: - crate = 3; + case FEC_3_4: + cr = 3; break; - case FEC_5_6: - crate = 5; + case FEC_5_6: + cr = 5; break; - case FEC_7_8: - default: - crate = 7; + case FEC_7_8: + default: + cr = 7; break; - } + } - if ((state->fe[0]->dtv_property_cache.layer[i].interleaving > 0) && - ((state->fe[0]->dtv_property_cache.layer[i].interleaving <= 3) || - (state->fe[0]->dtv_property_cache.layer[i].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)) - ) - timeI = state->fe[0]->dtv_property_cache.layer[i].interleaving; - else - timeI = 0; - dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[i].segment_count & 0xf) << 6) | - (crate << 3) | timeI); - if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) { - switch (max_constellation) { - case DQPSK: - case QPSK: - if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_16 || - state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64) - max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation; + if ((c->layer[layer_index].interleaving > 0) && ((c->layer[layer_index].interleaving <= 3) || (c->layer[layer_index].interleaving == 4 && c->isdbt_sb_mode == 1))) + time_intlv = c->layer[layer_index].interleaving; + else + time_intlv = 0; + + dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((c->layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv); + if (c->layer[layer_index].segment_count > 0) { + switch (max_constellation) { + case DQPSK: + case QPSK: + if (c->layer[layer_index].modulation == QAM_16 || c->layer[layer_index].modulation == QAM_64) + max_constellation = c->layer[layer_index].modulation; break; - case QAM_16: - if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64) - max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation; + case QAM_16: + if (c->layer[layer_index].modulation == QAM_64) + max_constellation = c->layer[layer_index].modulation; break; - } } } - mode = fft_to_mode(state); + return max_constellation; +} - //dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/ +static const u16 adp_Q64[4] = {0x0148, 0xfff0, 0x00a4, 0xfff8}; /* P_adp_regul_cnt 0.04, P_adp_noise_cnt -0.002, P_adp_regul_ext 0.02, P_adp_noise_ext -0.001 */ +static const u16 adp_Q16[4] = {0x023d, 0xffdf, 0x00a4, 0xfff0}; /* P_adp_regul_cnt 0.07, P_adp_noise_cnt -0.004, P_adp_regul_ext 0.02, P_adp_noise_ext -0.002 */ +static const u16 adp_Qdefault[4] = {0x099a, 0xffae, 0x0333, 0xfff8}; /* P_adp_regul_cnt 0.3, P_adp_noise_cnt -0.01, P_adp_regul_ext 0.1, P_adp_noise_ext -0.002 */ +static u16 dib8000_adp_fine_tune(struct dib8000_state *state, u16 max_constellation) +{ + u16 i, ana_gain = 0; + const u16 *adp; - dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | - ((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache. - isdbt_sb_mode & 1) << 4)); + /* channel estimation fine configuration */ + switch (max_constellation) { + case QAM_64: + ana_gain = 0x7; + adp = &adp_Q64[0]; + break; + case QAM_16: + ana_gain = 0x7; + adp = &adp_Q16[0]; + break; + default: + ana_gain = 0; + adp = &adp_Qdefault[0]; + break; + } - dprintk("mode = %d ; guard = %d", mode, state->fe[0]->dtv_property_cache.guard_interval); + for (i = 0; i < 4; i++) + dib8000_write_word(state, 215 + i, adp[i]); - /* signal optimization parameter */ + return ana_gain; +} - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) { - seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0]; - for (i = 1; i < 3; i++) - nbseg_diff += - (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; - for (i = 0; i < nbseg_diff; i++) - seg_diff_mask |= 1 << permu_seg[i + 1]; - } else { - for (i = 0; i < 3; i++) - nbseg_diff += - (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; - for (i = 0; i < nbseg_diff; i++) - seg_diff_mask |= 1 << permu_seg[i]; +static void dib8000_update_ana_gain(struct dib8000_state *state, u16 ana_gain) +{ + u16 i; + + dib8000_write_word(state, 116, ana_gain); + + /* update ADC target depending on ana_gain */ + if (ana_gain) { /* set -16dB ADC target for ana_gain=-1 */ + for (i = 0; i < 10; i++) + dib8000_write_word(state, 80 + i, adc_target_16dB[i]); + } else { /* set -22dB ADC target for ana_gain=0 */ + for (i = 0; i < 10; i++) + dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355); } - dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask); +} - state->differential_constellation = (seg_diff_mask != 0); - if (state->revision != 0x8090) - dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); - else - dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff); +static void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *ana_fe) +{ + u16 mode = 0; - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) - seg_mask13 = 0x00E0; - else // 1-segment - seg_mask13 = 0x0040; - } else - seg_mask13 = 0x1fff; + if (state->isdbt_cfg_loaded == 0) + for (mode = 0; mode < 24; mode++) + dib8000_write_word(state, 117 + mode, ana_fe[mode]); +} - // WRITE: Mode & Diff mask - dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask); +static const u16 lut_prbs_2k[14] = { + 0, 0x423, 0x009, 0x5C7, 0x7A6, 0x3D8, 0x527, 0x7FF, 0x79B, 0x3D6, 0x3A2, 0x53B, 0x2F4, 0x213 +}; +static const u16 lut_prbs_4k[14] = { + 0, 0x208, 0x0C3, 0x7B9, 0x423, 0x5C7, 0x3D8, 0x7FF, 0x3D6, 0x53B, 0x213, 0x029, 0x0D0, 0x48E +}; +static const u16 lut_prbs_8k[14] = { + 0, 0x740, 0x069, 0x7DD, 0x208, 0x7B9, 0x5C7, 0x7FF, 0x53B, 0x029, 0x48E, 0x4C4, 0x367, 0x684 +}; - if ((seg_diff_mask) || (state->fe[0]->dtv_property_cache.isdbt_sb_mode)) - dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); - else - dib8000_write_word(state, 268, (2 << 9) | 39); //init value +static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel) +{ + int sub_channel_prbs_group = 0; - // ---- SMALL ---- - // P_small_seg_diff - dib8000_write_word(state, 352, seg_diff_mask); // ADDR 352 + sub_channel_prbs_group = (subchannel / 3) + 1; + dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]); - dib8000_write_word(state, 353, seg_mask13); // ADDR 353 + switch (state->fe[0]->dtv_property_cache.transmission_mode) { + case TRANSMISSION_MODE_2K: + return lut_prbs_2k[sub_channel_prbs_group]; + case TRANSMISSION_MODE_4K: + return lut_prbs_4k[sub_channel_prbs_group]; + default: + case TRANSMISSION_MODE_8K: + return lut_prbs_8k[sub_channel_prbs_group]; + } +} + +static void dib8000_set_13seg_channel(struct dib8000_state *state) +{ + u16 i; + u16 coff_pow = 0x2800; -/* // P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */ + state->seg_mask = 0x1fff; /* All 13 segments enabled */ - // ---- SMALL ---- - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { - switch (state->fe[0]->dtv_property_cache.transmission_mode) { + /* ---- COFF ---- Carloff, the most robust --- */ + if (state->isdbt_cfg_loaded == 0) { /* if not Sound Broadcasting mode : put default values for 13 segments */ + dib8000_write_word(state, 180, (16 << 6) | 9); + dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2); + coff_pow = 0x2800; + for (i = 0; i < 6; i++) + dib8000_write_word(state, 181+i, coff_pow); + + /* P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1 */ + /* P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 */ + dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1); + + /* P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 */ + dib8000_write_word(state, 340, (8 << 6) | (6 << 0)); + /* P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 */ + dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); + + dib8000_write_word(state, 228, 0); /* default value */ + dib8000_write_word(state, 265, 31); /* default value */ + dib8000_write_word(state, 205, 0x200f); /* init value */ + } + + /* + * make the cpil_coff_lock more robust but slower p_coff_winlen + * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) + */ + + if (state->cfg.pll->ifreq == 0) + dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */ + + dib8000_load_ana_fe_coefs(state, ana_fe_coeff_13seg); +} + +static void dib8000_set_subchannel_prbs(struct dib8000_state *state, u16 init_prbs) +{ + u16 reg_1; + + reg_1 = dib8000_read_word(state, 1); + dib8000_write_word(state, 1, (init_prbs << 2) | (reg_1 & 0x3)); /* ADDR 1 */ +} + +static void dib8000_small_fine_tune(struct dib8000_state *state) +{ + u16 i; + const s16 *ncoeff; + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + + dib8000_write_word(state, 352, state->seg_diff_mask); + dib8000_write_word(state, 353, state->seg_mask); + + /* P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 */ + dib8000_write_word(state, 351, (c->isdbt_sb_mode << 9) | (c->isdbt_sb_mode << 8) | (13 << 4) | 5); + + if (c->isdbt_sb_mode) { + /* ---- SMALL ---- */ + switch (c->transmission_mode) { case TRANSMISSION_MODE_2K: - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { - if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) - ncoeff = coeff_2k_sb_1seg_dqpsk; - else // QPSK or QAM - ncoeff = coeff_2k_sb_1seg; - } else { // 3-segments - if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { - if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) - ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk; - else // QPSK or QAM on external segments - ncoeff = coeff_2k_sb_3seg_0dqpsk; - } else { // QPSK or QAM on central segment - if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) - ncoeff = coeff_2k_sb_3seg_1dqpsk; - else // QPSK or QAM on external segments - ncoeff = coeff_2k_sb_3seg; + if (c->isdbt_partial_reception == 0) { /* 1-seg */ + if (c->layer[0].modulation == DQPSK) /* DQPSK */ + ncoeff = coeff_2k_sb_1seg_dqpsk; + else /* QPSK or QAM */ + ncoeff = coeff_2k_sb_1seg; + } else { /* 3-segments */ + if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */ + if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ + ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk; + else /* QPSK or QAM on external segments */ + ncoeff = coeff_2k_sb_3seg_0dqpsk; + } else { /* QPSK or QAM on central segment */ + if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ + ncoeff = coeff_2k_sb_3seg_1dqpsk; + else /* QPSK or QAM on external segments */ + ncoeff = coeff_2k_sb_3seg; + } } - } - break; - + break; case TRANSMISSION_MODE_4K: - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { - if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) - ncoeff = coeff_4k_sb_1seg_dqpsk; - else // QPSK or QAM - ncoeff = coeff_4k_sb_1seg; - } else { // 3-segments - if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { - if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { - ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk; - } else { // QPSK or QAM on external segments - ncoeff = coeff_4k_sb_3seg_0dqpsk; + if (c->isdbt_partial_reception == 0) { /* 1-seg */ + if (c->layer[0].modulation == DQPSK) /* DQPSK */ + ncoeff = coeff_4k_sb_1seg_dqpsk; + else /* QPSK or QAM */ + ncoeff = coeff_4k_sb_1seg; + } else { /* 3-segments */ + if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */ + if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ + ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk; + else /* QPSK or QAM on external segments */ + ncoeff = coeff_4k_sb_3seg_0dqpsk; + } else { /* QPSK or QAM on central segment */ + if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ + ncoeff = coeff_4k_sb_3seg_1dqpsk; + else /* QPSK or QAM on external segments */ + ncoeff = coeff_4k_sb_3seg; } - } else { // QPSK or QAM on central segment - if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { - ncoeff = coeff_4k_sb_3seg_1dqpsk; - } else // QPSK or QAM on external segments - ncoeff = coeff_4k_sb_3seg; } - } - break; - + break; case TRANSMISSION_MODE_AUTO: case TRANSMISSION_MODE_8K: default: - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { - if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) - ncoeff = coeff_8k_sb_1seg_dqpsk; - else // QPSK or QAM - ncoeff = coeff_8k_sb_1seg; - } else { // 3-segments - if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { - if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { - ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk; - } else { // QPSK or QAM on external segments - ncoeff = coeff_8k_sb_3seg_0dqpsk; + if (c->isdbt_partial_reception == 0) { /* 1-seg */ + if (c->layer[0].modulation == DQPSK) /* DQPSK */ + ncoeff = coeff_8k_sb_1seg_dqpsk; + else /* QPSK or QAM */ + ncoeff = coeff_8k_sb_1seg; + } else { /* 3-segments */ + if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */ + if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ + ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk; + else /* QPSK or QAM on external segments */ + ncoeff = coeff_8k_sb_3seg_0dqpsk; + } else { /* QPSK or QAM on central segment */ + if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ + ncoeff = coeff_8k_sb_3seg_1dqpsk; + else /* QPSK or QAM on external segments */ + ncoeff = coeff_8k_sb_3seg; } - } else { // QPSK or QAM on central segment - if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { - ncoeff = coeff_8k_sb_3seg_1dqpsk; - } else // QPSK or QAM on external segments - ncoeff = coeff_8k_sb_3seg; } - } - break; + break; } + for (i = 0; i < 8; i++) dib8000_write_word(state, 343 + i, ncoeff[i]); } +} - // P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 - dib8000_write_word(state, 351, - (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5); +static const u16 coff_thres_1seg[3] = {300, 150, 80}; +static const u16 coff_thres_3seg[3] = {350, 300, 250}; +static void dib8000_set_sb_channel(struct dib8000_state *state) +{ + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + const u16 *coff; + u16 i; - // ---- COFF ---- - // Carloff, the most robust - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { + if (c->transmission_mode == TRANSMISSION_MODE_2K || c->transmission_mode == TRANSMISSION_MODE_4K) { + dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); /* adp_pass =1 */ + dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); /* pha3_force_pha_shift = 1 */ + } else { + dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); /* adp_pass =0 */ + dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); /* pha3_force_pha_shift = 0 */ + } - // P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64 - // P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 - dib8000_write_word(state, 187, - (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2) - | 0x3); + if (c->isdbt_partial_reception == 1) /* 3-segments */ + state->seg_mask = 0x00E0; + else /* 1-segment */ + state->seg_mask = 0x0040; -/* // P_small_coef_ext_enable = 1 */ -/* dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */ + dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { + /* ---- COFF ---- Carloff, the most robust --- */ + /* P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64, P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 */ + dib8000_write_word(state, 187, (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~c->isdbt_partial_reception & 1) << 2) | 0x3); - // P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width= (P_mode == 3) , P_coff_one_seg_sym= (P_mode-1) - if (mode == 3) - dib8000_write_word(state, 180, 0x1fcf | ((mode - 1) << 14)); - else - dib8000_write_word(state, 180, 0x0fcf | ((mode - 1) << 14)); - // P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, - // P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 - dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4); - // P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 - dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); - // P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 - dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); - - // P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k - dib8000_write_word(state, 181, 300); - dib8000_write_word(state, 182, 150); - dib8000_write_word(state, 183, 80); - dib8000_write_word(state, 184, 300); - dib8000_write_word(state, 185, 150); - dib8000_write_word(state, 186, 80); - } else { // Sound Broadcasting mode 3 seg - // P_coff_one_seg_sym= 1, P_coff_one_seg_width= 1, P_coff_winlen=63, P_coff_thres_lock=15 - /* if (mode == 3) */ - /* dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */ - /* else */ - /* dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */ - dib8000_write_word(state, 180, 0x1fcf | (1 << 14)); - - // P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, - // P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 - dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4); - // P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 - dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); - //P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 - dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); - - // P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k - dib8000_write_word(state, 181, 350); - dib8000_write_word(state, 182, 300); - dib8000_write_word(state, 183, 250); - dib8000_write_word(state, 184, 350); - dib8000_write_word(state, 185, 300); - dib8000_write_word(state, 186, 250); - } + dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); /* P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 */ + dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));/* P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 */ - } else if (state->isdbt_cfg_loaded == 0) { // if not Sound Broadcasting mode : put default values for 13 segments - dib8000_write_word(state, 180, (16 << 6) | 9); - dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2); - coff_pow = 0x2800; - for (i = 0; i < 6; i++) - dib8000_write_word(state, 181 + i, coff_pow); + /* Sound Broadcasting mode 1 seg */ + if (c->isdbt_partial_reception == 0) { + /* P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width = (P_mode == 3) , P_coff_one_seg_sym = (P_mode-1) */ + if (state->mode == 3) + dib8000_write_word(state, 180, 0x1fcf | ((state->mode - 1) << 14)); + else + dib8000_write_word(state, 180, 0x0fcf | ((state->mode - 1) << 14)); - // P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1, - // P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 - dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1); + /* P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 */ + dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4); + coff = &coff_thres_1seg[0]; + } else { /* Sound Broadcasting mode 3 seg */ + dib8000_write_word(state, 180, 0x1fcf | (1 << 14)); + /* P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 */ + dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4); + coff = &coff_thres_3seg[0]; + } - // P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 - dib8000_write_word(state, 340, (8 << 6) | (6 << 0)); - // P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 - dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); + dib8000_write_word(state, 228, 1); /* P_2d_mode_byp=1 */ + dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); /* P_cspu_win_cut = 0 */ + + if (c->isdbt_partial_reception == 0 && c->transmission_mode == TRANSMISSION_MODE_2K) + dib8000_write_word(state, 265, 15); /* P_equal_noise_sel = 15 */ + + /* Write COFF thres */ + for (i = 0 ; i < 3; i++) { + dib8000_write_word(state, 181+i, coff[i]); + dib8000_write_word(state, 184+i, coff[i]); } - // ---- FFT ---- - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 && state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) - dib8000_write_word(state, 178, 64); // P_fft_powrange=64 - else - dib8000_write_word(state, 178, 32); // P_fft_powrange=32 - /* make the cpil_coff_lock more robust but slower p_coff_winlen + /* + * make the cpil_coff_lock more robust but slower p_coff_winlen * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) */ - /* if ( ( nbseg_diff>0)&&(nbseg_diff<13)) - dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */ - - dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask); /* P_lmod4_seg_inh */ - dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask); /* P_pha3_seg_inh */ - dib8000_write_word(state, 225, ~seg_mask13 | seg_diff_mask); /* P_tac_seg_inh */ - if ((!state->fe[0]->dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0)) - dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */ - else - dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask); /* P_equal_noise_seg_inh */ - dib8000_write_word(state, 287, ~seg_mask13 | 0x1000); /* P_tmcc_seg_inh */ - //dib8000_write_word(state, 288, ~seg_mask13 | seg_diff_mask); /* P_tmcc_seg_eq_inh */ - if (!autosearching) - dib8000_write_word(state, 288, (~seg_mask13 | seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */ + + dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask); /* P_equal_noise_seg_inh */ + + if (c->isdbt_partial_reception == 0) + dib8000_write_word(state, 178, 64); /* P_fft_powrange = 64 */ else - dib8000_write_word(state, 288, 0x1fff); //disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. - dprintk("287 = %X (%d)", ~seg_mask13 | 0x1000, ~seg_mask13 | 0x1000); - - dib8000_write_word(state, 211, seg_mask13 & (~seg_diff_mask)); /* P_des_seg_enabled */ - - /* offset loop parameters */ - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) - /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */ - dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x40); - - else // Sound Broadcasting mode 3 seg - /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */ - dib8000_write_word(state, 32, ((10 - mode) << 12) | (6 << 8) | 0x60); - } else - // TODO in 13 seg, timf_alpha can always be the same or not ? - /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */ - dib8000_write_word(state, 32, ((9 - mode) << 12) | (6 << 8) | 0x80); - - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) - /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (11-P_mode) */ - dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (10 - mode)); - - else // Sound Broadcasting mode 3 seg - /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */ - dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (9 - mode)); - } else - /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */ - dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (8 - mode)); + dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */ +} - /* P_dvsy_sync_wait - reuse mode */ - switch (state->fe[0]->dtv_property_cache.transmission_mode) { - case TRANSMISSION_MODE_8K: - mode = 256; - break; - case TRANSMISSION_MODE_4K: - mode = 128; - break; - default: - case TRANSMISSION_MODE_2K: - mode = 64; - break; +static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq, u8 autosearching) +{ + u16 p_cfr_left_edge = 0, p_cfr_right_edge = 0; + u16 tmcc_pow = 0, ana_gain = 0, tmp = 0, i = 0, nbseg_diff = 0 ; + u16 max_constellation = DQPSK; + int init_prbs; + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + + /* P_mode */ + dib8000_write_word(state, 10, (seq << 4)); + + /* init mode */ + state->mode = fft_to_mode(state); + + /* set guard */ + tmp = dib8000_read_word(state, 1); + dib8000_write_word(state, 1, (tmp&0xfffc) | (c->guard_interval & 0x3)); + + dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | ((c->isdbt_partial_reception & 1) << 5) | ((c->isdbt_sb_mode & 1) << 4)); + + /* signal optimization parameter */ + if (c->isdbt_partial_reception) { + state->seg_diff_mask = (c->layer[0].modulation == DQPSK) << permu_seg[0]; + for (i = 1; i < 3; i++) + nbseg_diff += (c->layer[i].modulation == DQPSK) * c->layer[i].segment_count; + for (i = 0; i < nbseg_diff; i++) + state->seg_diff_mask |= 1 << permu_seg[i+1]; + } else { + for (i = 0; i < 3; i++) + nbseg_diff += (c->layer[i].modulation == DQPSK) * c->layer[i].segment_count; + for (i = 0; i < nbseg_diff; i++) + state->seg_diff_mask |= 1 << permu_seg[i]; } - if (state->cfg.diversity_delay == 0) - mode = (mode * (1 << (guard)) * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo + + if (state->seg_diff_mask) + dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); else - mode = (mode * (1 << (guard)) * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for DVSY-fifo - mode <<= 4; - dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | mode); + dib8000_write_word(state, 268, (2 << 9) | 39); /*init value */ - /* channel estimation fine configuration */ - switch (max_constellation) { - case QAM_64: - ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB - coeff[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ - coeff[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ - coeff[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ - coeff[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ - //if (!state->cfg.hostbus_diversity) //if diversity, we should prehaps use the configuration of the max_constallation -1 - break; - case QAM_16: - ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB - coeff[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ - coeff[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ - coeff[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ - coeff[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ - //if (!((state->cfg.hostbus_diversity) && (max_constellation == QAM_16))) - break; - default: - ana_gain = 0; // 0 : goes along with ADC target at -22dB to keep good mobile performance and lock at sensitivity level - coeff[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ - coeff[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ - coeff[2] = 0x0333; /* P_adp_regul_ext 0.1 */ - coeff[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ - break; + for (i = 0; i < 3; i++) + max_constellation = dib8000_set_layer(state, i, max_constellation); + if (autosearching == 0) { + state->layer_b_nb_seg = c->layer[1].segment_count; + state->layer_c_nb_seg = c->layer[2].segment_count; } - for (mode = 0; mode < 4; mode++) - dib8000_write_word(state, 215 + mode, coeff[mode]); - // update ana_gain depending on max constellation - dib8000_write_word(state, 116, ana_gain); - // update ADC target depending on ana_gain - if (ana_gain) { // set -16dB ADC target for ana_gain=-1 - for (i = 0; i < 10; i++) - dib8000_write_word(state, 80 + i, adc_target_16dB[i]); - } else { // set -22dB ADC target for ana_gain=0 - for (i = 0; i < 10; i++) - dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355); + /* WRITE: Mode & Diff mask */ + dib8000_write_word(state, 0, (state->mode << 13) | state->seg_diff_mask); + + state->differential_constellation = (state->seg_diff_mask != 0); + + /* channel estimation fine configuration */ + ana_gain = dib8000_adp_fine_tune(state, max_constellation); + + /* update ana_gain depending on max constellation */ + dib8000_update_ana_gain(state, ana_gain); + + /* ---- ANA_FE ---- */ + if (c->isdbt_partial_reception) /* 3-segments */ + dib8000_load_ana_fe_coefs(state, ana_fe_coeff_3seg); + else + dib8000_load_ana_fe_coefs(state, ana_fe_coeff_1seg); /* 1-segment */ + + /* TSB or ISDBT ? apply it now */ + if (c->isdbt_sb_mode) { + dib8000_set_sb_channel(state); + if (c->isdbt_sb_subchannel < 14) + init_prbs = dib8000_get_init_prbs(state, c->isdbt_sb_subchannel); + else + init_prbs = 0; + } else { + dib8000_set_13seg_channel(state); + init_prbs = 0xfff; } - // ---- ANA_FE ---- - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) - ana_fe = ana_fe_coeff_3seg; - else // 1-segment - ana_fe = ana_fe_coeff_1seg; - } else - ana_fe = ana_fe_coeff_13seg; + /* SMALL */ + dib8000_small_fine_tune(state); - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0) - for (mode = 0; mode < 24; mode++) - dib8000_write_word(state, 117 + mode, ana_fe[mode]); + dib8000_set_subchannel_prbs(state, init_prbs); - // ---- CHAN_BLK ---- + /* ---- CHAN_BLK ---- */ for (i = 0; i < 13; i++) { - if ((((~seg_diff_mask) >> i) & 1) == 1) { - P_cfr_left_edge += (1 << i) * ((i == 0) || ((((seg_mask13 & (~seg_diff_mask)) >> (i - 1)) & 1) == 0)); - P_cfr_right_edge += (1 << i) * ((i == 12) || ((((seg_mask13 & (~seg_diff_mask)) >> (i + 1)) & 1) == 0)); + if ((((~state->seg_diff_mask) >> i) & 1) == 1) { + p_cfr_left_edge += (1 << i) * ((i == 0) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i - 1)) & 1) == 0)); + p_cfr_right_edge += (1 << i) * ((i == 12) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i + 1)) & 1) == 0)); } } - dib8000_write_word(state, 222, P_cfr_left_edge); // P_cfr_left_edge - dib8000_write_word(state, 223, P_cfr_right_edge); // P_cfr_right_edge - // "P_cspu_left_edge" not used => do not care - // "P_cspu_right_edge" not used => do not care - - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { - dib8000_write_word(state, 228, 1); // P_2d_mode_byp=1 - dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); // P_cspu_win_cut = 0 - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0 - && state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) { - //dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0 - dib8000_write_word(state, 265, 15); // P_equal_noise_sel = 15 - } - } else if (state->isdbt_cfg_loaded == 0) { - dib8000_write_word(state, 228, 0); // default value - dib8000_write_word(state, 265, 31); // default value - dib8000_write_word(state, 205, 0x200f); // init value - } - // ---- TMCC ---- + dib8000_write_word(state, 222, p_cfr_left_edge); /* p_cfr_left_edge */ + dib8000_write_word(state, 223, p_cfr_right_edge); /* p_cfr_right_edge */ + /* "P_cspu_left_edge" & "P_cspu_right_edge" not used => do not care */ + + dib8000_write_word(state, 189, ~state->seg_mask | state->seg_diff_mask); /* P_lmod4_seg_inh */ + dib8000_write_word(state, 192, ~state->seg_mask | state->seg_diff_mask); /* P_pha3_seg_inh */ + dib8000_write_word(state, 225, ~state->seg_mask | state->seg_diff_mask); /* P_tac_seg_inh */ + + if (!autosearching) + dib8000_write_word(state, 288, (~state->seg_mask | state->seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */ + else + dib8000_write_word(state, 288, 0x1fff); /*disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. */ + + dib8000_write_word(state, 211, state->seg_mask & (~state->seg_diff_mask)); /* P_des_seg_enabled */ + dib8000_write_word(state, 287, ~state->seg_mask | 0x1000); /* P_tmcc_seg_inh */ + + dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */ + + /* ---- TMCC ---- */ for (i = 0; i < 3; i++) - tmcc_pow += - (((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count); - // Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); - // Threshold is set at 1/4 of max power. - tmcc_pow *= (1 << (9 - 2)); - - dib8000_write_word(state, 290, tmcc_pow); // P_tmcc_dec_thres_2k - dib8000_write_word(state, 291, tmcc_pow); // P_tmcc_dec_thres_4k - dib8000_write_word(state, 292, tmcc_pow); // P_tmcc_dec_thres_8k - //dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); - // ---- PHA3 ---- + tmcc_pow += (((c->layer[i].modulation == DQPSK) * 4 + 1) * c->layer[i].segment_count) ; + + /* Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); */ + /* Threshold is set at 1/4 of max power. */ + tmcc_pow *= (1 << (9-2)); + dib8000_write_word(state, 290, tmcc_pow); /* P_tmcc_dec_thres_2k */ + dib8000_write_word(state, 291, tmcc_pow); /* P_tmcc_dec_thres_4k */ + dib8000_write_word(state, 292, tmcc_pow); /* P_tmcc_dec_thres_8k */ + /*dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); */ + /* ---- PHA3 ---- */ if (state->isdbt_cfg_loaded == 0) - dib8000_write_word(state, 250, 3285); /*p_2d_hspeed_thr0 */ + dib8000_write_word(state, 250, 3285); /* p_2d_hspeed_thr0 */ - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) - state->isdbt_cfg_loaded = 0; - else - state->isdbt_cfg_loaded = 1; + state->isdbt_cfg_loaded = 0; +} +static u32 dib8000_wait_lock(struct dib8000_state *state, u32 internal, + u32 wait0_ms, u32 wait1_ms, u32 wait2_ms) +{ + u32 value = 0; /* P_search_end0 wait time */ + u16 reg = 11; /* P_search_end0 start addr */ + + for (reg = 11; reg < 16; reg += 2) { + if (reg == 11) { + if (state->revision == 0x8090) + value = internal * wait1_ms; + else + value = internal * wait0_ms; + } else if (reg == 13) + value = internal * wait1_ms; + else if (reg == 15) + value = internal * wait2_ms; + dib8000_write_word(state, reg, (u16)((value >> 16) & 0xffff)); + dib8000_write_word(state, (reg + 1), (u16)(value & 0xffff)); + } + return value; } static int dib8000_autosearch_start(struct dvb_frontend *fe) { - u8 factor; - u32 value; struct dib8000_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + u8 slist = 0; + u32 value, internal = state->cfg.pll->internal; - int slist = 0; - - state->fe[0]->dtv_property_cache.inversion = 0; - if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode) - state->fe[0]->dtv_property_cache.layer[0].segment_count = 13; - state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64; - state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3; - state->fe[0]->dtv_property_cache.layer[0].interleaving = 0; - - //choose the right list, in sb, always do everything - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { - state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; - state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; - slist = 7; - dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); - } else { - if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) { - if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { - slist = 7; - dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 to have autosearch start ok with mode2 - } else - slist = 3; - } else { - if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { - slist = 2; - dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 - } else - slist = 0; - } + if (state->revision == 0x8090) + internal = dib8000_read32(state, 23) / 1000; + + if (state->autosearch_state == AS_SEARCHING_FFT) { + dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */ + dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */ - if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) - state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; - if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) - state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; + dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x1fff) | (0 << 13) | (1 << 15)); /* P_mode = 0, P_restart_search=1 */ + dib8000_write_word(state, 1, (dib8000_read_word(state, 1) & 0xfffc) | 0); /* P_guard = 0 */ + dib8000_write_word(state, 6, 0); /* P_lock0_mask = 0 */ + dib8000_write_word(state, 7, 0); /* P_lock1_mask = 0 */ + dib8000_write_word(state, 8, 0); /* P_lock2_mask = 0 */ + dib8000_write_word(state, 10, (dib8000_read_word(state, 10) & 0x200) | (16 << 4) | (0 << 0)); /* P_search_list=16, P_search_maxtrial=0 */ - dprintk("using list for autosearch : %d", slist); - dib8000_set_channel(state, (unsigned char)slist, 1); - //dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 + if (state->revision == 0x8090) + value = dib8000_wait_lock(state, internal, 10, 10, 10); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ + else + value = dib8000_wait_lock(state, internal, 20, 20, 20); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ - factor = 1; + dib8000_write_word(state, 17, 0); + dib8000_write_word(state, 18, 200); /* P_search_rstst = 200 */ + dib8000_write_word(state, 19, 0); + dib8000_write_word(state, 20, 400); /* P_search_rstend = 400 */ + dib8000_write_word(state, 21, (value >> 16) & 0xffff); /* P_search_checkst */ + dib8000_write_word(state, 22, value & 0xffff); - //set lock_mask values + if (state->revision == 0x8090) + dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (0 << 8)); /* P_corm_alpha = 0 */ + else + dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (9 << 8)); /* P_corm_alpha = 3 */ + dib8000_write_word(state, 355, 2); /* P_search_param_max = 2 */ + + /* P_search_param_select = (1 | 1<<4 | 1 << 8) */ + dib8000_write_word(state, 356, 0); + dib8000_write_word(state, 357, 0x111); + + dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */ + dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */ + dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */ + } else if (state->autosearch_state == AS_SEARCHING_GUARD) { + c->transmission_mode = TRANSMISSION_MODE_8K; + c->guard_interval = GUARD_INTERVAL_1_8; + c->inversion = 0; + c->layer[0].modulation = QAM_64; + c->layer[0].fec = FEC_2_3; + c->layer[0].interleaving = 0; + c->layer[0].segment_count = 13; + + slist = 16; + c->transmission_mode = state->found_nfft; + + dib8000_set_isdbt_common_channel(state, slist, 1); + + /* set lock_mask values */ dib8000_write_word(state, 6, 0x4); - dib8000_write_word(state, 7, 0x8); + if (state->revision == 0x8090) + dib8000_write_word(state, 7, ((1 << 12) | (1 << 11) | (1 << 10)));/* tmcc_dec_lock, tmcc_sync_lock, tmcc_data_lock, tmcc_bch_uncor */ + else + dib8000_write_word(state, 7, 0x8); dib8000_write_word(state, 8, 0x1000); - //set lock_mask wait time values - value = 50 * state->cfg.pll->internal * factor; - dib8000_write_word(state, 11, (u16) ((value >> 16) & 0xffff)); // lock0 wait time - dib8000_write_word(state, 12, (u16) (value & 0xffff)); // lock0 wait time - value = 100 * state->cfg.pll->internal * factor; - dib8000_write_word(state, 13, (u16) ((value >> 16) & 0xffff)); // lock1 wait time - dib8000_write_word(state, 14, (u16) (value & 0xffff)); // lock1 wait time - value = 1000 * state->cfg.pll->internal * factor; - dib8000_write_word(state, 15, (u16) ((value >> 16) & 0xffff)); // lock2 wait time - dib8000_write_word(state, 16, (u16) (value & 0xffff)); // lock2 wait time + /* set lock_mask wait time values */ + if (state->revision == 0x8090) + dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ + else + dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ + + dib8000_write_word(state, 355, 3); /* P_search_param_max = 3 */ + + /* P_search_param_select = 0xf; look for the 4 different guard intervals */ + dib8000_write_word(state, 356, 0); + dib8000_write_word(state, 357, 0xf); value = dib8000_read_word(state, 0); - dib8000_write_word(state, 0, (u16) ((1 << 15) | value)); - dib8000_read_word(state, 1284); // reset the INT. n_irq_pending - dib8000_write_word(state, 0, (u16) value); + dib8000_write_word(state, 0, (u16)((1 << 15) | value)); + dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */ + dib8000_write_word(state, 0, (u16)value); + } else { + c->inversion = 0; + c->layer[0].modulation = QAM_64; + c->layer[0].fec = FEC_2_3; + c->layer[0].interleaving = 0; + c->layer[0].segment_count = 13; + if (!c->isdbt_sb_mode) + c->layer[0].segment_count = 13; + + /* choose the right list, in sb, always do everything */ + if (c->isdbt_sb_mode) { + slist = 7; + dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); + } else { + if (c->guard_interval == GUARD_INTERVAL_AUTO) { + if (c->transmission_mode == TRANSMISSION_MODE_AUTO) { + c->transmission_mode = TRANSMISSION_MODE_8K; + c->guard_interval = GUARD_INTERVAL_1_8; + slist = 7; + dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 to have autosearch start ok with mode2 */ + } else { + c->guard_interval = GUARD_INTERVAL_1_8; + slist = 3; + } + } else { + if (c->transmission_mode == TRANSMISSION_MODE_AUTO) { + c->transmission_mode = TRANSMISSION_MODE_8K; + slist = 2; + dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 */ + } else + slist = 0; + } + } + dprintk("Using list for autosearch : %d", slist); - } + dib8000_set_isdbt_common_channel(state, slist, 1); + + /* set lock_mask values */ + dib8000_write_word(state, 6, 0x4); + if (state->revision == 0x8090) + dib8000_write_word(state, 7, (1 << 12) | (1 << 11) | (1 << 10)); + else + dib8000_write_word(state, 7, 0x8); + dib8000_write_word(state, 8, 0x1000); + /* set lock_mask wait time values */ + if (state->revision == 0x8090) + dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ + else + dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ + + value = dib8000_read_word(state, 0); + dib8000_write_word(state, 0, (u16)((1 << 15) | value)); + dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */ + dib8000_write_word(state, 0, (u16)value); + } return 0; } @@ -2663,96 +2583,635 @@ static int dib8000_autosearch_irq(struct dvb_frontend *fe) struct dib8000_state *state = fe->demodulator_priv; u16 irq_pending = dib8000_read_word(state, 1284); - if (irq_pending & 0x1) { // failed - dprintk("dib8000_autosearch_irq failed"); - return 1; - } + if (state->autosearch_state == AS_SEARCHING_FFT) { + if (irq_pending & 0x1) { + dprintk("dib8000_autosearch_irq: max correlation result available"); + return 3; + } + } else { + if (irq_pending & 0x1) { /* failed */ + dprintk("dib8000_autosearch_irq failed"); + return 1; + } - if (irq_pending & 0x2) { // succeeded - dprintk("dib8000_autosearch_irq succeeded"); - return 2; + if (irq_pending & 0x2) { /* succeeded */ + dprintk("dib8000_autosearch_irq succeeded"); + return 2; + } } return 0; // still pending } -static int dib8000_tune(struct dvb_frontend *fe) +static void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff) { - struct dib8000_state *state = fe->demodulator_priv; - int ret = 0; - u16 lock, value, mode; + u16 tmp; - // we are already tuned - just resuming from suspend - if (state == NULL) - return -EINVAL; + tmp = dib8000_read_word(state, 771); + if (onoff) /* start P_restart_chd : channel_decoder */ + dib8000_write_word(state, 771, tmp & 0xfffd); + else /* stop P_restart_chd : channel_decoder */ + dib8000_write_word(state, 771, tmp | (1<<1)); +} + +static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz) +{ + s16 unit_khz_dds_val; + u32 abs_offset_khz = ABS(offset_khz); + u32 dds = state->cfg.pll->ifreq & 0x1ffffff; + u8 invert = !!(state->cfg.pll->ifreq & (1 << 25)); + u8 ratio; - mode = fft_to_mode(state); + if (state->revision == 0x8090) { + ratio = 4; + unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000); + if (offset_khz < 0) + dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val); + else + dds = (abs_offset_khz * unit_khz_dds_val); - dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000); - dib8000_set_channel(state, 0, 0); + if (invert) + dds = (1<<26) - dds; + } else { + ratio = 2; + unit_khz_dds_val = (u16) (67108864 / state->cfg.pll->internal); - // restart demod - ret |= dib8000_write_word(state, 770, 0x4000); - ret |= dib8000_write_word(state, 770, 0x0000); - msleep(45); + if (offset_khz < 0) + unit_khz_dds_val *= -1; - /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3 */ - /* ret |= dib8000_write_word(state, 29, (0 << 9) | (4 << 5) | (0 << 4) | (3 << 0) ); workaround inh_isi stays at 1 */ + /* IF tuner */ + if (invert) + dds -= abs_offset_khz * unit_khz_dds_val; + else + dds += abs_offset_khz * unit_khz_dds_val; + } - // never achieved a lock before - wait for timfreq to update - if (state->timf == 0) { - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) - msleep(300); - else // Sound Broadcasting mode 3 seg - msleep(500); - } else // 13 seg - msleep(200); + dprintk("setting a DDS frequency offset of %c%dkHz", invert ? '-' : ' ', dds / unit_khz_dds_val); + + if (abs_offset_khz <= (state->cfg.pll->internal / ratio)) { + /* Max dds offset is the half of the demod freq */ + dib8000_write_word(state, 26, invert); + dib8000_write_word(state, 27, (u16)(dds >> 16) & 0x1ff); + dib8000_write_word(state, 28, (u16)(dds & 0xffff)); } - if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { - if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { +} - /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40 alpha to check on board */ - dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40); - //dib8000_write_word(state, 32, (8 << 12) | (6 << 8) | 0x80); +static void dib8000_set_frequency_offset(struct dib8000_state *state) +{ + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + int i; + u32 current_rf; + int total_dds_offset_khz; - /* P_ctrl_sfreq_step= (12-P_mode) P_ctrl_sfreq_inh =0 P_ctrl_pha_off_max */ - ret |= dib8000_write_word(state, 37, (12 - mode) | ((5 + mode) << 5)); + if (state->fe[0]->ops.tuner_ops.get_frequency) + state->fe[0]->ops.tuner_ops.get_frequency(state->fe[0], ¤t_rf); + else + current_rf = c->frequency; + current_rf /= 1000; + total_dds_offset_khz = (int)current_rf - (int)c->frequency / 1000; - } else { // Sound Broadcasting mode 3 seg + if (c->isdbt_sb_mode) { + state->subchannel = c->isdbt_sb_subchannel; - /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 alpha to check on board */ - dib8000_write_word(state, 32, ((12 - mode) << 12) | (6 << 8) | 0x60); + i = dib8000_read_word(state, 26) & 1; /* P_dds_invspec */ + dib8000_write_word(state, 26, c->inversion ^ i); - ret |= dib8000_write_word(state, 37, (11 - mode) | ((5 + mode) << 5)); + if (state->cfg.pll->ifreq == 0) { /* low if tuner */ + if ((c->inversion ^ i) == 0) + dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1); + } else { + if ((c->inversion ^ i) == 0) + total_dds_offset_khz *= -1; } + } - } else { // 13 seg - /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 alpha to check on board */ - dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x80); + dprintk("%dkhz tuner offset (frequency = %dHz & current_rf = %dHz) total_dds_offset_hz = %d", c->frequency - current_rf, c->frequency, current_rf, total_dds_offset_khz); - ret |= dib8000_write_word(state, 37, (10 - mode) | ((5 + mode) << 5)); + /* apply dds offset now */ + dib8000_set_dds(state, total_dds_offset_khz); +} + +static u16 LUT_isdbt_symbol_duration[4] = { 26, 101, 63 }; + +static u32 dib8000_get_symbol_duration(struct dib8000_state *state) +{ + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + u16 i; + switch (c->transmission_mode) { + case TRANSMISSION_MODE_2K: + i = 0; + break; + case TRANSMISSION_MODE_4K: + i = 2; + break; + default: + case TRANSMISSION_MODE_AUTO: + case TRANSMISSION_MODE_8K: + i = 1; + break; } - // we achieved a coff_cpil_lock - it's time to update the timf - if (state->revision != 0x8090) - lock = dib8000_read_word(state, 568); + return (LUT_isdbt_symbol_duration[i] / (c->bandwidth_hz / 1000)) + 1; +} + +static void dib8000_set_isdbt_loop_params(struct dib8000_state *state, enum param_loop_step loop_step) +{ + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + u16 reg_32 = 0, reg_37 = 0; + + switch (loop_step) { + case LOOP_TUNE_1: + if (c->isdbt_sb_mode) { + if (c->isdbt_partial_reception == 0) { + reg_32 = ((11 - state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x40 */ + reg_37 = (3 << 5) | (0 << 4) | (10 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */ + } else { /* Sound Broadcasting mode 3 seg */ + reg_32 = ((10 - state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x60 */ + reg_37 = (3 << 5) | (0 << 4) | (9 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (9-P_mode) */ + } + } else { /* 13-seg start conf offset loop parameters */ + reg_32 = ((9 - state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */ + reg_37 = (3 << 5) | (0 << 4) | (8 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */ + } + break; + case LOOP_TUNE_2: + if (c->isdbt_sb_mode) { + if (c->isdbt_partial_reception == 0) { /* Sound Broadcasting mode 1 seg */ + reg_32 = ((13-state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40*/ + reg_37 = (12-state->mode) | ((5 + state->mode) << 5); + } else { /* Sound Broadcasting mode 3 seg */ + reg_32 = ((12-state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 */ + reg_37 = (11-state->mode) | ((5 + state->mode) << 5); + } + } else { /* 13 seg */ + reg_32 = ((11-state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 */ + reg_37 = ((5+state->mode) << 5) | (10 - state->mode); + } + break; + } + dib8000_write_word(state, 32, reg_32); + dib8000_write_word(state, 37, reg_37); +} + +static void dib8000_demod_restart(struct dib8000_state *state) +{ + dib8000_write_word(state, 770, 0x4000); + dib8000_write_word(state, 770, 0x0000); + return; +} + +static void dib8000_set_sync_wait(struct dib8000_state *state) +{ + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + u16 sync_wait = 64; + + /* P_dvsy_sync_wait - reuse mode */ + switch (c->transmission_mode) { + case TRANSMISSION_MODE_8K: + sync_wait = 256; + break; + case TRANSMISSION_MODE_4K: + sync_wait = 128; + break; + default: + case TRANSMISSION_MODE_2K: + sync_wait = 64; + break; + } + + if (state->cfg.diversity_delay == 0) + sync_wait = (sync_wait * (1 << (c->guard_interval)) * 3) / 2 + 48; /* add 50% SFN margin + compensate for one DVSY-fifo */ else - lock = dib8000_read_word(state, 570); - if ((lock >> 11) & 0x1) - dib8000_update_timf(state); + sync_wait = (sync_wait * (1 << (c->guard_interval)) * 3) / 2 + state->cfg.diversity_delay; /* add 50% SFN margin + compensate for DVSY-fifo */ - //now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start - dib8000_write_word(state, 6, 0x200); + dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4)); +} - if (state->revision == 0x8002) { - value = dib8000_read_word(state, 903); - dib8000_write_word(state, 903, value & ~(1 << 3)); - msleep(1); - dib8000_write_word(state, 903, value | (1 << 3)); +static u32 dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode) +{ + if (mode == SYMBOL_DEPENDENT_ON) + return systime() + (delay * state->symbol_duration); + else + return systime() + delay; +} + +static s32 dib8000_get_status(struct dvb_frontend *fe) +{ + struct dib8000_state *state = fe->demodulator_priv; + return state->status; +} + +enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) +{ + struct dib8000_state *state = fe->demodulator_priv; + return state->tune_state; +} +EXPORT_SYMBOL(dib8000_get_tune_state); + +int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) +{ + struct dib8000_state *state = fe->demodulator_priv; + + state->tune_state = tune_state; + return 0; +} +EXPORT_SYMBOL(dib8000_set_tune_state); + +static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe) +{ + struct dib8000_state *state = fe->demodulator_priv; + + state->status = FE_STATUS_TUNE_PENDING; + state->tune_state = CT_DEMOD_START; + return 0; +} + +static u16 dib8000_read_lock(struct dvb_frontend *fe) +{ + struct dib8000_state *state = fe->demodulator_priv; + + if (state->revision == 0x8090) + return dib8000_read_word(state, 570); + return dib8000_read_word(state, 568); +} + +static int dib8090p_init_sdram(struct dib8000_state *state) +{ + u16 reg = 0; + dprintk("init sdram"); + + reg = dib8000_read_word(state, 274) & 0xfff0; + dib8000_write_word(state, 274, reg | 0x7); /* P_dintlv_delay_ram = 7 because of MobileSdram */ + + dib8000_write_word(state, 1803, (7 << 2)); + + reg = dib8000_read_word(state, 1280); + dib8000_write_word(state, 1280, reg | (1 << 2)); /* force restart P_restart_sdram */ + dib8000_write_word(state, 1280, reg); /* release restart P_restart_sdram */ + + return 0; +} + +static int dib8000_tune(struct dvb_frontend *fe) +{ + struct dib8000_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + enum frontend_tune_state *tune_state = &state->tune_state; + + u16 locks, deeper_interleaver = 0, i; + int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */ + + u32 *timeout = &state->timeout; + u32 now = systime(); +#ifdef DIB8000_AGC_FREEZE + u16 agc1, agc2; +#endif + + u32 corm[4] = {0, 0, 0, 0}; + u8 find_index, max_value; + +#if 0 + if (*tune_state < CT_DEMOD_STOP) + dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u systime = %u", state->channel_parameters_set, *tune_state, state->autosearch_state, now); +#endif + + switch (*tune_state) { + case CT_DEMOD_START: /* 30 */ + if (state->revision == 0x8090) + dib8090p_init_sdram(state); + state->status = FE_STATUS_TUNE_PENDING; + if ((c->delivery_system != SYS_ISDBT) || + (c->inversion == INVERSION_AUTO) || + (c->transmission_mode == TRANSMISSION_MODE_AUTO) || + (c->guard_interval == GUARD_INTERVAL_AUTO) || + (((c->isdbt_layer_enabled & (1 << 0)) != 0) && + (c->layer[0].segment_count != 0xff) && + (c->layer[0].segment_count != 0) && + ((c->layer[0].modulation == QAM_AUTO) || + (c->layer[0].fec == FEC_AUTO))) || + (((c->isdbt_layer_enabled & (1 << 1)) != 0) && + (c->layer[1].segment_count != 0xff) && + (c->layer[1].segment_count != 0) && + ((c->layer[1].modulation == QAM_AUTO) || + (c->layer[1].fec == FEC_AUTO))) || + (((c->isdbt_layer_enabled & (1 << 2)) != 0) && + (c->layer[2].segment_count != 0xff) && + (c->layer[2].segment_count != 0) && + ((c->layer[2].modulation == QAM_AUTO) || + (c->layer[2].fec == FEC_AUTO))) || + (((c->layer[0].segment_count == 0) || + ((c->isdbt_layer_enabled & (1 << 0)) == 0)) && + ((c->layer[1].segment_count == 0) || + ((c->isdbt_layer_enabled & (2 << 0)) == 0)) && + ((c->layer[2].segment_count == 0) || ((c->isdbt_layer_enabled & (3 << 0)) == 0)))) + state->channel_parameters_set = 0; /* auto search */ + else + state->channel_parameters_set = 1; /* channel parameters are known */ + + dib8000_viterbi_state(state, 0); /* force chan dec in restart */ + + /* Layer monit */ + dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); + + dib8000_set_frequency_offset(state); + dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000); + + if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */ +#ifdef DIB8000_AGC_FREEZE + if (state->revision != 0x8090) { + state->agc1_max = dib8000_read_word(state, 108); + state->agc1_min = dib8000_read_word(state, 109); + state->agc2_max = dib8000_read_word(state, 110); + state->agc2_min = dib8000_read_word(state, 111); + agc1 = dib8000_read_word(state, 388); + agc2 = dib8000_read_word(state, 389); + dib8000_write_word(state, 108, agc1); + dib8000_write_word(state, 109, agc1); + dib8000_write_word(state, 110, agc2); + dib8000_write_word(state, 111, agc2); + } +#endif + state->autosearch_state = AS_SEARCHING_FFT; + state->found_nfft = TRANSMISSION_MODE_AUTO; + state->found_guard = GUARD_INTERVAL_AUTO; + *tune_state = CT_DEMOD_SEARCH_NEXT; + } else { /* we already know the channel struct so TUNE only ! */ + state->autosearch_state = AS_DONE; + *tune_state = CT_DEMOD_STEP_3; + } + state->symbol_duration = dib8000_get_symbol_duration(state); + break; + + case CT_DEMOD_SEARCH_NEXT: /* 51 */ + dib8000_autosearch_start(fe); + if (state->revision == 0x8090) + ret = 50; + else + ret = 15; + *tune_state = CT_DEMOD_STEP_1; + break; + + case CT_DEMOD_STEP_1: /* 31 */ + switch (dib8000_autosearch_irq(fe)) { + case 1: /* fail */ + state->status = FE_STATUS_TUNE_FAILED; + state->autosearch_state = AS_DONE; + *tune_state = CT_DEMOD_STOP; /* else we are done here */ + break; + case 2: /* Succes */ + state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */ + *tune_state = CT_DEMOD_STEP_3; + if (state->autosearch_state == AS_SEARCHING_GUARD) + *tune_state = CT_DEMOD_STEP_2; + else + state->autosearch_state = AS_DONE; + break; + case 3: /* Autosearch FFT max correlation endded */ + *tune_state = CT_DEMOD_STEP_2; + break; + } + break; + + case CT_DEMOD_STEP_2: + switch (state->autosearch_state) { + case AS_SEARCHING_FFT: + /* searching for the correct FFT */ + if (state->revision == 0x8090) { + corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597)); + corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599)); + corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601)); + } else { + corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595)); + corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597)); + corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599)); + } + /* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */ + + max_value = 0; + for (find_index = 1 ; find_index < 3 ; find_index++) { + if (corm[max_value] < corm[find_index]) + max_value = find_index ; + } + + switch (max_value) { + case 0: + state->found_nfft = TRANSMISSION_MODE_2K; + break; + case 1: + state->found_nfft = TRANSMISSION_MODE_4K; + break; + case 2: + default: + state->found_nfft = TRANSMISSION_MODE_8K; + break; + } + /* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */ + + *tune_state = CT_DEMOD_SEARCH_NEXT; + state->autosearch_state = AS_SEARCHING_GUARD; + if (state->revision == 0x8090) + ret = 50; + else + ret = 10; + break; + case AS_SEARCHING_GUARD: + /* searching for the correct guard interval */ + if (state->revision == 0x8090) + state->found_guard = dib8000_read_word(state, 572) & 0x3; + else + state->found_guard = dib8000_read_word(state, 570) & 0x3; + /* dprintk("guard interval found=%i", state->found_guard); */ + + *tune_state = CT_DEMOD_STEP_3; + break; + default: + /* the demod should never be in this state */ + state->status = FE_STATUS_TUNE_FAILED; + state->autosearch_state = AS_DONE; + *tune_state = CT_DEMOD_STOP; /* else we are done here */ + break; + } + break; + + case CT_DEMOD_STEP_3: /* 33 */ + state->symbol_duration = dib8000_get_symbol_duration(state); + dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1); + dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */ + *tune_state = CT_DEMOD_STEP_4; + break; + + case CT_DEMOD_STEP_4: /* (34) */ + dib8000_demod_restart(state); + + dib8000_set_sync_wait(state); + dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); + + locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */ + /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */ + *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON); + *tune_state = CT_DEMOD_STEP_5; + break; + + case CT_DEMOD_STEP_5: /* (35) */ + locks = dib8000_read_lock(fe); + if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */ + dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */ + if (!state->differential_constellation) { + /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */ + *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON); + *tune_state = CT_DEMOD_STEP_7; + } else { + *tune_state = CT_DEMOD_STEP_8; + } + } else if (now > *timeout) { + *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */ + } + break; + + case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */ + if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) { + /* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */ + if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */ + *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */ + else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */ + *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */ + dib8000_viterbi_state(state, 1); /* start viterbi chandec */ + dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); + state->status = FE_STATUS_TUNE_FAILED; + } + } else { + dib8000_viterbi_state(state, 1); /* start viterbi chandec */ + dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); + *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */ + state->status = FE_STATUS_TUNE_FAILED; + } + break; + + case CT_DEMOD_STEP_7: /* 37 */ + locks = dib8000_read_lock(fe); + if (locks & (1<<10)) { /* lmod4_lock */ + ret = 14; /* wait for 14 symbols */ + *tune_state = CT_DEMOD_STEP_8; + } else if (now > *timeout) + *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */ + break; + + case CT_DEMOD_STEP_8: /* 38 */ + dib8000_viterbi_state(state, 1); /* start viterbi chandec */ + dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); + + /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/ + if (c->isdbt_sb_mode + && c->isdbt_sb_subchannel < 14 + && !state->differential_constellation) { + state->subchannel = 0; + *tune_state = CT_DEMOD_STEP_11; + } else { + *tune_state = CT_DEMOD_STEP_9; + state->status = FE_STATUS_LOCKED; + } + break; + + case CT_DEMOD_STEP_9: /* 39 */ + if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */ + /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */ + for (i = 0; i < 3; i++) { + if (c->layer[i].interleaving >= deeper_interleaver) { + dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving); + if (c->layer[i].segment_count > 0) { /* valid layer */ + deeper_interleaver = c->layer[0].interleaving; + state->longest_intlv_layer = i; + } + } + } + + if (deeper_interleaver == 0) + locks = 2; /* locks is the tmp local variable name */ + else if (deeper_interleaver == 3) + locks = 8; + else + locks = 2 * deeper_interleaver; + + if (state->diversity_onoff != 0) /* because of diversity sync */ + locks *= 2; + + *timeout = now + (2000 * locks); /* give the mpeg lock 800ms if sram is present */ + dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %d", deeper_interleaver, state->longest_intlv_layer, locks, *timeout); + + *tune_state = CT_DEMOD_STEP_10; + } else + *tune_state = CT_DEMOD_STOP; + break; + + case CT_DEMOD_STEP_10: /* 40 */ + locks = dib8000_read_lock(fe); + if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */ + dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1); + if (c->isdbt_sb_mode + && c->isdbt_sb_subchannel < 14 + && !state->differential_constellation) + /* signal to the upper layer, that there was a channel found and the parameters can be read */ + state->status = FE_STATUS_DEMOD_SUCCESS; + else + state->status = FE_STATUS_DATA_LOCKED; + *tune_state = CT_DEMOD_STOP; + } else if (now > *timeout) { + if (c->isdbt_sb_mode + && c->isdbt_sb_subchannel < 14 + && !state->differential_constellation) { /* continue to try init prbs autosearch */ + state->subchannel += 3; + *tune_state = CT_DEMOD_STEP_11; + } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */ + if (locks & (0x7<<5)) { + dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1); + state->status = FE_STATUS_DATA_LOCKED; + } else + state->status = FE_STATUS_TUNE_FAILED; + *tune_state = CT_DEMOD_STOP; + } + } + break; + + case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */ + if (state->subchannel <= 41) { + dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel)); + *tune_state = CT_DEMOD_STEP_9; + } else { + *tune_state = CT_DEMOD_STOP; + state->status = FE_STATUS_TUNE_FAILED; + } + break; + + default: + break; + } + + /* tuning is finished - cleanup the demod */ + switch (*tune_state) { + case CT_DEMOD_STOP: /* (42) */ +#ifdef DIB8000_AGC_FREEZE + if ((state->revision != 0x8090) && (state->agc1_max != 0)) { + dib8000_write_word(state, 108, state->agc1_max); + dib8000_write_word(state, 109, state->agc1_min); + dib8000_write_word(state, 110, state->agc2_max); + dib8000_write_word(state, 111, state->agc2_min); + state->agc1_max = 0; + state->agc1_min = 0; + state->agc2_max = 0; + state->agc2_min = 0; + } +#endif + ret = FE_CALLBACK_TIME_NEVER; + break; + default: + break; } + if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3)) + return ret * state->symbol_duration; + if ((ret > 0) && (ret < state->symbol_duration)) + return state->symbol_duration; /* at least one symbol */ return ret; } @@ -2767,7 +3226,7 @@ static int dib8000_wakeup(struct dvb_frontend *fe) if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) dprintk("could not start Slow ADC"); - if (state->revision != 0x8090) + if (state->revision == 0x8090) dib8000_sad_calib(state); for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { @@ -2797,21 +3256,6 @@ static int dib8000_sleep(struct dvb_frontend *fe) return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); } -enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) -{ - struct dib8000_state *state = fe->demodulator_priv; - return state->tune_state; -} -EXPORT_SYMBOL(dib8000_get_tune_state); - -int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) -{ - struct dib8000_state *state = fe->demodulator_priv; - state->tune_state = tune_state; - return 0; -} -EXPORT_SYMBOL(dib8000_set_tune_state); - static int dib8000_get_frontend(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; @@ -2961,19 +3405,19 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) static int dib8000_set_frontend(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; - u8 nbr_pending, exit_condition, index_frontend; - s8 index_frontend_success = -1; - int time, ret; - int time_slave = FE_CALLBACK_TIME_NEVER; + struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; + int l, i, active, time, ret, time_slave = FE_CALLBACK_TIME_NEVER; + u8 exit_condition, index_frontend; + u32 delay, callback_time; - if (state->fe[0]->dtv_property_cache.frequency == 0) { + if (c->frequency == 0) { dprintk("dib8000: must at least specify frequency "); return 0; } - if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) { + if (c->bandwidth_hz == 0) { dprintk("dib8000: no bandwidth specified, set to default "); - state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000; + c->bandwidth_hz = 6000000; } for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { @@ -2981,18 +3425,36 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT; memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties)); - if (state->revision != 0x8090) - dib8000_set_output_mode(state->fe[index_frontend], - OUTMODE_HIGH_Z); - else - dib8096p_set_output_mode(state->fe[index_frontend], - OUTMODE_HIGH_Z); + /* set output mode and diversity input */ + if (state->revision != 0x8090) { + dib8000_set_diversity_in(state->fe[index_frontend], 1); + if (index_frontend != 0) + dib8000_set_output_mode(state->fe[index_frontend], + OUTMODE_DIVERSITY); + else + dib8000_set_output_mode(state->fe[0], OUTMODE_HIGH_Z); + } else { + dib8096p_set_diversity_in(state->fe[index_frontend], 1); + if (index_frontend != 0) + dib8096p_set_output_mode(state->fe[index_frontend], + OUTMODE_DIVERSITY); + else + dib8096p_set_output_mode(state->fe[0], OUTMODE_HIGH_Z); + } + + /* tune the tuner */ if (state->fe[index_frontend]->ops.tuner_ops.set_params) state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]); dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START); } + /* turn off the diversity of the last chip */ + if (state->revision != 0x8090) + dib8000_set_diversity_in(state->fe[index_frontend - 1], 0); + else + dib8096p_set_diversity_in(state->fe[index_frontend - 1], 0); + /* start up the AGC */ do { time = dib8000_agc_startup(state->fe[0]); @@ -3019,139 +3481,88 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START); - if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) || - (state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) || - (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) || - (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) || - (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) && - (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) && - (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) && - ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) || - (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) || - (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) && - (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) && - (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) && - ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) || - (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) || - (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) && - (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) && - (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) && - ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) || - (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) || - (((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) || - ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) && - ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) || - ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) && - ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) { - int i = 100; - u8 found = 0; - u8 tune_failed = 0; - + active = 1; + do { + callback_time = FE_CALLBACK_TIME_NEVER; for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - dib8000_set_bandwidth(state->fe[index_frontend], fe->dtv_property_cache.bandwidth_hz / 1000); - dib8000_autosearch_start(state->fe[index_frontend]); - } - - do { - msleep(20); - nbr_pending = 0; - exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */ - for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - if (((tune_failed >> index_frontend) & 0x1) == 0) { - found = dib8000_autosearch_irq(state->fe[index_frontend]); - switch (found) { - case 0: /* tune pending */ - nbr_pending++; - break; - case 2: - dprintk("autosearch succeed on the frontend%i", index_frontend); - exit_condition = 2; - index_frontend_success = index_frontend; - break; - default: - dprintk("unhandled autosearch result"); - case 1: - tune_failed |= (1 << index_frontend); - dprintk("autosearch failed for the frontend%i", index_frontend); - break; + delay = dib8000_tune(state->fe[index_frontend]); + if (delay != FE_CALLBACK_TIME_NEVER) + delay += systime(); + + /* we are in autosearch */ + if (state->channel_parameters_set == 0) { /* searching */ + if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) { + dprintk("autosearch succeeded on fe%i", index_frontend); + dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */ + state->channel_parameters_set = 1; + + for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) { + if (l != index_frontend) { /* and for all frontend except the successful one */ + dib8000_tune_restart_from_demod(state->fe[l]); + + state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; + state->fe[l]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion; + state->fe[l]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode; + state->fe[l]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval; + state->fe[l]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception; + for (i = 0; i < 3; i++) { + state->fe[l]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count; + state->fe[l]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving; + state->fe[l]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec; + state->fe[l]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation; + } + + } } } } - - /* if all tune are done and no success, exit: tune failed */ - if ((nbr_pending == 0) && (exit_condition == 0)) - exit_condition = 1; - } while ((exit_condition == 0) && i--); - - if (exit_condition == 1) { /* tune failed */ - dprintk("tune failed"); - return 0; + if (delay < callback_time) + callback_time = delay; + } + /* tuning is done when the master frontend is done (failed or success) */ + if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED || + dib8000_get_status(state->fe[0]) == FE_STATUS_LOCKED || + dib8000_get_status(state->fe[0]) == FE_STATUS_DATA_LOCKED) { + active = 0; + /* we need to wait for all frontends to be finished */ + for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_DEMOD_STOP) + active = 1; + } + if (active == 0) + dprintk("tuning done with status %d", dib8000_get_status(state->fe[0])); } - dprintk("tune success on frontend%i", index_frontend_success); - - dib8000_get_frontend(fe); - } + if ((active == 1) && (callback_time == FE_CALLBACK_TIME_NEVER)) { + dprintk("strange callback time something went wrong"); + active = 0; + } - for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) - ret = dib8000_tune(state->fe[index_frontend]); + while ((active == 1) && (systime() < callback_time)) + msleep(100); + } while (active); - /* set output mode and diversity input */ - if (state->revision != 0x8090) { + /* set output mode */ + if (state->revision != 0x8090) dib8000_set_output_mode(state->fe[0], state->cfg.output_mode); - for (index_frontend = 1; - (index_frontend < MAX_NUMBER_OF_FRONTENDS) && - (state->fe[index_frontend] != NULL); - index_frontend++) { - dib8000_set_output_mode(state->fe[index_frontend], - OUTMODE_DIVERSITY); - dib8000_set_diversity_in(state->fe[index_frontend-1], 1); - } - - /* turn off the diversity of the last chip */ - dib8000_set_diversity_in(state->fe[index_frontend-1], 0); - } else { + else { dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode); if (state->cfg.enMpegOutput == 0) { dib8096p_setDibTxMux(state, MPEG_ON_DIBTX); dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); } - for (index_frontend = 1; - (index_frontend < MAX_NUMBER_OF_FRONTENDS) && - (state->fe[index_frontend] != NULL); - index_frontend++) { - dib8096p_set_output_mode(state->fe[index_frontend], - OUTMODE_DIVERSITY); - dib8096p_set_diversity_in(state->fe[index_frontend-1], 1); - } - - /* turn off the diversity of the last chip */ - dib8096p_set_diversity_in(state->fe[index_frontend-1], 0); } return ret; } -static u16 dib8000_read_lock(struct dvb_frontend *fe) -{ - struct dib8000_state *state = fe->demodulator_priv; - - if (state->revision == 0x8090) - return dib8000_read_word(state, 570); - return dib8000_read_word(state, 568); -} - static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) { struct dib8000_state *state = fe->demodulator_priv; u16 lock_slave = 0, lock; u8 index_frontend; - if (state->revision == 0x8090) - lock = dib8000_read_word(state, 570); - else - lock = dib8000_read_word(state, 568); - + lock = dib8000_read_lock(fe); for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) lock_slave |= dib8000_read_lock(state->fe[index_frontend]); @@ -3545,10 +3956,11 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s dib8000_reset(fe); dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */ + state->current_demod_bw = 6000; return fe; - error: +error: kfree(state); return NULL; } diff --git a/drivers/media/dvb-frontends/dib8000.h b/drivers/media/dvb-frontends/dib8000.h index 9e7a2b1..b8c11e5 100644 --- a/drivers/media/dvb-frontends/dib8000.h +++ b/drivers/media/dvb-frontends/dib8000.h @@ -33,6 +33,8 @@ struct dib8000_config { u8 output_mode; u8 refclksel; u8 enMpegOutput:1; + + struct dibx000_bandwidth_config *plltable; }; #define DEFAULT_DIB8000_I2C_ADDRESS 18 @@ -58,7 +60,7 @@ extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ); extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf); extern int dib8000_update_pll(struct dvb_frontend *fe, - struct dibx000_bandwidth_config *pll); + struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio); extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave); extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe); extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index); @@ -147,7 +149,7 @@ static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe, return 0; } static inline int dib8000_update_pll(struct dvb_frontend *fe, - struct dibx000_bandwidth_config *pll) + struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; diff --git a/drivers/media/dvb-frontends/dibx000_common.h b/drivers/media/dvb-frontends/dibx000_common.h index 5f48488..b538e05 100644 --- a/drivers/media/dvb-frontends/dibx000_common.h +++ b/drivers/media/dvb-frontends/dibx000_common.h @@ -193,7 +193,8 @@ enum frontend_tune_state { CT_DEMOD_STEP_8, CT_DEMOD_STEP_9, CT_DEMOD_STEP_10, - CT_DEMOD_SEARCH_NEXT = 41, + CT_DEMOD_STEP_11, + CT_DEMOD_SEARCH_NEXT = 51, CT_DEMOD_STEP_LOCKED, CT_DEMOD_STOP, diff --git a/drivers/media/dvb-frontends/drxd.h b/drivers/media/dvb-frontends/drxd.h index 216c8c3..5f1d6b5 100644 --- a/drivers/media/dvb-frontends/drxd.h +++ b/drivers/media/dvb-frontends/drxd.h @@ -24,6 +24,7 @@ #ifndef _DRXD_H_ #define _DRXD_H_ +#include <linux/kconfig.h> #include <linux/types.h> #include <linux/i2c.h> @@ -51,8 +52,7 @@ struct drxd_config { s16(*osc_deviation) (void *priv, s16 dev, int flag); }; -#if defined(CONFIG_DVB_DRXD) || \ - (defined(CONFIG_DVB_DRXD_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_DRXD) extern struct dvb_frontend *drxd_attach(const struct drxd_config *config, void *priv, struct i2c_adapter *i2c, diff --git a/drivers/media/dvb-frontends/drxk.h b/drivers/media/dvb-frontends/drxk.h index 94fecfb..e666718 100644 --- a/drivers/media/dvb-frontends/drxk.h +++ b/drivers/media/dvb-frontends/drxk.h @@ -1,6 +1,7 @@ #ifndef _DRXK_H_ #define _DRXK_H_ +#include <linux/kconfig.h> #include <linux/types.h> #include <linux/i2c.h> @@ -52,8 +53,7 @@ struct drxk_config { int qam_demod_parameter_count; }; -#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_DRXK) extern struct dvb_frontend *drxk_attach(const struct drxk_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index c2fc7da0d..ec24d71 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -1947,8 +1947,7 @@ static int ShutDown(struct drxk_state *state) return 0; } -static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus, - u32 Time) +static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus) { int status = -EINVAL; @@ -2490,32 +2489,6 @@ error: return status; } -static int ReadIFAgc(struct drxk_state *state, u32 *pValue) -{ - u16 agcDacLvl; - int status; - u16 Level = 0; - - dprintk(1, "\n"); - - status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl); - if (status < 0) { - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - return status; - } - - *pValue = 0; - - if (agcDacLvl > DRXK_AGC_DAC_OFFSET) - Level = agcDacLvl - DRXK_AGC_DAC_OFFSET; - if (Level < 14000) - *pValue = (14000 - Level) / 4; - else - *pValue = 0; - - return status; -} - static int GetQAMSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise) { @@ -2654,12 +2627,7 @@ static int GetDVBTSignalToNoise(struct drxk_state *state, /* log(x) x = (16bits + 16bits) << 15 ->32 bits */ c = Log10Times100(SqrErrIQ); - iMER = a + b; - /* No negative MER, clip to zero */ - if (iMER > c) - iMER -= c; - else - iMER = 0; + iMER = a + b - c; } *pSignalToNoise = iMER; @@ -6380,46 +6348,257 @@ static int drxk_set_parameters(struct dvb_frontend *fe) fe->ops.tuner_ops.get_if_frequency(fe, &IF); Start(state, 0, IF); + /* After set_frontend, stats aren't avaliable */ + p->strength.stat[0].scale = FE_SCALE_RELATIVE; + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + /* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */ return 0; } -static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) +static int get_strength(struct drxk_state *state, u64 *strength) { + int status; + struct SCfgAgc rfAgc, ifAgc; + u32 totalGain = 0; + u32 atten = 0; + u32 agcRange = 0; + u16 scu_lvl = 0; + u16 scu_coc = 0; + /* FIXME: those are part of the tuner presets */ + u16 tunerRfGain = 50; /* Default value on az6007 driver */ + u16 tunerIfGain = 40; /* Default value on az6007 driver */ + + *strength = 0; + + if (IsDVBT(state)) { + rfAgc = state->m_dvbtRfAgcCfg; + ifAgc = state->m_dvbtIfAgcCfg; + } else if (IsQAM(state)) { + rfAgc = state->m_qamRfAgcCfg; + ifAgc = state->m_qamIfAgcCfg; + } else { + rfAgc = state->m_atvRfAgcCfg; + ifAgc = state->m_atvIfAgcCfg; + } + + if (rfAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) { + /* SCU outputLevel */ + status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl); + if (status < 0) + return status; + + /* SCU c.o.c. */ + read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc); + if (status < 0) + return status; + + if (((u32) scu_lvl + (u32) scu_coc) < 0xffff) + rfAgc.outputLevel = scu_lvl + scu_coc; + else + rfAgc.outputLevel = 0xffff; + + /* Take RF gain into account */ + totalGain += tunerRfGain; + + /* clip output value */ + if (rfAgc.outputLevel < rfAgc.minOutputLevel) + rfAgc.outputLevel = rfAgc.minOutputLevel; + if (rfAgc.outputLevel > rfAgc.maxOutputLevel) + rfAgc.outputLevel = rfAgc.maxOutputLevel; + + agcRange = (u32) (rfAgc.maxOutputLevel - rfAgc.minOutputLevel); + if (agcRange > 0) { + atten += 100UL * + ((u32)(tunerRfGain)) * + ((u32)(rfAgc.outputLevel - rfAgc.minOutputLevel)) + / agcRange; + } + } + + if (ifAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) { + status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A, + &ifAgc.outputLevel); + if (status < 0) + return status; + + status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, + &ifAgc.top); + if (status < 0) + return status; + + /* Take IF gain into account */ + totalGain += (u32) tunerIfGain; + + /* clip output value */ + if (ifAgc.outputLevel < ifAgc.minOutputLevel) + ifAgc.outputLevel = ifAgc.minOutputLevel; + if (ifAgc.outputLevel > ifAgc.maxOutputLevel) + ifAgc.outputLevel = ifAgc.maxOutputLevel; + + agcRange = (u32) (ifAgc.maxOutputLevel - ifAgc.minOutputLevel); + if (agcRange > 0) { + atten += 100UL * + ((u32)(tunerIfGain)) * + ((u32)(ifAgc.outputLevel - ifAgc.minOutputLevel)) + / agcRange; + } + } + + /* + * Convert to 0..65535 scale. + * If it can't be measured (AGC is disabled), just show 100%. + */ + if (totalGain > 0) + *strength = (65535UL * atten / totalGain / 100); + else + *strength = 65535; + + return 0; +} + +static int drxk_get_stats(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct drxk_state *state = fe->demodulator_priv; + int status; u32 stat; - - dprintk(1, "\n"); + u16 reg16; + u32 post_bit_count; + u32 post_bit_err_count; + u32 post_bit_error_scale; + u32 pre_bit_err_count; + u32 pre_bit_count; + u32 pkt_count; + u32 pkt_error_count; + s32 cnr; if (state->m_DrxkState == DRXK_NO_DEV) return -ENODEV; if (state->m_DrxkState == DRXK_UNINITIALIZED) return -EAGAIN; - *status = 0; - GetLockStatus(state, &stat, 0); + /* get status */ + state->fe_status = 0; + GetLockStatus(state, &stat); if (stat == MPEG_LOCK) - *status |= 0x1f; + state->fe_status |= 0x1f; if (stat == FEC_LOCK) - *status |= 0x0f; + state->fe_status |= 0x0f; if (stat == DEMOD_LOCK) - *status |= 0x07; - return 0; + state->fe_status |= 0x07; + + /* + * Estimate signal strength from AGC + */ + get_strength(state, &c->strength.stat[0].uvalue); + c->strength.stat[0].scale = FE_SCALE_RELATIVE; + + + if (stat >= DEMOD_LOCK) { + GetSignalToNoise(state, &cnr); + c->cnr.stat[0].svalue = cnr * 100; + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + } else { + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + + if (stat < FEC_LOCK) { + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return 0; + } + + /* Get post BER */ + + /* BER measurement is valid if at least FEC lock is achieved */ + + /* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written + to set nr of symbols or bits over which + to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */ + + /* Read registers for post/preViterbi BER calculation */ + status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, ®16); + if (status < 0) + goto error; + pre_bit_err_count = reg16; + + status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , ®16); + if (status < 0) + goto error; + pre_bit_count = reg16; + + /* Number of bit-errors */ + status = read16(state, FEC_RS_NR_BIT_ERRORS__A, ®16); + if (status < 0) + goto error; + post_bit_err_count = reg16; + + status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, ®16); + if (status < 0) + goto error; + post_bit_error_scale = reg16; + + status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, ®16); + if (status < 0) + goto error; + pkt_count = reg16; + + status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, ®16); + if (status < 0) + goto error; + pkt_error_count = reg16; + write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); + + post_bit_err_count *= post_bit_error_scale; + + post_bit_count = pkt_count * 204 * 8; + + /* Store the results */ + c->block_error.stat[0].scale = FE_SCALE_COUNTER; + c->block_error.stat[0].uvalue += pkt_error_count; + c->block_count.stat[0].scale = FE_SCALE_COUNTER; + c->block_count.stat[0].uvalue += pkt_count; + + c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->pre_bit_error.stat[0].uvalue += pre_bit_err_count; + c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->pre_bit_count.stat[0].uvalue += pre_bit_count; + + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue += post_bit_err_count; + c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_count.stat[0].uvalue += post_bit_count; + +error: + return status; } -static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber) + +static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct drxk_state *state = fe->demodulator_priv; + int rc; dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) - return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) - return -EAGAIN; + rc = drxk_get_stats(fe); + if (rc < 0) + return rc; + + *status = state->fe_status; - *ber = 0; return 0; } @@ -6427,7 +6606,7 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct drxk_state *state = fe->demodulator_priv; - u32 val = 0; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; dprintk(1, "\n"); @@ -6436,8 +6615,7 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe, if (state->m_DrxkState == DRXK_UNINITIALIZED) return -EAGAIN; - ReadIFAgc(state, &val); - *strength = val & 0xffff; + *strength = c->strength.stat[0].uvalue; return 0; } @@ -6454,6 +6632,10 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr) return -EAGAIN; GetSignalToNoise(state, &snr2); + + /* No negative SNR, clip to zero */ + if (snr2 < 0) + snr2 = 0; *snr = snr2 & 0xffff; return 0; } @@ -6529,7 +6711,6 @@ static struct dvb_frontend_ops drxk_ops = { .get_tune_settings = drxk_get_tune_settings, .read_status = drxk_read_status, - .read_ber = drxk_read_ber, .read_signal_strength = drxk_read_signal_strength, .read_snr = drxk_read_snr, .read_ucblocks = drxk_read_ucblocks, @@ -6538,6 +6719,7 @@ static struct dvb_frontend_ops drxk_ops = { struct dvb_frontend *drxk_attach(const struct drxk_config *config, struct i2c_adapter *i2c) { + struct dtv_frontend_properties *p; struct drxk_state *state = NULL; u8 adr = config->adr; int status; @@ -6618,6 +6800,27 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, } else if (init_drxk(state) < 0) goto error; + + /* Initialize stats */ + p = &state->frontend.dtv_property_cache; + p->strength.len = 1; + p->cnr.len = 1; + p->block_error.len = 1; + p->block_count.len = 1; + p->pre_bit_error.len = 1; + p->pre_bit_count.len = 1; + p->post_bit_error.len = 1; + p->post_bit_count.len = 1; + + p->strength.stat[0].scale = FE_SCALE_RELATIVE; + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + printk(KERN_INFO "drxk: frontend initialized.\n"); return &state->frontend; diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h index d18a896..b8424f1 100644 --- a/drivers/media/dvb-frontends/drxk_hard.h +++ b/drivers/media/dvb-frontends/drxk_hard.h @@ -345,6 +345,8 @@ struct drxk_state { bool antenna_dvbt; u16 antenna_gpio; + fe_status_t fe_status; + /* Firmware */ const char *microcode_name; struct completion fw_wait_load; diff --git a/drivers/media/dvb-frontends/drxk_map.h b/drivers/media/dvb-frontends/drxk_map.h index 23e16c1..761613f 100644 --- a/drivers/media/dvb-frontends/drxk_map.h +++ b/drivers/media/dvb-frontends/drxk_map.h @@ -10,6 +10,7 @@ #define FEC_RS_COMM_EXEC_STOP 0x0 #define FEC_RS_MEASUREMENT_PERIOD__A 0x1C30012 #define FEC_RS_MEASUREMENT_PRESCALE__A 0x1C30013 +#define FEC_RS_NR_BIT_ERRORS__A 0x1C30014 #define FEC_OC_MODE__A 0x1C40011 #define FEC_OC_MODE_PARITY__M 0x1 #define FEC_OC_DTO_MODE__A 0x1C40014 @@ -129,6 +130,8 @@ #define OFDM_EC_SB_PRIOR__A 0x3410013 #define OFDM_EC_SB_PRIOR_HI 0x0 #define OFDM_EC_SB_PRIOR_LO 0x1 +#define OFDM_EC_VD_ERR_BIT_CNT__A 0x3420017 +#define OFDM_EC_VD_IN_BIT_CNT__A 0x3420018 #define OFDM_EQ_TOP_TD_TPS_CONST__A 0x3010054 #define OFDM_EQ_TOP_TD_TPS_CONST__M 0x3 #define OFDM_EQ_TOP_TD_TPS_CONST_64QAM 0x2 diff --git a/drivers/media/dvb-frontends/ds3000.h b/drivers/media/dvb-frontends/ds3000.h index 478ad66..f9c21fb 100644 --- a/drivers/media/dvb-frontends/ds3000.h +++ b/drivers/media/dvb-frontends/ds3000.h @@ -22,6 +22,7 @@ #ifndef DS3000_H #define DS3000_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct ds3000_config { @@ -34,8 +35,7 @@ struct ds3000_config { void (*set_lock_led)(struct dvb_frontend *fe, int offon); }; -#if defined(CONFIG_DVB_DS3000) || \ - (defined(CONFIG_DVB_DS3000_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_DS3000) extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.h b/drivers/media/dvb-frontends/dvb_dummy_fe.h index 1fcb987..0cbf961 100644 --- a/drivers/media/dvb-frontends/dvb_dummy_fe.h +++ b/drivers/media/dvb-frontends/dvb_dummy_fe.h @@ -22,11 +22,11 @@ #ifndef DVB_DUMMY_FE_H #define DVB_DUMMY_FE_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include "dvb_frontend.h" -#if defined(CONFIG_DVB_DUMMY_FE) || (defined(CONFIG_DVB_DUMMY_FE_MODULE) && \ -defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_DUMMY_FE) extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void); extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void); extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void); diff --git a/drivers/media/dvb-frontends/ec100.h b/drivers/media/dvb-frontends/ec100.h index b847971..3755840 100644 --- a/drivers/media/dvb-frontends/ec100.h +++ b/drivers/media/dvb-frontends/ec100.h @@ -22,6 +22,7 @@ #ifndef EC100_H #define EC100_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct ec100_config { @@ -30,8 +31,7 @@ struct ec100_config { }; -#if defined(CONFIG_DVB_EC100) || \ - (defined(CONFIG_DVB_EC100_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_EC100) extern struct dvb_frontend *ec100_attach(const struct ec100_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/hd29l2.h b/drivers/media/dvb-frontends/hd29l2.h index 4ad00d7..05cd130 100644 --- a/drivers/media/dvb-frontends/hd29l2.h +++ b/drivers/media/dvb-frontends/hd29l2.h @@ -23,6 +23,7 @@ #ifndef HD29L2_H #define HD29L2_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct hd29l2_config { @@ -50,8 +51,7 @@ struct hd29l2_config { }; -#if defined(CONFIG_DVB_HD29L2) || \ - (defined(CONFIG_DVB_HD29L2_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_HD29L2) extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/isl6421.c b/drivers/media/dvb-frontends/isl6421.c index 0cb3f0f..c77002f 100644 --- a/drivers/media/dvb-frontends/isl6421.c +++ b/drivers/media/dvb-frontends/isl6421.c @@ -89,6 +89,30 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO; } +static int isl6421_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv; + struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0, + .buf = &isl6421->config, + .len = sizeof(isl6421->config) }; + + switch (tone) { + case SEC_TONE_ON: + isl6421->config |= ISL6421_ENT1; + break; + case SEC_TONE_OFF: + isl6421->config &= ~ISL6421_ENT1; + break; + default: + return -EINVAL; + } + + isl6421->config |= isl6421->override_or; + isl6421->config &= isl6421->override_and; + + return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + static void isl6421_release(struct dvb_frontend *fe) { /* power off */ @@ -100,7 +124,7 @@ static void isl6421_release(struct dvb_frontend *fe) } struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, - u8 override_set, u8 override_clear) + u8 override_set, u8 override_clear, bool override_tone) { struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL); if (!isl6421) @@ -131,6 +155,8 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter /* override frontend ops */ fe->ops.set_voltage = isl6421_set_voltage; fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage; + if (override_tone) + fe->ops.set_tone = isl6421_set_tone; return fe; } diff --git a/drivers/media/dvb-frontends/isl6421.h b/drivers/media/dvb-frontends/isl6421.h index e7ca7d1..630e7f8 100644 --- a/drivers/media/dvb-frontends/isl6421.h +++ b/drivers/media/dvb-frontends/isl6421.h @@ -42,10 +42,10 @@ #if IS_ENABLED(CONFIG_DVB_ISL6421) /* override_set and override_clear control which system register bits (above) to always set & clear */ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, - u8 override_set, u8 override_clear); + u8 override_set, u8 override_clear, bool override_tone); #else static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, - u8 override_set, u8 override_clear) + u8 override_set, u8 override_clear, bool override_tone) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; diff --git a/drivers/media/dvb-frontends/it913x-fe.h b/drivers/media/dvb-frontends/it913x-fe.h index 07fa459..df0ad42 100644 --- a/drivers/media/dvb-frontends/it913x-fe.h +++ b/drivers/media/dvb-frontends/it913x-fe.h @@ -21,6 +21,7 @@ #ifndef IT913X_FE_H #define IT913X_FE_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include "dvb_frontend.h" @@ -38,8 +39,7 @@ struct ite_config { u8 read_slevel; }; -#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \ -defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_IT913X_FE) extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct ite_config *config); #else diff --git a/drivers/media/dvb-frontends/ix2505v.h b/drivers/media/dvb-frontends/ix2505v.h index 67e89d6..1a735a7 100644 --- a/drivers/media/dvb-frontends/ix2505v.h +++ b/drivers/media/dvb-frontends/ix2505v.h @@ -20,6 +20,7 @@ #ifndef DVB_IX2505V_H #define DVB_IX2505V_H +#include <linux/kconfig.h> #include <linux/i2c.h> #include "dvb_frontend.h" @@ -48,8 +49,7 @@ struct ix2505v_config { }; -#if defined(CONFIG_DVB_IX2505V) || \ - (defined(CONFIG_DVB_IX2505V_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_IX2505V) extern struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe, const struct ix2505v_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/lg2160.h b/drivers/media/dvb-frontends/lg2160.h index 9e2c0f4..194a07a 100644 --- a/drivers/media/dvb-frontends/lg2160.h +++ b/drivers/media/dvb-frontends/lg2160.h @@ -22,6 +22,7 @@ #ifndef _LG2160_H_ #define _LG2160_H_ +#include <linux/kconfig.h> #include <linux/i2c.h> #include "dvb_frontend.h" @@ -56,18 +57,17 @@ struct lg2160_config { u16 if_khz; /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */ - int deny_i2c_rptr:1; + unsigned int deny_i2c_rptr:1; /* spectral inversion - 0:disabled 1:enabled */ - int spectral_inversion:1; + unsigned int spectral_inversion:1; unsigned int output_if; enum lg2160_spi_clock spi_clock; enum lg_chip_type lg_chip; }; -#if defined(CONFIG_DVB_LG2160) || (defined(CONFIG_DVB_LG2160_MODULE) && \ - defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_LG2160) extern struct dvb_frontend *lg2160_attach(const struct lg2160_config *config, struct i2c_adapter *i2c_adap); diff --git a/drivers/media/dvb-frontends/lgdt3305.h b/drivers/media/dvb-frontends/lgdt3305.h index 02172ec..d9ab556 100644 --- a/drivers/media/dvb-frontends/lgdt3305.h +++ b/drivers/media/dvb-frontends/lgdt3305.h @@ -22,6 +22,7 @@ #ifndef _LGDT3305_H_ #define _LGDT3305_H_ +#include <linux/kconfig.h> #include <linux/i2c.h> #include "dvb_frontend.h" @@ -73,8 +74,7 @@ struct lgdt3305_config { enum lgdt_demod_chip_type demod_chip; }; -#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \ - defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_LGDT3305) extern struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, struct i2c_adapter *i2c_adap); diff --git a/drivers/media/dvb-frontends/lgs8gl5.h b/drivers/media/dvb-frontends/lgs8gl5.h index d1417678..c2da596 100644 --- a/drivers/media/dvb-frontends/lgs8gl5.h +++ b/drivers/media/dvb-frontends/lgs8gl5.h @@ -23,6 +23,7 @@ #ifndef LGS8GL5_H #define LGS8GL5_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct lgs8gl5_config { @@ -30,8 +31,7 @@ struct lgs8gl5_config { u8 demod_address; }; -#if defined(CONFIG_DVB_LGS8GL5) || \ - (defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_LGS8GL5) extern struct dvb_frontend *lgs8gl5_attach( const struct lgs8gl5_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/lgs8gxx.h b/drivers/media/dvb-frontends/lgs8gxx.h index 33c3c5e..dadb78b 100644 --- a/drivers/media/dvb-frontends/lgs8gxx.h +++ b/drivers/media/dvb-frontends/lgs8gxx.h @@ -26,6 +26,7 @@ #ifndef __LGS8GXX_H__ #define __LGS8GXX_H__ +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include <linux/i2c.h> @@ -79,8 +80,7 @@ struct lgs8gxx_config { u8 tuner_address; }; -#if defined(CONFIG_DVB_LGS8GXX) || \ - (defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_LGS8GXX) extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/lnbh24.h b/drivers/media/dvb-frontends/lnbh24.h index c059b16..b327a4f 100644 --- a/drivers/media/dvb-frontends/lnbh24.h +++ b/drivers/media/dvb-frontends/lnbh24.h @@ -23,6 +23,8 @@ #ifndef _LNBH24_H #define _LNBH24_H +#include <linux/kconfig.h> + /* system register bits */ #define LNBH24_OLF 0x01 #define LNBH24_OTF 0x02 @@ -35,8 +37,7 @@ #include <linux/dvb/frontend.h> -#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_LNBP21) /* override_set and override_clear control which system register bits (above) to always set & clear */ extern struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe, diff --git a/drivers/media/dvb-frontends/lnbp21.h b/drivers/media/dvb-frontends/lnbp21.h index fcdf1c6..dbcbcc2 100644 --- a/drivers/media/dvb-frontends/lnbp21.h +++ b/drivers/media/dvb-frontends/lnbp21.h @@ -27,6 +27,8 @@ #ifndef _LNBP21_H #define _LNBP21_H +#include <linux/kconfig.h> + /* system register bits */ /* [RO] 0=OK; 1=over current limit flag */ #define LNBP21_OLF 0x01 @@ -55,8 +57,7 @@ #include <linux/dvb/frontend.h> -#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_LNBP21) /* override_set and override_clear control which system register bits (above) to always set & clear */ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, diff --git a/drivers/media/dvb-frontends/lnbp22.h b/drivers/media/dvb-frontends/lnbp22.h index 63e2dec..63861b3 100644 --- a/drivers/media/dvb-frontends/lnbp22.h +++ b/drivers/media/dvb-frontends/lnbp22.h @@ -28,6 +28,8 @@ #ifndef _LNBP22_H #define _LNBP22_H +#include <linux/kconfig.h> + /* Enable */ #define LNBP22_EN 0x10 /* Voltage selection */ @@ -37,8 +39,7 @@ #include <linux/dvb/frontend.h> -#if defined(CONFIG_DVB_LNBP22) || \ - (defined(CONFIG_DVB_LNBP22_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_LNBP22) /* * override_set and override_clear control which system register bits (above) * to always set & clear diff --git a/drivers/media/dvb-frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h index 5a8023e..14ce31e 100644 --- a/drivers/media/dvb-frontends/m88rs2000.h +++ b/drivers/media/dvb-frontends/m88rs2000.h @@ -20,6 +20,7 @@ #ifndef M88RS2000_H #define M88RS2000_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include "dvb_frontend.h" @@ -40,8 +41,7 @@ enum { CALL_IS_READ, }; -#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \ - defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_M88RS2000) extern struct dvb_frontend *m88rs2000_attach( const struct m88rs2000_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index 4faaf80..856374b 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -20,10 +20,24 @@ #include "dvb_frontend.h" #include "mb86a20s.h" +#define NUM_LAYERS 3 + static int debug = 1; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); +enum mb86a20s_bandwidth { + MB86A20S_13SEG = 0, + MB86A20S_13SEG_PARTIAL = 1, + MB86A20S_1SEG = 2, + MB86A20S_3SEG = 3, +}; + +u8 mb86a20s_subchannel[] = { + 0xb0, 0xc0, 0xd0, 0xe0, + 0xf0, 0x00, 0x10, 0x20, +}; + struct mb86a20s_state { struct i2c_adapter *i2c; const struct mb86a20s_config *config; @@ -31,7 +45,13 @@ struct mb86a20s_state { struct dvb_frontend frontend; - u32 estimated_rate[3]; + u32 if_freq; + enum mb86a20s_bandwidth bw; + bool inversion; + u32 subchannel; + + u32 estimated_rate[NUM_LAYERS]; + unsigned long get_strength_time; bool need_init; }; @@ -47,35 +67,33 @@ struct regdata { * Initialization sequence: Use whatevere default values that PV SBTVD * does on its initialisation, obtained via USB snoop */ -static struct regdata mb86a20s_init[] = { +static struct regdata mb86a20s_init1[] = { { 0x70, 0x0f }, { 0x70, 0xff }, { 0x08, 0x01 }, - { 0x09, 0x3e }, - { 0x50, 0xd1 }, { 0x51, 0x22 }, - { 0x39, 0x01 }, - { 0x71, 0x00 }, - { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 }, - { 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 }, + { 0x50, 0xd1 }, { 0x51, 0x20 }, +}; + +static struct regdata mb86a20s_init2[] = { { 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 }, { 0x3b, 0x21 }, - { 0x3c, 0x3a }, + { 0x3c, 0x38 }, { 0x01, 0x0d }, - { 0x04, 0x08 }, { 0x05, 0x05 }, + { 0x04, 0x08 }, { 0x05, 0x03 }, { 0x04, 0x0e }, { 0x05, 0x00 }, - { 0x04, 0x0f }, { 0x05, 0x14 }, - { 0x04, 0x0b }, { 0x05, 0x8c }, + { 0x04, 0x0f }, { 0x05, 0x37 }, + { 0x04, 0x0b }, { 0x05, 0x78 }, { 0x04, 0x00 }, { 0x05, 0x00 }, - { 0x04, 0x01 }, { 0x05, 0x07 }, - { 0x04, 0x02 }, { 0x05, 0x0f }, - { 0x04, 0x03 }, { 0x05, 0xa0 }, + { 0x04, 0x01 }, { 0x05, 0x1e }, + { 0x04, 0x02 }, { 0x05, 0x07 }, + { 0x04, 0x03 }, { 0x05, 0xd0 }, { 0x04, 0x09 }, { 0x05, 0x00 }, { 0x04, 0x0a }, { 0x05, 0xff }, - { 0x04, 0x27 }, { 0x05, 0x64 }, + { 0x04, 0x27 }, { 0x05, 0x00 }, { 0x04, 0x28 }, { 0x05, 0x00 }, - { 0x04, 0x1e }, { 0x05, 0xff }, - { 0x04, 0x29 }, { 0x05, 0x0a }, - { 0x04, 0x32 }, { 0x05, 0x0a }, + { 0x04, 0x1e }, { 0x05, 0x00 }, + { 0x04, 0x29 }, { 0x05, 0x64 }, + { 0x04, 0x32 }, { 0x05, 0x02 }, { 0x04, 0x14 }, { 0x05, 0x02 }, { 0x04, 0x04 }, { 0x05, 0x00 }, { 0x04, 0x05 }, { 0x05, 0x22 }, @@ -142,39 +160,39 @@ static struct regdata mb86a20s_init[] = { { 0x50, 0xd5 }, { 0x51, 0x01 }, /* Serial */ { 0x50, 0xd6 }, { 0x51, 0x1f }, { 0x50, 0xd2 }, { 0x51, 0x03 }, - { 0x50, 0xd7 }, { 0x51, 0x3f }, - { 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 }, - { 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c }, + { 0x50, 0xd7 }, { 0x51, 0xbf }, + { 0x28, 0x74 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0xff }, + { 0x28, 0x46 }, { 0x29, 0x00 }, { 0x2a, 0x1a }, { 0x2b, 0x0c }, { 0x04, 0x40 }, { 0x05, 0x00 }, - { 0x28, 0x00 }, { 0x29, 0x10 }, - { 0x28, 0x05 }, { 0x29, 0x02 }, + { 0x28, 0x00 }, { 0x2b, 0x08 }, + { 0x28, 0x05 }, { 0x2b, 0x00 }, { 0x1c, 0x01 }, - { 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 }, - { 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d }, - { 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 }, - { 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 }, - { 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 }, - { 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 }, - { 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 }, - { 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 }, - { 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e }, - { 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e }, - { 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 }, - { 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f }, - { 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 }, - { 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 }, - { 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe }, - { 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 }, - { 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee }, - { 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 }, - { 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f }, - { 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 }, - { 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 }, - { 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a }, - { 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc }, - { 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba }, - { 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 }, + { 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x1f }, + { 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x18 }, + { 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x12 }, + { 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x30 }, + { 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x37 }, + { 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 }, + { 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x09 }, + { 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x06 }, + { 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x7b }, + { 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x76 }, + { 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x7d }, + { 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x08 }, + { 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0b }, + { 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 }, + { 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xf2 }, + { 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xf3 }, + { 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x05 }, + { 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 }, + { 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f }, + { 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xef }, + { 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xd8 }, + { 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xf1 }, + { 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x3d }, + { 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x94 }, + { 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0xba }, { 0x50, 0x1e }, { 0x51, 0x5d }, { 0x50, 0x22 }, { 0x51, 0x00 }, { 0x50, 0x23 }, { 0x51, 0xc8 }, @@ -183,6 +201,8 @@ static struct regdata mb86a20s_init[] = { { 0x50, 0x26 }, { 0x51, 0x00 }, { 0x50, 0x27 }, { 0x51, 0xc3 }, { 0x50, 0x39 }, { 0x51, 0x02 }, + { 0xec, 0x0f }, + { 0xeb, 0x1f }, { 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 }, { 0xd0, 0x00 }, }; @@ -308,15 +328,23 @@ static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status) dev_dbg(&state->i2c->dev, "%s: Status = 0x%02x (state = %d)\n", __func__, *status, val); - return 0; + return val; } static int mb86a20s_read_signal_strength(struct dvb_frontend *fe) { struct mb86a20s_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int rc; unsigned rf_max, rf_min, rf; + if (state->get_strength_time && + (!time_after(jiffies, state->get_strength_time))) + return c->strength.stat[0].uvalue; + + /* Reset its value if an error happen */ + c->strength.stat[0].uvalue = 0; + /* Does a binary search to get RF strength */ rf_max = 0xfff; rf_min = 0; @@ -331,7 +359,7 @@ static int mb86a20s_read_signal_strength(struct dvb_frontend *fe) rc = mb86a20s_writereg(state, 0x04, 0x20); if (rc < 0) return rc; - rc = mb86a20s_writereg(state, 0x04, rf); + rc = mb86a20s_writereg(state, 0x05, rf); if (rc < 0) return rc; @@ -346,15 +374,19 @@ static int mb86a20s_read_signal_strength(struct dvb_frontend *fe) rf = (rf_max + rf_min) / 2; /* Rescale it from 2^12 (4096) to 2^16 */ - rf <<= (16 - 12); + rf = rf << (16 - 12); + if (rf) + rf |= (1 << 12) - 1; + dev_dbg(&state->i2c->dev, "%s: signal strength = %d (%d < RF=%d < %d)\n", __func__, rf, rf_min, rf >> 4, rf_max); - return rf; + c->strength.stat[0].uvalue = rf; + state->get_strength_time = jiffies + + msecs_to_jiffies(1000); + return 0; } } while (1); - - return 0; } static int mb86a20s_get_modulation(struct mb86a20s_state *state, @@ -534,12 +566,13 @@ static u32 isdbt_rate[3][5][4] = { }; static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer, - u32 modulation, u32 fec, u32 interleaving, + u32 modulation, u32 forward_error_correction, + u32 interleaving, u32 segment) { struct mb86a20s_state *state = fe->demodulator_priv; u32 rate; - int m, f, i; + int mod, fec, guard; /* * If modulation/fec/interleaving is not detected, the default is @@ -550,54 +583,54 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer, case DQPSK: case QPSK: default: - m = 0; + mod = 0; break; case QAM_16: - m = 1; + mod = 1; break; case QAM_64: - m = 2; + mod = 2; break; } - switch (fec) { + switch (forward_error_correction) { default: case FEC_1_2: case FEC_AUTO: - f = 0; + fec = 0; break; case FEC_2_3: - f = 1; + fec = 1; break; case FEC_3_4: - f = 2; + fec = 2; break; case FEC_5_6: - f = 3; + fec = 3; break; case FEC_7_8: - f = 4; + fec = 4; break; } switch (interleaving) { default: case GUARD_INTERVAL_1_4: - i = 0; + guard = 0; break; case GUARD_INTERVAL_1_8: - i = 1; + guard = 1; break; case GUARD_INTERVAL_1_16: - i = 2; + guard = 2; break; case GUARD_INTERVAL_1_32: - i = 3; + guard = 3; break; } /* Samples BER at BER_SAMPLING_RATE seconds */ - rate = isdbt_rate[m][f][i] * segment * BER_SAMPLING_RATE; + rate = isdbt_rate[mod][fec][guard] * segment * BER_SAMPLING_RATE; /* Avoids sampling too quickly or to overflow the register */ if (rate < 256) @@ -607,18 +640,18 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer, dev_dbg(&state->i2c->dev, "%s: layer %c bitrate: %d kbps; counter = %d (0x%06x)\n", - __func__, 'A' + layer, segment * isdbt_rate[m][f][i]/1000, + __func__, 'A' + layer, + segment * isdbt_rate[mod][fec][guard]/1000, rate, rate); state->estimated_rate[layer] = rate; } - static int mb86a20s_get_frontend(struct dvb_frontend *fe) { struct mb86a20s_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int i, rc; + int layer, rc; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); @@ -636,43 +669,43 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe) /* Get per-layer data */ - for (i = 0; i < 3; i++) { + for (layer = 0; layer < NUM_LAYERS; layer++) { dev_dbg(&state->i2c->dev, "%s: getting data for layer %c.\n", - __func__, 'A' + i); + __func__, 'A' + layer); - rc = mb86a20s_get_segment_count(state, i); + rc = mb86a20s_get_segment_count(state, layer); if (rc < 0) goto noperlayer_error; if (rc >= 0 && rc < 14) { - c->layer[i].segment_count = rc; + c->layer[layer].segment_count = rc; } else { - c->layer[i].segment_count = 0; - state->estimated_rate[i] = 0; + c->layer[layer].segment_count = 0; + state->estimated_rate[layer] = 0; continue; } - c->isdbt_layer_enabled |= 1 << i; - rc = mb86a20s_get_modulation(state, i); + c->isdbt_layer_enabled |= 1 << layer; + rc = mb86a20s_get_modulation(state, layer); if (rc < 0) goto noperlayer_error; dev_dbg(&state->i2c->dev, "%s: modulation %d.\n", __func__, rc); - c->layer[i].modulation = rc; - rc = mb86a20s_get_fec(state, i); + c->layer[layer].modulation = rc; + rc = mb86a20s_get_fec(state, layer); if (rc < 0) goto noperlayer_error; dev_dbg(&state->i2c->dev, "%s: FEC %d.\n", __func__, rc); - c->layer[i].fec = rc; - rc = mb86a20s_get_interleaving(state, i); + c->layer[layer].fec = rc; + rc = mb86a20s_get_interleaving(state, layer); if (rc < 0) goto noperlayer_error; dev_dbg(&state->i2c->dev, "%s: interleaving %d.\n", __func__, rc); - c->layer[i].interleaving = rc; - mb86a20s_layer_bitrate(fe, i, c->layer[i].modulation, - c->layer[i].fec, - c->layer[i].interleaving, - c->layer[i].segment_count); + c->layer[layer].interleaving = rc; + mb86a20s_layer_bitrate(fe, layer, c->layer[layer].modulation, + c->layer[layer].fec, + c->layer[layer].interleaving, + c->layer[layer].segment_count); } rc = mb86a20s_writereg(state, 0x6d, 0x84); @@ -735,7 +768,6 @@ static int mb86a20s_reset_counters(struct dvb_frontend *fe) /* Reset the counters, if the channel changed */ if (state->last_frequency != c->frequency) { - memset(&c->strength, 0, sizeof(c->strength)); memset(&c->cnr, 0, sizeof(c->cnr)); memset(&c->pre_bit_error, 0, sizeof(c->pre_bit_error)); memset(&c->pre_bit_count, 0, sizeof(c->pre_bit_count)); @@ -799,7 +831,7 @@ static int mb86a20s_get_pre_ber(struct dvb_frontend *fe, dev_dbg(&state->i2c->dev, "%s called.\n", __func__); - if (layer >= 3) + if (layer >= NUM_LAYERS) return -EINVAL; /* Check if the BER measures are already available */ @@ -933,7 +965,7 @@ static int mb86a20s_get_post_ber(struct dvb_frontend *fe, dev_dbg(&state->i2c->dev, "%s called.\n", __func__); - if (layer >= 3) + if (layer >= NUM_LAYERS) return -EINVAL; /* Check if the BER measures are already available */ @@ -1060,7 +1092,7 @@ static int mb86a20s_get_blk_error(struct dvb_frontend *fe, u32 collect_rate; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); - if (layer >= 3) + if (layer >= NUM_LAYERS) return -EINVAL; /* Check if the PER measures are already available */ @@ -1095,7 +1127,7 @@ static int mb86a20s_get_blk_error(struct dvb_frontend *fe, if (rc < 0) return rc; *error |= rc; - dev_err(&state->i2c->dev, "%s: block error for layer %c: %d.\n", + dev_dbg(&state->i2c->dev, "%s: block error for layer %c: %d.\n", __func__, 'A' + layer, *error); /* Read Bit Count */ @@ -1386,7 +1418,7 @@ static int mb86a20s_get_main_CNR(struct dvb_frontend *fe) return rc; if (!(rc & 0x40)) { - dev_info(&state->i2c->dev, "%s: CNR is not available yet.\n", + dev_dbg(&state->i2c->dev, "%s: CNR is not available yet.\n", __func__); return -EBUSY; } @@ -1425,7 +1457,7 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe) struct mb86a20s_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; u32 mer, cnr; - int rc, val, i; + int rc, val, layer; struct linear_segments *segs; unsigned segs_len; @@ -1441,33 +1473,33 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe) /* Check if data is available */ if (!(rc & 0x01)) { - dev_info(&state->i2c->dev, + dev_dbg(&state->i2c->dev, "%s: MER measures aren't available yet.\n", __func__); return -EBUSY; } /* Read all layers */ - for (i = 0; i < 3; i++) { - if (!(c->isdbt_layer_enabled & (1 << i))) { - c->cnr.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; + for (layer = 0; layer < NUM_LAYERS; layer++) { + if (!(c->isdbt_layer_enabled & (1 << layer))) { + c->cnr.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE; continue; } - rc = mb86a20s_writereg(state, 0x50, 0x52 + i * 3); + rc = mb86a20s_writereg(state, 0x50, 0x52 + layer * 3); if (rc < 0) return rc; rc = mb86a20s_readreg(state, 0x51); if (rc < 0) return rc; mer = rc << 16; - rc = mb86a20s_writereg(state, 0x50, 0x53 + i * 3); + rc = mb86a20s_writereg(state, 0x50, 0x53 + layer * 3); if (rc < 0) return rc; rc = mb86a20s_readreg(state, 0x51); if (rc < 0) return rc; mer |= rc << 8; - rc = mb86a20s_writereg(state, 0x50, 0x54 + i * 3); + rc = mb86a20s_writereg(state, 0x50, 0x54 + layer * 3); if (rc < 0) return rc; rc = mb86a20s_readreg(state, 0x51); @@ -1475,7 +1507,7 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe) return rc; mer |= rc; - switch (c->layer[i].modulation) { + switch (c->layer[layer].modulation) { case DQPSK: case QPSK: segs = cnr_qpsk_table; @@ -1493,12 +1525,12 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe) } cnr = interpolate_value(mer, segs, segs_len); - c->cnr.stat[1 + i].scale = FE_SCALE_DECIBEL; - c->cnr.stat[1 + i].svalue = cnr; + c->cnr.stat[1 + layer].scale = FE_SCALE_DECIBEL; + c->cnr.stat[1 + layer].svalue = cnr; dev_dbg(&state->i2c->dev, "%s: CNR for layer %c is %d.%03d dB (MER = %d).\n", - __func__, 'A' + i, cnr / 1000, cnr % 1000, mer); + __func__, 'A' + layer, cnr / 1000, cnr % 1000, mer); } @@ -1526,7 +1558,7 @@ static void mb86a20s_stats_not_ready(struct dvb_frontend *fe) { struct mb86a20s_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int i; + int layer; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); @@ -1536,35 +1568,35 @@ static void mb86a20s_stats_not_ready(struct dvb_frontend *fe) c->strength.len = 1; /* Per-layer stats - 3 layers + global */ - c->cnr.len = 4; - c->pre_bit_error.len = 4; - c->pre_bit_count.len = 4; - c->post_bit_error.len = 4; - c->post_bit_count.len = 4; - c->block_error.len = 4; - c->block_count.len = 4; + c->cnr.len = NUM_LAYERS + 1; + c->pre_bit_error.len = NUM_LAYERS + 1; + c->pre_bit_count.len = NUM_LAYERS + 1; + c->post_bit_error.len = NUM_LAYERS + 1; + c->post_bit_count.len = NUM_LAYERS + 1; + c->block_error.len = NUM_LAYERS + 1; + c->block_count.len = NUM_LAYERS + 1; /* Signal is always available */ c->strength.stat[0].scale = FE_SCALE_RELATIVE; c->strength.stat[0].uvalue = 0; /* Put all of them at FE_SCALE_NOT_AVAILABLE */ - for (i = 0; i < 4; i++) { - c->cnr.stat[i].scale = FE_SCALE_NOT_AVAILABLE; - c->pre_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; - c->pre_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; - c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; - c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; - c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; - c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; + for (layer = 0; layer < NUM_LAYERS + 1; layer++) { + c->cnr.stat[layer].scale = FE_SCALE_NOT_AVAILABLE; + c->pre_bit_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE; + c->pre_bit_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE; + c->block_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE; + c->block_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE; } } -static int mb86a20s_get_stats(struct dvb_frontend *fe) +static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr) { struct mb86a20s_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int rc = 0, i; + int rc = 0, layer; u32 bit_error = 0, bit_count = 0; u32 t_pre_bit_error = 0, t_pre_bit_count = 0; u32 t_post_bit_error = 0, t_post_bit_count = 0; @@ -1580,90 +1612,98 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) /* Get per-layer stats */ mb86a20s_get_blk_error_layer_CNR(fe); - for (i = 0; i < 3; i++) { - if (c->isdbt_layer_enabled & (1 << i)) { + /* + * At state 7, only CNR is available + * For BER measures, state=9 is required + * FIXME: we may get MER measures with state=8 + */ + if (status_nr < 9) + return 0; + + for (layer = 0; layer < NUM_LAYERS; layer++) { + if (c->isdbt_layer_enabled & (1 << layer)) { /* Layer is active and has rc segments */ active_layers++; /* Handle BER before vterbi */ - rc = mb86a20s_get_pre_ber(fe, i, + rc = mb86a20s_get_pre_ber(fe, layer, &bit_error, &bit_count); if (rc >= 0) { - c->pre_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; - c->pre_bit_error.stat[1 + i].uvalue += bit_error; - c->pre_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; - c->pre_bit_count.stat[1 + i].uvalue += bit_count; + c->pre_bit_error.stat[1 + layer].scale = FE_SCALE_COUNTER; + c->pre_bit_error.stat[1 + layer].uvalue += bit_error; + c->pre_bit_count.stat[1 + layer].scale = FE_SCALE_COUNTER; + c->pre_bit_count.stat[1 + layer].uvalue += bit_count; } else if (rc != -EBUSY) { /* * If an I/O error happened, * measures are now unavailable */ - c->pre_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; - c->pre_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; + c->pre_bit_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE; + c->pre_bit_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE; dev_err(&state->i2c->dev, "%s: Can't get BER for layer %c (error %d).\n", - __func__, 'A' + i, rc); + __func__, 'A' + layer, rc); } - if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) + if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE) pre_ber_layers++; /* Handle BER post vterbi */ - rc = mb86a20s_get_post_ber(fe, i, + rc = mb86a20s_get_post_ber(fe, layer, &bit_error, &bit_count); if (rc >= 0) { - c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; - c->post_bit_error.stat[1 + i].uvalue += bit_error; - c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; - c->post_bit_count.stat[1 + i].uvalue += bit_count; + c->post_bit_error.stat[1 + layer].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[1 + layer].uvalue += bit_error; + c->post_bit_count.stat[1 + layer].scale = FE_SCALE_COUNTER; + c->post_bit_count.stat[1 + layer].uvalue += bit_count; } else if (rc != -EBUSY) { /* * If an I/O error happened, * measures are now unavailable */ - c->post_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; - c->post_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE; dev_err(&state->i2c->dev, "%s: Can't get BER for layer %c (error %d).\n", - __func__, 'A' + i, rc); + __func__, 'A' + layer, rc); } - if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) + if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE) post_ber_layers++; /* Handle Block errors for PER/UCB reports */ - rc = mb86a20s_get_blk_error(fe, i, + rc = mb86a20s_get_blk_error(fe, layer, &block_error, &block_count); if (rc >= 0) { - c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER; - c->block_error.stat[1 + i].uvalue += block_error; - c->block_count.stat[1 + i].scale = FE_SCALE_COUNTER; - c->block_count.stat[1 + i].uvalue += block_count; + c->block_error.stat[1 + layer].scale = FE_SCALE_COUNTER; + c->block_error.stat[1 + layer].uvalue += block_error; + c->block_count.stat[1 + layer].scale = FE_SCALE_COUNTER; + c->block_count.stat[1 + layer].uvalue += block_count; } else if (rc != -EBUSY) { /* * If an I/O error happened, * measures are now unavailable */ - c->block_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; - c->block_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; + c->block_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE; + c->block_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE; dev_err(&state->i2c->dev, "%s: Can't get PER for layer %c (error %d).\n", - __func__, 'A' + i, rc); + __func__, 'A' + layer, rc); } - if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) + if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE) per_layers++; /* Update total preBER */ - t_pre_bit_error += c->pre_bit_error.stat[1 + i].uvalue; - t_pre_bit_count += c->pre_bit_count.stat[1 + i].uvalue; + t_pre_bit_error += c->pre_bit_error.stat[1 + layer].uvalue; + t_pre_bit_count += c->pre_bit_count.stat[1 + layer].uvalue; /* Update total postBER */ - t_post_bit_error += c->post_bit_error.stat[1 + i].uvalue; - t_post_bit_count += c->post_bit_count.stat[1 + i].uvalue; + t_post_bit_error += c->post_bit_error.stat[1 + layer].uvalue; + t_post_bit_count += c->post_bit_count.stat[1 + layer].uvalue; /* Update total PER */ - t_block_error += c->block_error.stat[1 + i].uvalue; - t_block_count += c->block_count.stat[1 + i].uvalue; + t_block_error += c->block_error.stat[1 + layer].uvalue; + t_block_count += c->block_count.stat[1 + layer].uvalue; } } @@ -1737,8 +1777,10 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe) static int mb86a20s_initfe(struct dvb_frontend *fe) { struct mb86a20s_state *state = fe->demodulator_priv; + u64 pll; + u32 fclk; int rc; - u8 regD5 = 1; + u8 regD5 = 1, reg71, reg09 = 0x3a; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); @@ -1746,10 +1788,78 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) fe->ops.i2c_gate_ctrl(fe, 0); /* Initialize the frontend */ - rc = mb86a20s_writeregdata(state, mb86a20s_init); + rc = mb86a20s_writeregdata(state, mb86a20s_init1); if (rc < 0) goto err; + if (!state->inversion) + reg09 |= 0x04; + rc = mb86a20s_writereg(state, 0x09, reg09); + if (rc < 0) + goto err; + if (!state->bw) + reg71 = 1; + else + reg71 = 0; + rc = mb86a20s_writereg(state, 0x39, reg71); + if (rc < 0) + goto err; + rc = mb86a20s_writereg(state, 0x71, state->bw); + if (rc < 0) + goto err; + if (state->subchannel) { + rc = mb86a20s_writereg(state, 0x44, state->subchannel); + if (rc < 0) + goto err; + } + + fclk = state->config->fclk; + if (!fclk) + fclk = 32571428; + + /* Adjust IF frequency to match tuner */ + if (fe->ops.tuner_ops.get_if_frequency) + fe->ops.tuner_ops.get_if_frequency(fe, &state->if_freq); + + if (!state->if_freq) + state->if_freq = 3300000; + + pll = (((u64)1) << 34) * state->if_freq; + do_div(pll, 63 * fclk); + pll = (1 << 25) - pll; + rc = mb86a20s_writereg(state, 0x28, 0x2a); + if (rc < 0) + goto err; + rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff); + if (rc < 0) + goto err; + rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff); + if (rc < 0) + goto err; + rc = mb86a20s_writereg(state, 0x2b, pll & 0xff); + if (rc < 0) + goto err; + dev_dbg(&state->i2c->dev, "%s: fclk=%d, IF=%d, clock reg=0x%06llx\n", + __func__, fclk, state->if_freq, (long long)pll); + + /* pll = freq[Hz] * 2^24/10^6 / 16.285714286 */ + pll = state->if_freq * 1677721600L; + do_div(pll, 1628571429L); + rc = mb86a20s_writereg(state, 0x28, 0x20); + if (rc < 0) + goto err; + rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff); + if (rc < 0) + goto err; + rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff); + if (rc < 0) + goto err; + rc = mb86a20s_writereg(state, 0x2b, pll & 0xff); + if (rc < 0) + goto err; + dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n", + __func__, state->if_freq, (long long)pll); + if (!state->config->is_serial) { regD5 &= ~1; @@ -1761,6 +1871,11 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) goto err; } + rc = mb86a20s_writeregdata(state, mb86a20s_init2); + if (rc < 0) + goto err; + + err: if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -1779,15 +1894,34 @@ err: static int mb86a20s_set_frontend(struct dvb_frontend *fe) { struct mb86a20s_state *state = fe->demodulator_priv; - int rc; -#if 0 - /* - * FIXME: Properly implement the set frontend properties - */ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -#endif + int rc, if_freq; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); + if (!c->isdbt_layer_enabled) + c->isdbt_layer_enabled = 7; + + if (c->isdbt_layer_enabled == 1) + state->bw = MB86A20S_1SEG; + else if (c->isdbt_partial_reception) + state->bw = MB86A20S_13SEG_PARTIAL; + else + state->bw = MB86A20S_13SEG; + + if (c->inversion == INVERSION_ON) + state->inversion = true; + else + state->inversion = false; + + if (!c->isdbt_sb_mode) { + state->subchannel = 0; + } else { + if (c->isdbt_sb_subchannel >= ARRAY_SIZE(mb86a20s_subchannel)) + c->isdbt_sb_subchannel = 0; + + state->subchannel = mb86a20s_subchannel[c->isdbt_sb_subchannel]; + } + /* * Gate should already be opened, but it doesn't hurt to * double-check @@ -1796,6 +1930,9 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe) fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.tuner_ops.set_params(fe); + if (fe->ops.tuner_ops.get_if_frequency) + fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); + /* * Make it more reliable: if, for some reason, the initial * device initialization doesn't happen, initialize it when @@ -1805,15 +1942,22 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe) * the agc callback logic is not called during DVB attach time, * causing mb86a20s to not be initialized with Kworld SBTVD. * So, this hack is needed, in order to make Kworld SBTVD to work. + * + * It is also needed to change the IF after the initial init. + * + * HACK: Always init the frontend when set_frontend is called: + * it was noticed that, on some devices, it fails to lock on a + * different channel. So, it is better to reset everything, even + * wasting some time, than to loose channel lock. */ - if (state->need_init) - mb86a20s_initfe(fe); + mb86a20s_initfe(fe); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception); mb86a20s_reset_counters(fe); + mb86a20s_stats_not_ready(fe); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -1825,8 +1969,7 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe, fe_status_t *status) { struct mb86a20s_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int rc; + int rc, status_nr; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); @@ -1834,12 +1977,12 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe, fe->ops.i2c_gate_ctrl(fe, 0); /* Get lock */ - rc = mb86a20s_read_status(fe, status); - if (!(*status & FE_HAS_LOCK)) { + status_nr = mb86a20s_read_status(fe, status); + if (status_nr < 7) { mb86a20s_stats_not_ready(fe); mb86a20s_reset_frontend_cache(fe); } - if (rc < 0) { + if (status_nr < 0) { dev_err(&state->i2c->dev, "%s: Can't read frontend lock status\n", __func__); goto error; @@ -1856,10 +1999,8 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe, rc = 0; /* Status is OK */ goto error; } - /* Fill signal strength */ - c->strength.stat[0].uvalue = rc; - if (*status & FE_HAS_LOCK) { + if (status_nr >= 7) { /* Get TMCC info*/ rc = mb86a20s_get_frontend(fe); if (rc < 0) { @@ -1870,7 +2011,7 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe, } /* Get statistics */ - rc = mb86a20s_get_stats(fe); + rc = mb86a20s_get_stats(fe, status_nr); if (rc < 0 && rc != -EBUSY) { dev_err(&state->i2c->dev, "%s: Can't get FE statistics.\n", __func__); @@ -1994,7 +2135,7 @@ static struct dvb_frontend_ops mb86a20s_ops = { /* Use dib8000 values per default */ .info = { .name = "Fujitsu mb86A20s", - .caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER | + .caps = FE_CAN_RECOVER | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | diff --git a/drivers/media/dvb-frontends/mb86a20s.h b/drivers/media/dvb-frontends/mb86a20s.h index bf22e77..6627a39 100644 --- a/drivers/media/dvb-frontends/mb86a20s.h +++ b/drivers/media/dvb-frontends/mb86a20s.h @@ -16,21 +16,25 @@ #ifndef MB86A20S_H #define MB86A20S_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> /** * struct mb86a20s_config - Define the per-device attributes of the frontend * + * @fclk: Clock frequency. If zero, assumes the default + * (32.57142 Mhz) * @demod_address: the demodulator's i2c address + * @is_serial: if true, TS is serial. Otherwise, TS is parallel */ struct mb86a20s_config { - u8 demod_address; - bool is_serial; + u32 fclk; + u8 demod_address; + bool is_serial; }; -#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_MB86A20S) extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, struct i2c_adapter *i2c); extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *); diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h index f4349a1..3313847 100644 --- a/drivers/media/dvb-frontends/rtl2830.h +++ b/drivers/media/dvb-frontends/rtl2830.h @@ -21,6 +21,7 @@ #ifndef RTL2830_H #define RTL2830_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct rtl2830_config { @@ -59,8 +60,7 @@ struct rtl2830_config { u8 agc_targ_val; }; -#if defined(CONFIG_DVB_RTL2830) || \ - (defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_RTL2830) extern struct dvb_frontend *rtl2830_attach( const struct rtl2830_config *config, struct i2c_adapter *i2c diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 7388769..facb848 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -380,13 +380,41 @@ err: return ret; } -static int rtl2832_init(struct dvb_frontend *fe) + +static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) { struct rtl2832_priv *priv = fe->demodulator_priv; - int i, ret, len; - u8 en_bbin; + int ret; u64 pset_iffreq; + u8 en_bbin = (if_freq == 0 ? 0x1 : 0x0); + + /* + * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22) + * / CrystalFreqHz) + */ + + pset_iffreq = if_freq % priv->cfg.xtal; + pset_iffreq *= 0x400000; + pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal); + pset_iffreq = -pset_iffreq; + pset_iffreq = pset_iffreq & 0x3fffff; + dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d pset_iffreq=%08x\n", + __func__, if_freq, (unsigned)pset_iffreq); + + ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin); + if (ret) + return ret; + + ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq); + + return (ret); +} + +static int rtl2832_init(struct dvb_frontend *fe) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; const struct rtl2832_reg_value *init; + int i, ret, len; /* initialization values for the demodulator registers */ struct rtl2832_reg_value rtl2832_initial_regs[] = { @@ -432,22 +460,10 @@ static int rtl2832_init(struct dvb_frontend *fe) {DVBT_TR_THD_SET2, 0x6}, {DVBT_TRK_KC_I2, 0x5}, {DVBT_CR_THD_SET2, 0x1}, - {DVBT_SPEC_INV, 0x0}, }; dev_dbg(&priv->i2c->dev, "%s:\n", __func__); - en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0); - - /* - * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22) - * / CrystalFreqHz) - */ - pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal; - pset_iffreq *= 0x400000; - pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal); - pset_iffreq = pset_iffreq & 0x3fffff; - for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) { ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg, rtl2832_initial_regs[i].value); @@ -472,6 +488,10 @@ static int rtl2832_init(struct dvb_frontend *fe) len = ARRAY_SIZE(rtl2832_tuner_init_e4000); init = rtl2832_tuner_init_e4000; break; + case RTL2832_TUNER_R820T: + len = ARRAY_SIZE(rtl2832_tuner_init_r820t); + init = rtl2832_tuner_init_r820t; + break; default: ret = -EINVAL; goto err; @@ -483,14 +503,26 @@ static int rtl2832_init(struct dvb_frontend *fe) goto err; } - /* if frequency settings */ - ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin); + if (!fe->ops.tuner_ops.get_if_frequency) { + ret = rtl2832_set_if(fe, priv->cfg.if_dvbt); if (ret) goto err; + } - ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq); - if (ret) - goto err; + /* + * r820t NIM code does a software reset here at the demod - + * may not be needed, as there's already a software reset at set_params() + */ +#if 1 + /* soft reset */ + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1); + if (ret) + goto err; + + ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0); + if (ret) + goto err; +#endif priv->sleeping = false; @@ -564,6 +596,19 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) if (fe->ops.tuner_ops.set_params) fe->ops.tuner_ops.set_params(fe); + /* If the frontend has get_if_frequency(), use it */ + if (fe->ops.tuner_ops.get_if_frequency) { + u32 if_freq; + + ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); + if (ret) + goto err; + + ret = rtl2832_set_if(fe, if_freq); + if (ret) + goto err; + } + switch (c->bandwidth_hz) { case 6000000: i = 0; diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index 785a466..91b2dcf 100644 --- a/drivers/media/dvb-frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -21,6 +21,7 @@ #ifndef RTL2832_H #define RTL2832_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct rtl2832_config { @@ -51,11 +52,11 @@ struct rtl2832_config { #define RTL2832_TUNER_FC0012 0x26 #define RTL2832_TUNER_E4000 0x27 #define RTL2832_TUNER_FC0013 0x29 +#define RTL2832_TUNER_R820T 0x2a u8 tuner; }; -#if defined(CONFIG_DVB_RTL2832) || \ - (defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_RTL2832) extern struct dvb_frontend *rtl2832_attach( const struct rtl2832_config *cfg, struct i2c_adapter *i2c diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 7d97ce9..b5f2b80 100644 --- a/drivers/media/dvb-frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -267,6 +267,7 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_tua9001[] = { {DVBT_OPT_ADC_IQ, 0x1}, {DVBT_AD_AVI, 0x0}, {DVBT_AD_AVQ, 0x0}, + {DVBT_SPEC_INV, 0x0}, }; static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = { @@ -300,6 +301,7 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = { {DVBT_GI_PGA_STATE, 0x0}, {DVBT_EN_AGC_PGA, 0x1}, {DVBT_IF_AGC_MAN, 0x0}, + {DVBT_SPEC_INV, 0x0}, }; static const struct rtl2832_reg_value rtl2832_tuner_init_e4000[] = { @@ -337,6 +339,32 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_e4000[] = { {DVBT_REG_MONSEL, 0x1}, {DVBT_REG_MON, 0x1}, {DVBT_REG_4MSEL, 0x0}, + {DVBT_SPEC_INV, 0x0}, +}; + +static const struct rtl2832_reg_value rtl2832_tuner_init_r820t[] = { + {DVBT_DAGC_TRG_VAL, 0x39}, + {DVBT_AGC_TARG_VAL_0, 0x0}, + {DVBT_AGC_TARG_VAL_8_1, 0x40}, + {DVBT_AAGC_LOOP_GAIN, 0x16}, + {DVBT_LOOP_GAIN2_3_0, 0x8}, + {DVBT_LOOP_GAIN2_4, 0x1}, + {DVBT_LOOP_GAIN3, 0x18}, + {DVBT_VTOP1, 0x35}, + {DVBT_VTOP2, 0x21}, + {DVBT_VTOP3, 0x21}, + {DVBT_KRF1, 0x0}, + {DVBT_KRF2, 0x40}, + {DVBT_KRF3, 0x10}, + {DVBT_KRF4, 0x10}, + {DVBT_IF_AGC_MIN, 0x80}, + {DVBT_IF_AGC_MAX, 0x7f}, + {DVBT_RF_AGC_MIN, 0x80}, + {DVBT_RF_AGC_MAX, 0x7f}, + {DVBT_POLAR_RF_AGC, 0x0}, + {DVBT_POLAR_IF_AGC, 0x0}, + {DVBT_AD7_SETTING, 0xe9f4}, + {DVBT_SPEC_INV, 0x1}, }; #endif /* RTL2832_PRIV_H */ diff --git a/drivers/media/dvb-frontends/s5h1409.h b/drivers/media/dvb-frontends/s5h1409.h index 91f2ebd..63b1e0a 100644 --- a/drivers/media/dvb-frontends/s5h1409.h +++ b/drivers/media/dvb-frontends/s5h1409.h @@ -22,6 +22,7 @@ #ifndef __S5H1409_H__ #define __S5H1409_H__ +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct s5h1409_config { @@ -66,8 +67,7 @@ struct s5h1409_config { u8 hvr1600_opt; }; -#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_S5H1409) extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/s5h1411.h b/drivers/media/dvb-frontends/s5h1411.h index 45ec0f8..e4f5687 100644 --- a/drivers/media/dvb-frontends/s5h1411.h +++ b/drivers/media/dvb-frontends/s5h1411.h @@ -22,6 +22,7 @@ #ifndef __S5H1411_H__ #define __S5H1411_H__ +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #define S5H1411_I2C_TOP_ADDR (0x32 >> 1) @@ -68,8 +69,7 @@ struct s5h1411_config { u8 status_mode; }; -#if defined(CONFIG_DVB_S5H1411) || \ - (defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_S5H1411) extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/s5h1432.h b/drivers/media/dvb-frontends/s5h1432.h index b57438c..70917dd 100644 --- a/drivers/media/dvb-frontends/s5h1432.h +++ b/drivers/media/dvb-frontends/s5h1432.h @@ -22,6 +22,7 @@ #ifndef __S5H1432_H__ #define __S5H1432_H__ +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #define S5H1432_I2C_TOP_ADDR (0x02 >> 1) @@ -74,8 +75,7 @@ struct s5h1432_config { u8 status_mode; }; -#if defined(CONFIG_DVB_S5H1432) || \ - (defined(CONFIG_DVB_S5H1432_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_S5H1432) extern struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/s921.h b/drivers/media/dvb-frontends/s921.h index f220d82..8d5e2a6 100644 --- a/drivers/media/dvb-frontends/s921.h +++ b/drivers/media/dvb-frontends/s921.h @@ -17,6 +17,7 @@ #ifndef S921_H #define S921_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct s921_config { @@ -24,8 +25,7 @@ struct s921_config { u8 demod_address; }; -#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_S921) extern struct dvb_frontend *s921_attach(const struct s921_config *config, struct i2c_adapter *i2c); extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *); diff --git a/drivers/media/dvb-frontends/si21xx.h b/drivers/media/dvb-frontends/si21xx.h index 141b5b8..1509fed 100644 --- a/drivers/media/dvb-frontends/si21xx.h +++ b/drivers/media/dvb-frontends/si21xx.h @@ -1,6 +1,7 @@ #ifndef SI21XX_H #define SI21XX_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include "dvb_frontend.h" @@ -12,8 +13,7 @@ struct si21xx_config { int min_delay_ms; }; -#if defined(CONFIG_DVB_SI21XX) || \ - (defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_SI21XX) extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/stb6000.h b/drivers/media/dvb-frontends/stb6000.h index 7be479c..a768189 100644 --- a/drivers/media/dvb-frontends/stb6000.h +++ b/drivers/media/dvb-frontends/stb6000.h @@ -23,6 +23,7 @@ #ifndef __DVB_STB6000_H__ #define __DVB_STB6000_H__ +#include <linux/kconfig.h> #include <linux/i2c.h> #include "dvb_frontend.h" @@ -34,8 +35,7 @@ * @param i2c i2c adapter to use. * @return FE pointer on success, NULL on failure. */ -#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_STB6000) extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/stv0288.h b/drivers/media/dvb-frontends/stv0288.h index f2b53db..a0bd931 100644 --- a/drivers/media/dvb-frontends/stv0288.h +++ b/drivers/media/dvb-frontends/stv0288.h @@ -27,6 +27,7 @@ #ifndef STV0288_H #define STV0288_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include "dvb_frontend.h" @@ -42,8 +43,7 @@ struct stv0288_config { int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); }; -#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \ - defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_STV0288) extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/stv0367.h b/drivers/media/dvb-frontends/stv0367.h index 93cc4a5..ea80b34 100644 --- a/drivers/media/dvb-frontends/stv0367.h +++ b/drivers/media/dvb-frontends/stv0367.h @@ -26,6 +26,7 @@ #ifndef STV0367_H #define STV0367_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include "dvb_frontend.h" @@ -38,8 +39,7 @@ struct stv0367_config { int clk_pol; }; -#if defined(CONFIG_DVB_STV0367) || (defined(CONFIG_DVB_STV0367_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_STV0367) extern struct dvb_frontend *stv0367ter_attach(const struct stv0367_config *config, struct i2c_adapter *i2c); diff --git a/drivers/media/dvb-frontends/stv0900.h b/drivers/media/dvb-frontends/stv0900.h index 91c7ee8..e2a6dc6 100644 --- a/drivers/media/dvb-frontends/stv0900.h +++ b/drivers/media/dvb-frontends/stv0900.h @@ -26,6 +26,7 @@ #ifndef STV0900_H #define STV0900_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include "dvb_frontend.h" @@ -57,8 +58,7 @@ struct stv0900_config { void (*set_lock_led)(struct dvb_frontend *fe, int offon); }; -#if defined(CONFIG_DVB_STV0900) || (defined(CONFIG_DVB_STV0900_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_STV0900) extern struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, struct i2c_adapter *i2c, int demod); #else diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c index f36eeef..56d470a 100644 --- a/drivers/media/dvb-frontends/stv090x.c +++ b/drivers/media/dvb-frontends/stv090x.c @@ -3906,12 +3906,12 @@ static int stv090x_sleep(struct dvb_frontend *fe) 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; + goto err_unlock; /* power off DiSEqC 1 */ reg = stv090x_read_reg(state, STV090x_TSTTNR2); STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0); if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0) - goto err; + goto err_unlock; /* check whether path 2 is already sleeping, that is when ADC2 is off */ @@ -3930,7 +3930,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) if (full_standby) STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1); if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) - goto err; + goto err_unlock; reg = stv090x_read_reg(state, STV090x_STOPCLK2); /* sampling 1 clock */ STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1); @@ -3941,7 +3941,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) if (full_standby) STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1); if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) - goto err; + goto err_unlock; break; case STV090x_DEMODULATOR_1: @@ -3949,12 +3949,12 @@ static int stv090x_sleep(struct dvb_frontend *fe) reg = stv090x_read_reg(state, STV090x_TSTTNR3); STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0); if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0) - goto err; + goto err_unlock; /* power off DiSEqC 2 */ reg = stv090x_read_reg(state, STV090x_TSTTNR4); STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0); if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0) - goto err; + goto err_unlock; /* check whether path 1 is already sleeping, that is when ADC1 is off */ @@ -3973,7 +3973,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) if (full_standby) STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1); if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) - goto err; + goto err_unlock; reg = stv090x_read_reg(state, STV090x_STOPCLK2); /* sampling 2 clock */ STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1); @@ -3984,7 +3984,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) if (full_standby) STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1); if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) - goto err; + goto err_unlock; break; default: @@ -3997,7 +3997,7 @@ static int stv090x_sleep(struct dvb_frontend *fe) reg = stv090x_read_reg(state, STV090x_SYNTCTRL); STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01); if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) - goto err; + goto err_unlock; } mutex_unlock(&state->internal->demod_lock); @@ -4005,8 +4005,10 @@ static int stv090x_sleep(struct dvb_frontend *fe) err_gateoff: stv090x_i2c_gate_ctrl(state, 0); -err: + goto err; +err_unlock: mutex_unlock(&state->internal->demod_lock); +err: dprintk(FE_ERROR, 1, "I/O error"); return -1; } diff --git a/drivers/media/dvb-frontends/stv6110.h b/drivers/media/dvb-frontends/stv6110.h index fe71bba..8fa07e6 100644 --- a/drivers/media/dvb-frontends/stv6110.h +++ b/drivers/media/dvb-frontends/stv6110.h @@ -25,6 +25,7 @@ #ifndef __DVB_STV6110_H__ #define __DVB_STV6110_H__ +#include <linux/kconfig.h> #include <linux/i2c.h> #include "dvb_frontend.h" @@ -45,8 +46,7 @@ struct stv6110_config { u8 clk_div; /* divisor value for the output clock */ }; -#if defined(CONFIG_DVB_STV6110) || (defined(CONFIG_DVB_STV6110_MODULE) \ - && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_STV6110) extern struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe, const struct stv6110_config *config, struct i2c_adapter *i2c); diff --git a/drivers/media/dvb-frontends/tda10048.h b/drivers/media/dvb-frontends/tda10048.h index fb2ef5a..5e7bf4e 100644 --- a/drivers/media/dvb-frontends/tda10048.h +++ b/drivers/media/dvb-frontends/tda10048.h @@ -22,6 +22,7 @@ #ifndef TDA10048_H #define TDA10048_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> #include <linux/firmware.h> @@ -72,8 +73,7 @@ struct tda10048_config { u8 pll_n; }; -#if defined(CONFIG_DVB_TDA10048) || \ - (defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_TDA10048) extern struct dvb_frontend *tda10048_attach( const struct tda10048_config *config, struct i2c_adapter *i2c); diff --git a/drivers/media/dvb-frontends/tda10071.h b/drivers/media/dvb-frontends/tda10071.h index bff1c38..f9542f6 100644 --- a/drivers/media/dvb-frontends/tda10071.h +++ b/drivers/media/dvb-frontends/tda10071.h @@ -21,6 +21,7 @@ #ifndef TDA10071_H #define TDA10071_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct tda10071_config { @@ -71,8 +72,7 @@ struct tda10071_config { }; -#if defined(CONFIG_DVB_TDA10071) || \ - (defined(CONFIG_DVB_TDA10071_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_TDA10071) extern struct dvb_frontend *tda10071_attach( const struct tda10071_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/tda18271c2dd.h b/drivers/media/dvb-frontends/tda18271c2dd.h index 1389c74..dd84f7b 100644 --- a/drivers/media/dvb-frontends/tda18271c2dd.h +++ b/drivers/media/dvb-frontends/tda18271c2dd.h @@ -1,7 +1,9 @@ #ifndef _TDA18271C2DD_H_ #define _TDA18271C2DD_H_ -#if defined(CONFIG_DVB_TDA18271C2DD) || (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \ - && defined(MODULE)) + +#include <linux/kconfig.h> + +#if IS_ENABLED(CONFIG_DVB_TDA18271C2DD) struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 adr); #else diff --git a/drivers/media/dvb-frontends/ts2020.h b/drivers/media/dvb-frontends/ts2020.h index c7e64af..5bcb9a7 100644 --- a/drivers/media/dvb-frontends/ts2020.h +++ b/drivers/media/dvb-frontends/ts2020.h @@ -22,6 +22,7 @@ #ifndef TS2020_H #define TS2020_H +#include <linux/kconfig.h> #include <linux/dvb/frontend.h> struct ts2020_config { @@ -29,8 +30,7 @@ struct ts2020_config { u8 clk_out_div; }; -#if defined(CONFIG_DVB_TS2020) || \ - (defined(CONFIG_DVB_TS2020_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_TS2020) extern struct dvb_frontend *ts2020_attach( struct dvb_frontend *fe, diff --git a/drivers/media/dvb-frontends/zl10036.h b/drivers/media/dvb-frontends/zl10036.h index d84b8f8..5f1e821 100644 --- a/drivers/media/dvb-frontends/zl10036.h +++ b/drivers/media/dvb-frontends/zl10036.h @@ -21,6 +21,7 @@ #ifndef DVB_ZL10036_H #define DVB_ZL10036_H +#include <linux/kconfig.h> #include <linux/i2c.h> #include "dvb_frontend.h" @@ -37,8 +38,7 @@ struct zl10036_config { int rf_loop_enable; }; -#if defined(CONFIG_DVB_ZL10036) || \ - (defined(CONFIG_DVB_ZL10036_MODULE) && defined(MODULE)) +#if IS_ENABLED(CONFIG_DVB_ZL10036) extern struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe, const struct zl10036_config *config, struct i2c_adapter *i2c); #else diff --git a/drivers/media/dvb-frontends/zl10039.h b/drivers/media/dvb-frontends/zl10039.h index 5eee7ea..750b9bc 100644 --- a/drivers/media/dvb-frontends/zl10039.h +++ b/drivers/media/dvb-frontends/zl10039.h @@ -22,8 +22,9 @@ #ifndef ZL10039_H #define ZL10039_H -#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \ - && defined(MODULE)) +#include <linux/kconfig.h> + +#if IS_ENABLED(CONFIG_DVB_ZL10039) struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, u8 i2c_addr, struct i2c_adapter *i2c); |