1 /*
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  *
5  *   Copyright (C) 2009-2010 Mauro Carvalho Chehab
6  *   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 <media/dvb_frontend.h>
29 #include "s921.h"
30 
31 static int debug = 1;
32 module_param(debug, int, 0644);
33 MODULE_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 
47 struct 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  */
62 static 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 
76 struct regdata {
77 	u8 reg;
78 	u8 data;
79 };
80 
81 static 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 
189 static struct regdata s921_prefreq[] = {
190 	{ 0x47, 0x60 },
191 	{ 0x68, 0x00 },
192 	{ 0x69, 0x89 },
193 	{ 0xf0, 0x48 },
194 	{ 0xf1, 0x19 },
195 };
196 
197 static struct regdata s921_postfreq[] = {
198 	{ 0xf5, 0xae },
199 	{ 0xf6, 0xb7 },
200 	{ 0xf7, 0xba },
201 	{ 0xf8, 0xd7 },
202 	{ 0x68, 0x0a },
203 	{ 0x69, 0x09 },
204 };
205 
s921_i2c_writereg(struct s921_state * state,u8 i2c_addr,int reg,int data)206 static 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, data == 0x%02x)\n",
218 		       __func__, rc, reg, data);
219 		return rc;
220 	}
221 
222 	return 0;
223 }
224 
s921_i2c_writeregdata(struct s921_state * state,u8 i2c_addr,struct regdata * rd,int size)225 static 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 
s921_i2c_readreg(struct s921_state * state,u8 i2c_addr,u8 reg)238 static 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 
s921_pll_tune(struct dvb_frontend * fe)265 static int s921_pll_tune(struct dvb_frontend *fe)
266 {
267 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
268 	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 
s921_initfe(struct dvb_frontend * fe)337 static 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 
s921_read_status(struct dvb_frontend * fe,enum fe_status * status)351 static int s921_read_status(struct dvb_frontend *fe, enum fe_status *status)
352 {
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 
s921_read_signal_strength(struct dvb_frontend * fe,u16 * strength)390 static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
391 {
392 	enum fe_status	status;
393 	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 
s921_set_frontend(struct dvb_frontend * fe)417 static int s921_set_frontend(struct dvb_frontend *fe)
418 {
419 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
420 	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 
427 	rc = s921_pll_tune(fe);
428 	if (rc < 0)
429 		return rc;
430 
431 	state->currentfreq = p->frequency;
432 
433 	return 0;
434 }
435 
s921_get_frontend(struct dvb_frontend * fe,struct dtv_frontend_properties * p)436 static int s921_get_frontend(struct dvb_frontend *fe,
437 			     struct dtv_frontend_properties *p)
438 {
439 	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;
443 	p->delivery_system = SYS_ISDBT;
444 
445 	return 0;
446 }
447 
s921_tune(struct dvb_frontend * fe,bool re_tune,unsigned int mode_flags,unsigned int * delay,enum fe_status * status)448 static int s921_tune(struct dvb_frontend *fe,
449 			bool re_tune,
450 			unsigned int mode_flags,
451 			unsigned int *delay,
452 			enum fe_status *status)
453 {
454 	int rc = 0;
455 
456 	dprintk("\n");
457 
458 	if (re_tune)
459 		rc = s921_set_frontend(fe);
460 
461 	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
462 		s921_read_status(fe, status);
463 
464 	return rc;
465 }
466 
s921_get_algo(struct dvb_frontend * fe)467 static enum dvbfe_algo s921_get_algo(struct dvb_frontend *fe)
468 {
469 	return DVBFE_ALGO_HW;
470 }
471 
s921_release(struct dvb_frontend * fe)472 static 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 
480 static const struct dvb_frontend_ops s921_ops;
481 
s921_attach(const struct s921_config * config,struct i2c_adapter * i2c)482 struct 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");
490 	if (!state) {
491 		rc("Unable to kzalloc\n");
492 		return NULL;
493 	}
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;
505 }
506 EXPORT_SYMBOL_GPL(s921_attach);
507 
508 static const struct dvb_frontend_ops s921_ops = {
509 	.delsys = { SYS_ISDBT },
510 	/* Use dib8000 values per default */
511 	.info = {
512 		.name = "Sharp S921",
513 		.frequency_min_hz = 470 * MHz,
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_hz = 806 * MHz,
520 		.caps =  FE_CAN_INVERSION_AUTO |
521 			 FE_CAN_FEC_1_2  | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
522 			 FE_CAN_FEC_5_6  | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
523 			 FE_CAN_QPSK     | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
524 			 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
525 			 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
526 			 FE_CAN_HIERARCHY_AUTO,
527 	},
528 
529 	.release = s921_release,
530 
531 	.init = s921_initfe,
532 	.set_frontend = s921_set_frontend,
533 	.get_frontend = s921_get_frontend,
534 	.read_status = s921_read_status,
535 	.read_signal_strength = s921_read_signal_strength,
536 	.tune = s921_tune,
537 	.get_frontend_algo = s921_get_algo,
538 };
539 
540 MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware");
541 MODULE_AUTHOR("Mauro Carvalho Chehab");
542 MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>");
543 MODULE_LICENSE("GPL");
544