1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun Driver for Spase SP8870 demodulator
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun Copyright (C) 1999 Juergen Peitz
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun /*
10*4882a593Smuzhiyun * This driver needs external firmware. Please use the command
11*4882a593Smuzhiyun * "<kerneldir>/scripts/get_dvb_firmware alps_tdlb7" to
12*4882a593Smuzhiyun * download/extract it, and then copy it to /usr/lib/hotplug/firmware
13*4882a593Smuzhiyun * or /lib/firmware (depending on configuration of firmware hotplug).
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun #define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/init.h>
18*4882a593Smuzhiyun #include <linux/module.h>
19*4882a593Smuzhiyun #include <linux/device.h>
20*4882a593Smuzhiyun #include <linux/firmware.h>
21*4882a593Smuzhiyun #include <linux/delay.h>
22*4882a593Smuzhiyun #include <linux/string.h>
23*4882a593Smuzhiyun #include <linux/slab.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <media/dvb_frontend.h>
26*4882a593Smuzhiyun #include "sp8870.h"
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun struct sp8870_state {
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun struct i2c_adapter* i2c;
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun const struct sp8870_config* config;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun struct dvb_frontend frontend;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /* demodulator private data */
38*4882a593Smuzhiyun u8 initialised:1;
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun static int debug;
42*4882a593Smuzhiyun #define dprintk(args...) \
43*4882a593Smuzhiyun do { \
44*4882a593Smuzhiyun if (debug) printk(KERN_DEBUG "sp8870: " args); \
45*4882a593Smuzhiyun } while (0)
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* firmware size for sp8870 */
48*4882a593Smuzhiyun #define SP8870_FIRMWARE_SIZE 16382
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* starting point for firmware in file 'Sc_main.mc' */
51*4882a593Smuzhiyun #define SP8870_FIRMWARE_OFFSET 0x0A
52*4882a593Smuzhiyun
sp8870_writereg(struct sp8870_state * state,u16 reg,u16 data)53*4882a593Smuzhiyun static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
56*4882a593Smuzhiyun struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 4 };
57*4882a593Smuzhiyun int err;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
60*4882a593Smuzhiyun dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
61*4882a593Smuzhiyun return -EREMOTEIO;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun return 0;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
sp8870_readreg(struct sp8870_state * state,u16 reg)67*4882a593Smuzhiyun static int sp8870_readreg (struct sp8870_state* state, u16 reg)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun int ret;
70*4882a593Smuzhiyun u8 b0 [] = { reg >> 8 , reg & 0xff };
71*4882a593Smuzhiyun u8 b1 [] = { 0, 0 };
72*4882a593Smuzhiyun struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
73*4882a593Smuzhiyun { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun ret = i2c_transfer (state->i2c, msg, 2);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun if (ret != 2) {
78*4882a593Smuzhiyun dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
79*4882a593Smuzhiyun return -1;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun return (b1[0] << 8 | b1[1]);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
sp8870_firmware_upload(struct sp8870_state * state,const struct firmware * fw)85*4882a593Smuzhiyun static int sp8870_firmware_upload (struct sp8870_state* state, const struct firmware *fw)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun struct i2c_msg msg;
88*4882a593Smuzhiyun const char *fw_buf = fw->data;
89*4882a593Smuzhiyun int fw_pos;
90*4882a593Smuzhiyun u8 tx_buf[255];
91*4882a593Smuzhiyun int tx_len;
92*4882a593Smuzhiyun int err = 0;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun dprintk ("%s: ...\n", __func__);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
97*4882a593Smuzhiyun return -EINVAL;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun // system controller stop
100*4882a593Smuzhiyun sp8870_writereg(state, 0x0F00, 0x0000);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun // instruction RAM register hiword
103*4882a593Smuzhiyun sp8870_writereg(state, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun // instruction RAM MWR
106*4882a593Smuzhiyun sp8870_writereg(state, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun // do firmware upload
109*4882a593Smuzhiyun fw_pos = SP8870_FIRMWARE_OFFSET;
110*4882a593Smuzhiyun while (fw_pos < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET){
111*4882a593Smuzhiyun tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - 252) ? 252 : SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - fw_pos;
112*4882a593Smuzhiyun // write register 0xCF0A
113*4882a593Smuzhiyun tx_buf[0] = 0xCF;
114*4882a593Smuzhiyun tx_buf[1] = 0x0A;
115*4882a593Smuzhiyun memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
116*4882a593Smuzhiyun msg.addr = state->config->demod_address;
117*4882a593Smuzhiyun msg.flags = 0;
118*4882a593Smuzhiyun msg.buf = tx_buf;
119*4882a593Smuzhiyun msg.len = tx_len + 2;
120*4882a593Smuzhiyun if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
121*4882a593Smuzhiyun printk("%s: firmware upload failed!\n", __func__);
122*4882a593Smuzhiyun printk ("%s: i2c error (err == %i)\n", __func__, err);
123*4882a593Smuzhiyun return err;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun fw_pos += tx_len;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun dprintk ("%s: done!\n", __func__);
129*4882a593Smuzhiyun return 0;
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun
sp8870_microcontroller_stop(struct sp8870_state * state)132*4882a593Smuzhiyun static void sp8870_microcontroller_stop (struct sp8870_state* state)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun sp8870_writereg(state, 0x0F08, 0x000);
135*4882a593Smuzhiyun sp8870_writereg(state, 0x0F09, 0x000);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun // microcontroller STOP
138*4882a593Smuzhiyun sp8870_writereg(state, 0x0F00, 0x000);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
sp8870_microcontroller_start(struct sp8870_state * state)141*4882a593Smuzhiyun static void sp8870_microcontroller_start (struct sp8870_state* state)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun sp8870_writereg(state, 0x0F08, 0x000);
144*4882a593Smuzhiyun sp8870_writereg(state, 0x0F09, 0x000);
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun // microcontroller START
147*4882a593Smuzhiyun sp8870_writereg(state, 0x0F00, 0x001);
148*4882a593Smuzhiyun // not documented but if we don't read 0x0D01 out here
149*4882a593Smuzhiyun // we don't get a correct data valid signal
150*4882a593Smuzhiyun sp8870_readreg(state, 0x0D01);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
sp8870_read_data_valid_signal(struct sp8870_state * state)153*4882a593Smuzhiyun static int sp8870_read_data_valid_signal(struct sp8870_state* state)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun return (sp8870_readreg(state, 0x0D02) > 0);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
configure_reg0xc05(struct dtv_frontend_properties * p,u16 * reg0xc05)158*4882a593Smuzhiyun static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun int known_parameters = 1;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun *reg0xc05 = 0x000;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun switch (p->modulation) {
165*4882a593Smuzhiyun case QPSK:
166*4882a593Smuzhiyun break;
167*4882a593Smuzhiyun case QAM_16:
168*4882a593Smuzhiyun *reg0xc05 |= (1 << 10);
169*4882a593Smuzhiyun break;
170*4882a593Smuzhiyun case QAM_64:
171*4882a593Smuzhiyun *reg0xc05 |= (2 << 10);
172*4882a593Smuzhiyun break;
173*4882a593Smuzhiyun case QAM_AUTO:
174*4882a593Smuzhiyun known_parameters = 0;
175*4882a593Smuzhiyun break;
176*4882a593Smuzhiyun default:
177*4882a593Smuzhiyun return -EINVAL;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun switch (p->hierarchy) {
181*4882a593Smuzhiyun case HIERARCHY_NONE:
182*4882a593Smuzhiyun break;
183*4882a593Smuzhiyun case HIERARCHY_1:
184*4882a593Smuzhiyun *reg0xc05 |= (1 << 7);
185*4882a593Smuzhiyun break;
186*4882a593Smuzhiyun case HIERARCHY_2:
187*4882a593Smuzhiyun *reg0xc05 |= (2 << 7);
188*4882a593Smuzhiyun break;
189*4882a593Smuzhiyun case HIERARCHY_4:
190*4882a593Smuzhiyun *reg0xc05 |= (3 << 7);
191*4882a593Smuzhiyun break;
192*4882a593Smuzhiyun case HIERARCHY_AUTO:
193*4882a593Smuzhiyun known_parameters = 0;
194*4882a593Smuzhiyun break;
195*4882a593Smuzhiyun default:
196*4882a593Smuzhiyun return -EINVAL;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun switch (p->code_rate_HP) {
200*4882a593Smuzhiyun case FEC_1_2:
201*4882a593Smuzhiyun break;
202*4882a593Smuzhiyun case FEC_2_3:
203*4882a593Smuzhiyun *reg0xc05 |= (1 << 3);
204*4882a593Smuzhiyun break;
205*4882a593Smuzhiyun case FEC_3_4:
206*4882a593Smuzhiyun *reg0xc05 |= (2 << 3);
207*4882a593Smuzhiyun break;
208*4882a593Smuzhiyun case FEC_5_6:
209*4882a593Smuzhiyun *reg0xc05 |= (3 << 3);
210*4882a593Smuzhiyun break;
211*4882a593Smuzhiyun case FEC_7_8:
212*4882a593Smuzhiyun *reg0xc05 |= (4 << 3);
213*4882a593Smuzhiyun break;
214*4882a593Smuzhiyun case FEC_AUTO:
215*4882a593Smuzhiyun known_parameters = 0;
216*4882a593Smuzhiyun break;
217*4882a593Smuzhiyun default:
218*4882a593Smuzhiyun return -EINVAL;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun if (known_parameters)
222*4882a593Smuzhiyun *reg0xc05 |= (2 << 1); /* use specified parameters */
223*4882a593Smuzhiyun else
224*4882a593Smuzhiyun *reg0xc05 |= (1 << 1); /* enable autoprobing */
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun return 0;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
sp8870_wake_up(struct sp8870_state * state)229*4882a593Smuzhiyun static int sp8870_wake_up(struct sp8870_state* state)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun // enable TS output and interface pins
232*4882a593Smuzhiyun return sp8870_writereg(state, 0xC18, 0x00D);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
sp8870_set_frontend_parameters(struct dvb_frontend * fe)235*4882a593Smuzhiyun static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun struct dtv_frontend_properties *p = &fe->dtv_property_cache;
238*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
239*4882a593Smuzhiyun int err;
240*4882a593Smuzhiyun u16 reg0xc05;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun if ((err = configure_reg0xc05(p, ®0xc05)))
243*4882a593Smuzhiyun return err;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun // system controller stop
246*4882a593Smuzhiyun sp8870_microcontroller_stop(state);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun // set tuner parameters
249*4882a593Smuzhiyun if (fe->ops.tuner_ops.set_params) {
250*4882a593Smuzhiyun fe->ops.tuner_ops.set_params(fe);
251*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun // sample rate correction bit [23..17]
255*4882a593Smuzhiyun sp8870_writereg(state, 0x0319, 0x000A);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun // sample rate correction bit [16..0]
258*4882a593Smuzhiyun sp8870_writereg(state, 0x031A, 0x0AAB);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun // integer carrier offset
261*4882a593Smuzhiyun sp8870_writereg(state, 0x0309, 0x0400);
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun // fractional carrier offset
264*4882a593Smuzhiyun sp8870_writereg(state, 0x030A, 0x0000);
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun // filter for 6/7/8 Mhz channel
267*4882a593Smuzhiyun if (p->bandwidth_hz == 6000000)
268*4882a593Smuzhiyun sp8870_writereg(state, 0x0311, 0x0002);
269*4882a593Smuzhiyun else if (p->bandwidth_hz == 7000000)
270*4882a593Smuzhiyun sp8870_writereg(state, 0x0311, 0x0001);
271*4882a593Smuzhiyun else
272*4882a593Smuzhiyun sp8870_writereg(state, 0x0311, 0x0000);
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun // scan order: 2k first = 0x0000, 8k first = 0x0001
275*4882a593Smuzhiyun if (p->transmission_mode == TRANSMISSION_MODE_2K)
276*4882a593Smuzhiyun sp8870_writereg(state, 0x0338, 0x0000);
277*4882a593Smuzhiyun else
278*4882a593Smuzhiyun sp8870_writereg(state, 0x0338, 0x0001);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun sp8870_writereg(state, 0xc05, reg0xc05);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun // read status reg in order to clear pending irqs
283*4882a593Smuzhiyun err = sp8870_readreg(state, 0x200);
284*4882a593Smuzhiyun if (err < 0)
285*4882a593Smuzhiyun return err;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun // system controller start
288*4882a593Smuzhiyun sp8870_microcontroller_start(state);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun return 0;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
sp8870_init(struct dvb_frontend * fe)293*4882a593Smuzhiyun static int sp8870_init (struct dvb_frontend* fe)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
296*4882a593Smuzhiyun const struct firmware *fw = NULL;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun sp8870_wake_up(state);
299*4882a593Smuzhiyun if (state->initialised) return 0;
300*4882a593Smuzhiyun state->initialised = 1;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun dprintk ("%s\n", __func__);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun /* request the firmware, this will block until someone uploads it */
306*4882a593Smuzhiyun printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE);
307*4882a593Smuzhiyun if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) {
308*4882a593Smuzhiyun printk("sp8870: no firmware upload (timeout or file not found?)\n");
309*4882a593Smuzhiyun return -EIO;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun if (sp8870_firmware_upload(state, fw)) {
313*4882a593Smuzhiyun printk("sp8870: writing firmware to device failed\n");
314*4882a593Smuzhiyun release_firmware(fw);
315*4882a593Smuzhiyun return -EIO;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun release_firmware(fw);
318*4882a593Smuzhiyun printk("sp8870: firmware upload complete\n");
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun /* enable TS output and interface pins */
321*4882a593Smuzhiyun sp8870_writereg(state, 0xc18, 0x00d);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun // system controller stop
324*4882a593Smuzhiyun sp8870_microcontroller_stop(state);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun // ADC mode
327*4882a593Smuzhiyun sp8870_writereg(state, 0x0301, 0x0003);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun // Reed Solomon parity bytes passed to output
330*4882a593Smuzhiyun sp8870_writereg(state, 0x0C13, 0x0001);
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun // MPEG clock is suppressed if no valid data
333*4882a593Smuzhiyun sp8870_writereg(state, 0x0C14, 0x0001);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun /* bit 0x010: enable data valid signal */
336*4882a593Smuzhiyun sp8870_writereg(state, 0x0D00, 0x010);
337*4882a593Smuzhiyun sp8870_writereg(state, 0x0D01, 0x000);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun return 0;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
sp8870_read_status(struct dvb_frontend * fe,enum fe_status * fe_status)342*4882a593Smuzhiyun static int sp8870_read_status(struct dvb_frontend *fe,
343*4882a593Smuzhiyun enum fe_status *fe_status)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
346*4882a593Smuzhiyun int status;
347*4882a593Smuzhiyun int signal;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun *fe_status = 0;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun status = sp8870_readreg (state, 0x0200);
352*4882a593Smuzhiyun if (status < 0)
353*4882a593Smuzhiyun return -EIO;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun signal = sp8870_readreg (state, 0x0303);
356*4882a593Smuzhiyun if (signal < 0)
357*4882a593Smuzhiyun return -EIO;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun if (signal > 0x0F)
360*4882a593Smuzhiyun *fe_status |= FE_HAS_SIGNAL;
361*4882a593Smuzhiyun if (status & 0x08)
362*4882a593Smuzhiyun *fe_status |= FE_HAS_SYNC;
363*4882a593Smuzhiyun if (status & 0x04)
364*4882a593Smuzhiyun *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun return 0;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
sp8870_read_ber(struct dvb_frontend * fe,u32 * ber)369*4882a593Smuzhiyun static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
372*4882a593Smuzhiyun int ret;
373*4882a593Smuzhiyun u32 tmp;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun *ber = 0;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun ret = sp8870_readreg(state, 0xC08);
378*4882a593Smuzhiyun if (ret < 0)
379*4882a593Smuzhiyun return -EIO;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun tmp = ret & 0x3F;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun ret = sp8870_readreg(state, 0xC07);
384*4882a593Smuzhiyun if (ret < 0)
385*4882a593Smuzhiyun return -EIO;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun tmp = ret << 6;
388*4882a593Smuzhiyun if (tmp >= 0x3FFF0)
389*4882a593Smuzhiyun tmp = ~0;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun *ber = tmp;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun return 0;
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun
sp8870_read_signal_strength(struct dvb_frontend * fe,u16 * signal)396*4882a593Smuzhiyun static int sp8870_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
399*4882a593Smuzhiyun int ret;
400*4882a593Smuzhiyun u16 tmp;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun *signal = 0;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun ret = sp8870_readreg (state, 0x306);
405*4882a593Smuzhiyun if (ret < 0)
406*4882a593Smuzhiyun return -EIO;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun tmp = ret << 8;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun ret = sp8870_readreg (state, 0x303);
411*4882a593Smuzhiyun if (ret < 0)
412*4882a593Smuzhiyun return -EIO;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun tmp |= ret;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun if (tmp)
417*4882a593Smuzhiyun *signal = 0xFFFF - tmp;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun return 0;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
sp8870_read_uncorrected_blocks(struct dvb_frontend * fe,u32 * ublocks)422*4882a593Smuzhiyun static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
425*4882a593Smuzhiyun int ret;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun *ublocks = 0;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun ret = sp8870_readreg(state, 0xC0C);
430*4882a593Smuzhiyun if (ret < 0)
431*4882a593Smuzhiyun return -EIO;
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun if (ret == 0xFFFF)
434*4882a593Smuzhiyun ret = ~0;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun *ublocks = ret;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun return 0;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun /* number of trials to recover from lockup */
442*4882a593Smuzhiyun #define MAXTRIALS 5
443*4882a593Smuzhiyun /* maximum checks for data valid signal */
444*4882a593Smuzhiyun #define MAXCHECKS 100
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun /* only for debugging: counter for detected lockups */
447*4882a593Smuzhiyun static int lockups;
448*4882a593Smuzhiyun /* only for debugging: counter for channel switches */
449*4882a593Smuzhiyun static int switches;
450*4882a593Smuzhiyun
sp8870_set_frontend(struct dvb_frontend * fe)451*4882a593Smuzhiyun static int sp8870_set_frontend(struct dvb_frontend *fe)
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun struct dtv_frontend_properties *p = &fe->dtv_property_cache;
454*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun /*
457*4882a593Smuzhiyun The firmware of the sp8870 sometimes locks up after setting frontend parameters.
458*4882a593Smuzhiyun We try to detect this by checking the data valid signal.
459*4882a593Smuzhiyun If it is not set after MAXCHECKS we try to recover the lockup by setting
460*4882a593Smuzhiyun the frontend parameters again.
461*4882a593Smuzhiyun */
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun int err = 0;
464*4882a593Smuzhiyun int valid = 0;
465*4882a593Smuzhiyun int trials = 0;
466*4882a593Smuzhiyun int check_count = 0;
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun dprintk("%s: frequency = %i\n", __func__, p->frequency);
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun for (trials = 1; trials <= MAXTRIALS; trials++) {
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun err = sp8870_set_frontend_parameters(fe);
473*4882a593Smuzhiyun if (err)
474*4882a593Smuzhiyun return err;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun for (check_count = 0; check_count < MAXCHECKS; check_count++) {
477*4882a593Smuzhiyun // valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
478*4882a593Smuzhiyun valid = sp8870_read_data_valid_signal(state);
479*4882a593Smuzhiyun if (valid) {
480*4882a593Smuzhiyun dprintk("%s: delay = %i usec\n",
481*4882a593Smuzhiyun __func__, check_count * 10);
482*4882a593Smuzhiyun break;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun udelay(10);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun if (valid)
487*4882a593Smuzhiyun break;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun if (!valid) {
491*4882a593Smuzhiyun printk("%s: firmware crash!!!!!!\n", __func__);
492*4882a593Smuzhiyun return -EIO;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun if (debug) {
496*4882a593Smuzhiyun if (valid) {
497*4882a593Smuzhiyun if (trials > 1) {
498*4882a593Smuzhiyun printk("%s: firmware lockup!!!\n", __func__);
499*4882a593Smuzhiyun printk("%s: recovered after %i trial(s))\n", __func__, trials - 1);
500*4882a593Smuzhiyun lockups++;
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun switches++;
504*4882a593Smuzhiyun printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun return 0;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
sp8870_sleep(struct dvb_frontend * fe)510*4882a593Smuzhiyun static int sp8870_sleep(struct dvb_frontend* fe)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun // tristate TS output and disable interface pins
515*4882a593Smuzhiyun return sp8870_writereg(state, 0xC18, 0x000);
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun
sp8870_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * fesettings)518*4882a593Smuzhiyun static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun fesettings->min_delay_ms = 350;
521*4882a593Smuzhiyun fesettings->step_size = 0;
522*4882a593Smuzhiyun fesettings->max_drift = 0;
523*4882a593Smuzhiyun return 0;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
sp8870_i2c_gate_ctrl(struct dvb_frontend * fe,int enable)526*4882a593Smuzhiyun static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun if (enable) {
531*4882a593Smuzhiyun return sp8870_writereg(state, 0x206, 0x001);
532*4882a593Smuzhiyun } else {
533*4882a593Smuzhiyun return sp8870_writereg(state, 0x206, 0x000);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
sp8870_release(struct dvb_frontend * fe)537*4882a593Smuzhiyun static void sp8870_release(struct dvb_frontend* fe)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun struct sp8870_state* state = fe->demodulator_priv;
540*4882a593Smuzhiyun kfree(state);
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun static const struct dvb_frontend_ops sp8870_ops;
544*4882a593Smuzhiyun
sp8870_attach(const struct sp8870_config * config,struct i2c_adapter * i2c)545*4882a593Smuzhiyun struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
546*4882a593Smuzhiyun struct i2c_adapter* i2c)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun struct sp8870_state* state = NULL;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /* allocate memory for the internal state */
551*4882a593Smuzhiyun state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL);
552*4882a593Smuzhiyun if (state == NULL) goto error;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /* setup the state */
555*4882a593Smuzhiyun state->config = config;
556*4882a593Smuzhiyun state->i2c = i2c;
557*4882a593Smuzhiyun state->initialised = 0;
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun /* check if the demod is there */
560*4882a593Smuzhiyun if (sp8870_readreg(state, 0x0200) < 0) goto error;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun /* create dvb_frontend */
563*4882a593Smuzhiyun memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
564*4882a593Smuzhiyun state->frontend.demodulator_priv = state;
565*4882a593Smuzhiyun return &state->frontend;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun error:
568*4882a593Smuzhiyun kfree(state);
569*4882a593Smuzhiyun return NULL;
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun static const struct dvb_frontend_ops sp8870_ops = {
573*4882a593Smuzhiyun .delsys = { SYS_DVBT },
574*4882a593Smuzhiyun .info = {
575*4882a593Smuzhiyun .name = "Spase SP8870 DVB-T",
576*4882a593Smuzhiyun .frequency_min_hz = 470 * MHz,
577*4882a593Smuzhiyun .frequency_max_hz = 860 * MHz,
578*4882a593Smuzhiyun .frequency_stepsize_hz = 166666,
579*4882a593Smuzhiyun .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
580*4882a593Smuzhiyun FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
581*4882a593Smuzhiyun FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
582*4882a593Smuzhiyun FE_CAN_QPSK | FE_CAN_QAM_16 |
583*4882a593Smuzhiyun FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
584*4882a593Smuzhiyun FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER
585*4882a593Smuzhiyun },
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun .release = sp8870_release,
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun .init = sp8870_init,
590*4882a593Smuzhiyun .sleep = sp8870_sleep,
591*4882a593Smuzhiyun .i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun .set_frontend = sp8870_set_frontend,
594*4882a593Smuzhiyun .get_tune_settings = sp8870_get_tune_settings,
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun .read_status = sp8870_read_status,
597*4882a593Smuzhiyun .read_ber = sp8870_read_ber,
598*4882a593Smuzhiyun .read_signal_strength = sp8870_read_signal_strength,
599*4882a593Smuzhiyun .read_ucblocks = sp8870_read_uncorrected_blocks,
600*4882a593Smuzhiyun };
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun module_param(debug, int, 0644);
603*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun MODULE_DESCRIPTION("Spase SP8870 DVB-T Demodulator driver");
606*4882a593Smuzhiyun MODULE_AUTHOR("Juergen Peitz");
607*4882a593Smuzhiyun MODULE_LICENSE("GPL");
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun EXPORT_SYMBOL(sp8870_attach);
610