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 37cd21b334SDaniel Scheller 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; 82cd21b334SDaniel Scheller struct mutex i2c_lock; 83cd21b334SDaniel Scheller struct mutex reg_lock; 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 210cd21b334SDaniel Scheller 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 267cd21b334SDaniel Scheller 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 33019bb3b71SDaniel Scheller 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 *********************************************************************/ 352cd21b334SDaniel Scheller static u8 s2car_loop[] = { 353cd21b334SDaniel Scheller /* Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 354cd21b334SDaniel Scheller * 20MPon 20MPoff 30MPon 30MPoff 355cd21b334SDaniel Scheller */ 356cd21b334SDaniel Scheller 357cd21b334SDaniel Scheller /* FE_QPSK_14 */ 358cd21b334SDaniel Scheller 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x2A, 0x1C, 0x3A, 0x3B, 359cd21b334SDaniel Scheller /* FE_QPSK_13 */ 360cd21b334SDaniel Scheller 0x0C, 0x3C, 0x0B, 0x3C, 0x2A, 0x2C, 0x3A, 0x0C, 0x3A, 0x2B, 361cd21b334SDaniel Scheller /* FE_QPSK_25 */ 362cd21b334SDaniel Scheller 0x1C, 0x3C, 0x1B, 0x3C, 0x3A, 0x1C, 0x3A, 0x3B, 0x3A, 0x2B, 363cd21b334SDaniel Scheller /* FE_QPSK_12 */ 364cd21b334SDaniel Scheller 0x0C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, 365cd21b334SDaniel Scheller /* FE_QPSK_35 */ 366cd21b334SDaniel Scheller 0x1C, 0x1C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, 367cd21b334SDaniel Scheller /* FE_QPSK_23 */ 368cd21b334SDaniel Scheller 0x2C, 0x2C, 0x2B, 0x1C, 0x0B, 0x2C, 0x0B, 0x0C, 0x2A, 0x2B, 369cd21b334SDaniel Scheller /* FE_QPSK_34 */ 370cd21b334SDaniel Scheller 0x3C, 0x2C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, 371cd21b334SDaniel Scheller /* FE_QPSK_45 */ 372cd21b334SDaniel Scheller 0x0D, 0x3C, 0x3B, 0x2C, 0x1B, 0x1C, 0x1B, 0x3B, 0x3A, 0x1B, 373cd21b334SDaniel Scheller /* FE_QPSK_56 */ 374cd21b334SDaniel Scheller 0x1D, 0x3C, 0x0C, 0x2C, 0x2B, 0x1C, 0x1B, 0x3B, 0x0B, 0x1B, 375cd21b334SDaniel Scheller /* FE_QPSK_89 */ 376cd21b334SDaniel Scheller 0x3D, 0x0D, 0x0C, 0x2C, 0x2B, 0x0C, 0x2B, 0x2B, 0x0B, 0x0B, 377cd21b334SDaniel Scheller /* FE_QPSK_910 */ 378cd21b334SDaniel Scheller 0x1E, 0x0D, 0x1C, 0x2C, 0x3B, 0x0C, 0x2B, 0x2B, 0x1B, 0x0B, 379cd21b334SDaniel Scheller /* FE_8PSK_35 */ 380cd21b334SDaniel Scheller 0x28, 0x09, 0x28, 0x09, 0x28, 0x09, 0x28, 0x08, 0x28, 0x27, 381cd21b334SDaniel Scheller /* FE_8PSK_23 */ 382cd21b334SDaniel Scheller 0x19, 0x29, 0x19, 0x29, 0x19, 0x29, 0x38, 0x19, 0x28, 0x09, 383cd21b334SDaniel Scheller /* FE_8PSK_34 */ 384cd21b334SDaniel Scheller 0x1A, 0x0B, 0x1A, 0x3A, 0x0A, 0x2A, 0x39, 0x2A, 0x39, 0x1A, 385cd21b334SDaniel Scheller /* FE_8PSK_56 */ 386cd21b334SDaniel Scheller 0x2B, 0x2B, 0x1B, 0x1B, 0x0B, 0x1B, 0x1A, 0x0B, 0x1A, 0x1A, 387cd21b334SDaniel Scheller /* FE_8PSK_89 */ 388cd21b334SDaniel Scheller 0x0C, 0x0C, 0x3B, 0x3B, 0x1B, 0x1B, 0x2A, 0x0B, 0x2A, 0x2A, 389cd21b334SDaniel Scheller /* FE_8PSK_910 */ 390cd21b334SDaniel Scheller 0x0C, 0x1C, 0x0C, 0x3B, 0x2B, 0x1B, 0x3A, 0x0B, 0x2A, 0x2A, 391cd21b334SDaniel Scheller 392cd21b334SDaniel Scheller /********************************************************************** 393cd21b334SDaniel Scheller * Tracking carrier loop carrier 16APSK 2/3 to 32APSK 9/10 long Frame 394cd21b334SDaniel Scheller **********************************************************************/ 395cd21b334SDaniel Scheller 396cd21b334SDaniel Scheller /* Modcod 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 397cd21b334SDaniel Scheller * 20MPoff 30MPon 30MPoff 398cd21b334SDaniel Scheller */ 399cd21b334SDaniel Scheller 400cd21b334SDaniel Scheller /* FE_16APSK_23 */ 401cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x0A, 0x39, 0x0A, 0x29, 0x0A, 402cd21b334SDaniel Scheller /* FE_16APSK_34 */ 403cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0A, 0x2A, 0x0A, 0x1A, 0x0A, 404cd21b334SDaniel Scheller /* FE_16APSK_45 */ 405cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, 406cd21b334SDaniel Scheller /* FE_16APSK_56 */ 407cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x1B, 0x0A, 0x3A, 0x0A, 0x2A, 0x0A, 408cd21b334SDaniel Scheller /* FE_16APSK_89 */ 409cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, 410cd21b334SDaniel Scheller /* FE_16APSK_910 */ 411cd21b334SDaniel Scheller 0x0A, 0x0A, 0x0A, 0x0A, 0x2B, 0x0A, 0x0B, 0x0A, 0x3A, 0x0A, 412cd21b334SDaniel Scheller /* FE_32APSK_34 */ 413cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 414cd21b334SDaniel Scheller /* FE_32APSK_45 */ 415cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 416cd21b334SDaniel Scheller /* FE_32APSK_56 */ 417cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 418cd21b334SDaniel Scheller /* FE_32APSK_89 */ 419cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 420cd21b334SDaniel Scheller /* FE_32APSK_910 */ 421cd21b334SDaniel Scheller 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 422cd21b334SDaniel Scheller }; 423cd21b334SDaniel Scheller 424cd21b334SDaniel Scheller static u8 get_optim_cloop(struct stv *state, 425cd21b334SDaniel Scheller enum fe_stv0910_mod_cod mod_cod, u32 pilots) 426cd21b334SDaniel Scheller { 427cd21b334SDaniel Scheller int i = 0; 428cd21b334SDaniel Scheller 429cd21b334SDaniel Scheller if (mod_cod >= FE_32APSK_910) 430cd21b334SDaniel Scheller i = ((int)FE_32APSK_910 - (int)FE_QPSK_14) * 10; 431cd21b334SDaniel Scheller else if (mod_cod >= FE_QPSK_14) 432cd21b334SDaniel Scheller i = ((int)mod_cod - (int)FE_QPSK_14) * 10; 433cd21b334SDaniel Scheller 434cd21b334SDaniel Scheller if (state->symbol_rate <= 3000000) 435cd21b334SDaniel Scheller i += 0; 436cd21b334SDaniel Scheller else if (state->symbol_rate <= 7000000) 437cd21b334SDaniel Scheller i += 2; 438cd21b334SDaniel Scheller else if (state->symbol_rate <= 15000000) 439cd21b334SDaniel Scheller i += 4; 440cd21b334SDaniel Scheller else if (state->symbol_rate <= 25000000) 441cd21b334SDaniel Scheller i += 6; 442cd21b334SDaniel Scheller else 443cd21b334SDaniel Scheller i += 8; 444cd21b334SDaniel Scheller 445cd21b334SDaniel Scheller if (!pilots) 446cd21b334SDaniel Scheller i += 1; 447cd21b334SDaniel Scheller 448cd21b334SDaniel Scheller return s2car_loop[i]; 449cd21b334SDaniel Scheller } 450cd21b334SDaniel Scheller 451cd21b334SDaniel Scheller static int get_cur_symbol_rate(struct stv *state, u32 *p_symbol_rate) 452cd21b334SDaniel Scheller { 453cd21b334SDaniel Scheller int status = 0; 454cd21b334SDaniel Scheller u8 symb_freq0; 455cd21b334SDaniel Scheller u8 symb_freq1; 456cd21b334SDaniel Scheller u8 symb_freq2; 457cd21b334SDaniel Scheller u8 symb_freq3; 458cd21b334SDaniel Scheller u8 tim_offs0; 459cd21b334SDaniel Scheller u8 tim_offs1; 460cd21b334SDaniel Scheller u8 tim_offs2; 461cd21b334SDaniel Scheller u32 symbol_rate; 462cd21b334SDaniel Scheller s32 timing_offset; 463cd21b334SDaniel Scheller 464cd21b334SDaniel Scheller *p_symbol_rate = 0; 465cd21b334SDaniel Scheller if (!state->started) 466cd21b334SDaniel Scheller return status; 467cd21b334SDaniel Scheller 468cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_SFR3 + state->regoff, &symb_freq3); 469cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_SFR2 + state->regoff, &symb_freq2); 470cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_SFR1 + state->regoff, &symb_freq1); 471cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_SFR0 + state->regoff, &symb_freq0); 472cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TMGREG2 + state->regoff, &tim_offs2); 473cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TMGREG1 + state->regoff, &tim_offs1); 474cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TMGREG0 + state->regoff, &tim_offs0); 475cd21b334SDaniel Scheller 476cd21b334SDaniel Scheller symbol_rate = ((u32) symb_freq3 << 24) | ((u32) symb_freq2 << 16) | 477cd21b334SDaniel Scheller ((u32) symb_freq1 << 8) | (u32) symb_freq0; 478cd21b334SDaniel Scheller timing_offset = ((u32) tim_offs2 << 16) | ((u32) tim_offs1 << 8) | 479cd21b334SDaniel Scheller (u32) tim_offs0; 480cd21b334SDaniel Scheller 481cd21b334SDaniel Scheller if ((timing_offset & (1<<23)) != 0) 482cd21b334SDaniel Scheller timing_offset |= 0xFF000000; /* Sign extent */ 483cd21b334SDaniel Scheller 484cd21b334SDaniel Scheller symbol_rate = (u32) (((u64) symbol_rate * state->base->mclk) >> 32); 485cd21b334SDaniel Scheller timing_offset = (s32) (((s64) symbol_rate * (s64) timing_offset) >> 29); 486cd21b334SDaniel Scheller 487cd21b334SDaniel Scheller *p_symbol_rate = symbol_rate + timing_offset; 488cd21b334SDaniel Scheller 489cd21b334SDaniel Scheller return 0; 490cd21b334SDaniel Scheller } 491cd21b334SDaniel Scheller 492cd21b334SDaniel Scheller static int get_signal_parameters(struct stv *state) 493cd21b334SDaniel Scheller { 494cd21b334SDaniel Scheller u8 tmp; 495cd21b334SDaniel Scheller 496cd21b334SDaniel Scheller if (!state->started) 497cd21b334SDaniel Scheller return -EINVAL; 498cd21b334SDaniel Scheller 499cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 500cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); 501cd21b334SDaniel Scheller state->mod_cod = (enum fe_stv0910_mod_cod) ((tmp & 0x7c) >> 2); 502cd21b334SDaniel Scheller state->pilots = (tmp & 0x01) != 0; 503cd21b334SDaniel Scheller state->fectype = (enum dvbs2_fectype) ((tmp & 0x02) >> 1); 504cd21b334SDaniel Scheller 505cd21b334SDaniel Scheller } else if (state->receive_mode == RCVMODE_DVBS) { 506cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); 507cd21b334SDaniel Scheller state->puncture_rate = FEC_NONE; 508cd21b334SDaniel Scheller switch (tmp & 0x1F) { 509cd21b334SDaniel Scheller case 0x0d: 510cd21b334SDaniel Scheller state->puncture_rate = FEC_1_2; 511cd21b334SDaniel Scheller break; 512cd21b334SDaniel Scheller case 0x12: 513cd21b334SDaniel Scheller state->puncture_rate = FEC_2_3; 514cd21b334SDaniel Scheller break; 515cd21b334SDaniel Scheller case 0x15: 516cd21b334SDaniel Scheller state->puncture_rate = FEC_3_4; 517cd21b334SDaniel Scheller break; 518cd21b334SDaniel Scheller case 0x18: 519cd21b334SDaniel Scheller state->puncture_rate = FEC_5_6; 520cd21b334SDaniel Scheller break; 521cd21b334SDaniel Scheller case 0x1a: 522cd21b334SDaniel Scheller state->puncture_rate = FEC_7_8; 523cd21b334SDaniel Scheller break; 524cd21b334SDaniel Scheller } 525cd21b334SDaniel Scheller state->is_vcm = 0; 526cd21b334SDaniel Scheller state->is_standard_broadcast = 1; 527cd21b334SDaniel Scheller state->feroll_off = FE_SAT_35; 528cd21b334SDaniel Scheller } 529cd21b334SDaniel Scheller return 0; 530cd21b334SDaniel Scheller } 531cd21b334SDaniel Scheller 532cd21b334SDaniel Scheller static int tracking_optimization(struct stv *state) 533cd21b334SDaniel Scheller { 534cd21b334SDaniel Scheller u32 symbol_rate = 0; 535cd21b334SDaniel Scheller u8 tmp; 536cd21b334SDaniel Scheller 537cd21b334SDaniel Scheller get_cur_symbol_rate(state, &symbol_rate); 538cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, &tmp); 539cd21b334SDaniel Scheller tmp &= ~0xC0; 540cd21b334SDaniel Scheller 541cd21b334SDaniel Scheller switch (state->receive_mode) { 542cd21b334SDaniel Scheller case RCVMODE_DVBS: 543cd21b334SDaniel Scheller tmp |= 0x40; 544cd21b334SDaniel Scheller break; 545cd21b334SDaniel Scheller case RCVMODE_DVBS2: 546cd21b334SDaniel Scheller tmp |= 0x80; 547cd21b334SDaniel Scheller break; 548cd21b334SDaniel Scheller default: 549cd21b334SDaniel Scheller tmp |= 0xC0; 550cd21b334SDaniel Scheller break; 551cd21b334SDaniel Scheller } 552cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, tmp); 553cd21b334SDaniel Scheller 554cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 555cd21b334SDaniel Scheller /* Disable Reed-Solomon */ 556cd21b334SDaniel Scheller write_shared_reg(state, 557cd21b334SDaniel Scheller RSTV0910_TSTTSRS, state->nr ? 0x02 : 0x01, 558cd21b334SDaniel Scheller 0x03); 559cd21b334SDaniel Scheller 560cd21b334SDaniel Scheller if (state->fectype == DVBS2_64K) { 561cd21b334SDaniel Scheller u8 aclc = get_optim_cloop(state, state->mod_cod, 562cd21b334SDaniel Scheller state->pilots); 563cd21b334SDaniel Scheller 564cd21b334SDaniel Scheller if (state->mod_cod <= FE_QPSK_910) { 565cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + 566cd21b334SDaniel Scheller state->regoff, aclc); 567cd21b334SDaniel Scheller } else if (state->mod_cod <= FE_8PSK_910) { 568cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + 569cd21b334SDaniel Scheller state->regoff, 0x2a); 570cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S28 + 571cd21b334SDaniel Scheller state->regoff, aclc); 572cd21b334SDaniel Scheller } else if (state->mod_cod <= FE_16APSK_910) { 573cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + 574cd21b334SDaniel Scheller state->regoff, 0x2a); 575cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S216A + 576cd21b334SDaniel Scheller state->regoff, aclc); 577cd21b334SDaniel Scheller } else if (state->mod_cod <= FE_32APSK_910) { 578cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + 579cd21b334SDaniel Scheller state->regoff, 0x2a); 580cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S232A + 581cd21b334SDaniel Scheller state->regoff, aclc); 582cd21b334SDaniel Scheller } 583cd21b334SDaniel Scheller } 584cd21b334SDaniel Scheller } 585cd21b334SDaniel Scheller return 0; 586cd21b334SDaniel Scheller } 587cd21b334SDaniel Scheller 588cd21b334SDaniel Scheller static s32 table_lookup(struct slookup *table, 58919bb3b71SDaniel Scheller int table_size, u32 reg_value) 590cd21b334SDaniel Scheller { 591cd21b334SDaniel Scheller s32 value; 592cd21b334SDaniel Scheller int imin = 0; 593cd21b334SDaniel Scheller int imax = table_size - 1; 594cd21b334SDaniel Scheller int i; 595cd21b334SDaniel Scheller s32 reg_diff; 596cd21b334SDaniel Scheller 597cd21b334SDaniel Scheller /* Assumes Table[0].RegValue > Table[imax].RegValue */ 598cd21b334SDaniel Scheller if (reg_value >= table[0].reg_value) 599cd21b334SDaniel Scheller value = table[0].value; 600cd21b334SDaniel Scheller else if (reg_value <= table[imax].reg_value) 601cd21b334SDaniel Scheller value = table[imax].value; 602cd21b334SDaniel Scheller else { 603cd21b334SDaniel Scheller while (imax-imin > 1) { 604cd21b334SDaniel Scheller i = (imax + imin) / 2; 605cd21b334SDaniel Scheller if ((table[imin].reg_value >= reg_value) && 606cd21b334SDaniel Scheller (reg_value >= table[i].reg_value)) 607cd21b334SDaniel Scheller imax = i; 608cd21b334SDaniel Scheller else 609cd21b334SDaniel Scheller imin = i; 610cd21b334SDaniel Scheller } 611cd21b334SDaniel Scheller 612cd21b334SDaniel Scheller reg_diff = table[imax].reg_value - table[imin].reg_value; 613cd21b334SDaniel Scheller value = table[imin].value; 614cd21b334SDaniel Scheller if (reg_diff != 0) 615cd21b334SDaniel Scheller value += ((s32)(reg_value - table[imin].reg_value) * 616cd21b334SDaniel Scheller (s32)(table[imax].value 617cd21b334SDaniel Scheller - table[imin].value)) 618cd21b334SDaniel Scheller / (reg_diff); 619cd21b334SDaniel Scheller } 620cd21b334SDaniel Scheller 621cd21b334SDaniel Scheller return value; 622cd21b334SDaniel Scheller } 623cd21b334SDaniel Scheller 624cd21b334SDaniel Scheller static int get_signal_to_noise(struct stv *state, s32 *signal_to_noise) 625cd21b334SDaniel Scheller { 626cd21b334SDaniel Scheller u8 data0; 627cd21b334SDaniel Scheller u8 data1; 628cd21b334SDaniel Scheller u16 data; 629cd21b334SDaniel Scheller int n_lookup; 630cd21b334SDaniel Scheller struct slookup *lookup; 631cd21b334SDaniel Scheller 632cd21b334SDaniel Scheller *signal_to_noise = 0; 633cd21b334SDaniel Scheller 634cd21b334SDaniel Scheller if (!state->started) 635cd21b334SDaniel Scheller return -EINVAL; 636cd21b334SDaniel Scheller 637cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 638cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_NNOSPLHT1 + state->regoff, 639cd21b334SDaniel Scheller &data1); 640cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_NNOSPLHT0 + state->regoff, 641cd21b334SDaniel Scheller &data0); 642cd21b334SDaniel Scheller n_lookup = ARRAY_SIZE(s2_sn_lookup); 643cd21b334SDaniel Scheller lookup = s2_sn_lookup; 644cd21b334SDaniel Scheller } else { 645cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_NNOSDATAT1 + state->regoff, 646cd21b334SDaniel Scheller &data1); 647cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_NNOSDATAT0 + state->regoff, 648cd21b334SDaniel Scheller &data0); 649cd21b334SDaniel Scheller n_lookup = ARRAY_SIZE(s1_sn_lookup); 650cd21b334SDaniel Scheller lookup = s1_sn_lookup; 651cd21b334SDaniel Scheller } 652cd21b334SDaniel Scheller data = (((u16)data1) << 8) | (u16) data0; 653cd21b334SDaniel Scheller *signal_to_noise = table_lookup(lookup, n_lookup, data); 654cd21b334SDaniel Scheller return 0; 655cd21b334SDaniel Scheller } 656cd21b334SDaniel Scheller 657cd21b334SDaniel Scheller static int get_bit_error_rate_s(struct stv *state, u32 *bernumerator, 658cd21b334SDaniel Scheller u32 *berdenominator) 659cd21b334SDaniel Scheller { 660cd21b334SDaniel Scheller u8 regs[3]; 661cd21b334SDaniel Scheller 662cd21b334SDaniel Scheller int status = read_regs(state, 663cd21b334SDaniel Scheller RSTV0910_P2_ERRCNT12 + state->regoff, 664cd21b334SDaniel Scheller regs, 3); 665cd21b334SDaniel Scheller 666cd21b334SDaniel Scheller if (status) 667cd21b334SDaniel Scheller return -EINVAL; 668cd21b334SDaniel Scheller 669cd21b334SDaniel Scheller if ((regs[0] & 0x80) == 0) { 670cd21b334SDaniel Scheller state->last_berdenominator = 1 << ((state->berscale * 2) + 671cd21b334SDaniel Scheller 10 + 3); 672cd21b334SDaniel Scheller state->last_bernumerator = ((u32) (regs[0] & 0x7F) << 16) | 673cd21b334SDaniel Scheller ((u32) regs[1] << 8) | regs[2]; 674cd21b334SDaniel Scheller if (state->last_bernumerator < 256 && state->berscale < 6) { 675cd21b334SDaniel Scheller state->berscale += 1; 676cd21b334SDaniel Scheller status = write_reg(state, RSTV0910_P2_ERRCTRL1 + 677cd21b334SDaniel Scheller state->regoff, 678cd21b334SDaniel Scheller 0x20 | state->berscale); 679cd21b334SDaniel Scheller } else if (state->last_bernumerator > 1024 && 680cd21b334SDaniel Scheller state->berscale > 2) { 681cd21b334SDaniel Scheller state->berscale -= 1; 682cd21b334SDaniel Scheller status = write_reg(state, RSTV0910_P2_ERRCTRL1 + 683cd21b334SDaniel Scheller state->regoff, 0x20 | 684cd21b334SDaniel Scheller state->berscale); 685cd21b334SDaniel Scheller } 686cd21b334SDaniel Scheller } 687cd21b334SDaniel Scheller *bernumerator = state->last_bernumerator; 688cd21b334SDaniel Scheller *berdenominator = state->last_berdenominator; 689cd21b334SDaniel Scheller return 0; 690cd21b334SDaniel Scheller } 691cd21b334SDaniel Scheller 692cd21b334SDaniel Scheller static u32 dvbs2_nbch(enum dvbs2_mod_cod mod_cod, enum dvbs2_fectype fectype) 693cd21b334SDaniel Scheller { 694cd21b334SDaniel Scheller static u32 nbch[][2] = { 69513c81489SDaniel Scheller { 0, 0}, /* DUMMY_PLF */ 696cd21b334SDaniel Scheller {16200, 3240}, /* QPSK_1_4, */ 697cd21b334SDaniel Scheller {21600, 5400}, /* QPSK_1_3, */ 698cd21b334SDaniel Scheller {25920, 6480}, /* QPSK_2_5, */ 699cd21b334SDaniel Scheller {32400, 7200}, /* QPSK_1_2, */ 700cd21b334SDaniel Scheller {38880, 9720}, /* QPSK_3_5, */ 701cd21b334SDaniel Scheller {43200, 10800}, /* QPSK_2_3, */ 702cd21b334SDaniel Scheller {48600, 11880}, /* QPSK_3_4, */ 703cd21b334SDaniel Scheller {51840, 12600}, /* QPSK_4_5, */ 704cd21b334SDaniel Scheller {54000, 13320}, /* QPSK_5_6, */ 705cd21b334SDaniel Scheller {57600, 14400}, /* QPSK_8_9, */ 706cd21b334SDaniel Scheller {58320, 16000}, /* QPSK_9_10, */ 707cd21b334SDaniel Scheller {43200, 9720}, /* 8PSK_3_5, */ 708cd21b334SDaniel Scheller {48600, 10800}, /* 8PSK_2_3, */ 709cd21b334SDaniel Scheller {51840, 11880}, /* 8PSK_3_4, */ 710cd21b334SDaniel Scheller {54000, 13320}, /* 8PSK_5_6, */ 711cd21b334SDaniel Scheller {57600, 14400}, /* 8PSK_8_9, */ 712cd21b334SDaniel Scheller {58320, 16000}, /* 8PSK_9_10, */ 713cd21b334SDaniel Scheller {43200, 10800}, /* 16APSK_2_3, */ 714cd21b334SDaniel Scheller {48600, 11880}, /* 16APSK_3_4, */ 715cd21b334SDaniel Scheller {51840, 12600}, /* 16APSK_4_5, */ 716cd21b334SDaniel Scheller {54000, 13320}, /* 16APSK_5_6, */ 717cd21b334SDaniel Scheller {57600, 14400}, /* 16APSK_8_9, */ 718cd21b334SDaniel Scheller {58320, 16000}, /* 16APSK_9_10 */ 719cd21b334SDaniel Scheller {48600, 11880}, /* 32APSK_3_4, */ 720cd21b334SDaniel Scheller {51840, 12600}, /* 32APSK_4_5, */ 721cd21b334SDaniel Scheller {54000, 13320}, /* 32APSK_5_6, */ 722cd21b334SDaniel Scheller {57600, 14400}, /* 32APSK_8_9, */ 723cd21b334SDaniel Scheller {58320, 16000}, /* 32APSK_9_10 */ 724cd21b334SDaniel Scheller }; 725cd21b334SDaniel Scheller 726cd21b334SDaniel Scheller if (mod_cod >= DVBS2_QPSK_1_4 && 727cd21b334SDaniel Scheller mod_cod <= DVBS2_32APSK_9_10 && fectype <= DVBS2_16K) 72813c81489SDaniel Scheller return nbch[mod_cod][fectype]; 729cd21b334SDaniel Scheller return 64800; 730cd21b334SDaniel Scheller } 731cd21b334SDaniel Scheller 732cd21b334SDaniel Scheller static int get_bit_error_rate_s2(struct stv *state, u32 *bernumerator, 733cd21b334SDaniel Scheller u32 *berdenominator) 734cd21b334SDaniel Scheller { 735cd21b334SDaniel Scheller u8 regs[3]; 736cd21b334SDaniel Scheller 737cd21b334SDaniel Scheller int status = read_regs(state, RSTV0910_P2_ERRCNT12 + state->regoff, 738cd21b334SDaniel Scheller regs, 3); 739cd21b334SDaniel Scheller 740cd21b334SDaniel Scheller if (status) 741cd21b334SDaniel Scheller return -EINVAL; 742cd21b334SDaniel Scheller 743cd21b334SDaniel Scheller if ((regs[0] & 0x80) == 0) { 744cd21b334SDaniel Scheller state->last_berdenominator = 745cd21b334SDaniel Scheller dvbs2_nbch((enum dvbs2_mod_cod) state->mod_cod, 746cd21b334SDaniel Scheller state->fectype) << 747cd21b334SDaniel Scheller (state->berscale * 2); 748cd21b334SDaniel Scheller state->last_bernumerator = (((u32) regs[0] & 0x7F) << 16) | 749cd21b334SDaniel Scheller ((u32) regs[1] << 8) | regs[2]; 750cd21b334SDaniel Scheller if (state->last_bernumerator < 256 && state->berscale < 6) { 751cd21b334SDaniel Scheller state->berscale += 1; 752cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, 753cd21b334SDaniel Scheller 0x20 | state->berscale); 754cd21b334SDaniel Scheller } else if (state->last_bernumerator > 1024 && 755cd21b334SDaniel Scheller state->berscale > 2) { 756cd21b334SDaniel Scheller state->berscale -= 1; 757cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ERRCTRL1 + state->regoff, 758cd21b334SDaniel Scheller 0x20 | state->berscale); 759cd21b334SDaniel Scheller } 760cd21b334SDaniel Scheller } 761cd21b334SDaniel Scheller *bernumerator = state->last_bernumerator; 762cd21b334SDaniel Scheller *berdenominator = state->last_berdenominator; 763cd21b334SDaniel Scheller return status; 764cd21b334SDaniel Scheller } 765cd21b334SDaniel Scheller 766cd21b334SDaniel Scheller static int get_bit_error_rate(struct stv *state, u32 *bernumerator, 767cd21b334SDaniel Scheller u32 *berdenominator) 768cd21b334SDaniel Scheller { 769cd21b334SDaniel Scheller *bernumerator = 0; 770cd21b334SDaniel Scheller *berdenominator = 1; 771cd21b334SDaniel Scheller 772cd21b334SDaniel Scheller switch (state->receive_mode) { 773cd21b334SDaniel Scheller case RCVMODE_DVBS: 774cd21b334SDaniel Scheller return get_bit_error_rate_s(state, 775cd21b334SDaniel Scheller bernumerator, berdenominator); 776cd21b334SDaniel Scheller case RCVMODE_DVBS2: 777cd21b334SDaniel Scheller return get_bit_error_rate_s2(state, 778cd21b334SDaniel Scheller bernumerator, berdenominator); 779cd21b334SDaniel Scheller default: 780cd21b334SDaniel Scheller break; 781cd21b334SDaniel Scheller } 782cd21b334SDaniel Scheller return 0; 783cd21b334SDaniel Scheller } 784cd21b334SDaniel Scheller 785cd21b334SDaniel Scheller static int set_mclock(struct stv *state, u32 master_clock) 786cd21b334SDaniel Scheller { 787cd21b334SDaniel Scheller u32 idf = 1; 788cd21b334SDaniel Scheller u32 odf = 4; 789cd21b334SDaniel Scheller u32 quartz = state->base->extclk / 1000000; 790cd21b334SDaniel Scheller u32 fphi = master_clock / 1000000; 791cd21b334SDaniel Scheller u32 ndiv = (fphi * odf * idf) / quartz; 792cd21b334SDaniel Scheller u32 cp = 7; 793cd21b334SDaniel Scheller u32 fvco; 794cd21b334SDaniel Scheller 795cd21b334SDaniel Scheller if (ndiv >= 7 && ndiv <= 71) 796cd21b334SDaniel Scheller cp = 7; 797cd21b334SDaniel Scheller else if (ndiv >= 72 && ndiv <= 79) 798cd21b334SDaniel Scheller cp = 8; 799cd21b334SDaniel Scheller else if (ndiv >= 80 && ndiv <= 87) 800cd21b334SDaniel Scheller cp = 9; 801cd21b334SDaniel Scheller else if (ndiv >= 88 && ndiv <= 95) 802cd21b334SDaniel Scheller cp = 10; 803cd21b334SDaniel Scheller else if (ndiv >= 96 && ndiv <= 103) 804cd21b334SDaniel Scheller cp = 11; 805cd21b334SDaniel Scheller else if (ndiv >= 104 && ndiv <= 111) 806cd21b334SDaniel Scheller cp = 12; 807cd21b334SDaniel Scheller else if (ndiv >= 112 && ndiv <= 119) 808cd21b334SDaniel Scheller cp = 13; 809cd21b334SDaniel Scheller else if (ndiv >= 120 && ndiv <= 127) 810cd21b334SDaniel Scheller cp = 14; 811cd21b334SDaniel Scheller else if (ndiv >= 128 && ndiv <= 135) 812cd21b334SDaniel Scheller cp = 15; 813cd21b334SDaniel Scheller else if (ndiv >= 136 && ndiv <= 143) 814cd21b334SDaniel Scheller cp = 16; 815cd21b334SDaniel Scheller else if (ndiv >= 144 && ndiv <= 151) 816cd21b334SDaniel Scheller cp = 17; 817cd21b334SDaniel Scheller else if (ndiv >= 152 && ndiv <= 159) 818cd21b334SDaniel Scheller cp = 18; 819cd21b334SDaniel Scheller else if (ndiv >= 160 && ndiv <= 167) 820cd21b334SDaniel Scheller cp = 19; 821cd21b334SDaniel Scheller else if (ndiv >= 168 && ndiv <= 175) 822cd21b334SDaniel Scheller cp = 20; 823cd21b334SDaniel Scheller else if (ndiv >= 176 && ndiv <= 183) 824cd21b334SDaniel Scheller cp = 21; 825cd21b334SDaniel Scheller else if (ndiv >= 184 && ndiv <= 191) 826cd21b334SDaniel Scheller cp = 22; 827cd21b334SDaniel Scheller else if (ndiv >= 192 && ndiv <= 199) 828cd21b334SDaniel Scheller cp = 23; 829cd21b334SDaniel Scheller else if (ndiv >= 200 && ndiv <= 207) 830cd21b334SDaniel Scheller cp = 24; 831cd21b334SDaniel Scheller else if (ndiv >= 208 && ndiv <= 215) 832cd21b334SDaniel Scheller cp = 25; 833cd21b334SDaniel Scheller else if (ndiv >= 216 && ndiv <= 223) 834cd21b334SDaniel Scheller cp = 26; 835cd21b334SDaniel Scheller else if (ndiv >= 224 && ndiv <= 225) 836cd21b334SDaniel Scheller cp = 27; 837cd21b334SDaniel Scheller 838cd21b334SDaniel Scheller write_reg(state, RSTV0910_NCOARSE, (cp << 3) | idf); 839cd21b334SDaniel Scheller write_reg(state, RSTV0910_NCOARSE2, odf); 840cd21b334SDaniel Scheller write_reg(state, RSTV0910_NCOARSE1, ndiv); 841cd21b334SDaniel Scheller 842cd21b334SDaniel Scheller fvco = (quartz * 2 * ndiv) / idf; 843cd21b334SDaniel Scheller state->base->mclk = fvco / (2 * odf) * 1000000; 844cd21b334SDaniel Scheller 845cd21b334SDaniel Scheller return 0; 846cd21b334SDaniel Scheller } 847cd21b334SDaniel Scheller 848cd21b334SDaniel Scheller static int stop(struct stv *state) 849cd21b334SDaniel Scheller { 850cd21b334SDaniel Scheller if (state->started) { 851cd21b334SDaniel Scheller u8 tmp; 852cd21b334SDaniel Scheller 853cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, 854cd21b334SDaniel Scheller state->tscfgh | 0x01); 855cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); 856cd21b334SDaniel Scheller tmp &= ~0x01; /*release reset DVBS2 packet delin*/ 857cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); 858cd21b334SDaniel Scheller /* Blind optim*/ 859cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_AGC2O + state->regoff, 0x5B); 860cd21b334SDaniel Scheller /* Stop the demod */ 861cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5c); 862cd21b334SDaniel Scheller state->started = 0; 863cd21b334SDaniel Scheller } 864cd21b334SDaniel Scheller state->receive_mode = RCVMODE_NONE; 865cd21b334SDaniel Scheller return 0; 866cd21b334SDaniel Scheller } 867cd21b334SDaniel Scheller 868cd21b334SDaniel Scheller static int init_search_param(struct stv *state) 869cd21b334SDaniel Scheller { 870cd21b334SDaniel Scheller u8 tmp; 871cd21b334SDaniel Scheller 872cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); 873cd21b334SDaniel Scheller tmp |= 0x20; // Filter_en (no effect if SIS=non-MIS 874cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); 875cd21b334SDaniel Scheller 876cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, &tmp); 877cd21b334SDaniel Scheller tmp &= ~0x02; // frame mode = 0 878cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PDELCTRL2 + state->regoff, tmp); 879cd21b334SDaniel Scheller 880cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_UPLCCST0 + state->regoff, 0xe0); 881cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ISIBITENA + state->regoff, 0x00); 882cd21b334SDaniel Scheller 883cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSSTATEM + state->regoff, &tmp); 884cd21b334SDaniel Scheller tmp &= ~0x01; // nosync = 0, in case next signal is standard TS 885cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSSTATEM + state->regoff, tmp); 886cd21b334SDaniel Scheller 887cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSCFGL + state->regoff, &tmp); 888cd21b334SDaniel Scheller tmp &= ~0x04; // embindvb = 0 889cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGL + state->regoff, tmp); 890cd21b334SDaniel Scheller 891cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSINSDELH + state->regoff, &tmp); 892cd21b334SDaniel Scheller tmp &= ~0x80; // syncbyte = 0 893cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSINSDELH + state->regoff, tmp); 894cd21b334SDaniel Scheller 895cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSINSDELM + state->regoff, &tmp); 896cd21b334SDaniel Scheller tmp &= ~0x08; // token = 0 897cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSINSDELM + state->regoff, tmp); 898cd21b334SDaniel Scheller 899cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_TSDLYSET2 + state->regoff, &tmp); 900cd21b334SDaniel Scheller tmp &= ~0x30; // hysteresis threshold = 0 901cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSDLYSET2 + state->regoff, tmp); 902cd21b334SDaniel Scheller 903cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_PDELCTRL0 + state->regoff, &tmp); 904cd21b334SDaniel Scheller tmp = (tmp & ~0x30) | 0x10; // isi obs mode = 1, observe min ISI 905cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PDELCTRL0 + state->regoff, tmp); 906cd21b334SDaniel Scheller 907cd21b334SDaniel Scheller return 0; 908cd21b334SDaniel Scheller } 909cd21b334SDaniel Scheller 910cd21b334SDaniel Scheller static int enable_puncture_rate(struct stv *state, enum fe_code_rate rate) 911cd21b334SDaniel Scheller { 912cd21b334SDaniel Scheller switch (rate) { 913cd21b334SDaniel Scheller case FEC_1_2: 914cd21b334SDaniel Scheller return write_reg(state, 915cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x01); 916cd21b334SDaniel Scheller case FEC_2_3: 917cd21b334SDaniel Scheller return write_reg(state, 918cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x02); 919cd21b334SDaniel Scheller case FEC_3_4: 920cd21b334SDaniel Scheller return write_reg(state, 921cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x04); 922cd21b334SDaniel Scheller case FEC_5_6: 923cd21b334SDaniel Scheller return write_reg(state, 924cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x08); 925cd21b334SDaniel Scheller case FEC_7_8: 926cd21b334SDaniel Scheller return write_reg(state, 927cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x20); 928cd21b334SDaniel Scheller case FEC_NONE: 929cd21b334SDaniel Scheller default: 930cd21b334SDaniel Scheller return write_reg(state, 931cd21b334SDaniel Scheller RSTV0910_P2_PRVIT + state->regoff, 0x2f); 932cd21b334SDaniel Scheller } 933cd21b334SDaniel Scheller } 934cd21b334SDaniel Scheller 935cd21b334SDaniel Scheller static int set_vth_default(struct stv *state) 936cd21b334SDaniel Scheller { 937cd21b334SDaniel Scheller state->vth[0] = 0xd7; 938cd21b334SDaniel Scheller state->vth[1] = 0x85; 939cd21b334SDaniel Scheller state->vth[2] = 0x58; 940cd21b334SDaniel Scheller state->vth[3] = 0x3a; 941cd21b334SDaniel Scheller state->vth[4] = 0x34; 942cd21b334SDaniel Scheller state->vth[5] = 0x28; 943cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 0, state->vth[0]); 944cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 1, state->vth[1]); 945cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 2, state->vth[2]); 946cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 3, state->vth[3]); 947cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 4, state->vth[4]); 948cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 5, state->vth[5]); 949cd21b334SDaniel Scheller return 0; 950cd21b334SDaniel Scheller } 951cd21b334SDaniel Scheller 952cd21b334SDaniel Scheller static int set_vth(struct stv *state) 953cd21b334SDaniel Scheller { 954cd21b334SDaniel Scheller static struct slookup vthlookup_table[] = { 955cd21b334SDaniel Scheller {250, 8780}, /*C/N=1.5dB*/ 956cd21b334SDaniel Scheller {100, 7405}, /*C/N=4.5dB*/ 957cd21b334SDaniel Scheller {40, 6330}, /*C/N=6.5dB*/ 958cd21b334SDaniel Scheller {12, 5224}, /*C/N=8.5dB*/ 959cd21b334SDaniel Scheller {5, 4236} /*C/N=10.5dB*/ 960cd21b334SDaniel Scheller }; 961cd21b334SDaniel Scheller 962cd21b334SDaniel Scheller int i; 963cd21b334SDaniel Scheller u8 tmp[2]; 964cd21b334SDaniel Scheller int status = read_regs(state, 965cd21b334SDaniel Scheller RSTV0910_P2_NNOSDATAT1 + state->regoff, 966cd21b334SDaniel Scheller tmp, 2); 967cd21b334SDaniel Scheller u16 reg_value = (tmp[0] << 8) | tmp[1]; 968cd21b334SDaniel Scheller s32 vth = table_lookup(vthlookup_table, ARRAY_SIZE(vthlookup_table), 969cd21b334SDaniel Scheller reg_value); 970cd21b334SDaniel Scheller 971cd21b334SDaniel Scheller for (i = 0; i < 6; i += 1) 972cd21b334SDaniel Scheller if (state->vth[i] > vth) 973cd21b334SDaniel Scheller state->vth[i] = vth; 974cd21b334SDaniel Scheller 975cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 0, state->vth[0]); 976cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 1, state->vth[1]); 977cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 2, state->vth[2]); 978cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 3, state->vth[3]); 979cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 4, state->vth[4]); 980cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_VTH12 + state->regoff + 5, state->vth[5]); 981cd21b334SDaniel Scheller return status; 982cd21b334SDaniel Scheller } 983cd21b334SDaniel Scheller 984cd21b334SDaniel Scheller static int start(struct stv *state, struct dtv_frontend_properties *p) 985cd21b334SDaniel Scheller { 986cd21b334SDaniel Scheller s32 freq; 987cd21b334SDaniel Scheller u8 reg_dmdcfgmd; 988cd21b334SDaniel Scheller u16 symb; 989ea71c62bSDaniel Scheller u32 scrambling_code = 1; 990cd21b334SDaniel Scheller 991cd21b334SDaniel Scheller if (p->symbol_rate < 100000 || p->symbol_rate > 70000000) 992cd21b334SDaniel Scheller return -EINVAL; 993cd21b334SDaniel Scheller 994cd21b334SDaniel Scheller state->receive_mode = RCVMODE_NONE; 995cd21b334SDaniel Scheller state->demod_lock_time = 0; 996cd21b334SDaniel Scheller 997cd21b334SDaniel Scheller /* Demod Stop */ 998cd21b334SDaniel Scheller if (state->started) 999cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x5C); 1000cd21b334SDaniel Scheller 1001cd21b334SDaniel Scheller init_search_param(state); 1002cd21b334SDaniel Scheller 1003ea71c62bSDaniel Scheller if (p->stream_id != NO_STREAM_ID_FILTER) { 1004ea71c62bSDaniel Scheller /* Backwards compatibility to "crazy" API. 1005ea71c62bSDaniel Scheller * PRBS X root cannot be 0, so this should always work. 1006ea71c62bSDaniel Scheller */ 1007ea71c62bSDaniel Scheller if (p->stream_id & 0xffffff00) 1008ea71c62bSDaniel Scheller scrambling_code = p->stream_id >> 8; 1009ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_ISIENTRY + state->regoff, 1010ea71c62bSDaniel Scheller p->stream_id & 0xff); 1011ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_ISIBITENA + state->regoff, 1012ea71c62bSDaniel Scheller 0xff); 1013ea71c62bSDaniel Scheller } 1014ea71c62bSDaniel Scheller 1015ea71c62bSDaniel Scheller if (scrambling_code != state->cur_scrambling_code) { 1016ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_PLROOT0 + state->regoff, 1017ea71c62bSDaniel Scheller scrambling_code & 0xff); 1018ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_PLROOT1 + state->regoff, 1019ea71c62bSDaniel Scheller (scrambling_code >> 8) & 0xff); 1020ea71c62bSDaniel Scheller write_reg(state, RSTV0910_P2_PLROOT2 + state->regoff, 1021ea71c62bSDaniel Scheller (scrambling_code >> 16) & 0x07); 1022ea71c62bSDaniel Scheller state->cur_scrambling_code = scrambling_code; 1023ea71c62bSDaniel Scheller } 1024ea71c62bSDaniel Scheller 1025cd21b334SDaniel Scheller if (p->symbol_rate <= 1000000) { /* SR <=1Msps */ 1026cd21b334SDaniel Scheller state->demod_timeout = 3000; 1027cd21b334SDaniel Scheller state->fec_timeout = 2000; 1028cd21b334SDaniel Scheller } else if (p->symbol_rate <= 2000000) { /* 1Msps < SR <=2Msps */ 1029cd21b334SDaniel Scheller state->demod_timeout = 2500; 1030cd21b334SDaniel Scheller state->fec_timeout = 1300; 1031cd21b334SDaniel Scheller } else if (p->symbol_rate <= 5000000) { /* 2Msps< SR <=5Msps */ 1032cd21b334SDaniel Scheller state->demod_timeout = 1000; 1033cd21b334SDaniel Scheller state->fec_timeout = 650; 1034cd21b334SDaniel Scheller } else if (p->symbol_rate <= 10000000) { /* 5Msps< SR <=10Msps */ 1035cd21b334SDaniel Scheller state->demod_timeout = 700; 1036cd21b334SDaniel Scheller state->fec_timeout = 350; 1037cd21b334SDaniel Scheller } else if (p->symbol_rate < 20000000) { /* 10Msps< SR <=20Msps */ 1038cd21b334SDaniel Scheller state->demod_timeout = 400; 1039cd21b334SDaniel Scheller state->fec_timeout = 200; 1040cd21b334SDaniel Scheller } else { /* SR >=20Msps */ 1041cd21b334SDaniel Scheller state->demod_timeout = 300; 1042cd21b334SDaniel Scheller state->fec_timeout = 200; 1043cd21b334SDaniel Scheller } 1044cd21b334SDaniel Scheller 1045cd21b334SDaniel Scheller /* Set the Init Symbol rate */ 1046cd21b334SDaniel Scheller symb = muldiv32(p->symbol_rate, 65536, state->base->mclk); 1047cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_SFRINIT1 + state->regoff, 1048cd21b334SDaniel Scheller ((symb >> 8) & 0x7F)); 1049cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_SFRINIT0 + state->regoff, (symb & 0xFF)); 1050cd21b334SDaniel Scheller 1051cd21b334SDaniel Scheller state->demod_bits |= 0x80; 1052cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DEMOD + state->regoff, state->demod_bits); 1053cd21b334SDaniel Scheller 1054cd21b334SDaniel Scheller /* FE_STV0910_SetSearchStandard */ 1055cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, ®_dmdcfgmd); 1056cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDCFGMD + state->regoff, 1057cd21b334SDaniel Scheller reg_dmdcfgmd |= 0xC0); 1058cd21b334SDaniel Scheller 1059cd21b334SDaniel Scheller write_shared_reg(state, 1060cd21b334SDaniel Scheller RSTV0910_TSTTSRS, state->nr ? 0x02 : 0x01, 0x00); 1061cd21b334SDaniel Scheller 1062cd21b334SDaniel Scheller /* Disable DSS */ 1063cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_FECM + state->regoff, 0x00); 1064cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_PRVIT + state->regoff, 0x2F); 1065cd21b334SDaniel Scheller 1066cd21b334SDaniel Scheller enable_puncture_rate(state, FEC_NONE); 1067cd21b334SDaniel Scheller 1068cd21b334SDaniel Scheller /* 8PSK 3/5, 8PSK 2/3 Poff tracking optimization WA*/ 1069cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S2Q + state->regoff, 0x0B); 1070cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S28 + state->regoff, 0x0A); 1071cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_BCLC2S2Q + state->regoff, 0x84); 1072cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_BCLC2S28 + state->regoff, 0x84); 1073cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CARHDR + state->regoff, 0x1C); 1074cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CARFREQ + state->regoff, 0x79); 1075cd21b334SDaniel Scheller 1076cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S216A + state->regoff, 0x29); 1077cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_ACLC2S232A + state->regoff, 0x09); 1078cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_BCLC2S216A + state->regoff, 0x84); 1079cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_BCLC2S232A + state->regoff, 0x84); 1080cd21b334SDaniel Scheller 1081cd21b334SDaniel Scheller /* Reset CAR3, bug DVBS2->DVBS1 lock*/ 1082cd21b334SDaniel Scheller /* Note: The bit is only pulsed -> no lock on shared register needed */ 1083cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSTRES0, state->nr ? 0x04 : 0x08); 1084cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSTRES0, 0); 1085cd21b334SDaniel Scheller 1086cd21b334SDaniel Scheller set_vth_default(state); 1087cd21b334SDaniel Scheller /* Reset demod */ 1088cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); 1089cd21b334SDaniel Scheller 1090cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CARCFG + state->regoff, 0x46); 1091cd21b334SDaniel Scheller 1092cd21b334SDaniel Scheller if (p->symbol_rate <= 5000000) 1093cd21b334SDaniel Scheller freq = (state->search_range / 2000) + 80; 1094cd21b334SDaniel Scheller else 1095cd21b334SDaniel Scheller freq = (state->search_range / 2000) + 1600; 1096cd21b334SDaniel Scheller freq = (freq << 16) / (state->base->mclk / 1000); 1097cd21b334SDaniel Scheller 1098cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRUP1 + state->regoff, 1099cd21b334SDaniel Scheller (freq >> 8) & 0xff); 1100cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRUP0 + state->regoff, (freq & 0xff)); 1101cd21b334SDaniel Scheller /*CFR Low Setting*/ 1102cd21b334SDaniel Scheller freq = -freq; 1103cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRLOW1 + state->regoff, 1104cd21b334SDaniel Scheller (freq >> 8) & 0xff); 1105cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRLOW0 + state->regoff, (freq & 0xff)); 1106cd21b334SDaniel Scheller 1107cd21b334SDaniel Scheller /* init the demod frequency offset to 0 */ 1108cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRINIT1 + state->regoff, 0); 1109cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CFRINIT0 + state->regoff, 0); 1110cd21b334SDaniel Scheller 1111cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x1F); 1112cd21b334SDaniel Scheller /* Trigger acq */ 1113cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDISTATE + state->regoff, 0x15); 1114cd21b334SDaniel Scheller 1115cd21b334SDaniel Scheller state->demod_lock_time += TUNING_DELAY; 1116cd21b334SDaniel Scheller state->started = 1; 1117cd21b334SDaniel Scheller 1118cd21b334SDaniel Scheller return 0; 1119cd21b334SDaniel Scheller } 1120cd21b334SDaniel Scheller 1121cd21b334SDaniel Scheller static int init_diseqc(struct stv *state) 1122cd21b334SDaniel Scheller { 1123cd21b334SDaniel Scheller u16 offs = state->nr ? 0x40 : 0; /* Address offset */ 1124cd21b334SDaniel Scheller u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); 1125cd21b334SDaniel Scheller 1126cd21b334SDaniel Scheller /* Disable receiver */ 1127cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); 1128cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ 1129cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ 1130cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq); 1131cd21b334SDaniel Scheller return 0; 1132cd21b334SDaniel Scheller } 1133cd21b334SDaniel Scheller 1134cd21b334SDaniel Scheller static int probe(struct stv *state) 1135cd21b334SDaniel Scheller { 1136cd21b334SDaniel Scheller u8 id; 1137cd21b334SDaniel Scheller 1138cd21b334SDaniel Scheller state->receive_mode = RCVMODE_NONE; 1139cd21b334SDaniel Scheller state->started = 0; 1140cd21b334SDaniel Scheller 1141cd21b334SDaniel Scheller if (read_reg(state, RSTV0910_MID, &id) < 0) 1142cd21b334SDaniel Scheller return -ENODEV; 1143cd21b334SDaniel Scheller 1144cd21b334SDaniel Scheller if (id != 0x51) 1145cd21b334SDaniel Scheller return -EINVAL; 1146cd21b334SDaniel Scheller 1147cd21b334SDaniel Scheller /* Configure the I2C repeater to off */ 1148cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_I2CRPT, 0x24); 1149cd21b334SDaniel Scheller /* Configure the I2C repeater to off */ 1150cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_I2CRPT, 0x24); 1151cd21b334SDaniel Scheller /* Set the I2C to oversampling ratio */ 1152cd21b334SDaniel Scheller write_reg(state, RSTV0910_I2CCFG, 0x88); /* state->i2ccfg */ 1153cd21b334SDaniel Scheller 1154cd21b334SDaniel Scheller write_reg(state, RSTV0910_OUTCFG, 0x00); /* OUTCFG */ 1155cd21b334SDaniel Scheller write_reg(state, RSTV0910_PADCFG, 0x05); /* RFAGC Pads Dev = 05 */ 1156cd21b334SDaniel Scheller write_reg(state, RSTV0910_SYNTCTRL, 0x02); /* SYNTCTRL */ 1157cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSGENERAL, state->tsgeneral); /* TSGENERAL */ 1158cd21b334SDaniel Scheller write_reg(state, RSTV0910_CFGEXT, 0x02); /* CFGEXT */ 1159cd21b334SDaniel Scheller 1160cd21b334SDaniel Scheller if (state->single) 1161cd21b334SDaniel Scheller write_reg(state, RSTV0910_GENCFG, 0x14); /* GENCFG */ 1162cd21b334SDaniel Scheller else 1163cd21b334SDaniel Scheller write_reg(state, RSTV0910_GENCFG, 0x15); /* GENCFG */ 1164cd21b334SDaniel Scheller 1165cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TNRCFG2, 0x02); /* IQSWAP = 0 */ 1166cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TNRCFG2, 0x82); /* IQSWAP = 1 */ 1167cd21b334SDaniel Scheller 1168cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_CAR3CFG, 0x02); 1169cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_CAR3CFG, 0x02); 1170cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DMDCFG4, 0x04); 1171cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_DMDCFG4, 0x04); 1172cd21b334SDaniel Scheller 1173cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSTRES0, 0x80); /* LDPC Reset */ 1174cd21b334SDaniel Scheller write_reg(state, RSTV0910_TSTRES0, 0x00); 1175cd21b334SDaniel Scheller 1176cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSPIDFLT1, 0x00); 1177cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSPIDFLT1, 0x00); 1178cd21b334SDaniel Scheller 1179cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TMGCFG2, 0x80); 1180cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TMGCFG2, 0x80); 1181cd21b334SDaniel Scheller 1182cd21b334SDaniel Scheller set_mclock(state, 135000000); 1183cd21b334SDaniel Scheller 1184cd21b334SDaniel Scheller /* TS output */ 1185cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh | 0x01); 1186cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh); 1187cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGM, 0xC0); /* Manual speed */ 1188cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGL, 0x20); 1189cd21b334SDaniel Scheller 1190cd21b334SDaniel Scheller /* Speed = 67.5 MHz */ 1191cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSSPEED, state->tsspeed); 1192cd21b334SDaniel Scheller 1193cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh | 0x01); 1194cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh); 1195cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGM, 0xC0); /* Manual speed */ 1196cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGL, 0x20); 1197cd21b334SDaniel Scheller 1198cd21b334SDaniel Scheller /* Speed = 67.5 MHz */ 1199cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSSPEED, state->tsspeed); 1200cd21b334SDaniel Scheller 1201cd21b334SDaniel Scheller /* Reset stream merger */ 1202cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh | 0x01); 1203cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh | 0x01); 1204cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_TSCFGH, state->tscfgh); 1205cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh); 1206cd21b334SDaniel Scheller 1207cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_I2CRPT, state->i2crpt); 1208cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_I2CRPT, state->i2crpt); 1209cd21b334SDaniel Scheller 1210cd21b334SDaniel Scheller init_diseqc(state); 1211cd21b334SDaniel Scheller return 0; 1212cd21b334SDaniel Scheller } 1213cd21b334SDaniel Scheller 1214cd21b334SDaniel Scheller 1215cd21b334SDaniel Scheller static int gate_ctrl(struct dvb_frontend *fe, int enable) 1216cd21b334SDaniel Scheller { 1217cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1218cd21b334SDaniel Scheller u8 i2crpt = state->i2crpt & ~0x86; 1219cd21b334SDaniel Scheller 1220cd21b334SDaniel Scheller if (enable) 1221cd21b334SDaniel Scheller mutex_lock(&state->base->i2c_lock); 1222cd21b334SDaniel Scheller 1223cd21b334SDaniel Scheller if (enable) 1224cd21b334SDaniel Scheller i2crpt |= 0x80; 1225cd21b334SDaniel Scheller else 1226cd21b334SDaniel Scheller i2crpt |= 0x02; 1227cd21b334SDaniel Scheller 1228cd21b334SDaniel Scheller if (write_reg(state, state->nr ? RSTV0910_P2_I2CRPT : 1229cd21b334SDaniel Scheller RSTV0910_P1_I2CRPT, i2crpt) < 0) 1230cd21b334SDaniel Scheller return -EIO; 1231cd21b334SDaniel Scheller 1232cd21b334SDaniel Scheller state->i2crpt = i2crpt; 1233cd21b334SDaniel Scheller 1234cd21b334SDaniel Scheller if (!enable) 1235cd21b334SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 1236cd21b334SDaniel Scheller return 0; 1237cd21b334SDaniel Scheller } 1238cd21b334SDaniel Scheller 1239cd21b334SDaniel Scheller static void release(struct dvb_frontend *fe) 1240cd21b334SDaniel Scheller { 1241cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1242cd21b334SDaniel Scheller 1243cd21b334SDaniel Scheller state->base->count--; 1244cd21b334SDaniel Scheller if (state->base->count == 0) { 1245cd21b334SDaniel Scheller list_del(&state->base->stvlist); 1246cd21b334SDaniel Scheller kfree(state->base); 1247cd21b334SDaniel Scheller } 1248cd21b334SDaniel Scheller kfree(state); 1249cd21b334SDaniel Scheller } 1250cd21b334SDaniel Scheller 1251cd21b334SDaniel Scheller static int set_parameters(struct dvb_frontend *fe) 1252cd21b334SDaniel Scheller { 1253cd21b334SDaniel Scheller int stat = 0; 1254cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1255cd21b334SDaniel Scheller u32 iffreq; 1256cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1257cd21b334SDaniel Scheller 1258cd21b334SDaniel Scheller stop(state); 1259cd21b334SDaniel Scheller if (fe->ops.tuner_ops.set_params) 1260cd21b334SDaniel Scheller fe->ops.tuner_ops.set_params(fe); 1261cd21b334SDaniel Scheller if (fe->ops.tuner_ops.get_if_frequency) 1262cd21b334SDaniel Scheller fe->ops.tuner_ops.get_if_frequency(fe, &iffreq); 1263cd21b334SDaniel Scheller state->symbol_rate = p->symbol_rate; 1264cd21b334SDaniel Scheller stat = start(state, p); 1265cd21b334SDaniel Scheller return stat; 1266cd21b334SDaniel Scheller } 1267cd21b334SDaniel Scheller 1268cd21b334SDaniel Scheller static int manage_matype_info(struct stv *state) 1269cd21b334SDaniel Scheller { 1270cd21b334SDaniel Scheller if (!state->started) 1271cd21b334SDaniel Scheller return -EINVAL; 1272cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 1273cd21b334SDaniel Scheller u8 bbheader[2]; 1274cd21b334SDaniel Scheller 1275cd21b334SDaniel Scheller read_regs(state, RSTV0910_P2_MATSTR1 + state->regoff, 1276cd21b334SDaniel Scheller bbheader, 2); 1277cd21b334SDaniel Scheller state->feroll_off = 1278cd21b334SDaniel Scheller (enum fe_stv0910_roll_off) (bbheader[0] & 0x03); 1279cd21b334SDaniel Scheller state->is_vcm = (bbheader[0] & 0x10) == 0; 1280cd21b334SDaniel Scheller state->is_standard_broadcast = (bbheader[0] & 0xFC) == 0xF0; 1281cd21b334SDaniel Scheller } else if (state->receive_mode == RCVMODE_DVBS) { 1282cd21b334SDaniel Scheller state->is_vcm = 0; 1283cd21b334SDaniel Scheller state->is_standard_broadcast = 1; 1284cd21b334SDaniel Scheller state->feroll_off = FE_SAT_35; 1285cd21b334SDaniel Scheller } 1286cd21b334SDaniel Scheller return 0; 1287cd21b334SDaniel Scheller } 1288cd21b334SDaniel Scheller 1289cd21b334SDaniel Scheller static int read_snr(struct dvb_frontend *fe) 1290cd21b334SDaniel Scheller { 1291cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1292cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1293cd21b334SDaniel Scheller s32 snrval; 1294cd21b334SDaniel Scheller 1295cd21b334SDaniel Scheller if (!get_signal_to_noise(state, &snrval)) { 1296cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_DECIBEL; 1297cd21b334SDaniel Scheller p->cnr.stat[0].uvalue = 100 * snrval; /* fix scale */ 1298cd21b334SDaniel Scheller } else 1299cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1300cd21b334SDaniel Scheller 1301cd21b334SDaniel Scheller return 0; 1302cd21b334SDaniel Scheller } 1303cd21b334SDaniel Scheller 1304cd21b334SDaniel Scheller static int read_ber(struct dvb_frontend *fe) 1305cd21b334SDaniel Scheller { 1306cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1307cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1308cd21b334SDaniel Scheller u32 n, d; 1309cd21b334SDaniel Scheller 1310cd21b334SDaniel Scheller get_bit_error_rate(state, &n, &d); 1311cd21b334SDaniel Scheller 1312cd21b334SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; 1313cd21b334SDaniel Scheller p->pre_bit_error.stat[0].uvalue = n; 1314cd21b334SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; 1315cd21b334SDaniel Scheller p->pre_bit_count.stat[0].uvalue = d; 1316cd21b334SDaniel Scheller 1317cd21b334SDaniel Scheller return 0; 1318cd21b334SDaniel Scheller } 1319cd21b334SDaniel Scheller 1320cd21b334SDaniel Scheller static void read_signal_strength(struct dvb_frontend *fe) 1321cd21b334SDaniel Scheller { 1322cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1323cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &state->fe.dtv_property_cache; 132419bb3b71SDaniel Scheller s64 strength; 132519bb3b71SDaniel Scheller u8 reg[2]; 132619bb3b71SDaniel Scheller u16 agc; 132719bb3b71SDaniel Scheller s32 padc, power = 0; 132819bb3b71SDaniel Scheller int i; 1329cd21b334SDaniel Scheller 133019bb3b71SDaniel Scheller read_regs(state, RSTV0910_P2_AGCIQIN1 + state->regoff, reg, 2); 133119bb3b71SDaniel Scheller 133219bb3b71SDaniel Scheller agc = (((u32) reg[0]) << 8) | reg[1]; 133319bb3b71SDaniel Scheller 133419bb3b71SDaniel Scheller for (i = 0; i < 5; i += 1) { 133519bb3b71SDaniel Scheller read_regs(state, RSTV0910_P2_POWERI + state->regoff, reg, 2); 133619bb3b71SDaniel Scheller power += (u32) reg[0] * (u32) reg[0] 133719bb3b71SDaniel Scheller + (u32) reg[1] * (u32) reg[1]; 133819bb3b71SDaniel Scheller usleep_range(3000, 4000); 133919bb3b71SDaniel Scheller } 134019bb3b71SDaniel Scheller power /= 5; 134119bb3b71SDaniel Scheller 134219bb3b71SDaniel Scheller padc = table_lookup(padc_lookup, ARRAY_SIZE(padc_lookup), power) + 352; 134319bb3b71SDaniel Scheller 134419bb3b71SDaniel Scheller strength = (padc - agc); 134519bb3b71SDaniel Scheller 134619bb3b71SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_DECIBEL; 134719bb3b71SDaniel Scheller p->strength.stat[0].uvalue = strength; 1348cd21b334SDaniel Scheller } 1349cd21b334SDaniel Scheller 1350cd21b334SDaniel Scheller static int read_status(struct dvb_frontend *fe, enum fe_status *status) 1351cd21b334SDaniel Scheller { 1352cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1353cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1354cd21b334SDaniel Scheller u8 dmd_state = 0; 1355cd21b334SDaniel Scheller u8 dstatus = 0; 1356cd21b334SDaniel Scheller enum receive_mode cur_receive_mode = RCVMODE_NONE; 1357cd21b334SDaniel Scheller u32 feclock = 0; 1358cd21b334SDaniel Scheller 1359cd21b334SDaniel Scheller *status = 0; 1360cd21b334SDaniel Scheller 1361cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDSTATE + state->regoff, &dmd_state); 1362cd21b334SDaniel Scheller 1363cd21b334SDaniel Scheller if (dmd_state & 0x40) { 1364cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DSTATUS + state->regoff, &dstatus); 1365cd21b334SDaniel Scheller if (dstatus & 0x08) 1366cd21b334SDaniel Scheller cur_receive_mode = (dmd_state & 0x20) ? 1367cd21b334SDaniel Scheller RCVMODE_DVBS : RCVMODE_DVBS2; 1368cd21b334SDaniel Scheller } 1369cd21b334SDaniel Scheller if (cur_receive_mode == RCVMODE_NONE) { 1370cd21b334SDaniel Scheller set_vth(state); 1371cd21b334SDaniel Scheller 1372cd21b334SDaniel Scheller /* reset signal statistics */ 1373cd21b334SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1374cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1375cd21b334SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1376cd21b334SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1377cd21b334SDaniel Scheller 1378cd21b334SDaniel Scheller return 0; 1379cd21b334SDaniel Scheller } 1380cd21b334SDaniel Scheller 1381cd21b334SDaniel Scheller *status |= (FE_HAS_SIGNAL 1382cd21b334SDaniel Scheller | FE_HAS_CARRIER 1383cd21b334SDaniel Scheller | FE_HAS_VITERBI 1384cd21b334SDaniel Scheller | FE_HAS_SYNC); 1385cd21b334SDaniel Scheller 1386cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_NONE) { 1387cd21b334SDaniel Scheller state->receive_mode = cur_receive_mode; 1388cd21b334SDaniel Scheller state->demod_lock_time = jiffies; 1389cd21b334SDaniel Scheller state->first_time_lock = 1; 1390cd21b334SDaniel Scheller 1391cd21b334SDaniel Scheller get_signal_parameters(state); 1392cd21b334SDaniel Scheller tracking_optimization(state); 1393cd21b334SDaniel Scheller 1394cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, 1395cd21b334SDaniel Scheller state->tscfgh); 1396cd21b334SDaniel Scheller usleep_range(3000, 4000); 1397cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, 1398cd21b334SDaniel Scheller state->tscfgh | 0x01); 1399cd21b334SDaniel Scheller write_reg(state, RSTV0910_P2_TSCFGH + state->regoff, 1400cd21b334SDaniel Scheller state->tscfgh); 1401cd21b334SDaniel Scheller } 1402cd21b334SDaniel Scheller if (dmd_state & 0x40) { 1403cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 1404cd21b334SDaniel Scheller u8 pdelstatus; 1405cd21b334SDaniel Scheller 1406cd21b334SDaniel Scheller read_reg(state, 1407cd21b334SDaniel Scheller RSTV0910_P2_PDELSTATUS1 + state->regoff, 1408cd21b334SDaniel Scheller &pdelstatus); 1409cd21b334SDaniel Scheller feclock = (pdelstatus & 0x02) != 0; 1410cd21b334SDaniel Scheller } else { 1411cd21b334SDaniel Scheller u8 vstatus; 1412cd21b334SDaniel Scheller 1413cd21b334SDaniel Scheller read_reg(state, 1414cd21b334SDaniel Scheller RSTV0910_P2_VSTATUSVIT + state->regoff, 1415cd21b334SDaniel Scheller &vstatus); 1416cd21b334SDaniel Scheller feclock = (vstatus & 0x08) != 0; 1417cd21b334SDaniel Scheller } 1418cd21b334SDaniel Scheller } 1419cd21b334SDaniel Scheller 1420cd21b334SDaniel Scheller if (feclock) { 1421cd21b334SDaniel Scheller *status |= FE_HAS_LOCK; 1422cd21b334SDaniel Scheller 1423cd21b334SDaniel Scheller if (state->first_time_lock) { 1424cd21b334SDaniel Scheller u8 tmp; 1425cd21b334SDaniel Scheller 1426cd21b334SDaniel Scheller state->first_time_lock = 0; 1427cd21b334SDaniel Scheller 1428cd21b334SDaniel Scheller manage_matype_info(state); 1429cd21b334SDaniel Scheller 1430cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 1431cd21b334SDaniel Scheller /* FSTV0910_P2_MANUALSX_ROLLOFF, 1432cd21b334SDaniel Scheller * FSTV0910_P2_MANUALS2_ROLLOFF = 0 1433cd21b334SDaniel Scheller */ 1434cd21b334SDaniel Scheller state->demod_bits &= ~0x84; 1435cd21b334SDaniel Scheller write_reg(state, 1436cd21b334SDaniel Scheller RSTV0910_P2_DEMOD + state->regoff, 1437cd21b334SDaniel Scheller state->demod_bits); 1438cd21b334SDaniel Scheller read_reg(state, 1439cd21b334SDaniel Scheller RSTV0910_P2_PDELCTRL2 + state->regoff, 1440cd21b334SDaniel Scheller &tmp); 1441cd21b334SDaniel Scheller /*reset DVBS2 packet delinator error counter */ 1442cd21b334SDaniel Scheller tmp |= 0x40; 1443cd21b334SDaniel Scheller write_reg(state, 1444cd21b334SDaniel Scheller RSTV0910_P2_PDELCTRL2 + state->regoff, 1445cd21b334SDaniel Scheller tmp); 1446cd21b334SDaniel Scheller /*reset DVBS2 packet delinator error counter */ 1447cd21b334SDaniel Scheller tmp &= ~0x40; 1448cd21b334SDaniel Scheller write_reg(state, 1449cd21b334SDaniel Scheller RSTV0910_P2_PDELCTRL2 + state->regoff, 1450cd21b334SDaniel Scheller tmp); 1451cd21b334SDaniel Scheller 1452cd21b334SDaniel Scheller state->berscale = 2; 1453cd21b334SDaniel Scheller state->last_bernumerator = 0; 1454cd21b334SDaniel Scheller state->last_berdenominator = 1; 1455cd21b334SDaniel Scheller /* force to PRE BCH Rate */ 1456cd21b334SDaniel Scheller write_reg(state, 1457cd21b334SDaniel Scheller RSTV0910_P2_ERRCTRL1 + state->regoff, 1458cd21b334SDaniel Scheller BER_SRC_S2 | state->berscale); 1459cd21b334SDaniel Scheller } else { 1460cd21b334SDaniel Scheller state->berscale = 2; 1461cd21b334SDaniel Scheller state->last_bernumerator = 0; 1462cd21b334SDaniel Scheller state->last_berdenominator = 1; 1463cd21b334SDaniel Scheller /* force to PRE RS Rate */ 1464cd21b334SDaniel Scheller write_reg(state, 1465cd21b334SDaniel Scheller RSTV0910_P2_ERRCTRL1 + state->regoff, 1466cd21b334SDaniel Scheller BER_SRC_S | state->berscale); 1467cd21b334SDaniel Scheller } 1468cd21b334SDaniel Scheller /*Reset the Total packet counter */ 1469cd21b334SDaniel Scheller write_reg(state, 1470cd21b334SDaniel Scheller RSTV0910_P2_FBERCPT4 + state->regoff, 0x00); 1471cd21b334SDaniel Scheller /* Reset the packet Error counter2 (and Set it to 1472cd21b334SDaniel Scheller * infinit error count mode ) 1473cd21b334SDaniel Scheller */ 1474cd21b334SDaniel Scheller write_reg(state, 1475cd21b334SDaniel Scheller RSTV0910_P2_ERRCTRL2 + state->regoff, 0xc1); 1476cd21b334SDaniel Scheller 1477cd21b334SDaniel Scheller set_vth_default(state); 1478cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS) 1479cd21b334SDaniel Scheller enable_puncture_rate(state, 1480cd21b334SDaniel Scheller state->puncture_rate); 1481cd21b334SDaniel Scheller } 1482cd21b334SDaniel Scheller } 1483cd21b334SDaniel Scheller 1484cd21b334SDaniel Scheller /* read signal statistics */ 1485cd21b334SDaniel Scheller 1486cd21b334SDaniel Scheller /* read signal strength */ 1487cd21b334SDaniel Scheller read_signal_strength(fe); 1488cd21b334SDaniel Scheller 1489cd21b334SDaniel Scheller /* read carrier/noise on FE_HAS_CARRIER */ 1490cd21b334SDaniel Scheller if (*status & FE_HAS_CARRIER) 1491cd21b334SDaniel Scheller read_snr(fe); 1492cd21b334SDaniel Scheller else 1493cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1494cd21b334SDaniel Scheller 1495cd21b334SDaniel Scheller /* read ber */ 1496cd21b334SDaniel Scheller if (*status & FE_HAS_VITERBI) 1497cd21b334SDaniel Scheller read_ber(fe); 1498cd21b334SDaniel Scheller else { 1499cd21b334SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1500cd21b334SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1501cd21b334SDaniel Scheller } 1502cd21b334SDaniel Scheller 1503cd21b334SDaniel Scheller return 0; 1504cd21b334SDaniel Scheller } 1505cd21b334SDaniel Scheller 1506cd21b334SDaniel Scheller static int get_frontend(struct dvb_frontend *fe, 1507cd21b334SDaniel Scheller struct dtv_frontend_properties *p) 1508cd21b334SDaniel Scheller { 1509cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1510cd21b334SDaniel Scheller u8 tmp; 1511cd21b334SDaniel Scheller 1512cd21b334SDaniel Scheller if (state->receive_mode == RCVMODE_DVBS2) { 1513cd21b334SDaniel Scheller u32 mc; 1514cd21b334SDaniel Scheller enum fe_modulation modcod2mod[0x20] = { 1515cd21b334SDaniel Scheller QPSK, QPSK, QPSK, QPSK, 1516cd21b334SDaniel Scheller QPSK, QPSK, QPSK, QPSK, 1517cd21b334SDaniel Scheller QPSK, QPSK, QPSK, QPSK, 1518cd21b334SDaniel Scheller PSK_8, PSK_8, PSK_8, PSK_8, 1519cd21b334SDaniel Scheller PSK_8, PSK_8, APSK_16, APSK_16, 1520cd21b334SDaniel Scheller APSK_16, APSK_16, APSK_16, APSK_16, 1521cd21b334SDaniel Scheller APSK_32, APSK_32, APSK_32, APSK_32, 1522cd21b334SDaniel Scheller APSK_32, 1523cd21b334SDaniel Scheller }; 1524cd21b334SDaniel Scheller enum fe_code_rate modcod2fec[0x20] = { 1525cd21b334SDaniel Scheller FEC_NONE, FEC_NONE, FEC_NONE, FEC_2_5, 1526cd21b334SDaniel Scheller FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4, 1527cd21b334SDaniel Scheller FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10, 1528cd21b334SDaniel Scheller FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6, 1529cd21b334SDaniel Scheller FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4, 1530cd21b334SDaniel Scheller FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10, 1531cd21b334SDaniel Scheller FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9, 1532cd21b334SDaniel Scheller FEC_9_10 1533cd21b334SDaniel Scheller }; 1534cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); 1535cd21b334SDaniel Scheller mc = ((tmp & 0x7c) >> 2); 1536cd21b334SDaniel Scheller p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF; 1537cd21b334SDaniel Scheller p->modulation = modcod2mod[mc]; 1538cd21b334SDaniel Scheller p->fec_inner = modcod2fec[mc]; 1539cd21b334SDaniel Scheller } else if (state->receive_mode == RCVMODE_DVBS) { 1540cd21b334SDaniel Scheller read_reg(state, RSTV0910_P2_VITCURPUN + state->regoff, &tmp); 1541cd21b334SDaniel Scheller switch (tmp & 0x1F) { 1542cd21b334SDaniel Scheller case 0x0d: 1543cd21b334SDaniel Scheller p->fec_inner = FEC_1_2; 1544cd21b334SDaniel Scheller break; 1545cd21b334SDaniel Scheller case 0x12: 1546cd21b334SDaniel Scheller p->fec_inner = FEC_2_3; 1547cd21b334SDaniel Scheller break; 1548cd21b334SDaniel Scheller case 0x15: 1549cd21b334SDaniel Scheller p->fec_inner = FEC_3_4; 1550cd21b334SDaniel Scheller break; 1551cd21b334SDaniel Scheller case 0x18: 1552cd21b334SDaniel Scheller p->fec_inner = FEC_5_6; 1553cd21b334SDaniel Scheller break; 1554cd21b334SDaniel Scheller case 0x1a: 1555cd21b334SDaniel Scheller p->fec_inner = FEC_7_8; 1556cd21b334SDaniel Scheller break; 1557cd21b334SDaniel Scheller default: 1558cd21b334SDaniel Scheller p->fec_inner = FEC_NONE; 1559cd21b334SDaniel Scheller break; 1560cd21b334SDaniel Scheller } 1561cd21b334SDaniel Scheller p->rolloff = ROLLOFF_35; 1562cd21b334SDaniel Scheller } 1563cd21b334SDaniel Scheller 1564cd21b334SDaniel Scheller return 0; 1565cd21b334SDaniel Scheller } 1566cd21b334SDaniel Scheller 1567cd21b334SDaniel Scheller static int tune(struct dvb_frontend *fe, bool re_tune, 1568cd21b334SDaniel Scheller unsigned int mode_flags, 1569cd21b334SDaniel Scheller unsigned int *delay, enum fe_status *status) 1570cd21b334SDaniel Scheller { 1571cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1572cd21b334SDaniel Scheller int r; 1573cd21b334SDaniel Scheller 1574cd21b334SDaniel Scheller if (re_tune) { 1575cd21b334SDaniel Scheller r = set_parameters(fe); 1576cd21b334SDaniel Scheller if (r) 1577cd21b334SDaniel Scheller return r; 1578cd21b334SDaniel Scheller state->tune_time = jiffies; 1579cd21b334SDaniel Scheller } 1580cd21b334SDaniel Scheller if (*status & FE_HAS_LOCK) 1581cd21b334SDaniel Scheller return 0; 1582cd21b334SDaniel Scheller *delay = HZ; 1583cd21b334SDaniel Scheller 1584cd21b334SDaniel Scheller r = read_status(fe, status); 1585cd21b334SDaniel Scheller if (r) 1586cd21b334SDaniel Scheller return r; 1587cd21b334SDaniel Scheller return 0; 1588cd21b334SDaniel Scheller } 1589cd21b334SDaniel Scheller 1590cd21b334SDaniel Scheller 1591cd21b334SDaniel Scheller static int get_algo(struct dvb_frontend *fe) 1592cd21b334SDaniel Scheller { 1593cd21b334SDaniel Scheller return DVBFE_ALGO_HW; 1594cd21b334SDaniel Scheller } 1595cd21b334SDaniel Scheller 1596cd21b334SDaniel Scheller static int set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) 1597cd21b334SDaniel Scheller { 1598cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1599cd21b334SDaniel Scheller u16 offs = state->nr ? 0x40 : 0; 1600cd21b334SDaniel Scheller 1601cd21b334SDaniel Scheller switch (tone) { 1602cd21b334SDaniel Scheller case SEC_TONE_ON: 1603cd21b334SDaniel Scheller return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x38); 1604cd21b334SDaniel Scheller case SEC_TONE_OFF: 1605cd21b334SDaniel Scheller return write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3a); 1606cd21b334SDaniel Scheller default: 1607cd21b334SDaniel Scheller break; 1608cd21b334SDaniel Scheller } 1609cd21b334SDaniel Scheller return -EINVAL; 1610cd21b334SDaniel Scheller } 1611cd21b334SDaniel Scheller 1612cd21b334SDaniel Scheller static int wait_dis(struct stv *state, u8 flag, u8 val) 1613cd21b334SDaniel Scheller { 1614cd21b334SDaniel Scheller int i; 1615cd21b334SDaniel Scheller u8 stat; 1616cd21b334SDaniel Scheller u16 offs = state->nr ? 0x40 : 0; 1617cd21b334SDaniel Scheller 1618cd21b334SDaniel Scheller for (i = 0; i < 10; i++) { 1619cd21b334SDaniel Scheller read_reg(state, RSTV0910_P1_DISTXSTATUS + offs, &stat); 1620cd21b334SDaniel Scheller if ((stat & flag) == val) 1621cd21b334SDaniel Scheller return 0; 1622cd21b334SDaniel Scheller usleep_range(10000, 11000); 1623cd21b334SDaniel Scheller } 1624cd21b334SDaniel Scheller return -ETIMEDOUT; 1625cd21b334SDaniel Scheller } 1626cd21b334SDaniel Scheller 1627cd21b334SDaniel Scheller static int send_master_cmd(struct dvb_frontend *fe, 1628cd21b334SDaniel Scheller struct dvb_diseqc_master_cmd *cmd) 1629cd21b334SDaniel Scheller { 1630cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1631cd21b334SDaniel Scheller u16 offs = state->nr ? 0x40 : 0; 1632cd21b334SDaniel Scheller int i; 1633cd21b334SDaniel Scheller 1634cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3E); 1635cd21b334SDaniel Scheller for (i = 0; i < cmd->msg_len; i++) { 1636cd21b334SDaniel Scheller wait_dis(state, 0x40, 0x00); 1637cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXFIFO + offs, cmd->msg[i]); 1638cd21b334SDaniel Scheller } 1639cd21b334SDaniel Scheller write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); 1640cd21b334SDaniel Scheller wait_dis(state, 0x20, 0x20); 1641cd21b334SDaniel Scheller return 0; 1642cd21b334SDaniel Scheller } 1643cd21b334SDaniel Scheller 1644cd21b334SDaniel Scheller static int sleep(struct dvb_frontend *fe) 1645cd21b334SDaniel Scheller { 1646cd21b334SDaniel Scheller struct stv *state = fe->demodulator_priv; 1647cd21b334SDaniel Scheller 1648cd21b334SDaniel Scheller stop(state); 1649cd21b334SDaniel Scheller return 0; 1650cd21b334SDaniel Scheller } 1651cd21b334SDaniel Scheller 1652cd21b334SDaniel Scheller static struct dvb_frontend_ops stv0910_ops = { 1653cd21b334SDaniel Scheller .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, 1654cd21b334SDaniel Scheller .info = { 1655cd21b334SDaniel Scheller .name = "STV0910", 1656cd21b334SDaniel Scheller .frequency_min = 950000, 1657cd21b334SDaniel Scheller .frequency_max = 2150000, 1658cd21b334SDaniel Scheller .frequency_stepsize = 0, 1659cd21b334SDaniel Scheller .frequency_tolerance = 0, 1660cd21b334SDaniel Scheller .symbol_rate_min = 1000000, 1661cd21b334SDaniel Scheller .symbol_rate_max = 70000000, 1662cd21b334SDaniel Scheller .caps = FE_CAN_INVERSION_AUTO | 1663cd21b334SDaniel Scheller FE_CAN_FEC_AUTO | 1664cd21b334SDaniel Scheller FE_CAN_QPSK | 1665ea71c62bSDaniel Scheller FE_CAN_2G_MODULATION | 1666ea71c62bSDaniel Scheller FE_CAN_MULTISTREAM 1667cd21b334SDaniel Scheller }, 1668cd21b334SDaniel Scheller .sleep = sleep, 1669cd21b334SDaniel Scheller .release = release, 1670cd21b334SDaniel Scheller .i2c_gate_ctrl = gate_ctrl, 16712f4675c0SDaniel Scheller .set_frontend = set_parameters, 1672cd21b334SDaniel Scheller .get_frontend_algo = get_algo, 1673cd21b334SDaniel Scheller .get_frontend = get_frontend, 1674cd21b334SDaniel Scheller .tune = tune, 1675cd21b334SDaniel Scheller .read_status = read_status, 1676cd21b334SDaniel Scheller .set_tone = set_tone, 1677cd21b334SDaniel Scheller 1678cd21b334SDaniel Scheller .diseqc_send_master_cmd = send_master_cmd, 1679cd21b334SDaniel Scheller }; 1680cd21b334SDaniel Scheller 1681cd21b334SDaniel Scheller static struct stv_base *match_base(struct i2c_adapter *i2c, u8 adr) 1682cd21b334SDaniel Scheller { 1683cd21b334SDaniel Scheller struct stv_base *p; 1684cd21b334SDaniel Scheller 1685cd21b334SDaniel Scheller list_for_each_entry(p, &stvlist, stvlist) 1686cd21b334SDaniel Scheller if (p->i2c == i2c && p->adr == adr) 1687cd21b334SDaniel Scheller return p; 1688cd21b334SDaniel Scheller return NULL; 1689cd21b334SDaniel Scheller } 1690cd21b334SDaniel Scheller 1691cd21b334SDaniel Scheller static void stv0910_init_stats(struct stv *state) 1692cd21b334SDaniel Scheller { 1693cd21b334SDaniel Scheller struct dtv_frontend_properties *p = &state->fe.dtv_property_cache; 1694cd21b334SDaniel Scheller 1695cd21b334SDaniel Scheller p->strength.len = 1; 1696cd21b334SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1697cd21b334SDaniel Scheller p->cnr.len = 1; 1698cd21b334SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1699cd21b334SDaniel Scheller p->pre_bit_error.len = 1; 1700cd21b334SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1701cd21b334SDaniel Scheller p->pre_bit_count.len = 1; 1702cd21b334SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1703cd21b334SDaniel Scheller } 1704cd21b334SDaniel Scheller 1705cd21b334SDaniel Scheller struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c, 1706cd21b334SDaniel Scheller struct stv0910_cfg *cfg, 1707cd21b334SDaniel Scheller int nr) 1708cd21b334SDaniel Scheller { 1709cd21b334SDaniel Scheller struct stv *state; 1710cd21b334SDaniel Scheller struct stv_base *base; 1711cd21b334SDaniel Scheller 1712cd21b334SDaniel Scheller state = kzalloc(sizeof(struct stv), GFP_KERNEL); 1713cd21b334SDaniel Scheller if (!state) 1714cd21b334SDaniel Scheller return NULL; 1715cd21b334SDaniel Scheller 1716cd21b334SDaniel Scheller state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40); 1717cd21b334SDaniel Scheller state->tsgeneral = (cfg->parallel == 2) ? 0x02 : 0x00; 1718cd21b334SDaniel Scheller state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4); 1719cd21b334SDaniel Scheller state->tsspeed = 0x28; 1720cd21b334SDaniel Scheller state->nr = nr; 1721cd21b334SDaniel Scheller state->regoff = state->nr ? 0 : 0x200; 1722cd21b334SDaniel Scheller state->search_range = 16000000; 1723cd21b334SDaniel Scheller state->demod_bits = 0x10; /* Inversion : Auto with reset to 0 */ 1724cd21b334SDaniel Scheller state->receive_mode = RCVMODE_NONE; 1725ea71c62bSDaniel Scheller state->cur_scrambling_code = (~0U); 1726cd21b334SDaniel Scheller state->single = cfg->single ? 1 : 0; 1727cd21b334SDaniel Scheller 1728cd21b334SDaniel Scheller base = match_base(i2c, cfg->adr); 1729cd21b334SDaniel Scheller if (base) { 1730cd21b334SDaniel Scheller base->count++; 1731cd21b334SDaniel Scheller state->base = base; 1732cd21b334SDaniel Scheller } else { 1733cd21b334SDaniel Scheller base = kzalloc(sizeof(struct stv_base), GFP_KERNEL); 1734cd21b334SDaniel Scheller if (!base) 1735cd21b334SDaniel Scheller goto fail; 1736cd21b334SDaniel Scheller base->i2c = i2c; 1737cd21b334SDaniel Scheller base->adr = cfg->adr; 1738cd21b334SDaniel Scheller base->count = 1; 1739cd21b334SDaniel Scheller base->extclk = cfg->clk ? cfg->clk : 30000000; 1740cd21b334SDaniel Scheller 1741cd21b334SDaniel Scheller mutex_init(&base->i2c_lock); 1742cd21b334SDaniel Scheller mutex_init(&base->reg_lock); 1743cd21b334SDaniel Scheller state->base = base; 1744cd21b334SDaniel Scheller if (probe(state) < 0) { 1745cd21b334SDaniel Scheller dev_info(&i2c->dev, "No demod found at adr %02X on %s\n", 1746cd21b334SDaniel Scheller cfg->adr, dev_name(&i2c->dev)); 1747cd21b334SDaniel Scheller kfree(base); 1748cd21b334SDaniel Scheller goto fail; 1749cd21b334SDaniel Scheller } 1750cd21b334SDaniel Scheller list_add(&base->stvlist, &stvlist); 1751cd21b334SDaniel Scheller } 1752cd21b334SDaniel Scheller state->fe.ops = stv0910_ops; 1753cd21b334SDaniel Scheller state->fe.demodulator_priv = state; 1754cd21b334SDaniel Scheller state->nr = nr; 1755cd21b334SDaniel Scheller 1756cd21b334SDaniel Scheller dev_info(&i2c->dev, "%s demod found at adr %02X on %s\n", 1757cd21b334SDaniel Scheller state->fe.ops.info.name, cfg->adr, dev_name(&i2c->dev)); 1758cd21b334SDaniel Scheller 1759cd21b334SDaniel Scheller stv0910_init_stats(state); 1760cd21b334SDaniel Scheller 1761cd21b334SDaniel Scheller return &state->fe; 1762cd21b334SDaniel Scheller 1763cd21b334SDaniel Scheller fail: 1764cd21b334SDaniel Scheller kfree(state); 1765cd21b334SDaniel Scheller return NULL; 1766cd21b334SDaniel Scheller } 1767cd21b334SDaniel Scheller EXPORT_SYMBOL_GPL(stv0910_attach); 1768cd21b334SDaniel Scheller 1769cd21b334SDaniel Scheller MODULE_DESCRIPTION("ST STV0910 multistandard frontend driver"); 1770cd21b334SDaniel Scheller MODULE_AUTHOR("Ralph and Marcus Metzler, Manfred Voelkel"); 1771cd21b334SDaniel Scheller MODULE_LICENSE("GPL"); 1772