1cd21b334SDaniel Scheller /* 2cd21b334SDaniel Scheller * Driver for the ST STV0910 DVB-S/S2 demodulator. 3cd21b334SDaniel Scheller * 4cd21b334SDaniel Scheller * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de> 5cd21b334SDaniel Scheller * Marcus Metzler <mocm@metzlerbros.de> 6cd21b334SDaniel Scheller * developed for Digital Devices GmbH 7cd21b334SDaniel Scheller * 8cd21b334SDaniel Scheller * This program is free software; you can redistribute it and/or 9cd21b334SDaniel Scheller * modify it under the terms of the GNU General Public License 10cd21b334SDaniel Scheller * version 2 only, as published by the Free Software Foundation. 11cd21b334SDaniel Scheller * 12cd21b334SDaniel Scheller * This program is distributed in the hope that it will be useful, 13cd21b334SDaniel Scheller * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cd21b334SDaniel Scheller * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15cd21b334SDaniel Scheller * GNU General Public License for more details. 16cd21b334SDaniel Scheller */ 17cd21b334SDaniel Scheller 18cd21b334SDaniel Scheller #include <linux/kernel.h> 19cd21b334SDaniel Scheller #include <linux/module.h> 20cd21b334SDaniel Scheller #include <linux/moduleparam.h> 21cd21b334SDaniel Scheller #include <linux/init.h> 22cd21b334SDaniel Scheller #include <linux/delay.h> 23cd21b334SDaniel Scheller #include <linux/firmware.h> 24cd21b334SDaniel Scheller #include <linux/i2c.h> 25cd21b334SDaniel Scheller #include <asm/div64.h> 26cd21b334SDaniel Scheller 27cd21b334SDaniel Scheller #include "dvb_math.h" 28cd21b334SDaniel Scheller #include "dvb_frontend.h" 29cd21b334SDaniel Scheller #include "stv0910.h" 30cd21b334SDaniel Scheller #include "stv0910_regs.h" 31cd21b334SDaniel Scheller 32cd21b334SDaniel Scheller #define EXT_CLOCK 30000000 33cd21b334SDaniel Scheller #define TUNING_DELAY 200 34cd21b334SDaniel Scheller #define BER_SRC_S 0x20 35cd21b334SDaniel Scheller #define BER_SRC_S2 0x20 36cd21b334SDaniel Scheller 37c16ad5deSDaniel Scheller static LIST_HEAD(stvlist); 38cd21b334SDaniel Scheller 39cd21b334SDaniel Scheller enum receive_mode { RCVMODE_NONE, RCVMODE_DVBS, RCVMODE_DVBS2, RCVMODE_AUTO }; 40cd21b334SDaniel Scheller 41cd21b334SDaniel Scheller enum dvbs2_fectype { DVBS2_64K, DVBS2_16K }; 42cd21b334SDaniel Scheller 43cd21b334SDaniel Scheller enum dvbs2_mod_cod { 44cd21b334SDaniel Scheller DVBS2_DUMMY_PLF, DVBS2_QPSK_1_4, DVBS2_QPSK_1_3, DVBS2_QPSK_2_5, 45cd21b334SDaniel Scheller DVBS2_QPSK_1_2, DVBS2_QPSK_3_5, DVBS2_QPSK_2_3, DVBS2_QPSK_3_4, 46cd21b334SDaniel Scheller DVBS2_QPSK_4_5, DVBS2_QPSK_5_6, DVBS2_QPSK_8_9, DVBS2_QPSK_9_10, 47cd21b334SDaniel Scheller DVBS2_8PSK_3_5, DVBS2_8PSK_2_3, DVBS2_8PSK_3_4, DVBS2_8PSK_5_6, 48cd21b334SDaniel Scheller DVBS2_8PSK_8_9, DVBS2_8PSK_9_10, DVBS2_16APSK_2_3, DVBS2_16APSK_3_4, 49cd21b334SDaniel Scheller DVBS2_16APSK_4_5, DVBS2_16APSK_5_6, DVBS2_16APSK_8_9, DVBS2_16APSK_9_10, 50cd21b334SDaniel Scheller DVBS2_32APSK_3_4, DVBS2_32APSK_4_5, DVBS2_32APSK_5_6, DVBS2_32APSK_8_9, 51cd21b334SDaniel Scheller DVBS2_32APSK_9_10 52cd21b334SDaniel Scheller }; 53cd21b334SDaniel Scheller 54cd21b334SDaniel Scheller enum fe_stv0910_mod_cod { 55cd21b334SDaniel Scheller FE_DUMMY_PLF, FE_QPSK_14, FE_QPSK_13, FE_QPSK_25, 56cd21b334SDaniel Scheller FE_QPSK_12, FE_QPSK_35, FE_QPSK_23, FE_QPSK_34, 57cd21b334SDaniel Scheller FE_QPSK_45, FE_QPSK_56, FE_QPSK_89, FE_QPSK_910, 58cd21b334SDaniel Scheller FE_8PSK_35, FE_8PSK_23, FE_8PSK_34, FE_8PSK_56, 59cd21b334SDaniel Scheller FE_8PSK_89, FE_8PSK_910, FE_16APSK_23, FE_16APSK_34, 60cd21b334SDaniel Scheller FE_16APSK_45, FE_16APSK_56, FE_16APSK_89, FE_16APSK_910, 61cd21b334SDaniel Scheller FE_32APSK_34, FE_32APSK_45, FE_32APSK_56, FE_32APSK_89, 62cd21b334SDaniel Scheller FE_32APSK_910 63cd21b334SDaniel Scheller }; 64cd21b334SDaniel Scheller 65cd21b334SDaniel Scheller enum fe_stv0910_roll_off { FE_SAT_35, FE_SAT_25, FE_SAT_20, FE_SAT_15 }; 66cd21b334SDaniel Scheller 67cd21b334SDaniel Scheller static inline u32 muldiv32(u32 a, u32 b, u32 c) 68cd21b334SDaniel Scheller { 69cd21b334SDaniel Scheller u64 tmp64; 70cd21b334SDaniel Scheller 71cd21b334SDaniel Scheller tmp64 = (u64)a * (u64)b; 72cd21b334SDaniel Scheller do_div(tmp64, c); 73cd21b334SDaniel Scheller 74cd21b334SDaniel Scheller return (u32)tmp64; 75cd21b334SDaniel Scheller } 76cd21b334SDaniel Scheller 77cd21b334SDaniel Scheller struct stv_base { 78cd21b334SDaniel Scheller struct list_head stvlist; 79cd21b334SDaniel Scheller 80cd21b334SDaniel Scheller u8 adr; 81cd21b334SDaniel Scheller struct i2c_adapter *i2c; 82ddb6a90dSDaniel Scheller struct mutex i2c_lock; /* shared I2C access protect */ 83ddb6a90dSDaniel Scheller struct mutex reg_lock; /* shared register write protect */ 84cd21b334SDaniel Scheller int count; 85cd21b334SDaniel Scheller 86cd21b334SDaniel Scheller u32 extclk; 87cd21b334SDaniel Scheller u32 mclk; 88cd21b334SDaniel Scheller }; 89cd21b334SDaniel Scheller 90cd21b334SDaniel Scheller struct stv { 91cd21b334SDaniel Scheller struct stv_base *base; 92cd21b334SDaniel Scheller struct dvb_frontend fe; 93cd21b334SDaniel Scheller int nr; 94cd21b334SDaniel Scheller u16 regoff; 95cd21b334SDaniel Scheller u8 i2crpt; 96cd21b334SDaniel Scheller u8 tscfgh; 97cd21b334SDaniel Scheller u8 tsgeneral; 98cd21b334SDaniel Scheller u8 tsspeed; 99cd21b334SDaniel Scheller u8 single; 100cd21b334SDaniel Scheller unsigned long tune_time; 101cd21b334SDaniel Scheller 102cd21b334SDaniel Scheller s32 search_range; 103cd21b334SDaniel Scheller u32 started; 104cd21b334SDaniel Scheller u32 demod_lock_time; 105cd21b334SDaniel Scheller enum receive_mode receive_mode; 106cd21b334SDaniel Scheller u32 demod_timeout; 107cd21b334SDaniel Scheller u32 fec_timeout; 108cd21b334SDaniel Scheller u32 first_time_lock; 109cd21b334SDaniel Scheller u8 demod_bits; 110cd21b334SDaniel Scheller u32 symbol_rate; 111cd21b334SDaniel Scheller 112cd21b334SDaniel Scheller u8 last_viterbi_rate; 113cd21b334SDaniel Scheller enum fe_code_rate puncture_rate; 114cd21b334SDaniel Scheller enum fe_stv0910_mod_cod mod_cod; 115cd21b334SDaniel Scheller enum dvbs2_fectype fectype; 116cd21b334SDaniel Scheller u32 pilots; 117cd21b334SDaniel Scheller enum fe_stv0910_roll_off feroll_off; 118cd21b334SDaniel Scheller 119cd21b334SDaniel Scheller int is_standard_broadcast; 120cd21b334SDaniel Scheller int is_vcm; 121cd21b334SDaniel Scheller 122ea71c62bSDaniel Scheller u32 cur_scrambling_code; 123ea71c62bSDaniel Scheller 124cd21b334SDaniel Scheller u32 last_bernumerator; 125cd21b334SDaniel Scheller u32 last_berdenominator; 126cd21b334SDaniel Scheller u8 berscale; 127cd21b334SDaniel Scheller 128cd21b334SDaniel Scheller u8 vth[6]; 129cd21b334SDaniel Scheller }; 130cd21b334SDaniel Scheller 131cd21b334SDaniel Scheller struct sinit_table { 132cd21b334SDaniel Scheller u16 address; 133cd21b334SDaniel Scheller u8 data; 134cd21b334SDaniel Scheller }; 135cd21b334SDaniel Scheller 136cd21b334SDaniel Scheller struct slookup { 137cd21b334SDaniel Scheller s16 value; 13819bb3b71SDaniel Scheller u32 reg_value; 139cd21b334SDaniel Scheller }; 140cd21b334SDaniel Scheller 141cd21b334SDaniel Scheller static inline int i2c_write(struct i2c_adapter *adap, u8 adr, 142cd21b334SDaniel Scheller u8 *data, int len) 143cd21b334SDaniel Scheller { 144cd21b334SDaniel Scheller struct i2c_msg msg = {.addr = adr, .flags = 0, 145cd21b334SDaniel Scheller .buf = data, .len = len}; 146cd21b334SDaniel Scheller 147cd21b334SDaniel Scheller if (i2c_transfer(adap, &msg, 1) != 1) { 148cd21b334SDaniel Scheller dev_warn(&adap->dev, "i2c write error ([%02x] %04x: %02x)\n", 149cd21b334SDaniel Scheller adr, (data[0] << 8) | data[1], 150cd21b334SDaniel Scheller (len > 2 ? data[2] : 0)); 151cd21b334SDaniel Scheller return -EREMOTEIO; 152cd21b334SDaniel Scheller } 153cd21b334SDaniel Scheller return 0; 154cd21b334SDaniel Scheller } 155cd21b334SDaniel Scheller 156cd21b334SDaniel Scheller static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, u16 reg, u8 val) 157cd21b334SDaniel Scheller { 158cd21b334SDaniel Scheller u8 msg[3] = {reg >> 8, reg & 0xff, val}; 159cd21b334SDaniel Scheller 160cd21b334SDaniel Scheller return i2c_write(adap, adr, msg, 3); 161cd21b334SDaniel Scheller } 162cd21b334SDaniel Scheller 163cd21b334SDaniel Scheller static int write_reg(struct stv *state, u16 reg, u8 val) 164cd21b334SDaniel Scheller { 165cd21b334SDaniel Scheller return i2c_write_reg16(state->base->i2c, state->base->adr, reg, val); 166cd21b334SDaniel Scheller } 167cd21b334SDaniel Scheller 168cd21b334SDaniel Scheller static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr, 169cd21b334SDaniel Scheller u16 reg, u8 *val, int count) 170cd21b334SDaniel Scheller { 171cd21b334SDaniel Scheller u8 msg[2] = {reg >> 8, reg & 0xff}; 172cd21b334SDaniel Scheller struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, 173cd21b334SDaniel Scheller .buf = msg, .len = 2}, 174cd21b334SDaniel Scheller {.addr = adr, .flags = I2C_M_RD, 175cd21b334SDaniel Scheller .buf = val, .len = count } }; 176cd21b334SDaniel Scheller 177cd21b334SDaniel Scheller if (i2c_transfer(adapter, msgs, 2) != 2) { 178cd21b334SDaniel Scheller dev_warn(&adapter->dev, "i2c read error ([%02x] %04x)\n", 179cd21b334SDaniel Scheller adr, reg); 180cd21b334SDaniel Scheller return -EREMOTEIO; 181cd21b334SDaniel Scheller } 182cd21b334SDaniel Scheller return 0; 183cd21b334SDaniel Scheller } 184cd21b334SDaniel Scheller 185cd21b334SDaniel Scheller static int read_reg(struct stv *state, u16 reg, u8 *val) 186cd21b334SDaniel Scheller { 187cd21b334SDaniel Scheller return i2c_read_regs16(state->base->i2c, state->base->adr, 188cd21b334SDaniel Scheller reg, val, 1); 189cd21b334SDaniel Scheller } 190cd21b334SDaniel Scheller 191cd21b334SDaniel Scheller static int read_regs(struct stv *state, u16 reg, u8 *val, int len) 192cd21b334SDaniel Scheller { 193cd21b334SDaniel Scheller return i2c_read_regs16(state->base->i2c, state->base->adr, 194cd21b334SDaniel Scheller reg, val, len); 195cd21b334SDaniel Scheller } 196cd21b334SDaniel Scheller 197cd21b334SDaniel Scheller static int write_shared_reg(struct stv *state, u16 reg, u8 mask, u8 val) 198cd21b334SDaniel Scheller { 199cd21b334SDaniel Scheller int status; 200cd21b334SDaniel Scheller u8 tmp; 201cd21b334SDaniel Scheller 202cd21b334SDaniel Scheller mutex_lock(&state->base->reg_lock); 203cd21b334SDaniel Scheller status = read_reg(state, reg, &tmp); 204cd21b334SDaniel Scheller if (!status) 205cd21b334SDaniel Scheller status = write_reg(state, reg, (tmp & ~mask) | (val & mask)); 206cd21b334SDaniel Scheller mutex_unlock(&state->base->reg_lock); 207cd21b334SDaniel Scheller return status; 208cd21b334SDaniel Scheller } 209cd21b334SDaniel Scheller 21020e671dfSDaniel Scheller static const struct slookup s1_sn_lookup[] = { 211cd21b334SDaniel Scheller { 0, 9242 }, /* C/N= 0dB */ 212cd21b334SDaniel Scheller { 5, 9105 }, /* C/N= 0.5dB */ 213cd21b334SDaniel Scheller { 10, 8950 }, /* C/N= 1.0dB */ 214cd21b334SDaniel Scheller { 15, 8780 }, /* C/N= 1.5dB */ 215cd21b334SDaniel Scheller { 20, 8566 }, /* C/N= 2.0dB */ 216cd21b334SDaniel Scheller { 25, 8366 }, /* C/N= 2.5dB */ 217cd21b334SDaniel Scheller { 30, 8146 }, /* C/N= 3.0dB */ 218cd21b334SDaniel Scheller { 35, 7908 }, /* C/N= 3.5dB */ 219cd21b334SDaniel Scheller { 40, 7666 }, /* C/N= 4.0dB */ 220cd21b334SDaniel Scheller { 45, 7405 }, /* C/N= 4.5dB */ 221cd21b334SDaniel Scheller { 50, 7136 }, /* C/N= 5.0dB */ 222cd21b334SDaniel Scheller { 55, 6861 }, /* C/N= 5.5dB */ 223cd21b334SDaniel Scheller { 60, 6576 }, /* C/N= 6.0dB */ 224cd21b334SDaniel Scheller { 65, 6330 }, /* C/N= 6.5dB */ 225cd21b334SDaniel Scheller { 70, 6048 }, /* C/N= 7.0dB */ 226cd21b334SDaniel Scheller { 75, 5768 }, /* C/N= 7.5dB */ 227cd21b334SDaniel Scheller { 80, 5492 }, /* C/N= 8.0dB */ 228cd21b334SDaniel Scheller { 85, 5224 }, /* C/N= 8.5dB */ 229cd21b334SDaniel Scheller { 90, 4959 }, /* C/N= 9.0dB */ 230cd21b334SDaniel Scheller { 95, 4709 }, /* C/N= 9.5dB */ 231cd21b334SDaniel Scheller { 100, 4467 }, /* C/N=10.0dB */ 232cd21b334SDaniel Scheller { 105, 4236 }, /* C/N=10.5dB */ 233cd21b334SDaniel Scheller { 110, 4013 }, /* C/N=11.0dB */ 234cd21b334SDaniel Scheller { 115, 3800 }, /* C/N=11.5dB */ 235cd21b334SDaniel Scheller { 120, 3598 }, /* C/N=12.0dB */ 236cd21b334SDaniel Scheller { 125, 3406 }, /* C/N=12.5dB */ 237cd21b334SDaniel Scheller { 130, 3225 }, /* C/N=13.0dB */ 238cd21b334SDaniel Scheller { 135, 3052 }, /* C/N=13.5dB */ 239cd21b334SDaniel Scheller { 140, 2889 }, /* C/N=14.0dB */ 240cd21b334SDaniel Scheller { 145, 2733 }, /* C/N=14.5dB */ 241cd21b334SDaniel Scheller { 150, 2587 }, /* C/N=15.0dB */ 242cd21b334SDaniel Scheller { 160, 2318 }, /* C/N=16.0dB */ 243cd21b334SDaniel Scheller { 170, 2077 }, /* C/N=17.0dB */ 244cd21b334SDaniel Scheller { 180, 1862 }, /* C/N=18.0dB */ 245cd21b334SDaniel Scheller { 190, 1670 }, /* C/N=19.0dB */ 246cd21b334SDaniel Scheller { 200, 1499 }, /* C/N=20.0dB */ 247cd21b334SDaniel Scheller { 210, 1347 }, /* C/N=21.0dB */ 248cd21b334SDaniel Scheller { 220, 1213 }, /* C/N=22.0dB */ 249cd21b334SDaniel Scheller { 230, 1095 }, /* C/N=23.0dB */ 250cd21b334SDaniel Scheller { 240, 992 }, /* C/N=24.0dB */ 251cd21b334SDaniel Scheller { 250, 900 }, /* C/N=25.0dB */ 252cd21b334SDaniel Scheller { 260, 826 }, /* C/N=26.0dB */ 253cd21b334SDaniel Scheller { 270, 758 }, /* C/N=27.0dB */ 254cd21b334SDaniel Scheller { 280, 702 }, /* C/N=28.0dB */ 255cd21b334SDaniel Scheller { 290, 653 }, /* C/N=29.0dB */ 256cd21b334SDaniel Scheller { 300, 613 }, /* C/N=30.0dB */ 257cd21b334SDaniel Scheller { 310, 579 }, /* C/N=31.0dB */ 258cd21b334SDaniel Scheller { 320, 550 }, /* C/N=32.0dB */ 259cd21b334SDaniel Scheller { 330, 526 }, /* C/N=33.0dB */ 260cd21b334SDaniel Scheller { 350, 490 }, /* C/N=33.0dB */ 261cd21b334SDaniel Scheller { 400, 445 }, /* C/N=40.0dB */ 262cd21b334SDaniel Scheller { 450, 430 }, /* C/N=45.0dB */ 263cd21b334SDaniel Scheller { 500, 426 }, /* C/N=50.0dB */ 264cd21b334SDaniel Scheller { 510, 425 } /* C/N=51.0dB */ 265cd21b334SDaniel Scheller }; 266cd21b334SDaniel Scheller 26720e671dfSDaniel Scheller static const struct slookup s2_sn_lookup[] = { 268cd21b334SDaniel Scheller { -30, 13950 }, /* C/N=-2.5dB */ 269cd21b334SDaniel Scheller { -25, 13580 }, /* C/N=-2.5dB */ 270cd21b334SDaniel Scheller { -20, 13150 }, /* C/N=-2.0dB */ 271cd21b334SDaniel Scheller { -15, 12760 }, /* C/N=-1.5dB */ 272cd21b334SDaniel Scheller { -10, 12345 }, /* C/N=-1.0dB */ 273cd21b334SDaniel Scheller { -5, 11900 }, /* C/N=-0.5dB */ 274cd21b334SDaniel Scheller { 0, 11520 }, /* C/N= 0dB */ 275cd21b334SDaniel Scheller { 5, 11080 }, /* C/N= 0.5dB */ 276cd21b334SDaniel Scheller { 10, 10630 }, /* C/N= 1.0dB */ 277cd21b334SDaniel Scheller { 15, 10210 }, /* C/N= 1.5dB */ 278cd21b334SDaniel Scheller { 20, 9790 }, /* C/N= 2.0dB */ 279cd21b334SDaniel Scheller { 25, 9390 }, /* C/N= 2.5dB */ 280cd21b334SDaniel Scheller { 30, 8970 }, /* C/N= 3.0dB */ 281cd21b334SDaniel Scheller { 35, 8575 }, /* C/N= 3.5dB */ 282cd21b334SDaniel Scheller { 40, 8180 }, /* C/N= 4.0dB */ 283cd21b334SDaniel Scheller { 45, 7800 }, /* C/N= 4.5dB */ 284cd21b334SDaniel Scheller { 50, 7430 }, /* C/N= 5.0dB */ 285cd21b334SDaniel Scheller { 55, 7080 }, /* C/N= 5.5dB */ 286cd21b334SDaniel Scheller { 60, 6720 }, /* C/N= 6.0dB */ 287cd21b334SDaniel Scheller { 65, 6320 }, /* C/N= 6.5dB */ 288cd21b334SDaniel Scheller { 70, 6060 }, /* C/N= 7.0dB */ 289cd21b334SDaniel Scheller { 75, 5760 }, /* C/N= 7.5dB */ 290cd21b334SDaniel Scheller { 80, 5480 }, /* C/N= 8.0dB */ 291cd21b334SDaniel Scheller { 85, 5200 }, /* C/N= 8.5dB */ 292cd21b334SDaniel Scheller { 90, 4930 }, /* C/N= 9.0dB */ 293cd21b334SDaniel Scheller { 95, 4680 }, /* C/N= 9.5dB */ 294cd21b334SDaniel Scheller { 100, 4425 }, /* C/N=10.0dB */ 295cd21b334SDaniel Scheller { 105, 4210 }, /* C/N=10.5dB */ 296cd21b334SDaniel Scheller { 110, 3980 }, /* C/N=11.0dB */ 297cd21b334SDaniel Scheller { 115, 3765 }, /* C/N=11.5dB */ 298cd21b334SDaniel Scheller { 120, 3570 }, /* C/N=12.0dB */ 299cd21b334SDaniel Scheller { 125, 3315 }, /* C/N=12.5dB */ 300cd21b334SDaniel Scheller { 130, 3140 }, /* C/N=13.0dB */ 301cd21b334SDaniel Scheller { 135, 2980 }, /* C/N=13.5dB */ 302cd21b334SDaniel Scheller { 140, 2820 }, /* C/N=14.0dB */ 303cd21b334SDaniel Scheller { 145, 2670 }, /* C/N=14.5dB */ 304cd21b334SDaniel Scheller { 150, 2535 }, /* C/N=15.0dB */ 305cd21b334SDaniel Scheller { 160, 2270 }, /* C/N=16.0dB */ 306cd21b334SDaniel Scheller { 170, 2035 }, /* C/N=17.0dB */ 307cd21b334SDaniel Scheller { 180, 1825 }, /* C/N=18.0dB */ 308cd21b334SDaniel Scheller { 190, 1650 }, /* C/N=19.0dB */ 309cd21b334SDaniel Scheller { 200, 1485 }, /* C/N=20.0dB */ 310cd21b334SDaniel Scheller { 210, 1340 }, /* C/N=21.0dB */ 311cd21b334SDaniel Scheller { 220, 1212 }, /* C/N=22.0dB */ 312cd21b334SDaniel Scheller { 230, 1100 }, /* C/N=23.0dB */ 313cd21b334SDaniel Scheller { 240, 1000 }, /* C/N=24.0dB */ 314cd21b334SDaniel Scheller { 250, 910 }, /* C/N=25.0dB */ 315cd21b334SDaniel Scheller { 260, 836 }, /* C/N=26.0dB */ 316cd21b334SDaniel Scheller { 270, 772 }, /* C/N=27.0dB */ 317cd21b334SDaniel Scheller { 280, 718 }, /* C/N=28.0dB */ 318cd21b334SDaniel Scheller { 290, 671 }, /* C/N=29.0dB */ 319cd21b334SDaniel Scheller { 300, 635 }, /* C/N=30.0dB */ 320cd21b334SDaniel Scheller { 310, 602 }, /* C/N=31.0dB */ 321cd21b334SDaniel Scheller { 320, 575 }, /* C/N=32.0dB */ 322cd21b334SDaniel Scheller { 330, 550 }, /* C/N=33.0dB */ 323cd21b334SDaniel Scheller { 350, 517 }, /* C/N=35.0dB */ 324cd21b334SDaniel Scheller { 400, 480 }, /* C/N=40.0dB */ 325cd21b334SDaniel Scheller { 450, 466 }, /* C/N=45.0dB */ 326cd21b334SDaniel Scheller { 500, 464 }, /* C/N=50.0dB */ 327cd21b334SDaniel Scheller { 510, 463 }, /* C/N=51.0dB */ 328cd21b334SDaniel Scheller }; 329cd21b334SDaniel Scheller 33020e671dfSDaniel Scheller static const struct slookup padc_lookup[] = { 33119bb3b71SDaniel Scheller { 0, 118000 }, /* PADC= +0dBm */ 33219bb3b71SDaniel Scheller { -100, 93600 }, /* PADC= -1dBm */ 33319bb3b71SDaniel Scheller { -200, 74500 }, /* PADC= -2dBm */ 33419bb3b71SDaniel Scheller { -300, 59100 }, /* PADC= -3dBm */ 33519bb3b71SDaniel Scheller { -400, 47000 }, /* PADC= -4dBm */ 33619bb3b71SDaniel Scheller { -500, 37300 }, /* PADC= -5dBm */ 33719bb3b71SDaniel Scheller { -600, 29650 }, /* PADC= -6dBm */ 33819bb3b71SDaniel Scheller { -700, 23520 }, /* PADC= -7dBm */ 33919bb3b71SDaniel Scheller { -900, 14850 }, /* PADC= -9dBm */ 34019bb3b71SDaniel Scheller { -1100, 9380 }, /* PADC=-11dBm */ 34119bb3b71SDaniel Scheller { -1300, 5910 }, /* PADC=-13dBm */ 34219bb3b71SDaniel Scheller { -1500, 3730 }, /* PADC=-15dBm */ 34319bb3b71SDaniel Scheller { -1700, 2354 }, /* PADC=-17dBm */ 34419bb3b71SDaniel Scheller { -1900, 1485 }, /* PADC=-19dBm */ 34519bb3b71SDaniel Scheller { -2000, 1179 }, /* PADC=-20dBm */ 34619bb3b71SDaniel Scheller { -2100, 1000 }, /* PADC=-21dBm */ 34719bb3b71SDaniel Scheller }; 34819bb3b71SDaniel Scheller 349cd21b334SDaniel Scheller /********************************************************************* 350cd21b334SDaniel Scheller * Tracking carrier loop carrier QPSK 1/4 to 8PSK 9/10 long Frame 351cd21b334SDaniel Scheller *********************************************************************/ 35220e671dfSDaniel Scheller static const u8 s2car_loop[] = { 3534f979d5cSDaniel Scheller /* 3544f979d5cSDaniel Scheller * Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 355cd21b334SDaniel Scheller * 20MPon 20MPoff 30MPon 30MPoff 356cd21b334SDaniel Scheller */ 357cd21b334SDaniel Scheller 358cd21b334SDaniel Scheller /* FE_QPSK_14 */ 359cd21b334SDaniel Scheller 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x2A, 0x1C, 0x3A, 0x3B, 360cd21b334SDaniel Scheller /* FE_QPSK_13 */ 361cd21b334SDaniel Scheller 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x3A, 0x0C, 0x3A, 0x2B, 362cd21b334SDaniel Scheller /* FE_QPSK_25 */ 363cd21b334SDaniel Scheller 0x1C, 0x3C, 0x1B, 0x3C, 0x3A, 0x1C, 0x3A, 0x3B, 0x3A, 0x2B, 364cd21b334SDaniel Scheller /* FE_QPSK_12 */ 365cd21b334SDaniel Scheller 0x0C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, 366cd21b334SDaniel Scheller /* FE_QPSK_35 */ 367cd21b334SDaniel Scheller 0x1C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, 368cd21b334SDaniel Scheller /* FE_QPSK_23 */ 369cd21b334SDaniel Scheller 0x2C, 0x2C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, 370cd21b334SDaniel Scheller /* FE_QPSK_34 */ 371cd21b334SDaniel Scheller 0x3C, 0x2C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, 372cd21b334SDaniel Scheller /* FE_QPSK_45 */ 373cd21b334SDaniel Scheller 0x0D, 0x3C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, 374cd21b334SDaniel Scheller /* FE_QPSK_56 */ 375cd21b334SDaniel Scheller 0x1D, 0x3C, 0x0C, 0x2C, 0x2B, 0x1C, 0x1B, 0x3B, 0x0B, 0x1B, 376cd21b334SDaniel Scheller /* FE_QPSK_89 */ 377cd21b334SDaniel Scheller 0x3D, 0x0D, 0x0C, 0x2C, 0x2B, 0x0C, 0x2B, 0x2B, 0x0B, 0x0B, 378cd21b334SDaniel Scheller /* FE_QPSK_910 */ 379cd21b334SDaniel Scheller 0x1E, 0x0D, 0x1C, 0x2C, 0x3B, 0x0C, 0x2B, 0x2B, 0x1B, 0x0B, 380cd21b334SDaniel Scheller /* FE_8PSK_35 */ 381cd21b334SDaniel Scheller 0x28, 0x09, 0x28, 0x09, 0x28, 0x09, 0x28, 0x08, 0x28, 0x27, 382cd21b334SDaniel Scheller /* FE_8PSK_23 */ 383cd21b334SDaniel Scheller 0x19, 0x29, 0x19, 0x29, 0x19, 0x29, 0x38, 0x19, 0x28, 0x09, 384cd21b334SDaniel Scheller /* FE_8PSK_34 */ 385cd21b334SDaniel Scheller 0x1A, 0x0B, 0x1A, 0x3A, 0x0A, 0x2A, 0x39, 0x2A, 0x39, 0x1A, 386cd21b334SDaniel Scheller /* FE_8PSK_56 */ 387cd21b334SDaniel Scheller 0x2B, 0x2B, 0x1B, 0x1B, 0x0B, 0x1B, 0x1A, 0x0B, 0x1A, 0x1A, 388cd21b334SDaniel Scheller /* FE_8PSK_89 */ 389cd21b334SDaniel Scheller 0x0C, 0x0C, 0x3B, 0x3B, 0x1B, 0x1B, 0x2A, 0x0B, 0x2A, 0x2A, 390cd21b334SDaniel Scheller /* FE_8PSK_910 */ 391cd21b334SDaniel Scheller 0x0C, 0x1C, 0x0C, 0x3B, 0x2B, 0x1B, 0x3A, 0x0B, 0x2A, 0x2A, 392cd21b334SDaniel Scheller 393cd21b334SDaniel Scheller /********************************************************************** 394cd21b334SDaniel Scheller * Tracking carrier loop carrier 16APSK 2/3 to 32APSK 9/10 long Frame 395cd21b334SDaniel Scheller **********************************************************************/ 396cd21b334SDaniel Scheller 3974f979d5cSDaniel Scheller /* 3984f979d5cSDaniel Scheller * Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 399cd21b334SDaniel Scheller * 20MPoff 30MPon 30MPoff 400cd21b334SDaniel Scheller */ 401cd21b334SDaniel Scheller 402cd21b334SDaniel Scheller /* FE_16APSK_23 */ 403cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x0A, 0x39, 0x0A, 0x29, 0x0A, 404cd21b334SDaniel Scheller /* FE_16APSK_34 */ 405cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0A, 0x2A, 0x0A, 0x1A, 0x0A, 406cd21b334SDaniel Scheller /* FE_16APSK_45 */ 407cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, 408cd21b334SDaniel Scheller /* FE_16APSK_56 */ 409cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, 410cd21b334SDaniel Scheller /* FE_16APSK_89 */ 411cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, 412cd21b334SDaniel Scheller /* FE_16APSK_910 */ 413cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, 414cd21b334SDaniel Scheller /* FE_32APSK_34 */ 415cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 416cd21b334SDaniel Scheller /* FE_32APSK_45 */ 417cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 418cd21b334SDaniel Scheller /* FE_32APSK_56 */ 419cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 420cd21b334SDaniel Scheller /* FE_32APSK_89 */ 421cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 422cd21b334SDaniel Scheller /* FE_32APSK_910 */ 423cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 424cd21b334SDaniel Scheller }; 425cd21b334SDaniel Scheller 426cd21b334SDaniel Scheller static u8 get_optim_cloop(struct stv *state, 427cd21b334SDaniel Scheller enum fe_stv0910_mod_cod mod_cod, u32 pilots) 428cd21b334SDaniel Scheller { 429cd21b334SDaniel Scheller int i = 0; 430cd21b334SDaniel Scheller 431cd21b334SDaniel Scheller if (mod_cod >= FE_32APSK_910) 432cd21b334SDaniel Scheller i = ((int)FE_32APSK_910 - (int)FE_QPSK_14) * 10; 433cd21b334SDaniel Scheller else if (mod_cod >= FE_QPSK_14) 434cd21b334SDaniel Scheller i = ((int)mod_cod - (int)FE_QPSK_14) * 10; 435cd21b334SDaniel Scheller 436cd21b334SDaniel Scheller if (state->symbol_rate <= 3000000) 437cd21b334SDaniel Scheller i += 0; 438cd21b334SDaniel Scheller else if (state->symbol_rate <= 7000000) 439cd21b334SDaniel Scheller i += 2; 440cd21b334SDaniel Scheller else if (state->symbol_rate <= 15000000) 441cd21b334SDaniel Scheller i += 4; 442cd21b334SDaniel Scheller else if (state->symbol_rate <= 25000000) 443cd21b334SDaniel Scheller i += 6; 444cd21b334SDaniel Scheller else 445cd21b334SDaniel Scheller i += 8; 446cd21b334SDaniel Scheller 447cd21b334SDaniel Scheller if (!pilots) 448cd21b334SDaniel Scheller i += 1; 449cd21b334SDaniel Scheller 450cd21b334SDaniel Scheller return s2car_loop[i]; 451cd21b334SDaniel Scheller } 452cd21b334SDaniel Scheller 453cd21b334SDaniel Scheller static int get_cur_symbol_rate(struct stv *state, u32 *p_symbol_rate) 454cd21b334SDaniel Scheller { 455cd21b334SDaniel Scheller int status = 0; 456cd21b334SDaniel Scheller u8 symb_freq0; 457cd21b334SDaniel Scheller u8 symb_freq1; 458cd21b334SDaniel Scheller u8 symb_freq2; 459cd21b334SDaniel Scheller u8 symb_freq3; 460cd21b334SDaniel Scheller u8 tim_offs0; 461cd21b334SDaniel Scheller u8 tim_offs1; 462cd21b334SDaniel Scheller u8 tim_offs2; 463cd21b334SDaniel Scheller u32 symbol_rate; 464cd21b334SDaniel Scheller s32 timing_offset; 465cd21b334SDaniel Scheller 466cd21b334SDaniel Scheller *p_symbol_rate = 0; 467cd21b334SDaniel Scheller if (!state->started) 468cd21b334SDaniel Scheller return status; 469cd21b334SDaniel Scheller 470cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_SFR3 + state->regoff, &symb_freq3); 471cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_SFR2 + state->regoff, &symb_freq2); 472cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_SFR1 + state->regoff, &symb_freq1); 473cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_SFR0 + state->regoff, &symb_freq0); 474cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TMGREG2 + state->regoff, &tim_offs2); 475cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TMGREG1 + state->regoff, &tim_offs1); 476cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TMGREG0 + state->regoff, &tim_offs0); 477cd21b334SDaniel Scheller 478cd21b334SDaniel Scheller symbol_rate = ((u32)symb_freq3 << 24) | ((u32)symb_freq2 << 16) | 479cd21b334SDaniel Scheller ((u32)symb_freq1 << 8) | (u32)symb_freq0; 480cd21b334SDaniel Scheller timing_offset = ((u32)tim_offs2 << 16) | ((u32)tim_offs1 << 8) | 481cd21b334SDaniel Scheller (u32)tim_offs0; 482cd21b334SDaniel Scheller 483cd21b334SDaniel Scheller if ((timing_offset & (1 << 23)) != 0) 484cd21b334SDaniel Scheller timing_offset |= 0xFF000000; /* Sign extent */ 485cd21b334SDaniel Scheller 486cd21b334SDaniel Scheller symbol_rate = (u32)(((u64)symbol_rate * state->base->mclk) >> 32); 487cd21b334SDaniel Scheller timing_offset = (s32)(((s64)symbol_rate * (s64)timing_offset) >> 29); 488cd21b334SDaniel Scheller 489cd21b334SDaniel Scheller *p_symbol_rate = symbol_rate + timing_offset; 490cd21b334SDaniel Scheller 491cd21b334SDaniel Scheller return 0; 492cd21b334SDaniel Scheller } 493cd21b334SDaniel Scheller 494cd21b334SDaniel Scheller static int get_signal_parameters(struct stv *state) 495cd21b334SDaniel Scheller { 496cd21b334SDaniel Scheller u8 tmp; 497cd21b334SDaniel Scheller 498cd21b334SDaniel Scheller if (!state->started) 499cd21b334SDaniel Scheller return -EINVAL; 500cd21b334SDaniel Scheller 501cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 502cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); 503cd21b334SDaniel Scheller state->mod_cod = (enum fe_stv0910_mod_cod)((tmp & 0x7c) >> 2); 504cd21b334SDaniel Scheller state->pilots = (tmp & 0x01) != 0; 505cd21b334SDaniel Scheller state->fectype = (enum dvbs2_fectype)((tmp & 0x02) >> 1); 506cd21b334SDaniel Scheller 507cd21b334SDaniel Scheller } else if (state->receive_mode == RCVMODE_DVBS) { 508cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); 509cd21b334SDaniel Scheller state->puncture_rate = FEC_NONE; 510cd21b334SDaniel Scheller switch (tmp & 0x1F) { 511cd21b334SDaniel Scheller case 0x0d: 512cd21b334SDaniel Scheller state->puncture_rate = FEC_1_2; 513cd21b334SDaniel Scheller break; 514cd21b334SDaniel Scheller case 0x12: 515cd21b334SDaniel Scheller state->puncture_rate = FEC_2_3; 516cd21b334SDaniel Scheller break; 517cd21b334SDaniel Scheller case 0x15: 518cd21b334SDaniel Scheller state->puncture_rate = FEC_3_4; 519cd21b334SDaniel Scheller break; 520cd21b334SDaniel Scheller case 0x18: 521cd21b334SDaniel Scheller state->puncture_rate = FEC_5_6; 522cd21b334SDaniel Scheller break; 523cd21b334SDaniel Scheller case 0x1a: 524cd21b334SDaniel Scheller state->puncture_rate = FEC_7_8; 525cd21b334SDaniel Scheller break; 526cd21b334SDaniel Scheller } 527cd21b334SDaniel Scheller state->is_vcm = 0; 528cd21b334SDaniel Scheller state->is_standard_broadcast = 1; 529cd21b334SDaniel Scheller state->feroll_off = FE_SAT_35; 530cd21b334SDaniel Scheller } 531cd21b334SDaniel Scheller return 0; 532cd21b334SDaniel Scheller } 533cd21b334SDaniel Scheller 534cd21b334SDaniel Scheller static int tracking_optimization(struct stv *state) 535cd21b334SDaniel Scheller { 536cd21b334SDaniel Scheller u32 symbol_rate = 0; 537cd21b334SDaniel Scheller u8 tmp; 538cd21b334SDaniel Scheller 539cd21b334SDaniel Scheller get_cur_symbol_rate(state, &symbol_rate); 540cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, &tmp); 541cd21b334SDaniel Scheller tmp &= ~0xC0; 542cd21b334SDaniel Scheller 543cd21b334SDaniel Scheller switch (state->receive_mode) { 544cd21b334SDaniel Scheller case RCVMODE_DVBS: 545cd21b334SDaniel Scheller tmp |= 0x40; 546cd21b334SDaniel Scheller break; 547cd21b334SDaniel Scheller case RCVMODE_DVBS2: 548cd21b334SDaniel Scheller tmp |= 0x80; 549cd21b334SDaniel Scheller break; 550cd21b334SDaniel Scheller default: 551cd21b334SDaniel Scheller tmp |= 0xC0; 552cd21b334SDaniel Scheller break; 553cd21b334SDaniel Scheller } 554cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, tmp); 555cd21b334SDaniel Scheller 556cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 557cd21b334SDaniel Scheller /* Disable Reed-Solomon */ 558cd21b334SDaniel Scheller write_shared_reg(state, 559cd21b334SDaniel Scheller RSTV0910_TSTTSRS, state->nr ? 0x02 : 0x01, 560cd21b334SDaniel Scheller 0x03); 561cd21b334SDaniel Scheller 562cd21b334SDaniel Scheller if (state->fectype == DVBS2_64K) { 563cd21b334SDaniel Scheller u8 aclc = get_optim_cloop(state, state->mod_cod, 564cd21b334SDaniel Scheller state->pilots); 565cd21b334SDaniel Scheller 566cd21b334SDaniel Scheller if (state->mod_cod <= FE_QPSK_910) { 567cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + 568cd21b334SDaniel Scheller state->regoff, aclc); 569cd21b334SDaniel Scheller } else if (state->mod_cod <= FE_8PSK_910) { 570cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + 571cd21b334SDaniel Scheller state->regoff, 0x2a); 572cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S28 + 573cd21b334SDaniel Scheller state->regoff, aclc); 574cd21b334SDaniel Scheller } else if (state->mod_cod <= FE_16APSK_910) { 575cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + 576cd21b334SDaniel Scheller state->regoff, 0x2a); 577cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S216A + 578cd21b334SDaniel Scheller state->regoff, aclc); 579cd21b334SDaniel Scheller } else if (state->mod_cod <= FE_32APSK_910) { 580cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + 581cd21b334SDaniel Scheller state->regoff, 0x2a); 582cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S232A + 583cd21b334SDaniel Scheller state->regoff, aclc); 584cd21b334SDaniel Scheller } 585cd21b334SDaniel Scheller } 586cd21b334SDaniel Scheller } 587cd21b334SDaniel Scheller return 0; 588cd21b334SDaniel Scheller } 589cd21b334SDaniel Scheller 59020e671dfSDaniel Scheller static s32 table_lookup(const struct slookup *table, 59119bb3b71SDaniel Scheller int table_size, u32 reg_value) 592cd21b334SDaniel Scheller { 593cd21b334SDaniel Scheller s32 value; 594cd21b334SDaniel Scheller int imin = 0; 595cd21b334SDaniel Scheller int imax = table_size - 1; 596cd21b334SDaniel Scheller int i; 597cd21b334SDaniel Scheller s32 reg_diff; 598cd21b334SDaniel Scheller 599cd21b334SDaniel Scheller /* Assumes Table[0].RegValue > Table[imax].RegValue */ 600ddb6a90dSDaniel Scheller if (reg_value >= table[0].reg_value) { 601cd21b334SDaniel Scheller value = table[0].value; 602ddb6a90dSDaniel Scheller } else if (reg_value <= table[imax].reg_value) { 603cd21b334SDaniel Scheller value = table[imax].value; 604ddb6a90dSDaniel Scheller } else { 605ddb6a90dSDaniel Scheller while ((imax - imin) > 1) { 606cd21b334SDaniel Scheller i = (imax + imin) / 2; 607cd21b334SDaniel Scheller if ((table[imin].reg_value >= reg_value) && 608cd21b334SDaniel Scheller (reg_value >= table[i].reg_value)) 609cd21b334SDaniel Scheller imax = i; 610cd21b334SDaniel Scheller else 611cd21b334SDaniel Scheller imin = i; 612cd21b334SDaniel Scheller } 613cd21b334SDaniel Scheller 614cd21b334SDaniel Scheller reg_diff = table[imax].reg_value - table[imin].reg_value; 615cd21b334SDaniel Scheller value = table[imin].value; 616cd21b334SDaniel Scheller if (reg_diff != 0) 617cd21b334SDaniel Scheller value += ((s32)(reg_value - table[imin].reg_value) * 618cd21b334SDaniel Scheller (s32)(table[imax].value 619cd21b334SDaniel Scheller - table[imin].value)) 620cd21b334SDaniel Scheller / (reg_diff); 621cd21b334SDaniel Scheller } 622cd21b334SDaniel Scheller 623cd21b334SDaniel Scheller return value; 624cd21b334SDaniel Scheller } 625cd21b334SDaniel Scheller 626cd21b334SDaniel Scheller static int get_signal_to_noise(struct stv *state, s32 *signal_to_noise) 627cd21b334SDaniel Scheller { 628cd21b334SDaniel Scheller u8 data0; 629cd21b334SDaniel Scheller u8 data1; 630cd21b334SDaniel Scheller u16 data; 631cd21b334SDaniel Scheller int n_lookup; 63220e671dfSDaniel Scheller const struct slookup *lookup; 633cd21b334SDaniel Scheller 634cd21b334SDaniel Scheller *signal_to_noise = 0; 635cd21b334SDaniel Scheller 636cd21b334SDaniel Scheller if (!state->started) 637cd21b334SDaniel Scheller return -EINVAL; 638cd21b334SDaniel Scheller 639cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 640cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_NNOSPLHT1 + state->regoff, 641cd21b334SDaniel Scheller &data1); 642cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_NNOSPLHT0 + state->regoff, 643cd21b334SDaniel Scheller &data0); 644cd21b334SDaniel Scheller n_lookup = ARRAY_SIZE(s2_sn_lookup); 645cd21b334SDaniel Scheller lookup = s2_sn_lookup; 646cd21b334SDaniel Scheller } else { 647cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_NNOSDATAT1 + state->regoff, 648cd21b334SDaniel Scheller &data1); 649cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_NNOSDATAT0 + state->regoff, 650cd21b334SDaniel Scheller &data0); 651cd21b334SDaniel Scheller n_lookup = ARRAY_SIZE(s1_sn_lookup); 652cd21b334SDaniel Scheller lookup = s1_sn_lookup; 653cd21b334SDaniel Scheller } 654cd21b334SDaniel Scheller data = (((u16)data1) << 8) | (u16)data0; 655cd21b334SDaniel Scheller *signal_to_noise = table_lookup(lookup, n_lookup, data); 656cd21b334SDaniel Scheller return 0; 657cd21b334SDaniel Scheller } 658cd21b334SDaniel Scheller 659cd21b334SDaniel Scheller static int get_bit_error_rate_s(struct stv *state, u32 *bernumerator, 660cd21b334SDaniel Scheller u32 *berdenominator) 661cd21b334SDaniel Scheller { 662cd21b334SDaniel Scheller u8 regs[3]; 663cd21b334SDaniel Scheller 664cd21b334SDaniel Scheller int status = read_regs(state, 665cd21b334SDaniel Scheller RSTV0910_P2_ERRCNT12 + state->regoff, 666cd21b334SDaniel Scheller regs, 3); 667cd21b334SDaniel Scheller 668cd21b334SDaniel Scheller if (status) 669cd21b334SDaniel Scheller return -EINVAL; 670cd21b334SDaniel Scheller 671cd21b334SDaniel Scheller if ((regs[0] & 0x80) == 0) { 672cd21b334SDaniel Scheller state->last_berdenominator = 1 << ((state->berscale * 2) + 673cd21b334SDaniel Scheller 10 + 3); 674cd21b334SDaniel Scheller state->last_bernumerator = ((u32)(regs[0] & 0x7F) << 16) | 675cd21b334SDaniel Scheller ((u32)regs[1] << 8) | regs[2]; 676cd21b334SDaniel Scheller if (state->last_bernumerator < 256 && state->berscale < 6) { 677cd21b334SDaniel Scheller state->berscale += 1; 678cd21b334SDaniel Scheller status = write_reg(state, RSTV0910_P2_ERRCTRL1 + 679cd21b334SDaniel Scheller state->regoff, 680cd21b334SDaniel Scheller 0x20 | state->berscale); 681cd21b334SDaniel Scheller } else if (state->last_bernumerator > 1024 && 682cd21b334SDaniel Scheller state->berscale > 2) { 683cd21b334SDaniel Scheller state->berscale -= 1; 684cd21b334SDaniel Scheller status = write_reg(state, RSTV0910_P2_ERRCTRL1 + 685cd21b334SDaniel Scheller state->regoff, 0x20 | 686cd21b334SDaniel Scheller state->berscale); 687cd21b334SDaniel Scheller } 688cd21b334SDaniel Scheller } 689cd21b334SDaniel Scheller *bernumerator = state->last_bernumerator; 690cd21b334SDaniel Scheller *berdenominator = state->last_berdenominator; 691cd21b334SDaniel Scheller return 0; 692cd21b334SDaniel Scheller } 693cd21b334SDaniel Scheller 694cd21b334SDaniel Scheller static u32 dvbs2_nbch(enum dvbs2_mod_cod mod_cod, enum dvbs2_fectype fectype) 695cd21b334SDaniel Scheller { 69620e671dfSDaniel Scheller static const u32 nbch[][2] = { 69713c81489SDaniel Scheller { 0, 0}, /* DUMMY_PLF */ 698cd21b334SDaniel Scheller {16200, 3240}, /* QPSK_1_4, */ 699cd21b334SDaniel Scheller {21600, 5400}, /* QPSK_1_3, */ 700cd21b334SDaniel Scheller {25920, 6480}, /* QPSK_2_5, */ 701cd21b334SDaniel Scheller {32400, 7200}, /* QPSK_1_2, */ 702cd21b334SDaniel Scheller {38880, 9720}, /* QPSK_3_5, */ 703cd21b334SDaniel Scheller {43200, 10800}, /* QPSK_2_3, */ 704cd21b334SDaniel Scheller {48600, 11880}, /* QPSK_3_4, */ 705cd21b334SDaniel Scheller {51840, 12600}, /* QPSK_4_5, */ 706cd21b334SDaniel Scheller {54000, 13320}, /* QPSK_5_6, */ 707cd21b334SDaniel Scheller {57600, 14400}, /* QPSK_8_9, */ 708cd21b334SDaniel Scheller {58320, 16000}, /* QPSK_9_10, */ 709cd21b334SDaniel Scheller {43200, 9720}, /* 8PSK_3_5, */ 710cd21b334SDaniel Scheller {48600, 10800}, /* 8PSK_2_3, */ 711cd21b334SDaniel Scheller {51840, 11880}, /* 8PSK_3_4, */ 712cd21b334SDaniel Scheller {54000, 13320}, /* 8PSK_5_6, */ 713cd21b334SDaniel Scheller {57600, 14400}, /* 8PSK_8_9, */ 714cd21b334SDaniel Scheller {58320, 16000}, /* 8PSK_9_10, */ 715cd21b334SDaniel Scheller {43200, 10800}, /* 16APSK_2_3, */ 716cd21b334SDaniel Scheller {48600, 11880}, /* 16APSK_3_4, */ 717cd21b334SDaniel Scheller {51840, 12600}, /* 16APSK_4_5, */ 718cd21b334SDaniel Scheller {54000, 13320}, /* 16APSK_5_6, */ 719cd21b334SDaniel Scheller {57600, 14400}, /* 16APSK_8_9, */ 720cd21b334SDaniel Scheller {58320, 16000}, /* 16APSK_9_10 */ 721cd21b334SDaniel Scheller {48600, 11880}, /* 32APSK_3_4, */ 722cd21b334SDaniel Scheller {51840, 12600}, /* 32APSK_4_5, */ 723cd21b334SDaniel Scheller {54000, 13320}, /* 32APSK_5_6, */ 724cd21b334SDaniel Scheller {57600, 14400}, /* 32APSK_8_9, */ 725cd21b334SDaniel Scheller {58320, 16000}, /* 32APSK_9_10 */ 726cd21b334SDaniel Scheller }; 727cd21b334SDaniel Scheller 728cd21b334SDaniel Scheller if (mod_cod >= DVBS2_QPSK_1_4 && 729cd21b334SDaniel Scheller mod_cod <= DVBS2_32APSK_9_10 && fectype <= DVBS2_16K) 73013c81489SDaniel Scheller return nbch[mod_cod][fectype]; 731cd21b334SDaniel Scheller return 64800; 732cd21b334SDaniel Scheller } 733cd21b334SDaniel Scheller 734cd21b334SDaniel Scheller static int get_bit_error_rate_s2(struct stv *state, u32 *bernumerator, 735cd21b334SDaniel Scheller u32 *berdenominator) 736cd21b334SDaniel Scheller { 737cd21b334SDaniel Scheller u8 regs[3]; 738cd21b334SDaniel Scheller 739cd21b334SDaniel Scheller int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, 740cd21b334SDaniel Scheller regs, 3); 741cd21b334SDaniel Scheller 742cd21b334SDaniel Scheller if (status) 743cd21b334SDaniel Scheller return -EINVAL; 744cd21b334SDaniel Scheller 745cd21b334SDaniel Scheller if ((regs[0] & 0x80) == 0) { 746cd21b334SDaniel Scheller state->last_berdenominator = 747cd21b334SDaniel Scheller dvbs2_nbch((enum dvbs2_mod_cod)state->mod_cod, 748cd21b334SDaniel Scheller state->fectype) << 749cd21b334SDaniel Scheller (state->berscale * 2); 750cd21b334SDaniel Scheller state->last_bernumerator = (((u32)regs[0] & 0x7F) << 16) | 751cd21b334SDaniel Scheller ((u32)regs[1] << 8) | regs[2]; 752cd21b334SDaniel Scheller if (state->last_bernumerator < 256 && state->berscale < 6) { 753cd21b334SDaniel Scheller state->berscale += 1; 754cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, 755cd21b334SDaniel Scheller 0x20 | state->berscale); 756cd21b334SDaniel Scheller } else if (state->last_bernumerator > 1024 && 757cd21b334SDaniel Scheller state->berscale > 2) { 758cd21b334SDaniel Scheller state->berscale -= 1; 759cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, 760cd21b334SDaniel Scheller 0x20 | state->berscale); 761cd21b334SDaniel Scheller } 762cd21b334SDaniel Scheller } 763cd21b334SDaniel Scheller *bernumerator = state->last_bernumerator; 764cd21b334SDaniel Scheller *berdenominator = state->last_berdenominator; 765cd21b334SDaniel Scheller return status; 766cd21b334SDaniel Scheller } 767cd21b334SDaniel Scheller 768cd21b334SDaniel Scheller static int get_bit_error_rate(struct stv *state, u32 *bernumerator, 769cd21b334SDaniel Scheller u32 *berdenominator) 770cd21b334SDaniel Scheller { 771cd21b334SDaniel Scheller *bernumerator = 0; 772cd21b334SDaniel Scheller *berdenominator = 1; 773cd21b334SDaniel Scheller 774cd21b334SDaniel Scheller switch (state->receive_mode) { 775cd21b334SDaniel Scheller case RCVMODE_DVBS: 776cd21b334SDaniel Scheller return get_bit_error_rate_s(state, 777cd21b334SDaniel Scheller bernumerator, berdenominator); 778cd21b334SDaniel Scheller case RCVMODE_DVBS2: 779cd21b334SDaniel Scheller return get_bit_error_rate_s2(state, 780cd21b334SDaniel Scheller bernumerator, berdenominator); 781cd21b334SDaniel Scheller default: 782cd21b334SDaniel Scheller break; 783cd21b334SDaniel Scheller } 784cd21b334SDaniel Scheller return 0; 785cd21b334SDaniel Scheller } 786cd21b334SDaniel Scheller 787cd21b334SDaniel Scheller static int set_mclock(struct stv *state, u32 master_clock) 788cd21b334SDaniel Scheller { 789cd21b334SDaniel Scheller u32 idf = 1; 790cd21b334SDaniel Scheller u32 odf = 4; 791cd21b334SDaniel Scheller u32 quartz = state->base->extclk / 1000000; 792cd21b334SDaniel Scheller u32 fphi = master_clock / 1000000; 793cd21b334SDaniel Scheller u32 ndiv = (fphi * odf * idf) / quartz; 794cd21b334SDaniel Scheller u32 cp = 7; 795cd21b334SDaniel Scheller u32 fvco; 796cd21b334SDaniel Scheller 797cd21b334SDaniel Scheller if (ndiv >= 7 && ndiv <= 71) 798cd21b334SDaniel Scheller cp = 7; 799cd21b334SDaniel Scheller else if (ndiv >= 72 && ndiv <= 79) 800cd21b334SDaniel Scheller cp = 8; 801cd21b334SDaniel Scheller else if (ndiv >= 80 && ndiv <= 87) 802cd21b334SDaniel Scheller cp = 9; 803cd21b334SDaniel Scheller else if (ndiv >= 88 && ndiv <= 95) 804cd21b334SDaniel Scheller cp = 10; 805cd21b334SDaniel Scheller else if (ndiv >= 96 && ndiv <= 103) 806cd21b334SDaniel Scheller cp = 11; 807cd21b334SDaniel Scheller else if (ndiv >= 104 && ndiv <= 111) 808cd21b334SDaniel Scheller cp = 12; 809cd21b334SDaniel Scheller else if (ndiv >= 112 && ndiv <= 119) 810cd21b334SDaniel Scheller cp = 13; 811cd21b334SDaniel Scheller else if (ndiv >= 120 && ndiv <= 127) 812cd21b334SDaniel Scheller cp = 14; 813cd21b334SDaniel Scheller else if (ndiv >= 128 && ndiv <= 135) 814cd21b334SDaniel Scheller cp = 15; 815cd21b334SDaniel Scheller else if (ndiv >= 136 && ndiv <= 143) 816cd21b334SDaniel Scheller cp = 16; 817cd21b334SDaniel Scheller else if (ndiv >= 144 && ndiv <= 151) 818cd21b334SDaniel Scheller cp = 17; 819cd21b334SDaniel Scheller else if (ndiv >= 152 && ndiv <= 159) 820cd21b334SDaniel Scheller cp = 18; 821cd21b334SDaniel Scheller else if (ndiv >= 160 && ndiv <= 167) 822cd21b334SDaniel Scheller cp = 19; 823cd21b334SDaniel Scheller else if (ndiv >= 168 && ndiv <= 175) 824cd21b334SDaniel Scheller cp = 20; 825cd21b334SDaniel Scheller else if (ndiv >= 176 && ndiv <= 183) 826cd21b334SDaniel Scheller cp = 21; 827cd21b334SDaniel Scheller else if (ndiv >= 184 && ndiv <= 191) 828cd21b334SDaniel Scheller cp = 22; 829cd21b334SDaniel Scheller else if (ndiv >= 192 && ndiv <= 199) 830cd21b334SDaniel Scheller cp = 23; 831cd21b334SDaniel Scheller else if (ndiv >= 200 && ndiv <= 207) 832cd21b334SDaniel Scheller cp = 24; 833cd21b334SDaniel Scheller else if (ndiv >= 208 && ndiv <= 215) 834cd21b334SDaniel Scheller cp = 25; 835cd21b334SDaniel Scheller else if (ndiv >= 216 && ndiv <= 223) 836cd21b334SDaniel Scheller cp = 26; 837cd21b334SDaniel Scheller else if (ndiv >= 224 && ndiv <= 225) 838cd21b334SDaniel Scheller cp = 27; 839cd21b334SDaniel Scheller 840cd21b334SDaniel Scheller write_reg(state, RSTV0910_NCOARSE, (cp << 3) | idf); 841cd21b334SDaniel Scheller write_reg(state, RSTV0910_NCOARSE2, odf); 842cd21b334SDaniel Scheller write_reg(state, RSTV0910_NCOARSE1, ndiv); 843cd21b334SDaniel Scheller 844cd21b334SDaniel Scheller fvco = (quartz * 2 * ndiv) / idf; 845cd21b334SDaniel Scheller state->base->mclk = fvco / (2 * odf) * 1000000; 846cd21b334SDaniel Scheller 847cd21b334SDaniel Scheller return 0; 848cd21b334SDaniel Scheller } 849cd21b334SDaniel Scheller 850cd21b334SDaniel Scheller static int stop(struct stv *state) 851cd21b334SDaniel Scheller { 852cd21b334SDaniel Scheller if (state->started) { 853cd21b334SDaniel Scheller u8 tmp; 854cd21b334SDaniel Scheller 855cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, 856cd21b334SDaniel Scheller state->tscfgh | 0x01); 857cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); 858cd21b334SDaniel Scheller tmp &= ~0x01; /* release reset DVBS2 packet delin */ 859cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); 860cd21b334SDaniel Scheller /* Blind optim*/ 861cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_AGC2O + state->regoff, 0x5B); 862cd21b334SDaniel Scheller /* Stop the demod */ 863cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5c); 864cd21b334SDaniel Scheller state->started = 0; 865cd21b334SDaniel Scheller } 866cd21b334SDaniel Scheller state->receive_mode = RCVMODE_NONE; 867cd21b334SDaniel Scheller return 0; 868cd21b334SDaniel Scheller } 869cd21b334SDaniel Scheller 870cd21b334SDaniel Scheller static int init_search_param(struct stv *state) 871cd21b334SDaniel Scheller { 872cd21b334SDaniel Scheller u8 tmp; 873cd21b334SDaniel Scheller 874cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); 8754f979d5cSDaniel Scheller tmp |= 0x20; /* Filter_en (no effect if SIS=non-MIS */ 876cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); 877cd21b334SDaniel Scheller 878cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, &tmp); 8794f979d5cSDaniel Scheller tmp &= ~0x02; /* frame mode = 0 */ 880cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, tmp); 881cd21b334SDaniel Scheller 882cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_UPLCCST0 + state->regoff, 0xe0); 883cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ISIBITENA + state->regoff, 0x00); 884cd21b334SDaniel Scheller 885cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSSTATEM + state->regoff, &tmp); 8864f979d5cSDaniel Scheller tmp &= ~0x01; /* nosync = 0, in case next signal is standard TS */ 887cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSSTATEM + state->regoff, tmp); 888cd21b334SDaniel Scheller 889cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSCFGL + state->regoff, &tmp); 8904f979d5cSDaniel Scheller tmp &= ~0x04; /* embindvb = 0 */ 891cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGL + state->regoff, tmp); 892cd21b334SDaniel Scheller 893cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSINSDELH + state->regoff, &tmp); 8944f979d5cSDaniel Scheller tmp &= ~0x80; /* syncbyte = 0 */ 895cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSINSDELH + state->regoff, tmp); 896cd21b334SDaniel Scheller 897cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSINSDELM + state->regoff, &tmp); 8984f979d5cSDaniel Scheller tmp &= ~0x08; /* token = 0 */ 899cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSINSDELM + state->regoff, tmp); 900cd21b334SDaniel Scheller 901cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSDLYSET2 + state->regoff, &tmp); 9024f979d5cSDaniel Scheller tmp &= ~0x30; /* hysteresis threshold = 0 */ 903cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSDLYSET2 + state->regoff, tmp); 904cd21b334SDaniel Scheller 905cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_PDELCTRL0 + state->regoff, &tmp); 9064f979d5cSDaniel Scheller tmp = (tmp & ~0x30) | 0x10; /* isi obs mode = 1, observe min ISI */ 907cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PDELCTRL0 + state->regoff, tmp); 908cd21b334SDaniel Scheller 909cd21b334SDaniel Scheller return 0; 910cd21b334SDaniel Scheller } 911cd21b334SDaniel Scheller 912cd21b334SDaniel Scheller static int enable_puncture_rate(struct stv *state, enum fe_code_rate rate) 913cd21b334SDaniel Scheller { 914cd21b334SDaniel Scheller switch (rate) { 915cd21b334SDaniel Scheller case FEC_1_2: 916cd21b334SDaniel Scheller return write_reg(state, 917cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x01); 918cd21b334SDaniel Scheller case FEC_2_3: 919cd21b334SDaniel Scheller return write_reg(state, 920cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x02); 921cd21b334SDaniel Scheller case FEC_3_4: 922cd21b334SDaniel Scheller return write_reg(state, 923cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x04); 924cd21b334SDaniel Scheller case FEC_5_6: 925cd21b334SDaniel Scheller return write_reg(state, 926cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x08); 927cd21b334SDaniel Scheller case FEC_7_8: 928cd21b334SDaniel Scheller return write_reg(state, 929cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x20); 930cd21b334SDaniel Scheller case FEC_NONE: 931cd21b334SDaniel Scheller default: 932cd21b334SDaniel Scheller return write_reg(state, 933cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x2f); 934cd21b334SDaniel Scheller } 935cd21b334SDaniel Scheller } 936cd21b334SDaniel Scheller 937cd21b334SDaniel Scheller static int set_vth_default(struct stv *state) 938cd21b334SDaniel Scheller { 939cd21b334SDaniel Scheller state->vth[0] = 0xd7; 940cd21b334SDaniel Scheller state->vth[1] = 0x85; 941cd21b334SDaniel Scheller state->vth[2] = 0x58; 942cd21b334SDaniel Scheller state->vth[3] = 0x3a; 943cd21b334SDaniel Scheller state->vth[4] = 0x34; 944cd21b334SDaniel Scheller state->vth[5] = 0x28; 945cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 0, state->vth[0]); 946cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 1, state->vth[1]); 947cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 2, state->vth[2]); 948cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 3, state->vth[3]); 949cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 4, state->vth[4]); 950cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 5, state->vth[5]); 951cd21b334SDaniel Scheller return 0; 952cd21b334SDaniel Scheller } 953cd21b334SDaniel Scheller 954cd21b334SDaniel Scheller static int set_vth(struct stv *state) 955cd21b334SDaniel Scheller { 95620e671dfSDaniel Scheller static const struct slookup vthlookup_table[] = { 957cd21b334SDaniel Scheller {250, 8780}, /* C/N= 1.5dB */ 958cd21b334SDaniel Scheller {100, 7405}, /* C/N= 4.5dB */ 959cd21b334SDaniel Scheller {40, 6330}, /* C/N= 6.5dB */ 960cd21b334SDaniel Scheller {12, 5224}, /* C/N= 8.5dB */ 961cd21b334SDaniel Scheller {5, 4236} /* C/N=10.5dB */ 962cd21b334SDaniel Scheller }; 963cd21b334SDaniel Scheller 964cd21b334SDaniel Scheller int i; 965cd21b334SDaniel Scheller u8 tmp[2]; 966cd21b334SDaniel Scheller int status = read_regs(state, 967cd21b334SDaniel Scheller RSTV0910_P2_NNOSDATAT1 + state->regoff, 968cd21b334SDaniel Scheller tmp, 2); 969cd21b334SDaniel Scheller u16 reg_value = (tmp[0] << 8) | tmp[1]; 970cd21b334SDaniel Scheller s32 vth = table_lookup(vthlookup_table, ARRAY_SIZE(vthlookup_table), 971cd21b334SDaniel Scheller reg_value); 972cd21b334SDaniel Scheller 973cd21b334SDaniel Scheller for (i = 0; i < 6; i += 1) 974cd21b334SDaniel Scheller if (state->vth[i] > vth) 975cd21b334SDaniel Scheller state->vth[i] = vth; 976cd21b334SDaniel Scheller 977cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 0, state->vth[0]); 978cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 1, state->vth[1]); 979cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 2, state->vth[2]); 980cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 3, state->vth[3]); 981cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 4, state->vth[4]); 982cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 5, state->vth[5]); 983cd21b334SDaniel Scheller return status; 984cd21b334SDaniel Scheller } 985cd21b334SDaniel Scheller 986cd21b334SDaniel Scheller static int start(struct stv *state, struct dtv_frontend_properties *p) 987cd21b334SDaniel Scheller { 988cd21b334SDaniel Scheller s32 freq; 989cd21b334SDaniel Scheller u8 reg_dmdcfgmd; 990cd21b334SDaniel Scheller u16 symb; 991ea71c62bSDaniel Scheller u32 scrambling_code = 1; 992cd21b334SDaniel Scheller 993cd21b334SDaniel Scheller if (p->symbol_rate < 100000 || p->symbol_rate > 70000000) 994cd21b334SDaniel Scheller return -EINVAL; 995cd21b334SDaniel Scheller 996cd21b334SDaniel Scheller state->receive_mode = RCVMODE_NONE; 997cd21b334SDaniel Scheller state->demod_lock_time = 0; 998cd21b334SDaniel Scheller 999cd21b334SDaniel Scheller /* Demod Stop */ 1000cd21b334SDaniel Scheller if (state->started) 1001cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5C); 1002cd21b334SDaniel Scheller 1003cd21b334SDaniel Scheller init_search_param(state); 1004cd21b334SDaniel Scheller 1005ea71c62bSDaniel Scheller if (p->stream_id != NO_STREAM_ID_FILTER) { 10064f979d5cSDaniel Scheller /* 10074f979d5cSDaniel Scheller * Backwards compatibility to "crazy" API. 1008ea71c62bSDaniel Scheller * PRBS X root cannot be 0, so this should always work. 1009ea71c62bSDaniel Scheller */ 1010ea71c62bSDaniel Scheller if (p->stream_id & 0xffffff00) 1011ea71c62bSDaniel Scheller scrambling_code = p->stream_id >> 8; 1012ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_ISIENTRY + state->regoff, 1013ea71c62bSDaniel Scheller p->stream_id & 0xff); 1014ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_ISIBITENA + state->regoff, 1015ea71c62bSDaniel Scheller 0xff); 1016ea71c62bSDaniel Scheller } 1017ea71c62bSDaniel Scheller 1018ea71c62bSDaniel Scheller if (scrambling_code != state->cur_scrambling_code) { 1019ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_PLROOT0 + state->regoff, 1020ea71c62bSDaniel Scheller scrambling_code & 0xff); 1021ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_PLROOT1 + state->regoff, 1022ea71c62bSDaniel Scheller (scrambling_code >> 8) & 0xff); 1023ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_PLROOT2 + state->regoff, 10240758ecdbSDaniel Scheller (scrambling_code >> 16) & 0x0f); 1025ea71c62bSDaniel Scheller state->cur_scrambling_code = scrambling_code; 1026ea71c62bSDaniel Scheller } 1027ea71c62bSDaniel Scheller 1028cd21b334SDaniel Scheller if (p->symbol_rate <= 1000000) { /* SR <=1Msps */ 1029cd21b334SDaniel Scheller state->demod_timeout = 3000; 1030cd21b334SDaniel Scheller state->fec_timeout = 2000; 1031cd21b334SDaniel Scheller } else if (p->symbol_rate <= 2000000) { /* 1Msps < SR <=2Msps */ 1032cd21b334SDaniel Scheller state->demod_timeout = 2500; 1033cd21b334SDaniel Scheller state->fec_timeout = 1300; 1034cd21b334SDaniel Scheller } else if (p->symbol_rate <= 5000000) { /* 2Msps< SR <=5Msps */ 1035cd21b334SDaniel Scheller state->demod_timeout = 1000; 1036cd21b334SDaniel Scheller state->fec_timeout = 650; 1037cd21b334SDaniel Scheller } else if (p->symbol_rate <= 10000000) { /* 5Msps< SR <=10Msps */ 1038cd21b334SDaniel Scheller state->demod_timeout = 700; 1039cd21b334SDaniel Scheller state->fec_timeout = 350; 1040cd21b334SDaniel Scheller } else if (p->symbol_rate < 20000000) { /* 10Msps< SR <=20Msps */ 1041cd21b334SDaniel Scheller state->demod_timeout = 400; 1042cd21b334SDaniel Scheller state->fec_timeout = 200; 1043cd21b334SDaniel Scheller } else { /* SR >=20Msps */ 1044cd21b334SDaniel Scheller state->demod_timeout = 300; 1045cd21b334SDaniel Scheller state->fec_timeout = 200; 1046cd21b334SDaniel Scheller } 1047cd21b334SDaniel Scheller 1048cd21b334SDaniel Scheller /* Set the Init Symbol rate */ 1049cd21b334SDaniel Scheller symb = muldiv32(p->symbol_rate, 65536, state->base->mclk); 1050cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_SFRINIT1 + state->regoff, 1051cd21b334SDaniel Scheller ((symb >> 8) & 0x7F)); 1052cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_SFRINIT0 + state->regoff, (symb & 0xFF)); 1053cd21b334SDaniel Scheller 1054cd21b334SDaniel Scheller state->demod_bits |= 0x80; 1055cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DEMOD + state->regoff, state->demod_bits); 1056cd21b334SDaniel Scheller 1057cd21b334SDaniel Scheller /* FE_STV0910_SetSearchStandard */ 1058cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, ®_dmdcfgmd); 1059cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, 1060cd21b334SDaniel Scheller reg_dmdcfgmd |= 0xC0); 1061cd21b334SDaniel Scheller 1062cd21b334SDaniel Scheller write_shared_reg(state, 1063cd21b334SDaniel Scheller RSTV0910_TSTTSRS, state->nr ? 0x02 : 0x01, 0x00); 1064cd21b334SDaniel Scheller 1065cd21b334SDaniel Scheller /* Disable DSS */ 1066cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_FECM + state->regoff, 0x00); 1067cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x2F); 1068cd21b334SDaniel Scheller 1069cd21b334SDaniel Scheller enable_puncture_rate(state, FEC_NONE); 1070cd21b334SDaniel Scheller 1071cd21b334SDaniel Scheller /* 8PSK 3/5, 8PSK 2/3 Poff tracking optimization WA */ 1072cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + state->regoff, 0x0B); 1073cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S28 + state->regoff, 0x0A); 1074cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_BCLC2S2Q + state->regoff, 0x84); 1075cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_BCLC2S28 + state->regoff, 0x84); 1076cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CARHDR + state->regoff, 0x1C); 1077cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CARFREQ + state->regoff, 0x79); 1078cd21b334SDaniel Scheller 1079cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S216A + state->regoff, 0x29); 1080cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S232A + state->regoff, 0x09); 1081cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_BCLC2S216A + state->regoff, 0x84); 1082cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_BCLC2S232A + state->regoff, 0x84); 1083cd21b334SDaniel Scheller 10844f979d5cSDaniel Scheller /* 10854f979d5cSDaniel Scheller * Reset CAR3, bug DVBS2->DVBS1 lock 10864f979d5cSDaniel Scheller * Note: The bit is only pulsed -> no lock on shared register needed 10874f979d5cSDaniel Scheller */ 1088cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSTRES0, state->nr ? 0x04 : 0x08); 1089cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSTRES0, 0); 1090cd21b334SDaniel Scheller 1091cd21b334SDaniel Scheller set_vth_default(state); 1092cd21b334SDaniel Scheller /* Reset demod */ 1093cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); 1094cd21b334SDaniel Scheller 1095cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CARCFG + state->regoff, 0x46); 1096cd21b334SDaniel Scheller 1097cd21b334SDaniel Scheller if (p->symbol_rate <= 5000000) 1098cd21b334SDaniel Scheller freq = (state->search_range / 2000) + 80; 1099cd21b334SDaniel Scheller else 1100cd21b334SDaniel Scheller freq = (state->search_range / 2000) + 1600; 1101cd21b334SDaniel Scheller freq = (freq << 16) / (state->base->mclk / 1000); 1102cd21b334SDaniel Scheller 1103cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRUP1 + state->regoff, 1104cd21b334SDaniel Scheller (freq >> 8) & 0xff); 1105cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRUP0 + state->regoff, (freq & 0xff)); 1106cd21b334SDaniel Scheller /* CFR Low Setting */ 1107cd21b334SDaniel Scheller freq = -freq; 1108cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRLOW1 + state->regoff, 1109cd21b334SDaniel Scheller (freq >> 8) & 0xff); 1110cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRLOW0 + state->regoff, (freq & 0xff)); 1111cd21b334SDaniel Scheller 1112cd21b334SDaniel Scheller /* init the demod frequency offset to 0 */ 1113cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRINIT1 + state->regoff, 0); 1114cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRINIT0 + state->regoff, 0); 1115cd21b334SDaniel Scheller 1116cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); 1117cd21b334SDaniel Scheller /* Trigger acq */ 1118cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x15); 1119cd21b334SDaniel Scheller 1120cd21b334SDaniel Scheller state->demod_lock_time += TUNING_DELAY; 1121cd21b334SDaniel Scheller state->started = 1; 1122cd21b334SDaniel Scheller 1123cd21b334SDaniel Scheller return 0; 1124cd21b334SDaniel Scheller } 1125cd21b334SDaniel Scheller 1126cd21b334SDaniel Scheller static int init_diseqc(struct stv *state) 1127cd21b334SDaniel Scheller { 1128cd21b334SDaniel Scheller u16 offs = state->nr ? 0x40 : 0; /* Address offset */ 1129cd21b334SDaniel Scheller u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); 1130cd21b334SDaniel Scheller 1131cd21b334SDaniel Scheller /* Disable receiver */ 1132cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); 1133cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ 1134cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ 1135cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq); 1136cd21b334SDaniel Scheller return 0; 1137cd21b334SDaniel Scheller } 1138cd21b334SDaniel Scheller 1139cd21b334SDaniel Scheller static int probe(struct stv *state) 1140cd21b334SDaniel Scheller { 1141cd21b334SDaniel Scheller u8 id; 1142cd21b334SDaniel Scheller 1143cd21b334SDaniel Scheller state->receive_mode = RCVMODE_NONE; 1144cd21b334SDaniel Scheller state->started = 0; 1145cd21b334SDaniel Scheller 1146cd21b334SDaniel Scheller if (read_reg(state, RSTV0910_MID, &id) < 0) 1147cd21b334SDaniel Scheller return -ENODEV; 1148cd21b334SDaniel Scheller 1149cd21b334SDaniel Scheller if (id != 0x51) 1150cd21b334SDaniel Scheller return -EINVAL; 1151cd21b334SDaniel Scheller 1152cd21b334SDaniel Scheller /* Configure the I2C repeater to off */ 1153cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_I2CRPT, 0x24); 1154cd21b334SDaniel Scheller /* Configure the I2C repeater to off */ 1155cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_I2CRPT, 0x24); 1156cd21b334SDaniel Scheller /* Set the I2C to oversampling ratio */ 1157cd21b334SDaniel Scheller write_reg(state, RSTV0910_I2CCFG, 0x88); /* state->i2ccfg */ 1158cd21b334SDaniel Scheller 1159cd21b334SDaniel Scheller write_reg(state, RSTV0910_OUTCFG, 0x00); /* OUTCFG */ 1160cd21b334SDaniel Scheller write_reg(state, RSTV0910_PADCFG, 0x05); /* RFAGC Pads Dev = 05 */ 1161cd21b334SDaniel Scheller write_reg(state, RSTV0910_SYNTCTRL, 0x02); /* SYNTCTRL */ 1162cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSGENERAL, state->tsgeneral); /* TSGENERAL */ 1163cd21b334SDaniel Scheller write_reg(state, RSTV0910_CFGEXT, 0x02); /* CFGEXT */ 1164cd21b334SDaniel Scheller 1165cd21b334SDaniel Scheller if (state->single) 1166cd21b334SDaniel Scheller write_reg(state, RSTV0910_GENCFG, 0x14); /* GENCFG */ 1167cd21b334SDaniel Scheller else 1168cd21b334SDaniel Scheller write_reg(state, RSTV0910_GENCFG, 0x15); /* GENCFG */ 1169cd21b334SDaniel Scheller 1170cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TNRCFG2, 0x02); /* IQSWAP = 0 */ 1171cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TNRCFG2, 0x82); /* IQSWAP = 1 */ 1172cd21b334SDaniel Scheller 1173cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_CAR3CFG, 0x02); 1174cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CAR3CFG, 0x02); 1175cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DMDCFG4, 0x04); 1176cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDCFG4, 0x04); 1177cd21b334SDaniel Scheller 1178cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSTRES0, 0x80); /* LDPC Reset */ 1179cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSTRES0, 0x00); 1180cd21b334SDaniel Scheller 1181cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSPIDFLT1, 0x00); 1182cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSPIDFLT1, 0x00); 1183cd21b334SDaniel Scheller 1184cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TMGCFG2, 0x80); 1185cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TMGCFG2, 0x80); 1186cd21b334SDaniel Scheller 1187cd21b334SDaniel Scheller set_mclock(state, 135000000); 1188cd21b334SDaniel Scheller 1189cd21b334SDaniel Scheller /* TS output */ 1190cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh | 0x01); 1191cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh); 1192cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGM, 0xC0); /* Manual speed */ 1193cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGL, 0x20); 1194cd21b334SDaniel Scheller 1195cd21b334SDaniel Scheller /* Speed = 67.5 MHz */ 1196cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSSPEED, state->tsspeed); 1197cd21b334SDaniel Scheller 1198cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh | 0x01); 1199cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh); 1200cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGM, 0xC0); /* Manual speed */ 1201cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGL, 0x20); 1202cd21b334SDaniel Scheller 1203cd21b334SDaniel Scheller /* Speed = 67.5 MHz */ 1204cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSSPEED, state->tsspeed); 1205cd21b334SDaniel Scheller 1206cd21b334SDaniel Scheller /* Reset stream merger */ 1207cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh | 0x01); 1208cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh | 0x01); 1209cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh); 1210cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh); 1211cd21b334SDaniel Scheller 1212cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_I2CRPT, state->i2crpt); 1213cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_I2CRPT, state->i2crpt); 1214cd21b334SDaniel Scheller 1215cd21b334SDaniel Scheller init_diseqc(state); 1216cd21b334SDaniel Scheller return 0; 1217cd21b334SDaniel Scheller } 1218cd21b334SDaniel Scheller 1219cd21b334SDaniel Scheller static int gate_ctrl(struct dvb_frontend *fe, int enable) 1220cd21b334SDaniel Scheller { 1221cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1222cd21b334SDaniel Scheller u8 i2crpt = state->i2crpt & ~0x86; 1223cd21b334SDaniel Scheller 1224cd21b334SDaniel Scheller if (enable) 1225cd21b334SDaniel Scheller mutex_lock(&state->base->i2c_lock); 1226cd21b334SDaniel Scheller 1227cd21b334SDaniel Scheller if (enable) 1228cd21b334SDaniel Scheller i2crpt |= 0x80; 1229cd21b334SDaniel Scheller else 1230cd21b334SDaniel Scheller i2crpt |= 0x02; 1231cd21b334SDaniel Scheller 1232cd21b334SDaniel Scheller if (write_reg(state, state->nr ? RSTV0910_P2_I2CRPT : 1233cd21b334SDaniel Scheller RSTV0910_P1_I2CRPT, i2crpt) < 0) 1234cd21b334SDaniel Scheller return -EIO; 1235cd21b334SDaniel Scheller 1236cd21b334SDaniel Scheller state->i2crpt = i2crpt; 1237cd21b334SDaniel Scheller 1238cd21b334SDaniel Scheller if (!enable) 1239cd21b334SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 1240cd21b334SDaniel Scheller return 0; 1241cd21b334SDaniel Scheller } 1242cd21b334SDaniel Scheller 1243cd21b334SDaniel Scheller static void release(struct dvb_frontend *fe) 1244cd21b334SDaniel Scheller { 1245cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1246cd21b334SDaniel Scheller 1247cd21b334SDaniel Scheller state->base->count--; 1248cd21b334SDaniel Scheller if (state->base->count == 0) { 1249cd21b334SDaniel Scheller list_del(&state->base->stvlist); 1250cd21b334SDaniel Scheller kfree(state->base); 1251cd21b334SDaniel Scheller } 1252cd21b334SDaniel Scheller kfree(state); 1253cd21b334SDaniel Scheller } 1254cd21b334SDaniel Scheller 1255cd21b334SDaniel Scheller static int set_parameters(struct dvb_frontend *fe) 1256cd21b334SDaniel Scheller { 1257cd21b334SDaniel Scheller int stat = 0; 1258cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1259cd21b334SDaniel Scheller u32 iffreq; 1260cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1261cd21b334SDaniel Scheller 1262cd21b334SDaniel Scheller stop(state); 1263cd21b334SDaniel Scheller if (fe->ops.tuner_ops.set_params) 1264cd21b334SDaniel Scheller fe->ops.tuner_ops.set_params(fe); 1265cd21b334SDaniel Scheller if (fe->ops.tuner_ops.get_if_frequency) 1266cd21b334SDaniel Scheller fe->ops.tuner_ops.get_if_frequency(fe, &iffreq); 1267cd21b334SDaniel Scheller state->symbol_rate = p->symbol_rate; 1268cd21b334SDaniel Scheller stat = start(state, p); 1269cd21b334SDaniel Scheller return stat; 1270cd21b334SDaniel Scheller } 1271cd21b334SDaniel Scheller 1272cd21b334SDaniel Scheller static int manage_matype_info(struct stv *state) 1273cd21b334SDaniel Scheller { 1274cd21b334SDaniel Scheller if (!state->started) 1275cd21b334SDaniel Scheller return -EINVAL; 1276cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 1277cd21b334SDaniel Scheller u8 bbheader[2]; 1278cd21b334SDaniel Scheller 1279cd21b334SDaniel Scheller read_regs(state, RSTV0910_P2_MATSTR1 + state->regoff, 1280cd21b334SDaniel Scheller bbheader, 2); 1281cd21b334SDaniel Scheller state->feroll_off = 1282cd21b334SDaniel Scheller (enum fe_stv0910_roll_off)(bbheader[0] & 0x03); 1283cd21b334SDaniel Scheller state->is_vcm = (bbheader[0] & 0x10) == 0; 1284cd21b334SDaniel Scheller state->is_standard_broadcast = (bbheader[0] & 0xFC) == 0xF0; 1285cd21b334SDaniel Scheller } else if (state->receive_mode == RCVMODE_DVBS) { 1286cd21b334SDaniel Scheller state->is_vcm = 0; 1287cd21b334SDaniel Scheller state->is_standard_broadcast = 1; 1288cd21b334SDaniel Scheller state->feroll_off = FE_SAT_35; 1289cd21b334SDaniel Scheller } 1290cd21b334SDaniel Scheller return 0; 1291cd21b334SDaniel Scheller } 1292cd21b334SDaniel Scheller 1293cd21b334SDaniel Scheller static int read_snr(struct dvb_frontend *fe) 1294cd21b334SDaniel Scheller { 1295cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1296cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1297cd21b334SDaniel Scheller s32 snrval; 1298cd21b334SDaniel Scheller 1299cd21b334SDaniel Scheller if (!get_signal_to_noise(state, &snrval)) { 1300cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_DECIBEL; 1301cd21b334SDaniel Scheller p->cnr.stat[0].uvalue = 100 * snrval; /* fix scale */ 1302ddb6a90dSDaniel Scheller } else { 1303cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1304ddb6a90dSDaniel Scheller } 1305cd21b334SDaniel Scheller 1306cd21b334SDaniel Scheller return 0; 1307cd21b334SDaniel Scheller } 1308cd21b334SDaniel Scheller 1309cd21b334SDaniel Scheller static int read_ber(struct dvb_frontend *fe) 1310cd21b334SDaniel Scheller { 1311cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1312cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1313cd21b334SDaniel Scheller u32 n, d; 1314cd21b334SDaniel Scheller 1315cd21b334SDaniel Scheller get_bit_error_rate(state, &n, &d); 1316cd21b334SDaniel Scheller 1317cd21b334SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; 1318cd21b334SDaniel Scheller p->pre_bit_error.stat[0].uvalue = n; 1319cd21b334SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; 1320cd21b334SDaniel Scheller p->pre_bit_count.stat[0].uvalue = d; 1321cd21b334SDaniel Scheller 1322cd21b334SDaniel Scheller return 0; 1323cd21b334SDaniel Scheller } 1324cd21b334SDaniel Scheller 1325cd21b334SDaniel Scheller static void read_signal_strength(struct dvb_frontend *fe) 1326cd21b334SDaniel Scheller { 1327cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1328cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &state->fe.dtv_property_cache; 132919bb3b71SDaniel Scheller u8 reg[2]; 133019bb3b71SDaniel Scheller u16 agc; 133119bb3b71SDaniel Scheller s32 padc, power = 0; 133219bb3b71SDaniel Scheller int i; 1333cd21b334SDaniel Scheller 133419bb3b71SDaniel Scheller read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, reg, 2); 133519bb3b71SDaniel Scheller 133619bb3b71SDaniel Scheller agc = (((u32)reg[0]) << 8) | reg[1]; 133719bb3b71SDaniel Scheller 133819bb3b71SDaniel Scheller for (i = 0; i < 5; i += 1) { 133919bb3b71SDaniel Scheller read_regs(state, RSTV0910_P2_POWERI + state->regoff, reg, 2); 134019bb3b71SDaniel Scheller power += (u32)reg[0] * (u32)reg[0] 134119bb3b71SDaniel Scheller + (u32)reg[1] * (u32)reg[1]; 134219bb3b71SDaniel Scheller usleep_range(3000, 4000); 134319bb3b71SDaniel Scheller } 134419bb3b71SDaniel Scheller power /= 5; 134519bb3b71SDaniel Scheller 134619bb3b71SDaniel Scheller padc = table_lookup(padc_lookup, ARRAY_SIZE(padc_lookup), power) + 352; 134719bb3b71SDaniel Scheller 134819bb3b71SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_DECIBEL; 1349399196edSDaniel Scheller p->strength.stat[0].svalue = (padc - agc); 1350cd21b334SDaniel Scheller } 1351cd21b334SDaniel Scheller 1352cd21b334SDaniel Scheller static int read_status(struct dvb_frontend *fe, enum fe_status *status) 1353cd21b334SDaniel Scheller { 1354cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1355cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1356cd21b334SDaniel Scheller u8 dmd_state = 0; 1357cd21b334SDaniel Scheller u8 dstatus = 0; 1358cd21b334SDaniel Scheller enum receive_mode cur_receive_mode = RCVMODE_NONE; 1359cd21b334SDaniel Scheller u32 feclock = 0; 1360cd21b334SDaniel Scheller 1361cd21b334SDaniel Scheller *status = 0; 1362cd21b334SDaniel Scheller 1363cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &dmd_state); 1364cd21b334SDaniel Scheller 1365cd21b334SDaniel Scheller if (dmd_state & 0x40) { 1366cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DSTATUS + state->regoff, &dstatus); 1367cd21b334SDaniel Scheller if (dstatus & 0x08) 1368cd21b334SDaniel Scheller cur_receive_mode = (dmd_state & 0x20) ? 1369cd21b334SDaniel Scheller RCVMODE_DVBS : RCVMODE_DVBS2; 1370cd21b334SDaniel Scheller } 1371cd21b334SDaniel Scheller if (cur_receive_mode == RCVMODE_NONE) { 1372cd21b334SDaniel Scheller set_vth(state); 1373cd21b334SDaniel Scheller 1374cd21b334SDaniel Scheller /* reset signal statistics */ 1375cd21b334SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1376cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1377cd21b334SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1378cd21b334SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1379cd21b334SDaniel Scheller 1380cd21b334SDaniel Scheller return 0; 1381cd21b334SDaniel Scheller } 1382cd21b334SDaniel Scheller 1383cd21b334SDaniel Scheller *status |= (FE_HAS_SIGNAL 1384cd21b334SDaniel Scheller | FE_HAS_CARRIER 1385cd21b334SDaniel Scheller | FE_HAS_VITERBI 1386cd21b334SDaniel Scheller | FE_HAS_SYNC); 1387cd21b334SDaniel Scheller 1388cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_NONE) { 1389cd21b334SDaniel Scheller state->receive_mode = cur_receive_mode; 1390cd21b334SDaniel Scheller state->demod_lock_time = jiffies; 1391cd21b334SDaniel Scheller state->first_time_lock = 1; 1392cd21b334SDaniel Scheller 1393cd21b334SDaniel Scheller get_signal_parameters(state); 1394cd21b334SDaniel Scheller tracking_optimization(state); 1395cd21b334SDaniel Scheller 1396cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, 1397cd21b334SDaniel Scheller state->tscfgh); 1398cd21b334SDaniel Scheller usleep_range(3000, 4000); 1399cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, 1400cd21b334SDaniel Scheller state->tscfgh | 0x01); 1401cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, 1402cd21b334SDaniel Scheller state->tscfgh); 1403cd21b334SDaniel Scheller } 1404cd21b334SDaniel Scheller if (dmd_state & 0x40) { 1405cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 1406cd21b334SDaniel Scheller u8 pdelstatus; 1407cd21b334SDaniel Scheller 1408cd21b334SDaniel Scheller read_reg(state, 1409cd21b334SDaniel Scheller RSTV0910_P2_PDELSTATUS1 + state->regoff, 1410cd21b334SDaniel Scheller &pdelstatus); 1411cd21b334SDaniel Scheller feclock = (pdelstatus & 0x02) != 0; 1412cd21b334SDaniel Scheller } else { 1413cd21b334SDaniel Scheller u8 vstatus; 1414cd21b334SDaniel Scheller 1415cd21b334SDaniel Scheller read_reg(state, 1416cd21b334SDaniel Scheller RSTV0910_P2_VSTATUSVIT + state->regoff, 1417cd21b334SDaniel Scheller &vstatus); 1418cd21b334SDaniel Scheller feclock = (vstatus & 0x08) != 0; 1419cd21b334SDaniel Scheller } 1420cd21b334SDaniel Scheller } 1421cd21b334SDaniel Scheller 1422cd21b334SDaniel Scheller if (feclock) { 1423cd21b334SDaniel Scheller *status |= FE_HAS_LOCK; 1424cd21b334SDaniel Scheller 1425cd21b334SDaniel Scheller if (state->first_time_lock) { 1426cd21b334SDaniel Scheller u8 tmp; 1427cd21b334SDaniel Scheller 1428cd21b334SDaniel Scheller state->first_time_lock = 0; 1429cd21b334SDaniel Scheller 1430cd21b334SDaniel Scheller manage_matype_info(state); 1431cd21b334SDaniel Scheller 1432cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 14334f979d5cSDaniel Scheller /* 14344f979d5cSDaniel Scheller * FSTV0910_P2_MANUALSX_ROLLOFF, 1435cd21b334SDaniel Scheller * FSTV0910_P2_MANUALS2_ROLLOFF = 0 1436cd21b334SDaniel Scheller */ 1437cd21b334SDaniel Scheller state->demod_bits &= ~0x84; 1438cd21b334SDaniel Scheller write_reg(state, 1439cd21b334SDaniel Scheller RSTV0910_P2_DEMOD + state->regoff, 1440cd21b334SDaniel Scheller state->demod_bits); 1441cd21b334SDaniel Scheller read_reg(state, 1442cd21b334SDaniel Scheller RSTV0910_P2_PDELCTRL2 + state->regoff, 1443cd21b334SDaniel Scheller &tmp); 1444cd21b334SDaniel Scheller /* reset DVBS2 packet delinator error counter */ 1445cd21b334SDaniel Scheller tmp |= 0x40; 1446cd21b334SDaniel Scheller write_reg(state, 1447cd21b334SDaniel Scheller RSTV0910_P2_PDELCTRL2 + state->regoff, 1448cd21b334SDaniel Scheller tmp); 1449cd21b334SDaniel Scheller /* reset DVBS2 packet delinator error counter */ 1450cd21b334SDaniel Scheller tmp &= ~0x40; 1451cd21b334SDaniel Scheller write_reg(state, 1452cd21b334SDaniel Scheller RSTV0910_P2_PDELCTRL2 + state->regoff, 1453cd21b334SDaniel Scheller tmp); 1454cd21b334SDaniel Scheller 1455cd21b334SDaniel Scheller state->berscale = 2; 1456cd21b334SDaniel Scheller state->last_bernumerator = 0; 1457cd21b334SDaniel Scheller state->last_berdenominator = 1; 1458cd21b334SDaniel Scheller /* force to PRE BCH Rate */ 1459cd21b334SDaniel Scheller write_reg(state, 1460cd21b334SDaniel Scheller RSTV0910_P2_ERRCTRL1 + state->regoff, 1461cd21b334SDaniel Scheller BER_SRC_S2 | state->berscale); 1462cd21b334SDaniel Scheller } else { 1463cd21b334SDaniel Scheller state->berscale = 2; 1464cd21b334SDaniel Scheller state->last_bernumerator = 0; 1465cd21b334SDaniel Scheller state->last_berdenominator = 1; 1466cd21b334SDaniel Scheller /* force to PRE RS Rate */ 1467cd21b334SDaniel Scheller write_reg(state, 1468cd21b334SDaniel Scheller RSTV0910_P2_ERRCTRL1 + state->regoff, 1469cd21b334SDaniel Scheller BER_SRC_S | state->berscale); 1470cd21b334SDaniel Scheller } 1471cd21b334SDaniel Scheller /* Reset the Total packet counter */ 1472cd21b334SDaniel Scheller write_reg(state, 1473cd21b334SDaniel Scheller RSTV0910_P2_FBERCPT4 + state->regoff, 0x00); 14744f979d5cSDaniel Scheller /* 14754f979d5cSDaniel Scheller * Reset the packet Error counter2 (and Set it to 1476cd21b334SDaniel Scheller * infinit error count mode) 1477cd21b334SDaniel Scheller */ 1478cd21b334SDaniel Scheller write_reg(state, 1479cd21b334SDaniel Scheller RSTV0910_P2_ERRCTRL2 + state->regoff, 0xc1); 1480cd21b334SDaniel Scheller 1481cd21b334SDaniel Scheller set_vth_default(state); 1482cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS) 1483cd21b334SDaniel Scheller enable_puncture_rate(state, 1484cd21b334SDaniel Scheller state->puncture_rate); 1485cd21b334SDaniel Scheller } 1486cd21b334SDaniel Scheller } 1487cd21b334SDaniel Scheller 1488cd21b334SDaniel Scheller /* read signal statistics */ 1489cd21b334SDaniel Scheller 1490cd21b334SDaniel Scheller /* read signal strength */ 1491cd21b334SDaniel Scheller read_signal_strength(fe); 1492cd21b334SDaniel Scheller 1493cd21b334SDaniel Scheller /* read carrier/noise on FE_HAS_CARRIER */ 1494cd21b334SDaniel Scheller if (*status & FE_HAS_CARRIER) 1495cd21b334SDaniel Scheller read_snr(fe); 1496cd21b334SDaniel Scheller else 1497cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1498cd21b334SDaniel Scheller 1499cd21b334SDaniel Scheller /* read ber */ 1500ddb6a90dSDaniel Scheller if (*status & FE_HAS_VITERBI) { 1501cd21b334SDaniel Scheller read_ber(fe); 1502ddb6a90dSDaniel Scheller } else { 1503cd21b334SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1504cd21b334SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1505cd21b334SDaniel Scheller } 1506cd21b334SDaniel Scheller 1507cd21b334SDaniel Scheller return 0; 1508cd21b334SDaniel Scheller } 1509cd21b334SDaniel Scheller 1510cd21b334SDaniel Scheller static int get_frontend(struct dvb_frontend *fe, 1511cd21b334SDaniel Scheller struct dtv_frontend_properties *p) 1512cd21b334SDaniel Scheller { 1513cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1514cd21b334SDaniel Scheller u8 tmp; 1515cd21b334SDaniel Scheller 1516cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 1517cd21b334SDaniel Scheller u32 mc; 151820e671dfSDaniel Scheller const enum fe_modulation modcod2mod[0x20] = { 1519cd21b334SDaniel Scheller QPSK, QPSK, QPSK, QPSK, 1520cd21b334SDaniel Scheller QPSK, QPSK, QPSK, QPSK, 1521cd21b334SDaniel Scheller QPSK, QPSK, QPSK, QPSK, 1522cd21b334SDaniel Scheller PSK_8, PSK_8, PSK_8, PSK_8, 1523cd21b334SDaniel Scheller PSK_8, PSK_8, APSK_16, APSK_16, 1524cd21b334SDaniel Scheller APSK_16, APSK_16, APSK_16, APSK_16, 1525cd21b334SDaniel Scheller APSK_32, APSK_32, APSK_32, APSK_32, 1526cd21b334SDaniel Scheller APSK_32, 1527cd21b334SDaniel Scheller }; 152820e671dfSDaniel Scheller const enum fe_code_rate modcod2fec[0x20] = { 1529cd21b334SDaniel Scheller FEC_NONE, FEC_NONE, FEC_NONE, FEC_2_5, 1530cd21b334SDaniel Scheller FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4, 1531cd21b334SDaniel Scheller FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10, 1532cd21b334SDaniel Scheller FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6, 1533cd21b334SDaniel Scheller FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4, 1534cd21b334SDaniel Scheller FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10, 1535cd21b334SDaniel Scheller FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9, 1536cd21b334SDaniel Scheller FEC_9_10 1537cd21b334SDaniel Scheller }; 1538cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); 1539cd21b334SDaniel Scheller mc = ((tmp & 0x7c) >> 2); 1540cd21b334SDaniel Scheller p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF; 1541cd21b334SDaniel Scheller p->modulation = modcod2mod[mc]; 1542cd21b334SDaniel Scheller p->fec_inner = modcod2fec[mc]; 1543cd21b334SDaniel Scheller } else if (state->receive_mode == RCVMODE_DVBS) { 1544cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); 1545cd21b334SDaniel Scheller switch (tmp & 0x1F) { 1546cd21b334SDaniel Scheller case 0x0d: 1547cd21b334SDaniel Scheller p->fec_inner = FEC_1_2; 1548cd21b334SDaniel Scheller break; 1549cd21b334SDaniel Scheller case 0x12: 1550cd21b334SDaniel Scheller p->fec_inner = FEC_2_3; 1551cd21b334SDaniel Scheller break; 1552cd21b334SDaniel Scheller case 0x15: 1553cd21b334SDaniel Scheller p->fec_inner = FEC_3_4; 1554cd21b334SDaniel Scheller break; 1555cd21b334SDaniel Scheller case 0x18: 1556cd21b334SDaniel Scheller p->fec_inner = FEC_5_6; 1557cd21b334SDaniel Scheller break; 1558cd21b334SDaniel Scheller case 0x1a: 1559cd21b334SDaniel Scheller p->fec_inner = FEC_7_8; 1560cd21b334SDaniel Scheller break; 1561cd21b334SDaniel Scheller default: 1562cd21b334SDaniel Scheller p->fec_inner = FEC_NONE; 1563cd21b334SDaniel Scheller break; 1564cd21b334SDaniel Scheller } 1565cd21b334SDaniel Scheller p->rolloff = ROLLOFF_35; 1566cd21b334SDaniel Scheller } 1567cd21b334SDaniel Scheller 1568cd21b334SDaniel Scheller return 0; 1569cd21b334SDaniel Scheller } 1570cd21b334SDaniel Scheller 1571cd21b334SDaniel Scheller static int tune(struct dvb_frontend *fe, bool re_tune, 1572cd21b334SDaniel Scheller unsigned int mode_flags, 1573cd21b334SDaniel Scheller unsigned int *delay, enum fe_status *status) 1574cd21b334SDaniel Scheller { 1575cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1576cd21b334SDaniel Scheller int r; 1577cd21b334SDaniel Scheller 1578cd21b334SDaniel Scheller if (re_tune) { 1579cd21b334SDaniel Scheller r = set_parameters(fe); 1580cd21b334SDaniel Scheller if (r) 1581cd21b334SDaniel Scheller return r; 1582cd21b334SDaniel Scheller state->tune_time = jiffies; 1583cd21b334SDaniel Scheller } 1584cd21b334SDaniel Scheller 1585cd21b334SDaniel Scheller r = read_status(fe, status); 1586cd21b334SDaniel Scheller if (r) 1587cd21b334SDaniel Scheller return r; 1588f0e72c29SDaniel Scheller 1589f0e72c29SDaniel Scheller if (*status & FE_HAS_LOCK) 1590f0e72c29SDaniel Scheller return 0; 1591f0e72c29SDaniel Scheller *delay = HZ; 1592f0e72c29SDaniel Scheller 1593cd21b334SDaniel Scheller return 0; 1594cd21b334SDaniel Scheller } 1595cd21b334SDaniel Scheller 1596cd21b334SDaniel Scheller static int get_algo(struct dvb_frontend *fe) 1597cd21b334SDaniel Scheller { 1598cd21b334SDaniel Scheller return DVBFE_ALGO_HW; 1599cd21b334SDaniel Scheller } 1600cd21b334SDaniel Scheller 1601cd21b334SDaniel Scheller static int set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) 1602cd21b334SDaniel Scheller { 1603cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1604cd21b334SDaniel Scheller u16 offs = state->nr ? 0x40 : 0; 1605cd21b334SDaniel Scheller 1606cd21b334SDaniel Scheller switch (tone) { 1607cd21b334SDaniel Scheller case SEC_TONE_ON: 1608cd21b334SDaniel Scheller return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x38); 1609cd21b334SDaniel Scheller case SEC_TONE_OFF: 1610cd21b334SDaniel Scheller return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3a); 1611cd21b334SDaniel Scheller default: 1612cd21b334SDaniel Scheller break; 1613cd21b334SDaniel Scheller } 1614cd21b334SDaniel Scheller return -EINVAL; 1615cd21b334SDaniel Scheller } 1616cd21b334SDaniel Scheller 1617cd21b334SDaniel Scheller static int wait_dis(struct stv *state, u8 flag, u8 val) 1618cd21b334SDaniel Scheller { 1619cd21b334SDaniel Scheller int i; 1620cd21b334SDaniel Scheller u8 stat; 1621cd21b334SDaniel Scheller u16 offs = state->nr ? 0x40 : 0; 1622cd21b334SDaniel Scheller 1623cd21b334SDaniel Scheller for (i = 0; i < 10; i++) { 1624cd21b334SDaniel Scheller read_reg(state, RSTV0910_P1_DISTXSTATUS + offs, &stat); 1625cd21b334SDaniel Scheller if ((stat & flag) == val) 1626cd21b334SDaniel Scheller return 0; 1627cd21b334SDaniel Scheller usleep_range(10000, 11000); 1628cd21b334SDaniel Scheller } 1629cd21b334SDaniel Scheller return -ETIMEDOUT; 1630cd21b334SDaniel Scheller } 1631cd21b334SDaniel Scheller 1632cd21b334SDaniel Scheller static int send_master_cmd(struct dvb_frontend *fe, 1633cd21b334SDaniel Scheller struct dvb_diseqc_master_cmd *cmd) 1634cd21b334SDaniel Scheller { 1635cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1636cd21b334SDaniel Scheller u16 offs = state->nr ? 0x40 : 0; 1637cd21b334SDaniel Scheller int i; 1638cd21b334SDaniel Scheller 1639cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3E); 1640cd21b334SDaniel Scheller for (i = 0; i < cmd->msg_len; i++) { 1641cd21b334SDaniel Scheller wait_dis(state, 0x40, 0x00); 1642cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXFIFO + offs, cmd->msg[i]); 1643cd21b334SDaniel Scheller } 1644cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); 1645cd21b334SDaniel Scheller wait_dis(state, 0x20, 0x20); 1646cd21b334SDaniel Scheller return 0; 1647cd21b334SDaniel Scheller } 1648cd21b334SDaniel Scheller 1649448461afSDaniel Scheller static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) 1650448461afSDaniel Scheller { 1651448461afSDaniel Scheller struct stv *state = fe->demodulator_priv; 1652448461afSDaniel Scheller u16 offs = state->nr ? 0x40 : 0; 1653448461afSDaniel Scheller u8 value; 1654448461afSDaniel Scheller 1655448461afSDaniel Scheller if (burst == SEC_MINI_A) { 1656448461afSDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3F); 1657448461afSDaniel Scheller value = 0x00; 1658448461afSDaniel Scheller } else { 1659448461afSDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3E); 1660448461afSDaniel Scheller value = 0xFF; 1661448461afSDaniel Scheller } 1662448461afSDaniel Scheller wait_dis(state, 0x40, 0x00); 1663448461afSDaniel Scheller write_reg(state, RSTV0910_P1_DISTXFIFO + offs, value); 1664448461afSDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); 1665448461afSDaniel Scheller wait_dis(state, 0x20, 0x20); 1666448461afSDaniel Scheller 1667448461afSDaniel Scheller return 0; 1668448461afSDaniel Scheller } 1669448461afSDaniel Scheller 1670cd21b334SDaniel Scheller static int sleep(struct dvb_frontend *fe) 1671cd21b334SDaniel Scheller { 1672cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1673cd21b334SDaniel Scheller 1674cd21b334SDaniel Scheller stop(state); 1675cd21b334SDaniel Scheller return 0; 1676cd21b334SDaniel Scheller } 1677cd21b334SDaniel Scheller 167820e671dfSDaniel Scheller static const struct dvb_frontend_ops stv0910_ops = { 1679cd21b334SDaniel Scheller .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, 1680cd21b334SDaniel Scheller .info = { 168120e671dfSDaniel Scheller .name = "ST STV0910", 1682cd21b334SDaniel Scheller .frequency_min = 950000, 1683cd21b334SDaniel Scheller .frequency_max = 2150000, 1684cd21b334SDaniel Scheller .frequency_stepsize = 0, 1685cd21b334SDaniel Scheller .frequency_tolerance = 0, 1686cd21b334SDaniel Scheller .symbol_rate_min = 1000000, 1687cd21b334SDaniel Scheller .symbol_rate_max = 70000000, 1688cd21b334SDaniel Scheller .caps = FE_CAN_INVERSION_AUTO | 1689cd21b334SDaniel Scheller FE_CAN_FEC_AUTO | 1690cd21b334SDaniel Scheller FE_CAN_QPSK | 1691ea71c62bSDaniel Scheller FE_CAN_2G_MODULATION | 1692ea71c62bSDaniel Scheller FE_CAN_MULTISTREAM 1693cd21b334SDaniel Scheller }, 1694cd21b334SDaniel Scheller .sleep = sleep, 1695cd21b334SDaniel Scheller .release = release, 1696cd21b334SDaniel Scheller .i2c_gate_ctrl = gate_ctrl, 16972f4675c0SDaniel Scheller .set_frontend = set_parameters, 1698cd21b334SDaniel Scheller .get_frontend_algo = get_algo, 1699cd21b334SDaniel Scheller .get_frontend = get_frontend, 1700cd21b334SDaniel Scheller .tune = tune, 1701cd21b334SDaniel Scheller .read_status = read_status, 1702cd21b334SDaniel Scheller .set_tone = set_tone, 1703cd21b334SDaniel Scheller 1704cd21b334SDaniel Scheller .diseqc_send_master_cmd = send_master_cmd, 1705448461afSDaniel Scheller .diseqc_send_burst = send_burst, 1706cd21b334SDaniel Scheller }; 1707cd21b334SDaniel Scheller 1708cd21b334SDaniel Scheller static struct stv_base *match_base(struct i2c_adapter *i2c, u8 adr) 1709cd21b334SDaniel Scheller { 1710cd21b334SDaniel Scheller struct stv_base *p; 1711cd21b334SDaniel Scheller 1712cd21b334SDaniel Scheller list_for_each_entry(p, &stvlist, stvlist) 1713cd21b334SDaniel Scheller if (p->i2c == i2c && p->adr == adr) 1714cd21b334SDaniel Scheller return p; 1715cd21b334SDaniel Scheller return NULL; 1716cd21b334SDaniel Scheller } 1717cd21b334SDaniel Scheller 1718cd21b334SDaniel Scheller static void stv0910_init_stats(struct stv *state) 1719cd21b334SDaniel Scheller { 1720cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &state->fe.dtv_property_cache; 1721cd21b334SDaniel Scheller 1722cd21b334SDaniel Scheller p->strength.len = 1; 1723cd21b334SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1724cd21b334SDaniel Scheller p->cnr.len = 1; 1725cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1726cd21b334SDaniel Scheller p->pre_bit_error.len = 1; 1727cd21b334SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1728cd21b334SDaniel Scheller p->pre_bit_count.len = 1; 1729cd21b334SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1730cd21b334SDaniel Scheller } 1731cd21b334SDaniel Scheller 1732cd21b334SDaniel Scheller struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, 1733cd21b334SDaniel Scheller struct stv0910_cfg *cfg, 1734cd21b334SDaniel Scheller int nr) 1735cd21b334SDaniel Scheller { 1736cd21b334SDaniel Scheller struct stv *state; 1737cd21b334SDaniel Scheller struct stv_base *base; 1738cd21b334SDaniel Scheller 1739ddb6a90dSDaniel Scheller state = kzalloc(sizeof(*state), GFP_KERNEL); 1740cd21b334SDaniel Scheller if (!state) 1741cd21b334SDaniel Scheller return NULL; 1742cd21b334SDaniel Scheller 1743cd21b334SDaniel Scheller state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40); 1744cd21b334SDaniel Scheller state->tsgeneral = (cfg->parallel == 2) ? 0x02 : 0x00; 1745cd21b334SDaniel Scheller state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4); 1746cd21b334SDaniel Scheller state->tsspeed = 0x28; 1747cd21b334SDaniel Scheller state->nr = nr; 1748cd21b334SDaniel Scheller state->regoff = state->nr ? 0 : 0x200; 1749cd21b334SDaniel Scheller state->search_range = 16000000; 1750cd21b334SDaniel Scheller state->demod_bits = 0x10; /* Inversion : Auto with reset to 0 */ 1751cd21b334SDaniel Scheller state->receive_mode = RCVMODE_NONE; 1752ea71c62bSDaniel Scheller state->cur_scrambling_code = (~0U); 1753cd21b334SDaniel Scheller state->single = cfg->single ? 1 : 0; 1754cd21b334SDaniel Scheller 1755cd21b334SDaniel Scheller base = match_base(i2c, cfg->adr); 1756cd21b334SDaniel Scheller if (base) { 1757cd21b334SDaniel Scheller base->count++; 1758cd21b334SDaniel Scheller state->base = base; 1759cd21b334SDaniel Scheller } else { 1760ddb6a90dSDaniel Scheller base = kzalloc(sizeof(*base), GFP_KERNEL); 1761cd21b334SDaniel Scheller if (!base) 1762cd21b334SDaniel Scheller goto fail; 1763cd21b334SDaniel Scheller base->i2c = i2c; 1764cd21b334SDaniel Scheller base->adr = cfg->adr; 1765cd21b334SDaniel Scheller base->count = 1; 1766cd21b334SDaniel Scheller base->extclk = cfg->clk ? cfg->clk : 30000000; 1767cd21b334SDaniel Scheller 1768cd21b334SDaniel Scheller mutex_init(&base->i2c_lock); 1769cd21b334SDaniel Scheller mutex_init(&base->reg_lock); 1770cd21b334SDaniel Scheller state->base = base; 1771cd21b334SDaniel Scheller if (probe(state) < 0) { 1772cd21b334SDaniel Scheller dev_info(&i2c->dev, "No demod found at adr %02X on %s\n", 1773cd21b334SDaniel Scheller cfg->adr, dev_name(&i2c->dev)); 1774cd21b334SDaniel Scheller kfree(base); 1775cd21b334SDaniel Scheller goto fail; 1776cd21b334SDaniel Scheller } 1777cd21b334SDaniel Scheller list_add(&base->stvlist, &stvlist); 1778cd21b334SDaniel Scheller } 1779cd21b334SDaniel Scheller state->fe.ops = stv0910_ops; 1780cd21b334SDaniel Scheller state->fe.demodulator_priv = state; 1781cd21b334SDaniel Scheller state->nr = nr; 1782cd21b334SDaniel Scheller 1783cd21b334SDaniel Scheller dev_info(&i2c->dev, "%s demod found at adr %02X on %s\n", 1784cd21b334SDaniel Scheller state->fe.ops.info.name, cfg->adr, dev_name(&i2c->dev)); 1785cd21b334SDaniel Scheller 1786cd21b334SDaniel Scheller stv0910_init_stats(state); 1787cd21b334SDaniel Scheller 1788cd21b334SDaniel Scheller return &state->fe; 1789cd21b334SDaniel Scheller 1790cd21b334SDaniel Scheller fail: 1791cd21b334SDaniel Scheller kfree(state); 1792cd21b334SDaniel Scheller return NULL; 1793cd21b334SDaniel Scheller } 1794cd21b334SDaniel Scheller EXPORT_SYMBOL_GPL(stv0910_attach); 1795cd21b334SDaniel Scheller 1796cd21b334SDaniel Scheller MODULE_DESCRIPTION("ST STV0910 multistandard frontend driver"); 1797cd21b334SDaniel Scheller MODULE_AUTHOR("Ralph and Marcus Metzler, Manfred Voelkel"); 1798cd21b334SDaniel Scheller MODULE_LICENSE("GPL"); 1799