blob: b2d9fe13e1a0fa823f414501376c5e22b7996a05 [file] [log] [blame]
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -03001/*
2 * Sharp VA3A5JZ921 One Seg Broadcast Module driver
3 * This device is labeled as just S. 921 at the top of the frontend can
4 *
Mauro Carvalho Chehab37e59f82014-02-07 08:03:07 -02005 * Copyright (C) 2009-2010 Mauro Carvalho Chehab
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -03006 * Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
7 *
8 * Developed for Leadership SBTVD 1seg device sold in Brazil
9 *
10 * Frontend module based on cx24123 driver, getting some info from
11 * the old s921 driver.
12 *
13 * FIXME: Need to port to DVB v5.2 API
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation version 2.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 */
24
25#include <linux/kernel.h>
26#include <asm/div64.h>
27
28#include "dvb_frontend.h"
29#include "s921.h"
30
31static int debug = 1;
32module_param(debug, int, 0644);
33MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
34
35#define rc(args...) do { \
36 printk(KERN_ERR "s921: " args); \
37} while (0)
38
39#define dprintk(args...) \
40 do { \
41 if (debug) { \
42 printk(KERN_DEBUG "s921: %s: ", __func__); \
43 printk(args); \
44 } \
45 } while (0)
46
47struct s921_state {
48 struct i2c_adapter *i2c;
49 const struct s921_config *config;
50
51 struct dvb_frontend frontend;
52
53 /* The Demod can't easily provide these, we cache them */
54 u32 currentfreq;
55};
56
57/*
58 * Various tuner defaults need to be established for a given frequency kHz.
59 * fixme: The bounds on the bands do not match the doc in real life.
60 * fixme: Some of them have been moved, other might need adjustment.
61 */
62static struct s921_bandselect_val {
63 u32 freq_low;
64 u8 band_reg;
65} s921_bandselect[] = {
66 { 0, 0x7b },
67 { 485140000, 0x5b },
68 { 515140000, 0x3b },
69 { 545140000, 0x1b },
70 { 599140000, 0xfb },
71 { 623140000, 0xdb },
72 { 659140000, 0xbb },
73 { 713140000, 0x9b },
74};
75
76struct regdata {
77 u8 reg;
78 u8 data;
79};
80
81static struct regdata s921_init[] = {
82 { 0x01, 0x80 }, /* Probably, a reset sequence */
83 { 0x01, 0x40 },
84 { 0x01, 0x80 },
85 { 0x01, 0x40 },
86
87 { 0x02, 0x00 },
88 { 0x03, 0x40 },
89 { 0x04, 0x01 },
90 { 0x05, 0x00 },
91 { 0x06, 0x00 },
92 { 0x07, 0x00 },
93 { 0x08, 0x00 },
94 { 0x09, 0x00 },
95 { 0x0a, 0x00 },
96 { 0x0b, 0x5a },
97 { 0x0c, 0x00 },
98 { 0x0d, 0x00 },
99 { 0x0f, 0x00 },
100 { 0x13, 0x1b },
101 { 0x14, 0x80 },
102 { 0x15, 0x40 },
103 { 0x17, 0x70 },
104 { 0x18, 0x01 },
105 { 0x19, 0x12 },
106 { 0x1a, 0x01 },
107 { 0x1b, 0x12 },
108 { 0x1c, 0xa0 },
109 { 0x1d, 0x00 },
110 { 0x1e, 0x0a },
111 { 0x1f, 0x08 },
112 { 0x20, 0x40 },
113 { 0x21, 0xff },
114 { 0x22, 0x4c },
115 { 0x23, 0x4e },
116 { 0x24, 0x4c },
117 { 0x25, 0x00 },
118 { 0x26, 0x00 },
119 { 0x27, 0xf4 },
120 { 0x28, 0x60 },
121 { 0x29, 0x88 },
122 { 0x2a, 0x40 },
123 { 0x2b, 0x40 },
124 { 0x2c, 0xff },
125 { 0x2d, 0x00 },
126 { 0x2e, 0xff },
127 { 0x2f, 0x00 },
128 { 0x30, 0x20 },
129 { 0x31, 0x06 },
130 { 0x32, 0x0c },
131 { 0x34, 0x0f },
132 { 0x37, 0xfe },
133 { 0x38, 0x00 },
134 { 0x39, 0x63 },
135 { 0x3a, 0x10 },
136 { 0x3b, 0x10 },
137 { 0x47, 0x00 },
138 { 0x49, 0xe5 },
139 { 0x4b, 0x00 },
140 { 0x50, 0xc0 },
141 { 0x52, 0x20 },
142 { 0x54, 0x5a },
143 { 0x55, 0x5b },
144 { 0x56, 0x40 },
145 { 0x57, 0x70 },
146 { 0x5c, 0x50 },
147 { 0x5d, 0x00 },
148 { 0x62, 0x17 },
149 { 0x63, 0x2f },
150 { 0x64, 0x6f },
151 { 0x68, 0x00 },
152 { 0x69, 0x89 },
153 { 0x6a, 0x00 },
154 { 0x6b, 0x00 },
155 { 0x6c, 0x00 },
156 { 0x6d, 0x00 },
157 { 0x6e, 0x00 },
158 { 0x70, 0x10 },
159 { 0x71, 0x00 },
160 { 0x75, 0x00 },
161 { 0x76, 0x30 },
162 { 0x77, 0x01 },
163 { 0xaf, 0x00 },
164 { 0xb0, 0xa0 },
165 { 0xb2, 0x3d },
166 { 0xb3, 0x25 },
167 { 0xb4, 0x8b },
168 { 0xb5, 0x4b },
169 { 0xb6, 0x3f },
170 { 0xb7, 0xff },
171 { 0xb8, 0xff },
172 { 0xb9, 0xfc },
173 { 0xba, 0x00 },
174 { 0xbb, 0x00 },
175 { 0xbc, 0x00 },
176 { 0xd0, 0x30 },
177 { 0xe4, 0x84 },
178 { 0xf0, 0x48 },
179 { 0xf1, 0x19 },
180 { 0xf2, 0x5a },
181 { 0xf3, 0x8e },
182 { 0xf4, 0x2d },
183 { 0xf5, 0x07 },
184 { 0xf6, 0x5a },
185 { 0xf7, 0xba },
186 { 0xf8, 0xd7 },
187};
188
189static struct regdata s921_prefreq[] = {
190 { 0x47, 0x60 },
191 { 0x68, 0x00 },
192 { 0x69, 0x89 },
193 { 0xf0, 0x48 },
194 { 0xf1, 0x19 },
195};
196
197static struct regdata s921_postfreq[] = {
198 { 0xf5, 0xae },
199 { 0xf6, 0xb7 },
200 { 0xf7, 0xba },
201 { 0xf8, 0xd7 },
202 { 0x68, 0x0a },
203 { 0x69, 0x09 },
204};
205
206static int s921_i2c_writereg(struct s921_state *state,
207 u8 i2c_addr, int reg, int data)
208{
209 u8 buf[] = { reg, data };
210 struct i2c_msg msg = {
211 .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
212 };
213 int rc;
214
215 rc = i2c_transfer(state->i2c, &msg, 1);
216 if (rc != 1) {
217 printk("%s: writereg rcor(rc == %i, reg == 0x%02x,"
218 " data == 0x%02x)\n", __func__, rc, reg, data);
219 return rc;
220 }
221
222 return 0;
223}
224
225static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr,
226 struct regdata *rd, int size)
227{
228 int i, rc;
229
230 for (i = 0; i < size; i++) {
231 rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data);
232 if (rc < 0)
233 return rc;
234 }
235 return 0;
236}
237
238static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg)
239{
240 u8 val;
241 int rc;
242 struct i2c_msg msg[] = {
243 { .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
244 { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
245 };
246
247 rc = i2c_transfer(state->i2c, msg, 2);
248
249 if (rc != 2) {
250 rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc);
251 return rc;
252 }
253
254 return val;
255}
256
257#define s921_readreg(state, reg) \
258 s921_i2c_readreg(state, state->config->demod_address, reg)
259#define s921_writereg(state, reg, val) \
260 s921_i2c_writereg(state, state->config->demod_address, reg, val)
261#define s921_writeregdata(state, regdata) \
262 s921_i2c_writeregdata(state, state->config->demod_address, \
263 regdata, ARRAY_SIZE(regdata))
264
Mauro Carvalho Chehab16e3d132011-12-26 13:42:21 -0300265static int s921_pll_tune(struct dvb_frontend *fe)
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300266{
Mauro Carvalho Chehab16e3d132011-12-26 13:42:21 -0300267 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300268 struct s921_state *state = fe->demodulator_priv;
269 int band, rc, i;
270 unsigned long f_offset;
271 u8 f_switch;
272 u64 offset;
273
274 dprintk("frequency=%i\n", p->frequency);
275
276 for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++)
277 if (p->frequency < s921_bandselect[band].freq_low)
278 break;
279 band--;
280
281 if (band < 0) {
282 rc("%s: frequency out of range\n", __func__);
283 return -EINVAL;
284 }
285
286 f_switch = s921_bandselect[band].band_reg;
287
288 offset = ((u64)p->frequency) * 258;
289 do_div(offset, 6000000);
290 f_offset = ((unsigned long)offset) + 2321;
291
292 rc = s921_writeregdata(state, s921_prefreq);
293 if (rc < 0)
294 return rc;
295
296 rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff);
297 if (rc < 0)
298 return rc;
299
300 rc = s921_writereg(state, 0xf3, f_offset & 0xff);
301 if (rc < 0)
302 return rc;
303
304 rc = s921_writereg(state, 0xf4, f_switch);
305 if (rc < 0)
306 return rc;
307
308 rc = s921_writeregdata(state, s921_postfreq);
309 if (rc < 0)
310 return rc;
311
312 for (i = 0 ; i < 6; i++) {
313 rc = s921_readreg(state, 0x80);
314 dprintk("status 0x80: %02x\n", rc);
315 }
316 rc = s921_writereg(state, 0x01, 0x40);
317 if (rc < 0)
318 return rc;
319
320 rc = s921_readreg(state, 0x01);
321 dprintk("status 0x01: %02x\n", rc);
322
323 rc = s921_readreg(state, 0x80);
324 dprintk("status 0x80: %02x\n", rc);
325
326 rc = s921_readreg(state, 0x80);
327 dprintk("status 0x80: %02x\n", rc);
328
329 rc = s921_readreg(state, 0x32);
330 dprintk("status 0x32: %02x\n", rc);
331
332 dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset);
333
334 return 0;
335}
336
337static int s921_initfe(struct dvb_frontend *fe)
338{
339 struct s921_state *state = fe->demodulator_priv;
340 int rc;
341
342 dprintk("\n");
343
344 rc = s921_writeregdata(state, s921_init);
345 if (rc < 0)
346 return rc;
347
348 return 0;
349}
350
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300351static int s921_read_status(struct dvb_frontend *fe, enum fe_status *status)
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300352{
353 struct s921_state *state = fe->demodulator_priv;
354 int regstatus, rc;
355
356 *status = 0;
357
358 rc = s921_readreg(state, 0x81);
359 if (rc < 0)
360 return rc;
361
362 regstatus = rc << 8;
363
364 rc = s921_readreg(state, 0x82);
365 if (rc < 0)
366 return rc;
367
368 regstatus |= rc;
369
370 dprintk("status = %04x\n", regstatus);
371
372 /* Full Sync - We don't know what each bit means on regs 0x81/0x82 */
373 if ((regstatus & 0xff) == 0x40) {
374 *status = FE_HAS_SIGNAL |
375 FE_HAS_CARRIER |
376 FE_HAS_VITERBI |
377 FE_HAS_SYNC |
378 FE_HAS_LOCK;
379 } else if (regstatus & 0x40) {
380 /* This is close to Full Sync, but not enough to get useful info */
381 *status = FE_HAS_SIGNAL |
382 FE_HAS_CARRIER |
383 FE_HAS_VITERBI |
384 FE_HAS_SYNC;
385 }
386
387 return 0;
388}
389
390static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
391{
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300392 enum fe_status status;
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300393 struct s921_state *state = fe->demodulator_priv;
394 int rc;
395
396 /* FIXME: Use the proper register for it... 0x80? */
397 rc = s921_read_status(fe, &status);
398 if (rc < 0)
399 return rc;
400
401 *strength = (status & FE_HAS_LOCK) ? 0xffff : 0;
402
403 dprintk("strength = 0x%04x\n", *strength);
404
405 rc = s921_readreg(state, 0x01);
406 dprintk("status 0x01: %02x\n", rc);
407
408 rc = s921_readreg(state, 0x80);
409 dprintk("status 0x80: %02x\n", rc);
410
411 rc = s921_readreg(state, 0x32);
412 dprintk("status 0x32: %02x\n", rc);
413
414 return 0;
415}
416
Mauro Carvalho Chehab16e3d132011-12-26 13:42:21 -0300417static int s921_set_frontend(struct dvb_frontend *fe)
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300418{
Mauro Carvalho Chehab16e3d132011-12-26 13:42:21 -0300419 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300420 struct s921_state *state = fe->demodulator_priv;
421 int rc;
422
423 dprintk("\n");
424
425 /* FIXME: We don't know how to use non-auto mode */
426
Mauro Carvalho Chehab16e3d132011-12-26 13:42:21 -0300427 rc = s921_pll_tune(fe);
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300428 if (rc < 0)
429 return rc;
430
431 state->currentfreq = p->frequency;
432
433 return 0;
434}
435
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -0300436static int s921_get_frontend(struct dvb_frontend *fe)
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300437{
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -0300438 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300439 struct s921_state *state = fe->demodulator_priv;
440
441 /* FIXME: Probably it is possible to get it from regs f1 and f2 */
442 p->frequency = state->currentfreq;
Mauro Carvalho Chehab63aad052011-12-27 08:25:33 -0300443 p->delivery_system = SYS_ISDBT;
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300444
445 return 0;
446}
447
448static int s921_tune(struct dvb_frontend *fe,
Mauro Carvalho Chehab7e072222011-12-26 17:48:33 -0300449 bool re_tune,
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300450 unsigned int mode_flags,
451 unsigned int *delay,
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300452 enum fe_status *status)
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300453{
454 int rc = 0;
455
456 dprintk("\n");
457
Mauro Carvalho Chehab7e072222011-12-26 17:48:33 -0300458 if (re_tune)
Mauro Carvalho Chehab16e3d132011-12-26 13:42:21 -0300459 rc = s921_set_frontend(fe);
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300460
461 if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
462 s921_read_status(fe, status);
463
464 return rc;
465}
466
467static int s921_get_algo(struct dvb_frontend *fe)
468{
469 return 1; /* FE_ALGO_HW */
470}
471
472static void s921_release(struct dvb_frontend *fe)
473{
474 struct s921_state *state = fe->demodulator_priv;
475
476 dprintk("\n");
477 kfree(state);
478}
479
480static struct dvb_frontend_ops s921_ops;
481
482struct dvb_frontend *s921_attach(const struct s921_config *config,
483 struct i2c_adapter *i2c)
484{
485 /* allocate memory for the internal state */
486 struct s921_state *state =
487 kzalloc(sizeof(struct s921_state), GFP_KERNEL);
488
489 dprintk("\n");
Peter Senna Tschudin4a0543e2012-09-12 08:56:01 -0300490 if (!state) {
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300491 rc("Unable to kzalloc\n");
Peter Senna Tschudin4a0543e2012-09-12 08:56:01 -0300492 return NULL;
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300493 }
494
495 /* setup the state */
496 state->config = config;
497 state->i2c = i2c;
498
499 /* create dvb_frontend */
500 memcpy(&state->frontend.ops, &s921_ops,
501 sizeof(struct dvb_frontend_ops));
502 state->frontend.demodulator_priv = state;
503
504 return &state->frontend;
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300505}
506EXPORT_SYMBOL(s921_attach);
507
508static struct dvb_frontend_ops s921_ops = {
Mauro Carvalho Chehab16e3d132011-12-26 13:42:21 -0300509 .delsys = { SYS_ISDBT },
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300510 /* Use dib8000 values per default */
511 .info = {
512 .name = "Sharp S921",
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300513 .frequency_min = 470000000,
514 /*
515 * Max should be 770MHz instead, according with Sharp docs,
516 * but Leadership doc says it works up to 806 MHz. This is
517 * required to get channel 69, used in Brazil
518 */
519 .frequency_max = 806000000,
520 .frequency_tolerance = 0,
521 .caps = FE_CAN_INVERSION_AUTO |
522 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
523 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
524 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
525 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
526 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
527 FE_CAN_HIERARCHY_AUTO,
528 },
529
530 .release = s921_release,
531
532 .init = s921_initfe,
Mauro Carvalho Chehab16e3d132011-12-26 13:42:21 -0300533 .set_frontend = s921_set_frontend,
534 .get_frontend = s921_get_frontend,
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300535 .read_status = s921_read_status,
536 .read_signal_strength = s921_read_signal_strength,
537 .tune = s921_tune,
538 .get_frontend_algo = s921_get_algo,
539};
540
541MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware");
Mauro Carvalho Chehab37e59f82014-02-07 08:03:07 -0200542MODULE_AUTHOR("Mauro Carvalho Chehab");
Mauro Carvalho Chehab3a509bb2010-09-10 16:49:47 -0300543MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>");
544MODULE_LICENSE("GPL");