1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2010-2013 Mauro Carvalho Chehab
6*4882a593Smuzhiyun * Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <asm/div64.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <media/dvb_frontend.h>
13*4882a593Smuzhiyun #include "mb86a20s.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define NUM_LAYERS 3
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun enum mb86a20s_bandwidth {
18*4882a593Smuzhiyun MB86A20S_13SEG = 0,
19*4882a593Smuzhiyun MB86A20S_13SEG_PARTIAL = 1,
20*4882a593Smuzhiyun MB86A20S_1SEG = 2,
21*4882a593Smuzhiyun MB86A20S_3SEG = 3,
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static u8 mb86a20s_subchannel[] = {
25*4882a593Smuzhiyun 0xb0, 0xc0, 0xd0, 0xe0,
26*4882a593Smuzhiyun 0xf0, 0x00, 0x10, 0x20,
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun struct mb86a20s_state {
30*4882a593Smuzhiyun struct i2c_adapter *i2c;
31*4882a593Smuzhiyun const struct mb86a20s_config *config;
32*4882a593Smuzhiyun u32 last_frequency;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun struct dvb_frontend frontend;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun u32 if_freq;
37*4882a593Smuzhiyun enum mb86a20s_bandwidth bw;
38*4882a593Smuzhiyun bool inversion;
39*4882a593Smuzhiyun u32 subchannel;
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun u32 estimated_rate[NUM_LAYERS];
42*4882a593Smuzhiyun unsigned long get_strength_time;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun bool need_init;
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun struct regdata {
48*4882a593Smuzhiyun u8 reg;
49*4882a593Smuzhiyun u8 data;
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun #define BER_SAMPLING_RATE 1 /* Seconds */
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /*
55*4882a593Smuzhiyun * Initialization sequence: Use whatevere default values that PV SBTVD
56*4882a593Smuzhiyun * does on its initialisation, obtained via USB snoop
57*4882a593Smuzhiyun */
58*4882a593Smuzhiyun static struct regdata mb86a20s_init1[] = {
59*4882a593Smuzhiyun { 0x70, 0x0f },
60*4882a593Smuzhiyun { 0x70, 0xff },
61*4882a593Smuzhiyun { 0x08, 0x01 },
62*4882a593Smuzhiyun { 0x50, 0xd1 }, { 0x51, 0x20 },
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun static struct regdata mb86a20s_init2[] = {
66*4882a593Smuzhiyun { 0x50, 0xd1 }, { 0x51, 0x22 },
67*4882a593Smuzhiyun { 0x39, 0x01 },
68*4882a593Smuzhiyun { 0x71, 0x00 },
69*4882a593Smuzhiyun { 0x3b, 0x21 },
70*4882a593Smuzhiyun { 0x3c, 0x3a },
71*4882a593Smuzhiyun { 0x01, 0x0d },
72*4882a593Smuzhiyun { 0x04, 0x08 }, { 0x05, 0x05 },
73*4882a593Smuzhiyun { 0x04, 0x0e }, { 0x05, 0x00 },
74*4882a593Smuzhiyun { 0x04, 0x0f }, { 0x05, 0x14 },
75*4882a593Smuzhiyun { 0x04, 0x0b }, { 0x05, 0x8c },
76*4882a593Smuzhiyun { 0x04, 0x00 }, { 0x05, 0x00 },
77*4882a593Smuzhiyun { 0x04, 0x01 }, { 0x05, 0x07 },
78*4882a593Smuzhiyun { 0x04, 0x02 }, { 0x05, 0x0f },
79*4882a593Smuzhiyun { 0x04, 0x03 }, { 0x05, 0xa0 },
80*4882a593Smuzhiyun { 0x04, 0x09 }, { 0x05, 0x00 },
81*4882a593Smuzhiyun { 0x04, 0x0a }, { 0x05, 0xff },
82*4882a593Smuzhiyun { 0x04, 0x27 }, { 0x05, 0x64 },
83*4882a593Smuzhiyun { 0x04, 0x28 }, { 0x05, 0x00 },
84*4882a593Smuzhiyun { 0x04, 0x1e }, { 0x05, 0xff },
85*4882a593Smuzhiyun { 0x04, 0x29 }, { 0x05, 0x0a },
86*4882a593Smuzhiyun { 0x04, 0x32 }, { 0x05, 0x0a },
87*4882a593Smuzhiyun { 0x04, 0x14 }, { 0x05, 0x02 },
88*4882a593Smuzhiyun { 0x04, 0x04 }, { 0x05, 0x00 },
89*4882a593Smuzhiyun { 0x04, 0x05 }, { 0x05, 0x22 },
90*4882a593Smuzhiyun { 0x04, 0x06 }, { 0x05, 0x0e },
91*4882a593Smuzhiyun { 0x04, 0x07 }, { 0x05, 0xd8 },
92*4882a593Smuzhiyun { 0x04, 0x12 }, { 0x05, 0x00 },
93*4882a593Smuzhiyun { 0x04, 0x13 }, { 0x05, 0xff },
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun * On this demod, when the bit count reaches the count below,
97*4882a593Smuzhiyun * it collects the bit error count. The bit counters are initialized
98*4882a593Smuzhiyun * to 65535 here. This warrants that all of them will be quickly
99*4882a593Smuzhiyun * calculated when device gets locked. As TMCC is parsed, the values
100*4882a593Smuzhiyun * will be adjusted later in the driver's code.
101*4882a593Smuzhiyun */
102*4882a593Smuzhiyun { 0x52, 0x01 }, /* Turn on BER before Viterbi */
103*4882a593Smuzhiyun { 0x50, 0xa7 }, { 0x51, 0x00 },
104*4882a593Smuzhiyun { 0x50, 0xa8 }, { 0x51, 0xff },
105*4882a593Smuzhiyun { 0x50, 0xa9 }, { 0x51, 0xff },
106*4882a593Smuzhiyun { 0x50, 0xaa }, { 0x51, 0x00 },
107*4882a593Smuzhiyun { 0x50, 0xab }, { 0x51, 0xff },
108*4882a593Smuzhiyun { 0x50, 0xac }, { 0x51, 0xff },
109*4882a593Smuzhiyun { 0x50, 0xad }, { 0x51, 0x00 },
110*4882a593Smuzhiyun { 0x50, 0xae }, { 0x51, 0xff },
111*4882a593Smuzhiyun { 0x50, 0xaf }, { 0x51, 0xff },
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /*
114*4882a593Smuzhiyun * On this demod, post BER counts blocks. When the count reaches the
115*4882a593Smuzhiyun * value below, it collects the block error count. The block counters
116*4882a593Smuzhiyun * are initialized to 127 here. This warrants that all of them will be
117*4882a593Smuzhiyun * quickly calculated when device gets locked. As TMCC is parsed, the
118*4882a593Smuzhiyun * values will be adjusted later in the driver's code.
119*4882a593Smuzhiyun */
120*4882a593Smuzhiyun { 0x5e, 0x07 }, /* Turn on BER after Viterbi */
121*4882a593Smuzhiyun { 0x50, 0xdc }, { 0x51, 0x00 },
122*4882a593Smuzhiyun { 0x50, 0xdd }, { 0x51, 0x7f },
123*4882a593Smuzhiyun { 0x50, 0xde }, { 0x51, 0x00 },
124*4882a593Smuzhiyun { 0x50, 0xdf }, { 0x51, 0x7f },
125*4882a593Smuzhiyun { 0x50, 0xe0 }, { 0x51, 0x00 },
126*4882a593Smuzhiyun { 0x50, 0xe1 }, { 0x51, 0x7f },
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun /*
129*4882a593Smuzhiyun * On this demod, when the block count reaches the count below,
130*4882a593Smuzhiyun * it collects the block error count. The block counters are initialized
131*4882a593Smuzhiyun * to 127 here. This warrants that all of them will be quickly
132*4882a593Smuzhiyun * calculated when device gets locked. As TMCC is parsed, the values
133*4882a593Smuzhiyun * will be adjusted later in the driver's code.
134*4882a593Smuzhiyun */
135*4882a593Smuzhiyun { 0x50, 0xb0 }, { 0x51, 0x07 }, /* Enable PER */
136*4882a593Smuzhiyun { 0x50, 0xb2 }, { 0x51, 0x00 },
137*4882a593Smuzhiyun { 0x50, 0xb3 }, { 0x51, 0x7f },
138*4882a593Smuzhiyun { 0x50, 0xb4 }, { 0x51, 0x00 },
139*4882a593Smuzhiyun { 0x50, 0xb5 }, { 0x51, 0x7f },
140*4882a593Smuzhiyun { 0x50, 0xb6 }, { 0x51, 0x00 },
141*4882a593Smuzhiyun { 0x50, 0xb7 }, { 0x51, 0x7f },
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun { 0x50, 0x50 }, { 0x51, 0x02 }, /* MER manual mode */
144*4882a593Smuzhiyun { 0x50, 0x51 }, { 0x51, 0x04 }, /* MER symbol 4 */
145*4882a593Smuzhiyun { 0x45, 0x04 }, /* CN symbol 4 */
146*4882a593Smuzhiyun { 0x48, 0x04 }, /* CN manual mode */
147*4882a593Smuzhiyun { 0x50, 0xd5 }, { 0x51, 0x01 },
148*4882a593Smuzhiyun { 0x50, 0xd6 }, { 0x51, 0x1f },
149*4882a593Smuzhiyun { 0x50, 0xd2 }, { 0x51, 0x03 },
150*4882a593Smuzhiyun { 0x50, 0xd7 }, { 0x51, 0x3f },
151*4882a593Smuzhiyun { 0x1c, 0x01 },
152*4882a593Smuzhiyun { 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
153*4882a593Smuzhiyun { 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
154*4882a593Smuzhiyun { 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
155*4882a593Smuzhiyun { 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
156*4882a593Smuzhiyun { 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
157*4882a593Smuzhiyun { 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
158*4882a593Smuzhiyun { 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
159*4882a593Smuzhiyun { 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
160*4882a593Smuzhiyun { 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
161*4882a593Smuzhiyun { 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
162*4882a593Smuzhiyun { 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
163*4882a593Smuzhiyun { 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
164*4882a593Smuzhiyun { 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
165*4882a593Smuzhiyun { 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
166*4882a593Smuzhiyun { 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
167*4882a593Smuzhiyun { 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
168*4882a593Smuzhiyun { 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
169*4882a593Smuzhiyun { 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
170*4882a593Smuzhiyun { 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
171*4882a593Smuzhiyun { 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
172*4882a593Smuzhiyun { 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
173*4882a593Smuzhiyun { 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
174*4882a593Smuzhiyun { 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
175*4882a593Smuzhiyun { 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
176*4882a593Smuzhiyun { 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
177*4882a593Smuzhiyun { 0x50, 0x1e }, { 0x51, 0x5d },
178*4882a593Smuzhiyun { 0x50, 0x22 }, { 0x51, 0x00 },
179*4882a593Smuzhiyun { 0x50, 0x23 }, { 0x51, 0xc8 },
180*4882a593Smuzhiyun { 0x50, 0x24 }, { 0x51, 0x00 },
181*4882a593Smuzhiyun { 0x50, 0x25 }, { 0x51, 0xf0 },
182*4882a593Smuzhiyun { 0x50, 0x26 }, { 0x51, 0x00 },
183*4882a593Smuzhiyun { 0x50, 0x27 }, { 0x51, 0xc3 },
184*4882a593Smuzhiyun { 0x50, 0x39 }, { 0x51, 0x02 },
185*4882a593Smuzhiyun { 0x50, 0xd5 }, { 0x51, 0x01 },
186*4882a593Smuzhiyun { 0xd0, 0x00 },
187*4882a593Smuzhiyun };
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun static struct regdata mb86a20s_reset_reception[] = {
190*4882a593Smuzhiyun { 0x70, 0xf0 },
191*4882a593Smuzhiyun { 0x70, 0xff },
192*4882a593Smuzhiyun { 0x08, 0x01 },
193*4882a593Smuzhiyun { 0x08, 0x00 },
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun static struct regdata mb86a20s_per_ber_reset[] = {
197*4882a593Smuzhiyun { 0x53, 0x00 }, /* pre BER Counter reset */
198*4882a593Smuzhiyun { 0x53, 0x07 },
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun { 0x5f, 0x00 }, /* post BER Counter reset */
201*4882a593Smuzhiyun { 0x5f, 0x07 },
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun { 0x50, 0xb1 }, /* PER Counter reset */
204*4882a593Smuzhiyun { 0x51, 0x07 },
205*4882a593Smuzhiyun { 0x51, 0x00 },
206*4882a593Smuzhiyun };
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /*
209*4882a593Smuzhiyun * I2C read/write functions and macros
210*4882a593Smuzhiyun */
211*4882a593Smuzhiyun
mb86a20s_i2c_writereg(struct mb86a20s_state * state,u8 i2c_addr,u8 reg,u8 data)212*4882a593Smuzhiyun static int mb86a20s_i2c_writereg(struct mb86a20s_state *state,
213*4882a593Smuzhiyun u8 i2c_addr, u8 reg, u8 data)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun u8 buf[] = { reg, data };
216*4882a593Smuzhiyun struct i2c_msg msg = {
217*4882a593Smuzhiyun .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
218*4882a593Smuzhiyun };
219*4882a593Smuzhiyun int rc;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun rc = i2c_transfer(state->i2c, &msg, 1);
222*4882a593Smuzhiyun if (rc != 1) {
223*4882a593Smuzhiyun dev_err(&state->i2c->dev,
224*4882a593Smuzhiyun "%s: writereg error (rc == %i, reg == 0x%02x, data == 0x%02x)\n",
225*4882a593Smuzhiyun __func__, rc, reg, data);
226*4882a593Smuzhiyun return rc;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return 0;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
mb86a20s_i2c_writeregdata(struct mb86a20s_state * state,u8 i2c_addr,struct regdata * rd,int size)232*4882a593Smuzhiyun static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state,
233*4882a593Smuzhiyun u8 i2c_addr, struct regdata *rd, int size)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun int i, rc;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun for (i = 0; i < size; i++) {
238*4882a593Smuzhiyun rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg,
239*4882a593Smuzhiyun rd[i].data);
240*4882a593Smuzhiyun if (rc < 0)
241*4882a593Smuzhiyun return rc;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun return 0;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
mb86a20s_i2c_readreg(struct mb86a20s_state * state,u8 i2c_addr,u8 reg)246*4882a593Smuzhiyun static int mb86a20s_i2c_readreg(struct mb86a20s_state *state,
247*4882a593Smuzhiyun u8 i2c_addr, u8 reg)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun u8 val;
250*4882a593Smuzhiyun int rc;
251*4882a593Smuzhiyun struct i2c_msg msg[] = {
252*4882a593Smuzhiyun { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 },
253*4882a593Smuzhiyun { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
254*4882a593Smuzhiyun };
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun rc = i2c_transfer(state->i2c, msg, 2);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (rc != 2) {
259*4882a593Smuzhiyun dev_err(&state->i2c->dev, "%s: reg=0x%x (error=%d)\n",
260*4882a593Smuzhiyun __func__, reg, rc);
261*4882a593Smuzhiyun return (rc < 0) ? rc : -EIO;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun return val;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun #define mb86a20s_readreg(state, reg) \
268*4882a593Smuzhiyun mb86a20s_i2c_readreg(state, state->config->demod_address, reg)
269*4882a593Smuzhiyun #define mb86a20s_writereg(state, reg, val) \
270*4882a593Smuzhiyun mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val)
271*4882a593Smuzhiyun #define mb86a20s_writeregdata(state, regdata) \
272*4882a593Smuzhiyun mb86a20s_i2c_writeregdata(state, state->config->demod_address, \
273*4882a593Smuzhiyun regdata, ARRAY_SIZE(regdata))
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /*
276*4882a593Smuzhiyun * Ancillary internal routines (likely compiled inlined)
277*4882a593Smuzhiyun *
278*4882a593Smuzhiyun * The functions below assume that gateway lock has already obtained
279*4882a593Smuzhiyun */
280*4882a593Smuzhiyun
mb86a20s_read_status(struct dvb_frontend * fe,enum fe_status * status)281*4882a593Smuzhiyun static int mb86a20s_read_status(struct dvb_frontend *fe, enum fe_status *status)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
284*4882a593Smuzhiyun int val;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun *status = 0;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun val = mb86a20s_readreg(state, 0x0a);
289*4882a593Smuzhiyun if (val < 0)
290*4882a593Smuzhiyun return val;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun val &= 0xf;
293*4882a593Smuzhiyun if (val >= 2)
294*4882a593Smuzhiyun *status |= FE_HAS_SIGNAL;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun if (val >= 4)
297*4882a593Smuzhiyun *status |= FE_HAS_CARRIER;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun if (val >= 5)
300*4882a593Smuzhiyun *status |= FE_HAS_VITERBI;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun if (val >= 7)
303*4882a593Smuzhiyun *status |= FE_HAS_SYNC;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun /*
306*4882a593Smuzhiyun * Actually, on state S8, it starts receiving TS, but the TS
307*4882a593Smuzhiyun * output is only on normal state after the transition to S9.
308*4882a593Smuzhiyun */
309*4882a593Smuzhiyun if (val >= 9)
310*4882a593Smuzhiyun *status |= FE_HAS_LOCK;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: Status = 0x%02x (state = %d)\n",
313*4882a593Smuzhiyun __func__, *status, val);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun return val;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
mb86a20s_read_signal_strength(struct dvb_frontend * fe)318*4882a593Smuzhiyun static int mb86a20s_read_signal_strength(struct dvb_frontend *fe)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
321*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
322*4882a593Smuzhiyun int rc;
323*4882a593Smuzhiyun unsigned rf_max, rf_min, rf;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (state->get_strength_time &&
326*4882a593Smuzhiyun (!time_after(jiffies, state->get_strength_time)))
327*4882a593Smuzhiyun return c->strength.stat[0].uvalue;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /* Reset its value if an error happen */
330*4882a593Smuzhiyun c->strength.stat[0].uvalue = 0;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun /* Does a binary search to get RF strength */
333*4882a593Smuzhiyun rf_max = 0xfff;
334*4882a593Smuzhiyun rf_min = 0;
335*4882a593Smuzhiyun do {
336*4882a593Smuzhiyun rf = (rf_max + rf_min) / 2;
337*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x04, 0x1f);
338*4882a593Smuzhiyun if (rc < 0)
339*4882a593Smuzhiyun return rc;
340*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x05, rf >> 8);
341*4882a593Smuzhiyun if (rc < 0)
342*4882a593Smuzhiyun return rc;
343*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x04, 0x20);
344*4882a593Smuzhiyun if (rc < 0)
345*4882a593Smuzhiyun return rc;
346*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x05, rf);
347*4882a593Smuzhiyun if (rc < 0)
348*4882a593Smuzhiyun return rc;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x02);
351*4882a593Smuzhiyun if (rc < 0)
352*4882a593Smuzhiyun return rc;
353*4882a593Smuzhiyun if (rc & 0x08)
354*4882a593Smuzhiyun rf_min = (rf_max + rf_min) / 2;
355*4882a593Smuzhiyun else
356*4882a593Smuzhiyun rf_max = (rf_max + rf_min) / 2;
357*4882a593Smuzhiyun if (rf_max - rf_min < 4) {
358*4882a593Smuzhiyun rf = (rf_max + rf_min) / 2;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun /* Rescale it from 2^12 (4096) to 2^16 */
361*4882a593Smuzhiyun rf = rf << (16 - 12);
362*4882a593Smuzhiyun if (rf)
363*4882a593Smuzhiyun rf |= (1 << 12) - 1;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
366*4882a593Smuzhiyun "%s: signal strength = %d (%d < RF=%d < %d)\n",
367*4882a593Smuzhiyun __func__, rf, rf_min, rf >> 4, rf_max);
368*4882a593Smuzhiyun c->strength.stat[0].uvalue = rf;
369*4882a593Smuzhiyun state->get_strength_time = jiffies +
370*4882a593Smuzhiyun msecs_to_jiffies(1000);
371*4882a593Smuzhiyun return 0;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun } while (1);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
mb86a20s_get_modulation(struct mb86a20s_state * state,unsigned layer)376*4882a593Smuzhiyun static int mb86a20s_get_modulation(struct mb86a20s_state *state,
377*4882a593Smuzhiyun unsigned layer)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun int rc;
380*4882a593Smuzhiyun static unsigned char reg[] = {
381*4882a593Smuzhiyun [0] = 0x86, /* Layer A */
382*4882a593Smuzhiyun [1] = 0x8a, /* Layer B */
383*4882a593Smuzhiyun [2] = 0x8e, /* Layer C */
384*4882a593Smuzhiyun };
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun if (layer >= ARRAY_SIZE(reg))
387*4882a593Smuzhiyun return -EINVAL;
388*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
389*4882a593Smuzhiyun if (rc < 0)
390*4882a593Smuzhiyun return rc;
391*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x6e);
392*4882a593Smuzhiyun if (rc < 0)
393*4882a593Smuzhiyun return rc;
394*4882a593Smuzhiyun switch ((rc >> 4) & 0x07) {
395*4882a593Smuzhiyun case 0:
396*4882a593Smuzhiyun return DQPSK;
397*4882a593Smuzhiyun case 1:
398*4882a593Smuzhiyun return QPSK;
399*4882a593Smuzhiyun case 2:
400*4882a593Smuzhiyun return QAM_16;
401*4882a593Smuzhiyun case 3:
402*4882a593Smuzhiyun return QAM_64;
403*4882a593Smuzhiyun default:
404*4882a593Smuzhiyun return QAM_AUTO;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
mb86a20s_get_fec(struct mb86a20s_state * state,unsigned layer)408*4882a593Smuzhiyun static int mb86a20s_get_fec(struct mb86a20s_state *state,
409*4882a593Smuzhiyun unsigned layer)
410*4882a593Smuzhiyun {
411*4882a593Smuzhiyun int rc;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun static unsigned char reg[] = {
414*4882a593Smuzhiyun [0] = 0x87, /* Layer A */
415*4882a593Smuzhiyun [1] = 0x8b, /* Layer B */
416*4882a593Smuzhiyun [2] = 0x8f, /* Layer C */
417*4882a593Smuzhiyun };
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun if (layer >= ARRAY_SIZE(reg))
420*4882a593Smuzhiyun return -EINVAL;
421*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
422*4882a593Smuzhiyun if (rc < 0)
423*4882a593Smuzhiyun return rc;
424*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x6e);
425*4882a593Smuzhiyun if (rc < 0)
426*4882a593Smuzhiyun return rc;
427*4882a593Smuzhiyun switch ((rc >> 4) & 0x07) {
428*4882a593Smuzhiyun case 0:
429*4882a593Smuzhiyun return FEC_1_2;
430*4882a593Smuzhiyun case 1:
431*4882a593Smuzhiyun return FEC_2_3;
432*4882a593Smuzhiyun case 2:
433*4882a593Smuzhiyun return FEC_3_4;
434*4882a593Smuzhiyun case 3:
435*4882a593Smuzhiyun return FEC_5_6;
436*4882a593Smuzhiyun case 4:
437*4882a593Smuzhiyun return FEC_7_8;
438*4882a593Smuzhiyun default:
439*4882a593Smuzhiyun return FEC_AUTO;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
mb86a20s_get_interleaving(struct mb86a20s_state * state,unsigned layer)443*4882a593Smuzhiyun static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
444*4882a593Smuzhiyun unsigned layer)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun int rc;
447*4882a593Smuzhiyun int interleaving[] = {
448*4882a593Smuzhiyun 0, 1, 2, 4, 8
449*4882a593Smuzhiyun };
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun static unsigned char reg[] = {
452*4882a593Smuzhiyun [0] = 0x88, /* Layer A */
453*4882a593Smuzhiyun [1] = 0x8c, /* Layer B */
454*4882a593Smuzhiyun [2] = 0x90, /* Layer C */
455*4882a593Smuzhiyun };
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun if (layer >= ARRAY_SIZE(reg))
458*4882a593Smuzhiyun return -EINVAL;
459*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
460*4882a593Smuzhiyun if (rc < 0)
461*4882a593Smuzhiyun return rc;
462*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x6e);
463*4882a593Smuzhiyun if (rc < 0)
464*4882a593Smuzhiyun return rc;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun return interleaving[(rc >> 4) & 0x07];
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
mb86a20s_get_segment_count(struct mb86a20s_state * state,unsigned layer)469*4882a593Smuzhiyun static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
470*4882a593Smuzhiyun unsigned layer)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun int rc, count;
473*4882a593Smuzhiyun static unsigned char reg[] = {
474*4882a593Smuzhiyun [0] = 0x89, /* Layer A */
475*4882a593Smuzhiyun [1] = 0x8d, /* Layer B */
476*4882a593Smuzhiyun [2] = 0x91, /* Layer C */
477*4882a593Smuzhiyun };
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun if (layer >= ARRAY_SIZE(reg))
482*4882a593Smuzhiyun return -EINVAL;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
485*4882a593Smuzhiyun if (rc < 0)
486*4882a593Smuzhiyun return rc;
487*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x6e);
488*4882a593Smuzhiyun if (rc < 0)
489*4882a593Smuzhiyun return rc;
490*4882a593Smuzhiyun count = (rc >> 4) & 0x0f;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: segments: %d.\n", __func__, count);
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun return count;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
mb86a20s_reset_frontend_cache(struct dvb_frontend * fe)497*4882a593Smuzhiyun static void mb86a20s_reset_frontend_cache(struct dvb_frontend *fe)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
500*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun /* Fixed parameters */
505*4882a593Smuzhiyun c->delivery_system = SYS_ISDBT;
506*4882a593Smuzhiyun c->bandwidth_hz = 6000000;
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun /* Initialize values that will be later autodetected */
509*4882a593Smuzhiyun c->isdbt_layer_enabled = 0;
510*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_AUTO;
511*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_AUTO;
512*4882a593Smuzhiyun c->isdbt_sb_mode = 0;
513*4882a593Smuzhiyun c->isdbt_sb_segment_count = 0;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun /*
517*4882a593Smuzhiyun * Estimates the bit rate using the per-segment bit rate given by
518*4882a593Smuzhiyun * ABNT/NBR 15601 spec (table 4).
519*4882a593Smuzhiyun */
520*4882a593Smuzhiyun static const u32 isdbt_rate[3][5][4] = {
521*4882a593Smuzhiyun { /* DQPSK/QPSK */
522*4882a593Smuzhiyun { 280850, 312060, 330420, 340430 }, /* 1/2 */
523*4882a593Smuzhiyun { 374470, 416080, 440560, 453910 }, /* 2/3 */
524*4882a593Smuzhiyun { 421280, 468090, 495630, 510650 }, /* 3/4 */
525*4882a593Smuzhiyun { 468090, 520100, 550700, 567390 }, /* 5/6 */
526*4882a593Smuzhiyun { 491500, 546110, 578230, 595760 }, /* 7/8 */
527*4882a593Smuzhiyun }, { /* QAM16 */
528*4882a593Smuzhiyun { 561710, 624130, 660840, 680870 }, /* 1/2 */
529*4882a593Smuzhiyun { 748950, 832170, 881120, 907820 }, /* 2/3 */
530*4882a593Smuzhiyun { 842570, 936190, 991260, 1021300 }, /* 3/4 */
531*4882a593Smuzhiyun { 936190, 1040210, 1101400, 1134780 }, /* 5/6 */
532*4882a593Smuzhiyun { 983000, 1092220, 1156470, 1191520 }, /* 7/8 */
533*4882a593Smuzhiyun }, { /* QAM64 */
534*4882a593Smuzhiyun { 842570, 936190, 991260, 1021300 }, /* 1/2 */
535*4882a593Smuzhiyun { 1123430, 1248260, 1321680, 1361740 }, /* 2/3 */
536*4882a593Smuzhiyun { 1263860, 1404290, 1486900, 1531950 }, /* 3/4 */
537*4882a593Smuzhiyun { 1404290, 1560320, 1652110, 1702170 }, /* 5/6 */
538*4882a593Smuzhiyun { 1474500, 1638340, 1734710, 1787280 }, /* 7/8 */
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun };
541*4882a593Smuzhiyun
isdbt_layer_min_bitrate(struct dtv_frontend_properties * c,u32 layer)542*4882a593Smuzhiyun static u32 isdbt_layer_min_bitrate(struct dtv_frontend_properties *c,
543*4882a593Smuzhiyun u32 layer)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun int mod, fec, guard;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /*
548*4882a593Smuzhiyun * If modulation/fec/guard is not detected, the default is
549*4882a593Smuzhiyun * to consider the lowest bit rate, to avoid taking too long time
550*4882a593Smuzhiyun * to get BER.
551*4882a593Smuzhiyun */
552*4882a593Smuzhiyun switch (c->layer[layer].modulation) {
553*4882a593Smuzhiyun case DQPSK:
554*4882a593Smuzhiyun case QPSK:
555*4882a593Smuzhiyun default:
556*4882a593Smuzhiyun mod = 0;
557*4882a593Smuzhiyun break;
558*4882a593Smuzhiyun case QAM_16:
559*4882a593Smuzhiyun mod = 1;
560*4882a593Smuzhiyun break;
561*4882a593Smuzhiyun case QAM_64:
562*4882a593Smuzhiyun mod = 2;
563*4882a593Smuzhiyun break;
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun switch (c->layer[layer].fec) {
567*4882a593Smuzhiyun default:
568*4882a593Smuzhiyun case FEC_1_2:
569*4882a593Smuzhiyun case FEC_AUTO:
570*4882a593Smuzhiyun fec = 0;
571*4882a593Smuzhiyun break;
572*4882a593Smuzhiyun case FEC_2_3:
573*4882a593Smuzhiyun fec = 1;
574*4882a593Smuzhiyun break;
575*4882a593Smuzhiyun case FEC_3_4:
576*4882a593Smuzhiyun fec = 2;
577*4882a593Smuzhiyun break;
578*4882a593Smuzhiyun case FEC_5_6:
579*4882a593Smuzhiyun fec = 3;
580*4882a593Smuzhiyun break;
581*4882a593Smuzhiyun case FEC_7_8:
582*4882a593Smuzhiyun fec = 4;
583*4882a593Smuzhiyun break;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun switch (c->guard_interval) {
587*4882a593Smuzhiyun default:
588*4882a593Smuzhiyun case GUARD_INTERVAL_1_4:
589*4882a593Smuzhiyun guard = 0;
590*4882a593Smuzhiyun break;
591*4882a593Smuzhiyun case GUARD_INTERVAL_1_8:
592*4882a593Smuzhiyun guard = 1;
593*4882a593Smuzhiyun break;
594*4882a593Smuzhiyun case GUARD_INTERVAL_1_16:
595*4882a593Smuzhiyun guard = 2;
596*4882a593Smuzhiyun break;
597*4882a593Smuzhiyun case GUARD_INTERVAL_1_32:
598*4882a593Smuzhiyun guard = 3;
599*4882a593Smuzhiyun break;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun return isdbt_rate[mod][fec][guard] * c->layer[layer].segment_count;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
mb86a20s_get_frontend(struct dvb_frontend * fe)605*4882a593Smuzhiyun static int mb86a20s_get_frontend(struct dvb_frontend *fe)
606*4882a593Smuzhiyun {
607*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
608*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
609*4882a593Smuzhiyun int layer, rc, rate, counter;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun /* Reset frontend cache to default values */
614*4882a593Smuzhiyun mb86a20s_reset_frontend_cache(fe);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun /* Check for partial reception */
617*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x6d, 0x85);
618*4882a593Smuzhiyun if (rc < 0)
619*4882a593Smuzhiyun return rc;
620*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x6e);
621*4882a593Smuzhiyun if (rc < 0)
622*4882a593Smuzhiyun return rc;
623*4882a593Smuzhiyun c->isdbt_partial_reception = (rc & 0x10) ? 1 : 0;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun /* Get per-layer data */
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun for (layer = 0; layer < NUM_LAYERS; layer++) {
628*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: getting data for layer %c.\n",
629*4882a593Smuzhiyun __func__, 'A' + layer);
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun rc = mb86a20s_get_segment_count(state, layer);
632*4882a593Smuzhiyun if (rc < 0)
633*4882a593Smuzhiyun goto noperlayer_error;
634*4882a593Smuzhiyun if (rc >= 0 && rc < 14) {
635*4882a593Smuzhiyun c->layer[layer].segment_count = rc;
636*4882a593Smuzhiyun } else {
637*4882a593Smuzhiyun c->layer[layer].segment_count = 0;
638*4882a593Smuzhiyun state->estimated_rate[layer] = 0;
639*4882a593Smuzhiyun continue;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun c->isdbt_layer_enabled |= 1 << layer;
642*4882a593Smuzhiyun rc = mb86a20s_get_modulation(state, layer);
643*4882a593Smuzhiyun if (rc < 0)
644*4882a593Smuzhiyun goto noperlayer_error;
645*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: modulation %d.\n",
646*4882a593Smuzhiyun __func__, rc);
647*4882a593Smuzhiyun c->layer[layer].modulation = rc;
648*4882a593Smuzhiyun rc = mb86a20s_get_fec(state, layer);
649*4882a593Smuzhiyun if (rc < 0)
650*4882a593Smuzhiyun goto noperlayer_error;
651*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: FEC %d.\n",
652*4882a593Smuzhiyun __func__, rc);
653*4882a593Smuzhiyun c->layer[layer].fec = rc;
654*4882a593Smuzhiyun rc = mb86a20s_get_interleaving(state, layer);
655*4882a593Smuzhiyun if (rc < 0)
656*4882a593Smuzhiyun goto noperlayer_error;
657*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: interleaving %d.\n",
658*4882a593Smuzhiyun __func__, rc);
659*4882a593Smuzhiyun c->layer[layer].interleaving = rc;
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun rate = isdbt_layer_min_bitrate(c, layer);
662*4882a593Smuzhiyun counter = rate * BER_SAMPLING_RATE;
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /* Avoids sampling too quickly or to overflow the register */
665*4882a593Smuzhiyun if (counter < 256)
666*4882a593Smuzhiyun counter = 256;
667*4882a593Smuzhiyun else if (counter > (1 << 24) - 1)
668*4882a593Smuzhiyun counter = (1 << 24) - 1;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
671*4882a593Smuzhiyun "%s: layer %c bitrate: %d kbps; counter = %d (0x%06x)\n",
672*4882a593Smuzhiyun __func__, 'A' + layer, rate / 1000, counter, counter);
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun state->estimated_rate[layer] = counter;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x6d, 0x84);
678*4882a593Smuzhiyun if (rc < 0)
679*4882a593Smuzhiyun return rc;
680*4882a593Smuzhiyun if ((rc & 0x60) == 0x20) {
681*4882a593Smuzhiyun c->isdbt_sb_mode = 1;
682*4882a593Smuzhiyun /* At least, one segment should exist */
683*4882a593Smuzhiyun if (!c->isdbt_sb_segment_count)
684*4882a593Smuzhiyun c->isdbt_sb_segment_count = 1;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun /* Get transmission mode and guard interval */
688*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x07);
689*4882a593Smuzhiyun if (rc < 0)
690*4882a593Smuzhiyun return rc;
691*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_AUTO;
692*4882a593Smuzhiyun if ((rc & 0x60) == 0x20) {
693*4882a593Smuzhiyun /* Only modes 2 and 3 are supported */
694*4882a593Smuzhiyun switch ((rc >> 2) & 0x03) {
695*4882a593Smuzhiyun case 1:
696*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_4K;
697*4882a593Smuzhiyun break;
698*4882a593Smuzhiyun case 2:
699*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_8K;
700*4882a593Smuzhiyun break;
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_AUTO;
704*4882a593Smuzhiyun if (!(rc & 0x10)) {
705*4882a593Smuzhiyun /* Guard interval 1/32 is not supported */
706*4882a593Smuzhiyun switch (rc & 0x3) {
707*4882a593Smuzhiyun case 0:
708*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_4;
709*4882a593Smuzhiyun break;
710*4882a593Smuzhiyun case 1:
711*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_8;
712*4882a593Smuzhiyun break;
713*4882a593Smuzhiyun case 2:
714*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_16;
715*4882a593Smuzhiyun break;
716*4882a593Smuzhiyun }
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun return 0;
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun noperlayer_error:
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun /* per-layer info is incomplete; discard all per-layer */
723*4882a593Smuzhiyun c->isdbt_layer_enabled = 0;
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun return rc;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
mb86a20s_reset_counters(struct dvb_frontend * fe)728*4882a593Smuzhiyun static int mb86a20s_reset_counters(struct dvb_frontend *fe)
729*4882a593Smuzhiyun {
730*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
731*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
732*4882a593Smuzhiyun int rc, val;
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun /* Reset the counters, if the channel changed */
737*4882a593Smuzhiyun if (state->last_frequency != c->frequency) {
738*4882a593Smuzhiyun memset(&c->cnr, 0, sizeof(c->cnr));
739*4882a593Smuzhiyun memset(&c->pre_bit_error, 0, sizeof(c->pre_bit_error));
740*4882a593Smuzhiyun memset(&c->pre_bit_count, 0, sizeof(c->pre_bit_count));
741*4882a593Smuzhiyun memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
742*4882a593Smuzhiyun memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
743*4882a593Smuzhiyun memset(&c->block_error, 0, sizeof(c->block_error));
744*4882a593Smuzhiyun memset(&c->block_count, 0, sizeof(c->block_count));
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun state->last_frequency = c->frequency;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun /* Clear status for most stats */
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun /* BER/PER counter reset */
752*4882a593Smuzhiyun rc = mb86a20s_writeregdata(state, mb86a20s_per_ber_reset);
753*4882a593Smuzhiyun if (rc < 0)
754*4882a593Smuzhiyun goto err;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun /* CNR counter reset */
757*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x45);
758*4882a593Smuzhiyun if (rc < 0)
759*4882a593Smuzhiyun goto err;
760*4882a593Smuzhiyun val = rc;
761*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x45, val | 0x10);
762*4882a593Smuzhiyun if (rc < 0)
763*4882a593Smuzhiyun goto err;
764*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x45, val & 0x6f);
765*4882a593Smuzhiyun if (rc < 0)
766*4882a593Smuzhiyun goto err;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun /* MER counter reset */
769*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0x50);
770*4882a593Smuzhiyun if (rc < 0)
771*4882a593Smuzhiyun goto err;
772*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
773*4882a593Smuzhiyun if (rc < 0)
774*4882a593Smuzhiyun goto err;
775*4882a593Smuzhiyun val = rc;
776*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, val | 0x01);
777*4882a593Smuzhiyun if (rc < 0)
778*4882a593Smuzhiyun goto err;
779*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, val & 0x06);
780*4882a593Smuzhiyun if (rc < 0)
781*4882a593Smuzhiyun goto err;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun goto ok;
784*4882a593Smuzhiyun err:
785*4882a593Smuzhiyun dev_err(&state->i2c->dev,
786*4882a593Smuzhiyun "%s: Can't reset FE statistics (error %d).\n",
787*4882a593Smuzhiyun __func__, rc);
788*4882a593Smuzhiyun ok:
789*4882a593Smuzhiyun return rc;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun
mb86a20s_get_pre_ber(struct dvb_frontend * fe,unsigned layer,u32 * error,u32 * count)792*4882a593Smuzhiyun static int mb86a20s_get_pre_ber(struct dvb_frontend *fe,
793*4882a593Smuzhiyun unsigned layer,
794*4882a593Smuzhiyun u32 *error, u32 *count)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
797*4882a593Smuzhiyun int rc, val;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun if (layer >= NUM_LAYERS)
802*4882a593Smuzhiyun return -EINVAL;
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun /* Check if the BER measures are already available */
805*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x54);
806*4882a593Smuzhiyun if (rc < 0)
807*4882a593Smuzhiyun return rc;
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun /* Check if data is available for that layer */
810*4882a593Smuzhiyun if (!(rc & (1 << layer))) {
811*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
812*4882a593Smuzhiyun "%s: preBER for layer %c is not available yet.\n",
813*4882a593Smuzhiyun __func__, 'A' + layer);
814*4882a593Smuzhiyun return -EBUSY;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun /* Read Bit Error Count */
818*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x55 + layer * 3);
819*4882a593Smuzhiyun if (rc < 0)
820*4882a593Smuzhiyun return rc;
821*4882a593Smuzhiyun *error = rc << 16;
822*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x56 + layer * 3);
823*4882a593Smuzhiyun if (rc < 0)
824*4882a593Smuzhiyun return rc;
825*4882a593Smuzhiyun *error |= rc << 8;
826*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x57 + layer * 3);
827*4882a593Smuzhiyun if (rc < 0)
828*4882a593Smuzhiyun return rc;
829*4882a593Smuzhiyun *error |= rc;
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
832*4882a593Smuzhiyun "%s: bit error before Viterbi for layer %c: %d.\n",
833*4882a593Smuzhiyun __func__, 'A' + layer, *error);
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun /* Read Bit Count */
836*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xa7 + layer * 3);
837*4882a593Smuzhiyun if (rc < 0)
838*4882a593Smuzhiyun return rc;
839*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
840*4882a593Smuzhiyun if (rc < 0)
841*4882a593Smuzhiyun return rc;
842*4882a593Smuzhiyun *count = rc << 16;
843*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xa8 + layer * 3);
844*4882a593Smuzhiyun if (rc < 0)
845*4882a593Smuzhiyun return rc;
846*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
847*4882a593Smuzhiyun if (rc < 0)
848*4882a593Smuzhiyun return rc;
849*4882a593Smuzhiyun *count |= rc << 8;
850*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xa9 + layer * 3);
851*4882a593Smuzhiyun if (rc < 0)
852*4882a593Smuzhiyun return rc;
853*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
854*4882a593Smuzhiyun if (rc < 0)
855*4882a593Smuzhiyun return rc;
856*4882a593Smuzhiyun *count |= rc;
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
859*4882a593Smuzhiyun "%s: bit count before Viterbi for layer %c: %d.\n",
860*4882a593Smuzhiyun __func__, 'A' + layer, *count);
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun /*
864*4882a593Smuzhiyun * As we get TMCC data from the frontend, we can better estimate the
865*4882a593Smuzhiyun * BER bit counters, in order to do the BER measure during a longer
866*4882a593Smuzhiyun * time. Use those data, if available, to update the bit count
867*4882a593Smuzhiyun * measure.
868*4882a593Smuzhiyun */
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun if (state->estimated_rate[layer]
871*4882a593Smuzhiyun && state->estimated_rate[layer] != *count) {
872*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
873*4882a593Smuzhiyun "%s: updating layer %c preBER counter to %d.\n",
874*4882a593Smuzhiyun __func__, 'A' + layer, state->estimated_rate[layer]);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun /* Turn off BER before Viterbi */
877*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x52, 0x00);
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun /* Update counter for this layer */
880*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xa7 + layer * 3);
881*4882a593Smuzhiyun if (rc < 0)
882*4882a593Smuzhiyun return rc;
883*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51,
884*4882a593Smuzhiyun state->estimated_rate[layer] >> 16);
885*4882a593Smuzhiyun if (rc < 0)
886*4882a593Smuzhiyun return rc;
887*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xa8 + layer * 3);
888*4882a593Smuzhiyun if (rc < 0)
889*4882a593Smuzhiyun return rc;
890*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51,
891*4882a593Smuzhiyun state->estimated_rate[layer] >> 8);
892*4882a593Smuzhiyun if (rc < 0)
893*4882a593Smuzhiyun return rc;
894*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xa9 + layer * 3);
895*4882a593Smuzhiyun if (rc < 0)
896*4882a593Smuzhiyun return rc;
897*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51,
898*4882a593Smuzhiyun state->estimated_rate[layer]);
899*4882a593Smuzhiyun if (rc < 0)
900*4882a593Smuzhiyun return rc;
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun /* Turn on BER before Viterbi */
903*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x52, 0x01);
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun /* Reset all preBER counters */
906*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x53, 0x00);
907*4882a593Smuzhiyun if (rc < 0)
908*4882a593Smuzhiyun return rc;
909*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x53, 0x07);
910*4882a593Smuzhiyun } else {
911*4882a593Smuzhiyun /* Reset counter to collect new data */
912*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x53);
913*4882a593Smuzhiyun if (rc < 0)
914*4882a593Smuzhiyun return rc;
915*4882a593Smuzhiyun val = rc;
916*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x53, val & ~(1 << layer));
917*4882a593Smuzhiyun if (rc < 0)
918*4882a593Smuzhiyun return rc;
919*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x53, val | (1 << layer));
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun return rc;
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun
mb86a20s_get_post_ber(struct dvb_frontend * fe,unsigned layer,u32 * error,u32 * count)925*4882a593Smuzhiyun static int mb86a20s_get_post_ber(struct dvb_frontend *fe,
926*4882a593Smuzhiyun unsigned layer,
927*4882a593Smuzhiyun u32 *error, u32 *count)
928*4882a593Smuzhiyun {
929*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
930*4882a593Smuzhiyun u32 counter, collect_rate;
931*4882a593Smuzhiyun int rc, val;
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun if (layer >= NUM_LAYERS)
936*4882a593Smuzhiyun return -EINVAL;
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun /* Check if the BER measures are already available */
939*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x60);
940*4882a593Smuzhiyun if (rc < 0)
941*4882a593Smuzhiyun return rc;
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun /* Check if data is available for that layer */
944*4882a593Smuzhiyun if (!(rc & (1 << layer))) {
945*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
946*4882a593Smuzhiyun "%s: post BER for layer %c is not available yet.\n",
947*4882a593Smuzhiyun __func__, 'A' + layer);
948*4882a593Smuzhiyun return -EBUSY;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun /* Read Bit Error Count */
952*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x64 + layer * 3);
953*4882a593Smuzhiyun if (rc < 0)
954*4882a593Smuzhiyun return rc;
955*4882a593Smuzhiyun *error = rc << 16;
956*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x65 + layer * 3);
957*4882a593Smuzhiyun if (rc < 0)
958*4882a593Smuzhiyun return rc;
959*4882a593Smuzhiyun *error |= rc << 8;
960*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x66 + layer * 3);
961*4882a593Smuzhiyun if (rc < 0)
962*4882a593Smuzhiyun return rc;
963*4882a593Smuzhiyun *error |= rc;
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
966*4882a593Smuzhiyun "%s: post bit error for layer %c: %d.\n",
967*4882a593Smuzhiyun __func__, 'A' + layer, *error);
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun /* Read Bit Count */
970*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xdc + layer * 2);
971*4882a593Smuzhiyun if (rc < 0)
972*4882a593Smuzhiyun return rc;
973*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
974*4882a593Smuzhiyun if (rc < 0)
975*4882a593Smuzhiyun return rc;
976*4882a593Smuzhiyun counter = rc << 8;
977*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xdd + layer * 2);
978*4882a593Smuzhiyun if (rc < 0)
979*4882a593Smuzhiyun return rc;
980*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
981*4882a593Smuzhiyun if (rc < 0)
982*4882a593Smuzhiyun return rc;
983*4882a593Smuzhiyun counter |= rc;
984*4882a593Smuzhiyun *count = counter * 204 * 8;
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
987*4882a593Smuzhiyun "%s: post bit count for layer %c: %d.\n",
988*4882a593Smuzhiyun __func__, 'A' + layer, *count);
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun /*
991*4882a593Smuzhiyun * As we get TMCC data from the frontend, we can better estimate the
992*4882a593Smuzhiyun * BER bit counters, in order to do the BER measure during a longer
993*4882a593Smuzhiyun * time. Use those data, if available, to update the bit count
994*4882a593Smuzhiyun * measure.
995*4882a593Smuzhiyun */
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun if (!state->estimated_rate[layer])
998*4882a593Smuzhiyun goto reset_measurement;
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun collect_rate = state->estimated_rate[layer] / 204 / 8;
1001*4882a593Smuzhiyun if (collect_rate < 32)
1002*4882a593Smuzhiyun collect_rate = 32;
1003*4882a593Smuzhiyun if (collect_rate > 65535)
1004*4882a593Smuzhiyun collect_rate = 65535;
1005*4882a593Smuzhiyun if (collect_rate != counter) {
1006*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
1007*4882a593Smuzhiyun "%s: updating postBER counter on layer %c to %d.\n",
1008*4882a593Smuzhiyun __func__, 'A' + layer, collect_rate);
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun /* Turn off BER after Viterbi */
1011*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x5e, 0x00);
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun /* Update counter for this layer */
1014*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xdc + layer * 2);
1015*4882a593Smuzhiyun if (rc < 0)
1016*4882a593Smuzhiyun return rc;
1017*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, collect_rate >> 8);
1018*4882a593Smuzhiyun if (rc < 0)
1019*4882a593Smuzhiyun return rc;
1020*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xdd + layer * 2);
1021*4882a593Smuzhiyun if (rc < 0)
1022*4882a593Smuzhiyun return rc;
1023*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, collect_rate & 0xff);
1024*4882a593Smuzhiyun if (rc < 0)
1025*4882a593Smuzhiyun return rc;
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun /* Turn on BER after Viterbi */
1028*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x5e, 0x07);
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun /* Reset all preBER counters */
1031*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x5f, 0x00);
1032*4882a593Smuzhiyun if (rc < 0)
1033*4882a593Smuzhiyun return rc;
1034*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x5f, 0x07);
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun return rc;
1037*4882a593Smuzhiyun }
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun reset_measurement:
1040*4882a593Smuzhiyun /* Reset counter to collect new data */
1041*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x5f);
1042*4882a593Smuzhiyun if (rc < 0)
1043*4882a593Smuzhiyun return rc;
1044*4882a593Smuzhiyun val = rc;
1045*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x5f, val & ~(1 << layer));
1046*4882a593Smuzhiyun if (rc < 0)
1047*4882a593Smuzhiyun return rc;
1048*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x5f, val | (1 << layer));
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun return rc;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun
mb86a20s_get_blk_error(struct dvb_frontend * fe,unsigned layer,u32 * error,u32 * count)1053*4882a593Smuzhiyun static int mb86a20s_get_blk_error(struct dvb_frontend *fe,
1054*4882a593Smuzhiyun unsigned layer,
1055*4882a593Smuzhiyun u32 *error, u32 *count)
1056*4882a593Smuzhiyun {
1057*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
1058*4882a593Smuzhiyun int rc, val;
1059*4882a593Smuzhiyun u32 collect_rate;
1060*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun if (layer >= NUM_LAYERS)
1063*4882a593Smuzhiyun return -EINVAL;
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun /* Check if the PER measures are already available */
1066*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb8);
1067*4882a593Smuzhiyun if (rc < 0)
1068*4882a593Smuzhiyun return rc;
1069*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1070*4882a593Smuzhiyun if (rc < 0)
1071*4882a593Smuzhiyun return rc;
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun /* Check if data is available for that layer */
1074*4882a593Smuzhiyun
1075*4882a593Smuzhiyun if (!(rc & (1 << layer))) {
1076*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
1077*4882a593Smuzhiyun "%s: block counts for layer %c aren't available yet.\n",
1078*4882a593Smuzhiyun __func__, 'A' + layer);
1079*4882a593Smuzhiyun return -EBUSY;
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun /* Read Packet error Count */
1083*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb9 + layer * 2);
1084*4882a593Smuzhiyun if (rc < 0)
1085*4882a593Smuzhiyun return rc;
1086*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1087*4882a593Smuzhiyun if (rc < 0)
1088*4882a593Smuzhiyun return rc;
1089*4882a593Smuzhiyun *error = rc << 8;
1090*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xba + layer * 2);
1091*4882a593Smuzhiyun if (rc < 0)
1092*4882a593Smuzhiyun return rc;
1093*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1094*4882a593Smuzhiyun if (rc < 0)
1095*4882a593Smuzhiyun return rc;
1096*4882a593Smuzhiyun *error |= rc;
1097*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: block error for layer %c: %d.\n",
1098*4882a593Smuzhiyun __func__, 'A' + layer, *error);
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun /* Read Bit Count */
1101*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb2 + layer * 2);
1102*4882a593Smuzhiyun if (rc < 0)
1103*4882a593Smuzhiyun return rc;
1104*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1105*4882a593Smuzhiyun if (rc < 0)
1106*4882a593Smuzhiyun return rc;
1107*4882a593Smuzhiyun *count = rc << 8;
1108*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb3 + layer * 2);
1109*4882a593Smuzhiyun if (rc < 0)
1110*4882a593Smuzhiyun return rc;
1111*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1112*4882a593Smuzhiyun if (rc < 0)
1113*4882a593Smuzhiyun return rc;
1114*4882a593Smuzhiyun *count |= rc;
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
1117*4882a593Smuzhiyun "%s: block count for layer %c: %d.\n",
1118*4882a593Smuzhiyun __func__, 'A' + layer, *count);
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun /*
1121*4882a593Smuzhiyun * As we get TMCC data from the frontend, we can better estimate the
1122*4882a593Smuzhiyun * BER bit counters, in order to do the BER measure during a longer
1123*4882a593Smuzhiyun * time. Use those data, if available, to update the bit count
1124*4882a593Smuzhiyun * measure.
1125*4882a593Smuzhiyun */
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun if (!state->estimated_rate[layer])
1128*4882a593Smuzhiyun goto reset_measurement;
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun collect_rate = state->estimated_rate[layer] / 204 / 8;
1131*4882a593Smuzhiyun if (collect_rate < 32)
1132*4882a593Smuzhiyun collect_rate = 32;
1133*4882a593Smuzhiyun if (collect_rate > 65535)
1134*4882a593Smuzhiyun collect_rate = 65535;
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun if (collect_rate != *count) {
1137*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
1138*4882a593Smuzhiyun "%s: updating PER counter on layer %c to %d.\n",
1139*4882a593Smuzhiyun __func__, 'A' + layer, collect_rate);
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun /* Stop PER measurement */
1142*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb0);
1143*4882a593Smuzhiyun if (rc < 0)
1144*4882a593Smuzhiyun return rc;
1145*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, 0x00);
1146*4882a593Smuzhiyun if (rc < 0)
1147*4882a593Smuzhiyun return rc;
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun /* Update this layer's counter */
1150*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb2 + layer * 2);
1151*4882a593Smuzhiyun if (rc < 0)
1152*4882a593Smuzhiyun return rc;
1153*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, collect_rate >> 8);
1154*4882a593Smuzhiyun if (rc < 0)
1155*4882a593Smuzhiyun return rc;
1156*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb3 + layer * 2);
1157*4882a593Smuzhiyun if (rc < 0)
1158*4882a593Smuzhiyun return rc;
1159*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, collect_rate & 0xff);
1160*4882a593Smuzhiyun if (rc < 0)
1161*4882a593Smuzhiyun return rc;
1162*4882a593Smuzhiyun
1163*4882a593Smuzhiyun /* start PER measurement */
1164*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb0);
1165*4882a593Smuzhiyun if (rc < 0)
1166*4882a593Smuzhiyun return rc;
1167*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, 0x07);
1168*4882a593Smuzhiyun if (rc < 0)
1169*4882a593Smuzhiyun return rc;
1170*4882a593Smuzhiyun
1171*4882a593Smuzhiyun /* Reset all counters to collect new data */
1172*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb1);
1173*4882a593Smuzhiyun if (rc < 0)
1174*4882a593Smuzhiyun return rc;
1175*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, 0x07);
1176*4882a593Smuzhiyun if (rc < 0)
1177*4882a593Smuzhiyun return rc;
1178*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, 0x00);
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun return rc;
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun reset_measurement:
1184*4882a593Smuzhiyun /* Reset counter to collect new data */
1185*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xb1);
1186*4882a593Smuzhiyun if (rc < 0)
1187*4882a593Smuzhiyun return rc;
1188*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1189*4882a593Smuzhiyun if (rc < 0)
1190*4882a593Smuzhiyun return rc;
1191*4882a593Smuzhiyun val = rc;
1192*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, val | (1 << layer));
1193*4882a593Smuzhiyun if (rc < 0)
1194*4882a593Smuzhiyun return rc;
1195*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, val & ~(1 << layer));
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun return rc;
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun struct linear_segments {
1201*4882a593Smuzhiyun unsigned x, y;
1202*4882a593Smuzhiyun };
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun /*
1205*4882a593Smuzhiyun * All tables below return a dB/1000 measurement
1206*4882a593Smuzhiyun */
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun static const struct linear_segments cnr_to_db_table[] = {
1209*4882a593Smuzhiyun { 19648, 0},
1210*4882a593Smuzhiyun { 18187, 1000},
1211*4882a593Smuzhiyun { 16534, 2000},
1212*4882a593Smuzhiyun { 14823, 3000},
1213*4882a593Smuzhiyun { 13161, 4000},
1214*4882a593Smuzhiyun { 11622, 5000},
1215*4882a593Smuzhiyun { 10279, 6000},
1216*4882a593Smuzhiyun { 9089, 7000},
1217*4882a593Smuzhiyun { 8042, 8000},
1218*4882a593Smuzhiyun { 7137, 9000},
1219*4882a593Smuzhiyun { 6342, 10000},
1220*4882a593Smuzhiyun { 5641, 11000},
1221*4882a593Smuzhiyun { 5030, 12000},
1222*4882a593Smuzhiyun { 4474, 13000},
1223*4882a593Smuzhiyun { 3988, 14000},
1224*4882a593Smuzhiyun { 3556, 15000},
1225*4882a593Smuzhiyun { 3180, 16000},
1226*4882a593Smuzhiyun { 2841, 17000},
1227*4882a593Smuzhiyun { 2541, 18000},
1228*4882a593Smuzhiyun { 2276, 19000},
1229*4882a593Smuzhiyun { 2038, 20000},
1230*4882a593Smuzhiyun { 1800, 21000},
1231*4882a593Smuzhiyun { 1625, 22000},
1232*4882a593Smuzhiyun { 1462, 23000},
1233*4882a593Smuzhiyun { 1324, 24000},
1234*4882a593Smuzhiyun { 1175, 25000},
1235*4882a593Smuzhiyun { 1063, 26000},
1236*4882a593Smuzhiyun { 980, 27000},
1237*4882a593Smuzhiyun { 907, 28000},
1238*4882a593Smuzhiyun { 840, 29000},
1239*4882a593Smuzhiyun { 788, 30000},
1240*4882a593Smuzhiyun };
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun static const struct linear_segments cnr_64qam_table[] = {
1243*4882a593Smuzhiyun { 3922688, 0},
1244*4882a593Smuzhiyun { 3920384, 1000},
1245*4882a593Smuzhiyun { 3902720, 2000},
1246*4882a593Smuzhiyun { 3894784, 3000},
1247*4882a593Smuzhiyun { 3882496, 4000},
1248*4882a593Smuzhiyun { 3872768, 5000},
1249*4882a593Smuzhiyun { 3858944, 6000},
1250*4882a593Smuzhiyun { 3851520, 7000},
1251*4882a593Smuzhiyun { 3838976, 8000},
1252*4882a593Smuzhiyun { 3829248, 9000},
1253*4882a593Smuzhiyun { 3818240, 10000},
1254*4882a593Smuzhiyun { 3806976, 11000},
1255*4882a593Smuzhiyun { 3791872, 12000},
1256*4882a593Smuzhiyun { 3767040, 13000},
1257*4882a593Smuzhiyun { 3720960, 14000},
1258*4882a593Smuzhiyun { 3637504, 15000},
1259*4882a593Smuzhiyun { 3498496, 16000},
1260*4882a593Smuzhiyun { 3296000, 17000},
1261*4882a593Smuzhiyun { 3031040, 18000},
1262*4882a593Smuzhiyun { 2715392, 19000},
1263*4882a593Smuzhiyun { 2362624, 20000},
1264*4882a593Smuzhiyun { 1963264, 21000},
1265*4882a593Smuzhiyun { 1649664, 22000},
1266*4882a593Smuzhiyun { 1366784, 23000},
1267*4882a593Smuzhiyun { 1120768, 24000},
1268*4882a593Smuzhiyun { 890880, 25000},
1269*4882a593Smuzhiyun { 723456, 26000},
1270*4882a593Smuzhiyun { 612096, 27000},
1271*4882a593Smuzhiyun { 518912, 28000},
1272*4882a593Smuzhiyun { 448256, 29000},
1273*4882a593Smuzhiyun { 388864, 30000},
1274*4882a593Smuzhiyun };
1275*4882a593Smuzhiyun
1276*4882a593Smuzhiyun static const struct linear_segments cnr_16qam_table[] = {
1277*4882a593Smuzhiyun { 5314816, 0},
1278*4882a593Smuzhiyun { 5219072, 1000},
1279*4882a593Smuzhiyun { 5118720, 2000},
1280*4882a593Smuzhiyun { 4998912, 3000},
1281*4882a593Smuzhiyun { 4875520, 4000},
1282*4882a593Smuzhiyun { 4736000, 5000},
1283*4882a593Smuzhiyun { 4604160, 6000},
1284*4882a593Smuzhiyun { 4458752, 7000},
1285*4882a593Smuzhiyun { 4300288, 8000},
1286*4882a593Smuzhiyun { 4092928, 9000},
1287*4882a593Smuzhiyun { 3836160, 10000},
1288*4882a593Smuzhiyun { 3521024, 11000},
1289*4882a593Smuzhiyun { 3155968, 12000},
1290*4882a593Smuzhiyun { 2756864, 13000},
1291*4882a593Smuzhiyun { 2347008, 14000},
1292*4882a593Smuzhiyun { 1955072, 15000},
1293*4882a593Smuzhiyun { 1593600, 16000},
1294*4882a593Smuzhiyun { 1297920, 17000},
1295*4882a593Smuzhiyun { 1043968, 18000},
1296*4882a593Smuzhiyun { 839680, 19000},
1297*4882a593Smuzhiyun { 672256, 20000},
1298*4882a593Smuzhiyun { 523008, 21000},
1299*4882a593Smuzhiyun { 424704, 22000},
1300*4882a593Smuzhiyun { 345088, 23000},
1301*4882a593Smuzhiyun { 280064, 24000},
1302*4882a593Smuzhiyun { 221440, 25000},
1303*4882a593Smuzhiyun { 179712, 26000},
1304*4882a593Smuzhiyun { 151040, 27000},
1305*4882a593Smuzhiyun { 128512, 28000},
1306*4882a593Smuzhiyun { 110080, 29000},
1307*4882a593Smuzhiyun { 95744, 30000},
1308*4882a593Smuzhiyun };
1309*4882a593Smuzhiyun
1310*4882a593Smuzhiyun static const struct linear_segments cnr_qpsk_table[] = {
1311*4882a593Smuzhiyun { 2834176, 0},
1312*4882a593Smuzhiyun { 2683648, 1000},
1313*4882a593Smuzhiyun { 2536960, 2000},
1314*4882a593Smuzhiyun { 2391808, 3000},
1315*4882a593Smuzhiyun { 2133248, 4000},
1316*4882a593Smuzhiyun { 1906176, 5000},
1317*4882a593Smuzhiyun { 1666560, 6000},
1318*4882a593Smuzhiyun { 1422080, 7000},
1319*4882a593Smuzhiyun { 1189632, 8000},
1320*4882a593Smuzhiyun { 976384, 9000},
1321*4882a593Smuzhiyun { 790272, 10000},
1322*4882a593Smuzhiyun { 633344, 11000},
1323*4882a593Smuzhiyun { 505600, 12000},
1324*4882a593Smuzhiyun { 402944, 13000},
1325*4882a593Smuzhiyun { 320768, 14000},
1326*4882a593Smuzhiyun { 255488, 15000},
1327*4882a593Smuzhiyun { 204032, 16000},
1328*4882a593Smuzhiyun { 163072, 17000},
1329*4882a593Smuzhiyun { 130304, 18000},
1330*4882a593Smuzhiyun { 105216, 19000},
1331*4882a593Smuzhiyun { 83456, 20000},
1332*4882a593Smuzhiyun { 65024, 21000},
1333*4882a593Smuzhiyun { 52480, 22000},
1334*4882a593Smuzhiyun { 42752, 23000},
1335*4882a593Smuzhiyun { 34560, 24000},
1336*4882a593Smuzhiyun { 27136, 25000},
1337*4882a593Smuzhiyun { 22016, 26000},
1338*4882a593Smuzhiyun { 18432, 27000},
1339*4882a593Smuzhiyun { 15616, 28000},
1340*4882a593Smuzhiyun { 13312, 29000},
1341*4882a593Smuzhiyun { 11520, 30000},
1342*4882a593Smuzhiyun };
1343*4882a593Smuzhiyun
interpolate_value(u32 value,const struct linear_segments * segments,unsigned len)1344*4882a593Smuzhiyun static u32 interpolate_value(u32 value, const struct linear_segments *segments,
1345*4882a593Smuzhiyun unsigned len)
1346*4882a593Smuzhiyun {
1347*4882a593Smuzhiyun u64 tmp64;
1348*4882a593Smuzhiyun u32 dx, dy;
1349*4882a593Smuzhiyun int i, ret;
1350*4882a593Smuzhiyun
1351*4882a593Smuzhiyun if (value >= segments[0].x)
1352*4882a593Smuzhiyun return segments[0].y;
1353*4882a593Smuzhiyun if (value < segments[len-1].x)
1354*4882a593Smuzhiyun return segments[len-1].y;
1355*4882a593Smuzhiyun
1356*4882a593Smuzhiyun for (i = 1; i < len - 1; i++) {
1357*4882a593Smuzhiyun /* If value is identical, no need to interpolate */
1358*4882a593Smuzhiyun if (value == segments[i].x)
1359*4882a593Smuzhiyun return segments[i].y;
1360*4882a593Smuzhiyun if (value > segments[i].x)
1361*4882a593Smuzhiyun break;
1362*4882a593Smuzhiyun }
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun /* Linear interpolation between the two (x,y) points */
1365*4882a593Smuzhiyun dy = segments[i].y - segments[i - 1].y;
1366*4882a593Smuzhiyun dx = segments[i - 1].x - segments[i].x;
1367*4882a593Smuzhiyun tmp64 = value - segments[i].x;
1368*4882a593Smuzhiyun tmp64 *= dy;
1369*4882a593Smuzhiyun do_div(tmp64, dx);
1370*4882a593Smuzhiyun ret = segments[i].y - tmp64;
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun return ret;
1373*4882a593Smuzhiyun }
1374*4882a593Smuzhiyun
mb86a20s_get_main_CNR(struct dvb_frontend * fe)1375*4882a593Smuzhiyun static int mb86a20s_get_main_CNR(struct dvb_frontend *fe)
1376*4882a593Smuzhiyun {
1377*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
1378*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1379*4882a593Smuzhiyun u32 cnr_linear, cnr;
1380*4882a593Smuzhiyun int rc, val;
1381*4882a593Smuzhiyun
1382*4882a593Smuzhiyun /* Check if CNR is available */
1383*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x45);
1384*4882a593Smuzhiyun if (rc < 0)
1385*4882a593Smuzhiyun return rc;
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun if (!(rc & 0x40)) {
1388*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: CNR is not available yet.\n",
1389*4882a593Smuzhiyun __func__);
1390*4882a593Smuzhiyun return -EBUSY;
1391*4882a593Smuzhiyun }
1392*4882a593Smuzhiyun val = rc;
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x46);
1395*4882a593Smuzhiyun if (rc < 0)
1396*4882a593Smuzhiyun return rc;
1397*4882a593Smuzhiyun cnr_linear = rc << 8;
1398*4882a593Smuzhiyun
1399*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x46);
1400*4882a593Smuzhiyun if (rc < 0)
1401*4882a593Smuzhiyun return rc;
1402*4882a593Smuzhiyun cnr_linear |= rc;
1403*4882a593Smuzhiyun
1404*4882a593Smuzhiyun cnr = interpolate_value(cnr_linear,
1405*4882a593Smuzhiyun cnr_to_db_table, ARRAY_SIZE(cnr_to_db_table));
1406*4882a593Smuzhiyun
1407*4882a593Smuzhiyun c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
1408*4882a593Smuzhiyun c->cnr.stat[0].svalue = cnr;
1409*4882a593Smuzhiyun
1410*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: CNR is %d.%03d dB (%d)\n",
1411*4882a593Smuzhiyun __func__, cnr / 1000, cnr % 1000, cnr_linear);
1412*4882a593Smuzhiyun
1413*4882a593Smuzhiyun /* CNR counter reset */
1414*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x45, val | 0x10);
1415*4882a593Smuzhiyun if (rc < 0)
1416*4882a593Smuzhiyun return rc;
1417*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x45, val & 0x6f);
1418*4882a593Smuzhiyun
1419*4882a593Smuzhiyun return rc;
1420*4882a593Smuzhiyun }
1421*4882a593Smuzhiyun
mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend * fe)1422*4882a593Smuzhiyun static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe)
1423*4882a593Smuzhiyun {
1424*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
1425*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1426*4882a593Smuzhiyun u32 mer, cnr;
1427*4882a593Smuzhiyun int rc, val, layer;
1428*4882a593Smuzhiyun const struct linear_segments *segs;
1429*4882a593Smuzhiyun unsigned segs_len;
1430*4882a593Smuzhiyun
1431*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun /* Check if the measures are already available */
1434*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0x5b);
1435*4882a593Smuzhiyun if (rc < 0)
1436*4882a593Smuzhiyun return rc;
1437*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1438*4882a593Smuzhiyun if (rc < 0)
1439*4882a593Smuzhiyun return rc;
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun /* Check if data is available */
1442*4882a593Smuzhiyun if (!(rc & 0x01)) {
1443*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
1444*4882a593Smuzhiyun "%s: MER measures aren't available yet.\n", __func__);
1445*4882a593Smuzhiyun return -EBUSY;
1446*4882a593Smuzhiyun }
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun /* Read all layers */
1449*4882a593Smuzhiyun for (layer = 0; layer < NUM_LAYERS; layer++) {
1450*4882a593Smuzhiyun if (!(c->isdbt_layer_enabled & (1 << layer))) {
1451*4882a593Smuzhiyun c->cnr.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
1452*4882a593Smuzhiyun continue;
1453*4882a593Smuzhiyun }
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0x52 + layer * 3);
1456*4882a593Smuzhiyun if (rc < 0)
1457*4882a593Smuzhiyun return rc;
1458*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1459*4882a593Smuzhiyun if (rc < 0)
1460*4882a593Smuzhiyun return rc;
1461*4882a593Smuzhiyun mer = rc << 16;
1462*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0x53 + layer * 3);
1463*4882a593Smuzhiyun if (rc < 0)
1464*4882a593Smuzhiyun return rc;
1465*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1466*4882a593Smuzhiyun if (rc < 0)
1467*4882a593Smuzhiyun return rc;
1468*4882a593Smuzhiyun mer |= rc << 8;
1469*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0x54 + layer * 3);
1470*4882a593Smuzhiyun if (rc < 0)
1471*4882a593Smuzhiyun return rc;
1472*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1473*4882a593Smuzhiyun if (rc < 0)
1474*4882a593Smuzhiyun return rc;
1475*4882a593Smuzhiyun mer |= rc;
1476*4882a593Smuzhiyun
1477*4882a593Smuzhiyun switch (c->layer[layer].modulation) {
1478*4882a593Smuzhiyun case DQPSK:
1479*4882a593Smuzhiyun case QPSK:
1480*4882a593Smuzhiyun segs = cnr_qpsk_table;
1481*4882a593Smuzhiyun segs_len = ARRAY_SIZE(cnr_qpsk_table);
1482*4882a593Smuzhiyun break;
1483*4882a593Smuzhiyun case QAM_16:
1484*4882a593Smuzhiyun segs = cnr_16qam_table;
1485*4882a593Smuzhiyun segs_len = ARRAY_SIZE(cnr_16qam_table);
1486*4882a593Smuzhiyun break;
1487*4882a593Smuzhiyun default:
1488*4882a593Smuzhiyun case QAM_64:
1489*4882a593Smuzhiyun segs = cnr_64qam_table;
1490*4882a593Smuzhiyun segs_len = ARRAY_SIZE(cnr_64qam_table);
1491*4882a593Smuzhiyun break;
1492*4882a593Smuzhiyun }
1493*4882a593Smuzhiyun cnr = interpolate_value(mer, segs, segs_len);
1494*4882a593Smuzhiyun
1495*4882a593Smuzhiyun c->cnr.stat[1 + layer].scale = FE_SCALE_DECIBEL;
1496*4882a593Smuzhiyun c->cnr.stat[1 + layer].svalue = cnr;
1497*4882a593Smuzhiyun
1498*4882a593Smuzhiyun dev_dbg(&state->i2c->dev,
1499*4882a593Smuzhiyun "%s: CNR for layer %c is %d.%03d dB (MER = %d).\n",
1500*4882a593Smuzhiyun __func__, 'A' + layer, cnr / 1000, cnr % 1000, mer);
1501*4882a593Smuzhiyun
1502*4882a593Smuzhiyun }
1503*4882a593Smuzhiyun
1504*4882a593Smuzhiyun /* Start a new MER measurement */
1505*4882a593Smuzhiyun /* MER counter reset */
1506*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0x50);
1507*4882a593Smuzhiyun if (rc < 0)
1508*4882a593Smuzhiyun return rc;
1509*4882a593Smuzhiyun rc = mb86a20s_readreg(state, 0x51);
1510*4882a593Smuzhiyun if (rc < 0)
1511*4882a593Smuzhiyun return rc;
1512*4882a593Smuzhiyun val = rc;
1513*4882a593Smuzhiyun
1514*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, val | 0x01);
1515*4882a593Smuzhiyun if (rc < 0)
1516*4882a593Smuzhiyun return rc;
1517*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, val & 0x06);
1518*4882a593Smuzhiyun if (rc < 0)
1519*4882a593Smuzhiyun return rc;
1520*4882a593Smuzhiyun
1521*4882a593Smuzhiyun return 0;
1522*4882a593Smuzhiyun }
1523*4882a593Smuzhiyun
mb86a20s_stats_not_ready(struct dvb_frontend * fe)1524*4882a593Smuzhiyun static void mb86a20s_stats_not_ready(struct dvb_frontend *fe)
1525*4882a593Smuzhiyun {
1526*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
1527*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1528*4882a593Smuzhiyun int layer;
1529*4882a593Smuzhiyun
1530*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
1531*4882a593Smuzhiyun
1532*4882a593Smuzhiyun /* Fill the length of each status counter */
1533*4882a593Smuzhiyun
1534*4882a593Smuzhiyun /* Only global stats */
1535*4882a593Smuzhiyun c->strength.len = 1;
1536*4882a593Smuzhiyun
1537*4882a593Smuzhiyun /* Per-layer stats - 3 layers + global */
1538*4882a593Smuzhiyun c->cnr.len = NUM_LAYERS + 1;
1539*4882a593Smuzhiyun c->pre_bit_error.len = NUM_LAYERS + 1;
1540*4882a593Smuzhiyun c->pre_bit_count.len = NUM_LAYERS + 1;
1541*4882a593Smuzhiyun c->post_bit_error.len = NUM_LAYERS + 1;
1542*4882a593Smuzhiyun c->post_bit_count.len = NUM_LAYERS + 1;
1543*4882a593Smuzhiyun c->block_error.len = NUM_LAYERS + 1;
1544*4882a593Smuzhiyun c->block_count.len = NUM_LAYERS + 1;
1545*4882a593Smuzhiyun
1546*4882a593Smuzhiyun /* Signal is always available */
1547*4882a593Smuzhiyun c->strength.stat[0].scale = FE_SCALE_RELATIVE;
1548*4882a593Smuzhiyun c->strength.stat[0].uvalue = 0;
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun /* Put all of them at FE_SCALE_NOT_AVAILABLE */
1551*4882a593Smuzhiyun for (layer = 0; layer < NUM_LAYERS + 1; layer++) {
1552*4882a593Smuzhiyun c->cnr.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
1553*4882a593Smuzhiyun c->pre_bit_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
1554*4882a593Smuzhiyun c->pre_bit_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
1555*4882a593Smuzhiyun c->post_bit_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
1556*4882a593Smuzhiyun c->post_bit_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
1557*4882a593Smuzhiyun c->block_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
1558*4882a593Smuzhiyun c->block_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
1559*4882a593Smuzhiyun }
1560*4882a593Smuzhiyun }
1561*4882a593Smuzhiyun
mb86a20s_get_stats(struct dvb_frontend * fe,int status_nr)1562*4882a593Smuzhiyun static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr)
1563*4882a593Smuzhiyun {
1564*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
1565*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1566*4882a593Smuzhiyun int rc = 0, layer;
1567*4882a593Smuzhiyun u32 bit_error = 0, bit_count = 0;
1568*4882a593Smuzhiyun u32 t_pre_bit_error = 0, t_pre_bit_count = 0;
1569*4882a593Smuzhiyun u32 t_post_bit_error = 0, t_post_bit_count = 0;
1570*4882a593Smuzhiyun u32 block_error = 0, block_count = 0;
1571*4882a593Smuzhiyun u32 t_block_error = 0, t_block_count = 0;
1572*4882a593Smuzhiyun int active_layers = 0, pre_ber_layers = 0, post_ber_layers = 0;
1573*4882a593Smuzhiyun int per_layers = 0;
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
1576*4882a593Smuzhiyun
1577*4882a593Smuzhiyun mb86a20s_get_main_CNR(fe);
1578*4882a593Smuzhiyun
1579*4882a593Smuzhiyun /* Get per-layer stats */
1580*4882a593Smuzhiyun mb86a20s_get_blk_error_layer_CNR(fe);
1581*4882a593Smuzhiyun
1582*4882a593Smuzhiyun /*
1583*4882a593Smuzhiyun * At state 7, only CNR is available
1584*4882a593Smuzhiyun * For BER measures, state=9 is required
1585*4882a593Smuzhiyun * FIXME: we may get MER measures with state=8
1586*4882a593Smuzhiyun */
1587*4882a593Smuzhiyun if (status_nr < 9)
1588*4882a593Smuzhiyun return 0;
1589*4882a593Smuzhiyun
1590*4882a593Smuzhiyun for (layer = 0; layer < NUM_LAYERS; layer++) {
1591*4882a593Smuzhiyun if (c->isdbt_layer_enabled & (1 << layer)) {
1592*4882a593Smuzhiyun /* Layer is active and has rc segments */
1593*4882a593Smuzhiyun active_layers++;
1594*4882a593Smuzhiyun
1595*4882a593Smuzhiyun /* Handle BER before vterbi */
1596*4882a593Smuzhiyun rc = mb86a20s_get_pre_ber(fe, layer,
1597*4882a593Smuzhiyun &bit_error, &bit_count);
1598*4882a593Smuzhiyun if (rc >= 0) {
1599*4882a593Smuzhiyun c->pre_bit_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
1600*4882a593Smuzhiyun c->pre_bit_error.stat[1 + layer].uvalue += bit_error;
1601*4882a593Smuzhiyun c->pre_bit_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
1602*4882a593Smuzhiyun c->pre_bit_count.stat[1 + layer].uvalue += bit_count;
1603*4882a593Smuzhiyun } else if (rc != -EBUSY) {
1604*4882a593Smuzhiyun /*
1605*4882a593Smuzhiyun * If an I/O error happened,
1606*4882a593Smuzhiyun * measures are now unavailable
1607*4882a593Smuzhiyun */
1608*4882a593Smuzhiyun c->pre_bit_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
1609*4882a593Smuzhiyun c->pre_bit_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
1610*4882a593Smuzhiyun dev_err(&state->i2c->dev,
1611*4882a593Smuzhiyun "%s: Can't get BER for layer %c (error %d).\n",
1612*4882a593Smuzhiyun __func__, 'A' + layer, rc);
1613*4882a593Smuzhiyun }
1614*4882a593Smuzhiyun if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
1615*4882a593Smuzhiyun pre_ber_layers++;
1616*4882a593Smuzhiyun
1617*4882a593Smuzhiyun /* Handle BER post vterbi */
1618*4882a593Smuzhiyun rc = mb86a20s_get_post_ber(fe, layer,
1619*4882a593Smuzhiyun &bit_error, &bit_count);
1620*4882a593Smuzhiyun if (rc >= 0) {
1621*4882a593Smuzhiyun c->post_bit_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
1622*4882a593Smuzhiyun c->post_bit_error.stat[1 + layer].uvalue += bit_error;
1623*4882a593Smuzhiyun c->post_bit_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
1624*4882a593Smuzhiyun c->post_bit_count.stat[1 + layer].uvalue += bit_count;
1625*4882a593Smuzhiyun } else if (rc != -EBUSY) {
1626*4882a593Smuzhiyun /*
1627*4882a593Smuzhiyun * If an I/O error happened,
1628*4882a593Smuzhiyun * measures are now unavailable
1629*4882a593Smuzhiyun */
1630*4882a593Smuzhiyun c->post_bit_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
1631*4882a593Smuzhiyun c->post_bit_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
1632*4882a593Smuzhiyun dev_err(&state->i2c->dev,
1633*4882a593Smuzhiyun "%s: Can't get BER for layer %c (error %d).\n",
1634*4882a593Smuzhiyun __func__, 'A' + layer, rc);
1635*4882a593Smuzhiyun }
1636*4882a593Smuzhiyun if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
1637*4882a593Smuzhiyun post_ber_layers++;
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun /* Handle Block errors for PER/UCB reports */
1640*4882a593Smuzhiyun rc = mb86a20s_get_blk_error(fe, layer,
1641*4882a593Smuzhiyun &block_error,
1642*4882a593Smuzhiyun &block_count);
1643*4882a593Smuzhiyun if (rc >= 0) {
1644*4882a593Smuzhiyun c->block_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
1645*4882a593Smuzhiyun c->block_error.stat[1 + layer].uvalue += block_error;
1646*4882a593Smuzhiyun c->block_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
1647*4882a593Smuzhiyun c->block_count.stat[1 + layer].uvalue += block_count;
1648*4882a593Smuzhiyun } else if (rc != -EBUSY) {
1649*4882a593Smuzhiyun /*
1650*4882a593Smuzhiyun * If an I/O error happened,
1651*4882a593Smuzhiyun * measures are now unavailable
1652*4882a593Smuzhiyun */
1653*4882a593Smuzhiyun c->block_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
1654*4882a593Smuzhiyun c->block_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
1655*4882a593Smuzhiyun dev_err(&state->i2c->dev,
1656*4882a593Smuzhiyun "%s: Can't get PER for layer %c (error %d).\n",
1657*4882a593Smuzhiyun __func__, 'A' + layer, rc);
1658*4882a593Smuzhiyun
1659*4882a593Smuzhiyun }
1660*4882a593Smuzhiyun if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
1661*4882a593Smuzhiyun per_layers++;
1662*4882a593Smuzhiyun
1663*4882a593Smuzhiyun /* Update total preBER */
1664*4882a593Smuzhiyun t_pre_bit_error += c->pre_bit_error.stat[1 + layer].uvalue;
1665*4882a593Smuzhiyun t_pre_bit_count += c->pre_bit_count.stat[1 + layer].uvalue;
1666*4882a593Smuzhiyun
1667*4882a593Smuzhiyun /* Update total postBER */
1668*4882a593Smuzhiyun t_post_bit_error += c->post_bit_error.stat[1 + layer].uvalue;
1669*4882a593Smuzhiyun t_post_bit_count += c->post_bit_count.stat[1 + layer].uvalue;
1670*4882a593Smuzhiyun
1671*4882a593Smuzhiyun /* Update total PER */
1672*4882a593Smuzhiyun t_block_error += c->block_error.stat[1 + layer].uvalue;
1673*4882a593Smuzhiyun t_block_count += c->block_count.stat[1 + layer].uvalue;
1674*4882a593Smuzhiyun }
1675*4882a593Smuzhiyun }
1676*4882a593Smuzhiyun
1677*4882a593Smuzhiyun /*
1678*4882a593Smuzhiyun * Start showing global count if at least one error count is
1679*4882a593Smuzhiyun * available.
1680*4882a593Smuzhiyun */
1681*4882a593Smuzhiyun if (pre_ber_layers) {
1682*4882a593Smuzhiyun /*
1683*4882a593Smuzhiyun * At least one per-layer BER measure was read. We can now
1684*4882a593Smuzhiyun * calculate the total BER
1685*4882a593Smuzhiyun *
1686*4882a593Smuzhiyun * Total Bit Error/Count is calculated as the sum of the
1687*4882a593Smuzhiyun * bit errors on all active layers.
1688*4882a593Smuzhiyun */
1689*4882a593Smuzhiyun c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
1690*4882a593Smuzhiyun c->pre_bit_error.stat[0].uvalue = t_pre_bit_error;
1691*4882a593Smuzhiyun c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
1692*4882a593Smuzhiyun c->pre_bit_count.stat[0].uvalue = t_pre_bit_count;
1693*4882a593Smuzhiyun } else {
1694*4882a593Smuzhiyun c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1695*4882a593Smuzhiyun c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
1696*4882a593Smuzhiyun }
1697*4882a593Smuzhiyun
1698*4882a593Smuzhiyun /*
1699*4882a593Smuzhiyun * Start showing global count if at least one error count is
1700*4882a593Smuzhiyun * available.
1701*4882a593Smuzhiyun */
1702*4882a593Smuzhiyun if (post_ber_layers) {
1703*4882a593Smuzhiyun /*
1704*4882a593Smuzhiyun * At least one per-layer BER measure was read. We can now
1705*4882a593Smuzhiyun * calculate the total BER
1706*4882a593Smuzhiyun *
1707*4882a593Smuzhiyun * Total Bit Error/Count is calculated as the sum of the
1708*4882a593Smuzhiyun * bit errors on all active layers.
1709*4882a593Smuzhiyun */
1710*4882a593Smuzhiyun c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
1711*4882a593Smuzhiyun c->post_bit_error.stat[0].uvalue = t_post_bit_error;
1712*4882a593Smuzhiyun c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
1713*4882a593Smuzhiyun c->post_bit_count.stat[0].uvalue = t_post_bit_count;
1714*4882a593Smuzhiyun } else {
1715*4882a593Smuzhiyun c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1716*4882a593Smuzhiyun c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
1717*4882a593Smuzhiyun }
1718*4882a593Smuzhiyun
1719*4882a593Smuzhiyun if (per_layers) {
1720*4882a593Smuzhiyun /*
1721*4882a593Smuzhiyun * At least one per-layer UCB measure was read. We can now
1722*4882a593Smuzhiyun * calculate the total UCB
1723*4882a593Smuzhiyun *
1724*4882a593Smuzhiyun * Total block Error/Count is calculated as the sum of the
1725*4882a593Smuzhiyun * block errors on all active layers.
1726*4882a593Smuzhiyun */
1727*4882a593Smuzhiyun c->block_error.stat[0].scale = FE_SCALE_COUNTER;
1728*4882a593Smuzhiyun c->block_error.stat[0].uvalue = t_block_error;
1729*4882a593Smuzhiyun c->block_count.stat[0].scale = FE_SCALE_COUNTER;
1730*4882a593Smuzhiyun c->block_count.stat[0].uvalue = t_block_count;
1731*4882a593Smuzhiyun } else {
1732*4882a593Smuzhiyun c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1733*4882a593Smuzhiyun c->block_count.stat[0].scale = FE_SCALE_COUNTER;
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun
1736*4882a593Smuzhiyun return rc;
1737*4882a593Smuzhiyun }
1738*4882a593Smuzhiyun
1739*4882a593Smuzhiyun /*
1740*4882a593Smuzhiyun * The functions below are called via DVB callbacks, so they need to
1741*4882a593Smuzhiyun * properly use the I2C gate control
1742*4882a593Smuzhiyun */
1743*4882a593Smuzhiyun
mb86a20s_initfe(struct dvb_frontend * fe)1744*4882a593Smuzhiyun static int mb86a20s_initfe(struct dvb_frontend *fe)
1745*4882a593Smuzhiyun {
1746*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
1747*4882a593Smuzhiyun u64 pll;
1748*4882a593Smuzhiyun u32 fclk;
1749*4882a593Smuzhiyun int rc;
1750*4882a593Smuzhiyun u8 regD5 = 1, reg71, reg09 = 0x3a;
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
1753*4882a593Smuzhiyun
1754*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1755*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 0);
1756*4882a593Smuzhiyun
1757*4882a593Smuzhiyun /* Initialize the frontend */
1758*4882a593Smuzhiyun rc = mb86a20s_writeregdata(state, mb86a20s_init1);
1759*4882a593Smuzhiyun if (rc < 0)
1760*4882a593Smuzhiyun goto err;
1761*4882a593Smuzhiyun
1762*4882a593Smuzhiyun if (!state->inversion)
1763*4882a593Smuzhiyun reg09 |= 0x04;
1764*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x09, reg09);
1765*4882a593Smuzhiyun if (rc < 0)
1766*4882a593Smuzhiyun goto err;
1767*4882a593Smuzhiyun if (!state->bw)
1768*4882a593Smuzhiyun reg71 = 1;
1769*4882a593Smuzhiyun else
1770*4882a593Smuzhiyun reg71 = 0;
1771*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x39, reg71);
1772*4882a593Smuzhiyun if (rc < 0)
1773*4882a593Smuzhiyun goto err;
1774*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x71, state->bw);
1775*4882a593Smuzhiyun if (rc < 0)
1776*4882a593Smuzhiyun goto err;
1777*4882a593Smuzhiyun if (state->subchannel) {
1778*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x44, state->subchannel);
1779*4882a593Smuzhiyun if (rc < 0)
1780*4882a593Smuzhiyun goto err;
1781*4882a593Smuzhiyun }
1782*4882a593Smuzhiyun
1783*4882a593Smuzhiyun fclk = state->config->fclk;
1784*4882a593Smuzhiyun if (!fclk)
1785*4882a593Smuzhiyun fclk = 32571428;
1786*4882a593Smuzhiyun
1787*4882a593Smuzhiyun /* Adjust IF frequency to match tuner */
1788*4882a593Smuzhiyun if (fe->ops.tuner_ops.get_if_frequency)
1789*4882a593Smuzhiyun fe->ops.tuner_ops.get_if_frequency(fe, &state->if_freq);
1790*4882a593Smuzhiyun
1791*4882a593Smuzhiyun if (!state->if_freq)
1792*4882a593Smuzhiyun state->if_freq = 3300000;
1793*4882a593Smuzhiyun
1794*4882a593Smuzhiyun pll = (((u64)1) << 34) * state->if_freq;
1795*4882a593Smuzhiyun do_div(pll, 63 * fclk);
1796*4882a593Smuzhiyun pll = (1 << 25) - pll;
1797*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x28, 0x2a);
1798*4882a593Smuzhiyun if (rc < 0)
1799*4882a593Smuzhiyun goto err;
1800*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff);
1801*4882a593Smuzhiyun if (rc < 0)
1802*4882a593Smuzhiyun goto err;
1803*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff);
1804*4882a593Smuzhiyun if (rc < 0)
1805*4882a593Smuzhiyun goto err;
1806*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x2b, pll & 0xff);
1807*4882a593Smuzhiyun if (rc < 0)
1808*4882a593Smuzhiyun goto err;
1809*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: fclk=%d, IF=%d, clock reg=0x%06llx\n",
1810*4882a593Smuzhiyun __func__, fclk, state->if_freq, (long long)pll);
1811*4882a593Smuzhiyun
1812*4882a593Smuzhiyun /* pll = freq[Hz] * 2^24/10^6 / 16.285714286 */
1813*4882a593Smuzhiyun pll = state->if_freq * 1677721600L;
1814*4882a593Smuzhiyun do_div(pll, 1628571429L);
1815*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x28, 0x20);
1816*4882a593Smuzhiyun if (rc < 0)
1817*4882a593Smuzhiyun goto err;
1818*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff);
1819*4882a593Smuzhiyun if (rc < 0)
1820*4882a593Smuzhiyun goto err;
1821*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff);
1822*4882a593Smuzhiyun if (rc < 0)
1823*4882a593Smuzhiyun goto err;
1824*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x2b, pll & 0xff);
1825*4882a593Smuzhiyun if (rc < 0)
1826*4882a593Smuzhiyun goto err;
1827*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n",
1828*4882a593Smuzhiyun __func__, state->if_freq, (long long)pll);
1829*4882a593Smuzhiyun
1830*4882a593Smuzhiyun if (!state->config->is_serial)
1831*4882a593Smuzhiyun regD5 &= ~1;
1832*4882a593Smuzhiyun
1833*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x50, 0xd5);
1834*4882a593Smuzhiyun if (rc < 0)
1835*4882a593Smuzhiyun goto err;
1836*4882a593Smuzhiyun rc = mb86a20s_writereg(state, 0x51, regD5);
1837*4882a593Smuzhiyun if (rc < 0)
1838*4882a593Smuzhiyun goto err;
1839*4882a593Smuzhiyun
1840*4882a593Smuzhiyun rc = mb86a20s_writeregdata(state, mb86a20s_init2);
1841*4882a593Smuzhiyun if (rc < 0)
1842*4882a593Smuzhiyun goto err;
1843*4882a593Smuzhiyun
1844*4882a593Smuzhiyun
1845*4882a593Smuzhiyun err:
1846*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1847*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 1);
1848*4882a593Smuzhiyun
1849*4882a593Smuzhiyun if (rc < 0) {
1850*4882a593Smuzhiyun state->need_init = true;
1851*4882a593Smuzhiyun dev_info(&state->i2c->dev,
1852*4882a593Smuzhiyun "mb86a20s: Init failed. Will try again later\n");
1853*4882a593Smuzhiyun } else {
1854*4882a593Smuzhiyun state->need_init = false;
1855*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "Initialization succeeded.\n");
1856*4882a593Smuzhiyun }
1857*4882a593Smuzhiyun return rc;
1858*4882a593Smuzhiyun }
1859*4882a593Smuzhiyun
mb86a20s_set_frontend(struct dvb_frontend * fe)1860*4882a593Smuzhiyun static int mb86a20s_set_frontend(struct dvb_frontend *fe)
1861*4882a593Smuzhiyun {
1862*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
1863*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1864*4882a593Smuzhiyun int rc, if_freq;
1865*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
1866*4882a593Smuzhiyun
1867*4882a593Smuzhiyun if (!c->isdbt_layer_enabled)
1868*4882a593Smuzhiyun c->isdbt_layer_enabled = 7;
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun if (c->isdbt_layer_enabled == 1)
1871*4882a593Smuzhiyun state->bw = MB86A20S_1SEG;
1872*4882a593Smuzhiyun else if (c->isdbt_partial_reception)
1873*4882a593Smuzhiyun state->bw = MB86A20S_13SEG_PARTIAL;
1874*4882a593Smuzhiyun else
1875*4882a593Smuzhiyun state->bw = MB86A20S_13SEG;
1876*4882a593Smuzhiyun
1877*4882a593Smuzhiyun if (c->inversion == INVERSION_ON)
1878*4882a593Smuzhiyun state->inversion = true;
1879*4882a593Smuzhiyun else
1880*4882a593Smuzhiyun state->inversion = false;
1881*4882a593Smuzhiyun
1882*4882a593Smuzhiyun if (!c->isdbt_sb_mode) {
1883*4882a593Smuzhiyun state->subchannel = 0;
1884*4882a593Smuzhiyun } else {
1885*4882a593Smuzhiyun if (c->isdbt_sb_subchannel >= ARRAY_SIZE(mb86a20s_subchannel))
1886*4882a593Smuzhiyun c->isdbt_sb_subchannel = 0;
1887*4882a593Smuzhiyun
1888*4882a593Smuzhiyun state->subchannel = mb86a20s_subchannel[c->isdbt_sb_subchannel];
1889*4882a593Smuzhiyun }
1890*4882a593Smuzhiyun
1891*4882a593Smuzhiyun /*
1892*4882a593Smuzhiyun * Gate should already be opened, but it doesn't hurt to
1893*4882a593Smuzhiyun * double-check
1894*4882a593Smuzhiyun */
1895*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1896*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 1);
1897*4882a593Smuzhiyun fe->ops.tuner_ops.set_params(fe);
1898*4882a593Smuzhiyun
1899*4882a593Smuzhiyun if (fe->ops.tuner_ops.get_if_frequency)
1900*4882a593Smuzhiyun fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
1901*4882a593Smuzhiyun
1902*4882a593Smuzhiyun /*
1903*4882a593Smuzhiyun * Make it more reliable: if, for some reason, the initial
1904*4882a593Smuzhiyun * device initialization doesn't happen, initialize it when
1905*4882a593Smuzhiyun * a SBTVD parameters are adjusted.
1906*4882a593Smuzhiyun *
1907*4882a593Smuzhiyun * Unfortunately, due to a hard to track bug at tda829x/tda18271,
1908*4882a593Smuzhiyun * the agc callback logic is not called during DVB attach time,
1909*4882a593Smuzhiyun * causing mb86a20s to not be initialized with Kworld SBTVD.
1910*4882a593Smuzhiyun * So, this hack is needed, in order to make Kworld SBTVD to work.
1911*4882a593Smuzhiyun *
1912*4882a593Smuzhiyun * It is also needed to change the IF after the initial init.
1913*4882a593Smuzhiyun *
1914*4882a593Smuzhiyun * HACK: Always init the frontend when set_frontend is called:
1915*4882a593Smuzhiyun * it was noticed that, on some devices, it fails to lock on a
1916*4882a593Smuzhiyun * different channel. So, it is better to reset everything, even
1917*4882a593Smuzhiyun * wasting some time, than to loose channel lock.
1918*4882a593Smuzhiyun */
1919*4882a593Smuzhiyun mb86a20s_initfe(fe);
1920*4882a593Smuzhiyun
1921*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1922*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 0);
1923*4882a593Smuzhiyun
1924*4882a593Smuzhiyun rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);
1925*4882a593Smuzhiyun mb86a20s_reset_counters(fe);
1926*4882a593Smuzhiyun mb86a20s_stats_not_ready(fe);
1927*4882a593Smuzhiyun
1928*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1929*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 1);
1930*4882a593Smuzhiyun
1931*4882a593Smuzhiyun return rc;
1932*4882a593Smuzhiyun }
1933*4882a593Smuzhiyun
mb86a20s_read_status_and_stats(struct dvb_frontend * fe,enum fe_status * status)1934*4882a593Smuzhiyun static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
1935*4882a593Smuzhiyun enum fe_status *status)
1936*4882a593Smuzhiyun {
1937*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
1938*4882a593Smuzhiyun int rc, status_nr;
1939*4882a593Smuzhiyun
1940*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
1941*4882a593Smuzhiyun
1942*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1943*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 0);
1944*4882a593Smuzhiyun
1945*4882a593Smuzhiyun /* Get lock */
1946*4882a593Smuzhiyun status_nr = mb86a20s_read_status(fe, status);
1947*4882a593Smuzhiyun if (status_nr < 7) {
1948*4882a593Smuzhiyun mb86a20s_stats_not_ready(fe);
1949*4882a593Smuzhiyun mb86a20s_reset_frontend_cache(fe);
1950*4882a593Smuzhiyun }
1951*4882a593Smuzhiyun if (status_nr < 0) {
1952*4882a593Smuzhiyun dev_err(&state->i2c->dev,
1953*4882a593Smuzhiyun "%s: Can't read frontend lock status\n", __func__);
1954*4882a593Smuzhiyun rc = status_nr;
1955*4882a593Smuzhiyun goto error;
1956*4882a593Smuzhiyun }
1957*4882a593Smuzhiyun
1958*4882a593Smuzhiyun /* Get signal strength */
1959*4882a593Smuzhiyun rc = mb86a20s_read_signal_strength(fe);
1960*4882a593Smuzhiyun if (rc < 0) {
1961*4882a593Smuzhiyun dev_err(&state->i2c->dev,
1962*4882a593Smuzhiyun "%s: Can't reset VBER registers.\n", __func__);
1963*4882a593Smuzhiyun mb86a20s_stats_not_ready(fe);
1964*4882a593Smuzhiyun mb86a20s_reset_frontend_cache(fe);
1965*4882a593Smuzhiyun
1966*4882a593Smuzhiyun rc = 0; /* Status is OK */
1967*4882a593Smuzhiyun goto error;
1968*4882a593Smuzhiyun }
1969*4882a593Smuzhiyun
1970*4882a593Smuzhiyun if (status_nr >= 7) {
1971*4882a593Smuzhiyun /* Get TMCC info*/
1972*4882a593Smuzhiyun rc = mb86a20s_get_frontend(fe);
1973*4882a593Smuzhiyun if (rc < 0) {
1974*4882a593Smuzhiyun dev_err(&state->i2c->dev,
1975*4882a593Smuzhiyun "%s: Can't get FE TMCC data.\n", __func__);
1976*4882a593Smuzhiyun rc = 0; /* Status is OK */
1977*4882a593Smuzhiyun goto error;
1978*4882a593Smuzhiyun }
1979*4882a593Smuzhiyun
1980*4882a593Smuzhiyun /* Get statistics */
1981*4882a593Smuzhiyun rc = mb86a20s_get_stats(fe, status_nr);
1982*4882a593Smuzhiyun if (rc < 0 && rc != -EBUSY) {
1983*4882a593Smuzhiyun dev_err(&state->i2c->dev,
1984*4882a593Smuzhiyun "%s: Can't get FE statistics.\n", __func__);
1985*4882a593Smuzhiyun rc = 0;
1986*4882a593Smuzhiyun goto error;
1987*4882a593Smuzhiyun }
1988*4882a593Smuzhiyun rc = 0; /* Don't return EBUSY to userspace */
1989*4882a593Smuzhiyun }
1990*4882a593Smuzhiyun goto ok;
1991*4882a593Smuzhiyun
1992*4882a593Smuzhiyun error:
1993*4882a593Smuzhiyun mb86a20s_stats_not_ready(fe);
1994*4882a593Smuzhiyun
1995*4882a593Smuzhiyun ok:
1996*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1997*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 1);
1998*4882a593Smuzhiyun
1999*4882a593Smuzhiyun return rc;
2000*4882a593Smuzhiyun }
2001*4882a593Smuzhiyun
mb86a20s_read_signal_strength_from_cache(struct dvb_frontend * fe,u16 * strength)2002*4882a593Smuzhiyun static int mb86a20s_read_signal_strength_from_cache(struct dvb_frontend *fe,
2003*4882a593Smuzhiyun u16 *strength)
2004*4882a593Smuzhiyun {
2005*4882a593Smuzhiyun struct dtv_frontend_properties *c = &fe->dtv_property_cache;
2006*4882a593Smuzhiyun
2007*4882a593Smuzhiyun
2008*4882a593Smuzhiyun *strength = c->strength.stat[0].uvalue;
2009*4882a593Smuzhiyun
2010*4882a593Smuzhiyun return 0;
2011*4882a593Smuzhiyun }
2012*4882a593Smuzhiyun
mb86a20s_tune(struct dvb_frontend * fe,bool re_tune,unsigned int mode_flags,unsigned int * delay,enum fe_status * status)2013*4882a593Smuzhiyun static int mb86a20s_tune(struct dvb_frontend *fe,
2014*4882a593Smuzhiyun bool re_tune,
2015*4882a593Smuzhiyun unsigned int mode_flags,
2016*4882a593Smuzhiyun unsigned int *delay,
2017*4882a593Smuzhiyun enum fe_status *status)
2018*4882a593Smuzhiyun {
2019*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
2020*4882a593Smuzhiyun int rc = 0;
2021*4882a593Smuzhiyun
2022*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
2023*4882a593Smuzhiyun
2024*4882a593Smuzhiyun if (re_tune)
2025*4882a593Smuzhiyun rc = mb86a20s_set_frontend(fe);
2026*4882a593Smuzhiyun
2027*4882a593Smuzhiyun if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
2028*4882a593Smuzhiyun mb86a20s_read_status_and_stats(fe, status);
2029*4882a593Smuzhiyun
2030*4882a593Smuzhiyun return rc;
2031*4882a593Smuzhiyun }
2032*4882a593Smuzhiyun
mb86a20s_release(struct dvb_frontend * fe)2033*4882a593Smuzhiyun static void mb86a20s_release(struct dvb_frontend *fe)
2034*4882a593Smuzhiyun {
2035*4882a593Smuzhiyun struct mb86a20s_state *state = fe->demodulator_priv;
2036*4882a593Smuzhiyun
2037*4882a593Smuzhiyun dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
2038*4882a593Smuzhiyun
2039*4882a593Smuzhiyun kfree(state);
2040*4882a593Smuzhiyun }
2041*4882a593Smuzhiyun
mb86a20s_get_frontend_algo(struct dvb_frontend * fe)2042*4882a593Smuzhiyun static enum dvbfe_algo mb86a20s_get_frontend_algo(struct dvb_frontend *fe)
2043*4882a593Smuzhiyun {
2044*4882a593Smuzhiyun return DVBFE_ALGO_HW;
2045*4882a593Smuzhiyun }
2046*4882a593Smuzhiyun
2047*4882a593Smuzhiyun static const struct dvb_frontend_ops mb86a20s_ops;
2048*4882a593Smuzhiyun
mb86a20s_attach(const struct mb86a20s_config * config,struct i2c_adapter * i2c)2049*4882a593Smuzhiyun struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
2050*4882a593Smuzhiyun struct i2c_adapter *i2c)
2051*4882a593Smuzhiyun {
2052*4882a593Smuzhiyun struct mb86a20s_state *state;
2053*4882a593Smuzhiyun u8 rev;
2054*4882a593Smuzhiyun
2055*4882a593Smuzhiyun dev_dbg(&i2c->dev, "%s called.\n", __func__);
2056*4882a593Smuzhiyun
2057*4882a593Smuzhiyun /* allocate memory for the internal state */
2058*4882a593Smuzhiyun state = kzalloc(sizeof(*state), GFP_KERNEL);
2059*4882a593Smuzhiyun if (!state)
2060*4882a593Smuzhiyun return NULL;
2061*4882a593Smuzhiyun
2062*4882a593Smuzhiyun /* setup the state */
2063*4882a593Smuzhiyun state->config = config;
2064*4882a593Smuzhiyun state->i2c = i2c;
2065*4882a593Smuzhiyun
2066*4882a593Smuzhiyun /* create dvb_frontend */
2067*4882a593Smuzhiyun memcpy(&state->frontend.ops, &mb86a20s_ops,
2068*4882a593Smuzhiyun sizeof(struct dvb_frontend_ops));
2069*4882a593Smuzhiyun state->frontend.demodulator_priv = state;
2070*4882a593Smuzhiyun
2071*4882a593Smuzhiyun /* Check if it is a mb86a20s frontend */
2072*4882a593Smuzhiyun rev = mb86a20s_readreg(state, 0);
2073*4882a593Smuzhiyun if (rev != 0x13) {
2074*4882a593Smuzhiyun kfree(state);
2075*4882a593Smuzhiyun dev_dbg(&i2c->dev,
2076*4882a593Smuzhiyun "Frontend revision %d is unknown - aborting.\n",
2077*4882a593Smuzhiyun rev);
2078*4882a593Smuzhiyun return NULL;
2079*4882a593Smuzhiyun }
2080*4882a593Smuzhiyun
2081*4882a593Smuzhiyun dev_info(&i2c->dev, "Detected a Fujitsu mb86a20s frontend\n");
2082*4882a593Smuzhiyun return &state->frontend;
2083*4882a593Smuzhiyun }
2084*4882a593Smuzhiyun EXPORT_SYMBOL(mb86a20s_attach);
2085*4882a593Smuzhiyun
2086*4882a593Smuzhiyun static const struct dvb_frontend_ops mb86a20s_ops = {
2087*4882a593Smuzhiyun .delsys = { SYS_ISDBT },
2088*4882a593Smuzhiyun /* Use dib8000 values per default */
2089*4882a593Smuzhiyun .info = {
2090*4882a593Smuzhiyun .name = "Fujitsu mb86A20s",
2091*4882a593Smuzhiyun .caps = FE_CAN_RECOVER |
2092*4882a593Smuzhiyun FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
2093*4882a593Smuzhiyun FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
2094*4882a593Smuzhiyun FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
2095*4882a593Smuzhiyun FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO |
2096*4882a593Smuzhiyun FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
2097*4882a593Smuzhiyun /* Actually, those values depend on the used tuner */
2098*4882a593Smuzhiyun .frequency_min_hz = 45 * MHz,
2099*4882a593Smuzhiyun .frequency_max_hz = 864 * MHz,
2100*4882a593Smuzhiyun .frequency_stepsize_hz = 62500,
2101*4882a593Smuzhiyun },
2102*4882a593Smuzhiyun
2103*4882a593Smuzhiyun .release = mb86a20s_release,
2104*4882a593Smuzhiyun
2105*4882a593Smuzhiyun .init = mb86a20s_initfe,
2106*4882a593Smuzhiyun .set_frontend = mb86a20s_set_frontend,
2107*4882a593Smuzhiyun .read_status = mb86a20s_read_status_and_stats,
2108*4882a593Smuzhiyun .read_signal_strength = mb86a20s_read_signal_strength_from_cache,
2109*4882a593Smuzhiyun .tune = mb86a20s_tune,
2110*4882a593Smuzhiyun .get_frontend_algo = mb86a20s_get_frontend_algo,
2111*4882a593Smuzhiyun };
2112*4882a593Smuzhiyun
2113*4882a593Smuzhiyun MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware");
2114*4882a593Smuzhiyun MODULE_AUTHOR("Mauro Carvalho Chehab");
2115*4882a593Smuzhiyun MODULE_LICENSE("GPL");
2116