1 /*
2  *  mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
3  *
4  *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #include "mxl111sf-tuner.h"
22 #include "mxl111sf-phy.h"
23 #include "mxl111sf-reg.h"
24 
25 /* debug */
26 static int mxl111sf_tuner_debug;
27 module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
28 MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
29 
30 #define mxl_dbg(fmt, arg...) \
31 	if (mxl111sf_tuner_debug) \
32 		mxl_printk(KERN_DEBUG, fmt, ##arg)
33 
34 #define err pr_err
35 
36 /* ------------------------------------------------------------------------ */
37 
38 struct mxl111sf_tuner_state {
39 	struct mxl111sf_state *mxl_state;
40 
41 	struct mxl111sf_tuner_config *cfg;
42 
43 	enum mxl_if_freq if_freq;
44 
45 	u32 frequency;
46 	u32 bandwidth;
47 };
48 
49 static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
50 				   u8 addr, u8 *data)
51 {
52 	return (state->cfg->read_reg) ?
53 		state->cfg->read_reg(state->mxl_state, addr, data) :
54 		-EINVAL;
55 }
56 
57 static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
58 				    u8 addr, u8 data)
59 {
60 	return (state->cfg->write_reg) ?
61 		state->cfg->write_reg(state->mxl_state, addr, data) :
62 		-EINVAL;
63 }
64 
65 static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
66 			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
67 {
68 	return (state->cfg->program_regs) ?
69 		state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
70 		-EINVAL;
71 }
72 
73 static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
74 					  int onoff)
75 {
76 	return (state->cfg->top_master_ctrl) ?
77 		state->cfg->top_master_ctrl(state->mxl_state, onoff) :
78 		-EINVAL;
79 }
80 
81 /* ------------------------------------------------------------------------ */
82 
83 static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
84 	{0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
85 			       DIG_MODEINDEX, _A, _CSF, */
86 	{0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
87 	{0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
88 	{0,    0,    0}
89 };
90 
91 /* ------------------------------------------------------------------------ */
92 
93 static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
94 								  u8 bw)
95 {
96 	u8 filt_bw;
97 
98 	/* set channel bandwidth */
99 	switch (bw) {
100 	case 0: /* ATSC */
101 		filt_bw = 25;
102 		break;
103 	case 1: /* QAM */
104 		filt_bw = 69;
105 		break;
106 	case 6:
107 		filt_bw = 21;
108 		break;
109 	case 7:
110 		filt_bw = 42;
111 		break;
112 	case 8:
113 		filt_bw = 63;
114 		break;
115 	default:
116 		err("%s: invalid bandwidth setting!", __func__);
117 		return NULL;
118 	}
119 
120 	/* calculate RF channel */
121 	freq /= 1000000;
122 
123 	freq *= 64;
124 #if 0
125 	/* do round */
126 	freq += 0.5;
127 #endif
128 	/* set bandwidth */
129 	mxl_phy_tune_rf[0].data = filt_bw;
130 
131 	/* set RF */
132 	mxl_phy_tune_rf[1].data = (freq & 0xff);
133 	mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
134 
135 	/* start tune */
136 	return mxl_phy_tune_rf;
137 }
138 
139 static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
140 {
141 	int ret;
142 	u8 ctrl;
143 #if 0
144 	u16 iffcw;
145 	u32 if_freq;
146 #endif
147 	mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
148 		state->cfg->invert_spectrum, state->cfg->if_freq);
149 
150 	/* set IF polarity */
151 	ctrl = state->cfg->invert_spectrum;
152 
153 	ctrl |= state->cfg->if_freq;
154 
155 	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
156 	if (mxl_fail(ret))
157 		goto fail;
158 
159 #if 0
160 	if_freq /= 1000000;
161 
162 	/* do round */
163 	if_freq += 0.5;
164 
165 	if (MXL_IF_LO == state->cfg->if_freq) {
166 		ctrl = 0x08;
167 		iffcw = (u16)(if_freq / (108 * 4096));
168 	} else if (MXL_IF_HI == state->cfg->if_freq) {
169 		ctrl = 0x08;
170 		iffcw = (u16)(if_freq / (216 * 4096));
171 	} else {
172 		ctrl = 0;
173 		iffcw = 0;
174 	}
175 
176 	ctrl |= (iffcw >> 8);
177 #endif
178 	ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
179 	if (mxl_fail(ret))
180 		goto fail;
181 
182 	ctrl &= 0xf0;
183 	ctrl |= 0x90;
184 
185 	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
186 	if (mxl_fail(ret))
187 		goto fail;
188 
189 #if 0
190 	ctrl = iffcw & 0x00ff;
191 #endif
192 	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
193 	if (mxl_fail(ret))
194 		goto fail;
195 
196 	state->if_freq = state->cfg->if_freq;
197 fail:
198 	return ret;
199 }
200 
201 static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
202 {
203 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
204 	static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
205 	int ret;
206 	u8 mxl_mode;
207 
208 	mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
209 
210 	/* stop tune */
211 	ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
212 	if (mxl_fail(ret))
213 		goto fail;
214 
215 	/* check device mode */
216 	ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
217 	if (mxl_fail(ret))
218 		goto fail;
219 
220 	/* Fill out registers for channel tune */
221 	reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
222 	if (!reg_ctrl_array)
223 		return -EINVAL;
224 
225 	ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
226 	if (mxl_fail(ret))
227 		goto fail;
228 
229 	if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
230 		/* IF tuner mode only */
231 		mxl1x1sf_tuner_top_master_ctrl(state, 0);
232 		mxl1x1sf_tuner_top_master_ctrl(state, 1);
233 		mxl1x1sf_tuner_set_if_output_freq(state);
234 	}
235 
236 	ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
237 	if (mxl_fail(ret))
238 		goto fail;
239 
240 	if (state->cfg->ant_hunt)
241 		state->cfg->ant_hunt(fe);
242 fail:
243 	return ret;
244 }
245 
246 static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
247 					  int *rf_synth_lock,
248 					  int *ref_synth_lock)
249 {
250 	int ret;
251 	u8 data;
252 
253 	*rf_synth_lock = 0;
254 	*ref_synth_lock = 0;
255 
256 	ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
257 	if (mxl_fail(ret))
258 		goto fail;
259 
260 	*ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
261 	*rf_synth_lock  = ((data & 0x0c) == 0x0c) ? 1 : 0;
262 fail:
263 	return ret;
264 }
265 
266 #if 0
267 static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
268 					 int onoff)
269 {
270 	return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
271 					onoff ? 1 : 0);
272 }
273 #endif
274 
275 /* ------------------------------------------------------------------------ */
276 
277 static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
278 {
279 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
280 	u32 delsys  = c->delivery_system;
281 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
282 	int ret;
283 	u8 bw;
284 
285 	mxl_dbg("()");
286 
287 	switch (delsys) {
288 	case SYS_ATSC:
289 	case SYS_ATSCMH:
290 		bw = 0; /* ATSC */
291 		break;
292 	case SYS_DVBC_ANNEX_B:
293 		bw = 1; /* US CABLE */
294 		break;
295 	case SYS_DVBT:
296 		switch (c->bandwidth_hz) {
297 		case 6000000:
298 			bw = 6;
299 			break;
300 		case 7000000:
301 			bw = 7;
302 			break;
303 		case 8000000:
304 			bw = 8;
305 			break;
306 		default:
307 			err("%s: bandwidth not set!", __func__);
308 			return -EINVAL;
309 		}
310 		break;
311 	default:
312 		err("%s: modulation type not supported!", __func__);
313 		return -EINVAL;
314 	}
315 	ret = mxl1x1sf_tune_rf(fe, c->frequency, bw);
316 	if (mxl_fail(ret))
317 		goto fail;
318 
319 	state->frequency = c->frequency;
320 	state->bandwidth = c->bandwidth_hz;
321 fail:
322 	return ret;
323 }
324 
325 /* ------------------------------------------------------------------------ */
326 
327 #if 0
328 static int mxl111sf_tuner_init(struct dvb_frontend *fe)
329 {
330 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
331 	int ret;
332 
333 	/* wake from standby handled by usb driver */
334 
335 	return ret;
336 }
337 
338 static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
339 {
340 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
341 	int ret;
342 
343 	/* enter standby mode handled by usb driver */
344 
345 	return ret;
346 }
347 #endif
348 
349 /* ------------------------------------------------------------------------ */
350 
351 static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
352 {
353 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
354 	int rf_locked, ref_locked, ret;
355 
356 	*status = 0;
357 
358 	ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
359 	if (mxl_fail(ret))
360 		goto fail;
361 	mxl_info("%s%s", rf_locked ? "rf locked " : "",
362 		 ref_locked ? "ref locked" : "");
363 
364 	if ((rf_locked) || (ref_locked))
365 		*status |= TUNER_STATUS_LOCKED;
366 fail:
367 	return ret;
368 }
369 
370 static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
371 {
372 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
373 	u8 val1, val2;
374 	int ret;
375 
376 	*strength = 0;
377 
378 	ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
379 	if (mxl_fail(ret))
380 		goto fail;
381 	ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
382 	if (mxl_fail(ret))
383 		goto fail;
384 	ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
385 	if (mxl_fail(ret))
386 		goto fail;
387 
388 	*strength = val1 | ((val2 & 0x07) << 8);
389 fail:
390 	ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
391 	mxl_fail(ret);
392 
393 	return ret;
394 }
395 
396 /* ------------------------------------------------------------------------ */
397 
398 static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
399 {
400 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
401 	*frequency = state->frequency;
402 	return 0;
403 }
404 
405 static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
406 {
407 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
408 	*bandwidth = state->bandwidth;
409 	return 0;
410 }
411 
412 static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe,
413 					   u32 *frequency)
414 {
415 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
416 
417 	*frequency = 0;
418 
419 	switch (state->if_freq) {
420 	case MXL_IF_4_0:   /* 4.0   MHz */
421 		*frequency = 4000000;
422 		break;
423 	case MXL_IF_4_5:   /* 4.5   MHz */
424 		*frequency = 4500000;
425 		break;
426 	case MXL_IF_4_57:  /* 4.57  MHz */
427 		*frequency = 4570000;
428 		break;
429 	case MXL_IF_5_0:   /* 5.0   MHz */
430 		*frequency = 5000000;
431 		break;
432 	case MXL_IF_5_38:  /* 5.38  MHz */
433 		*frequency = 5380000;
434 		break;
435 	case MXL_IF_6_0:   /* 6.0   MHz */
436 		*frequency = 6000000;
437 		break;
438 	case MXL_IF_6_28:  /* 6.28  MHz */
439 		*frequency = 6280000;
440 		break;
441 	case MXL_IF_7_2:   /* 7.2   MHz */
442 		*frequency = 7200000;
443 		break;
444 	case MXL_IF_35_25: /* 35.25 MHz */
445 		*frequency = 35250000;
446 		break;
447 	case MXL_IF_36:    /* 36    MHz */
448 		*frequency = 36000000;
449 		break;
450 	case MXL_IF_36_15: /* 36.15 MHz */
451 		*frequency = 36150000;
452 		break;
453 	case MXL_IF_44:    /* 44    MHz */
454 		*frequency = 44000000;
455 		break;
456 	}
457 	return 0;
458 }
459 
460 static int mxl111sf_tuner_release(struct dvb_frontend *fe)
461 {
462 	struct mxl111sf_tuner_state *state = fe->tuner_priv;
463 	mxl_dbg("()");
464 	kfree(state);
465 	fe->tuner_priv = NULL;
466 	return 0;
467 }
468 
469 /* ------------------------------------------------------------------------- */
470 
471 static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
472 	.info = {
473 		.name = "MaxLinear MxL111SF",
474 #if 0
475 		.frequency_min  = ,
476 		.frequency_max  = ,
477 		.frequency_step = ,
478 #endif
479 	},
480 #if 0
481 	.init              = mxl111sf_tuner_init,
482 	.sleep             = mxl111sf_tuner_sleep,
483 #endif
484 	.set_params        = mxl111sf_tuner_set_params,
485 	.get_status        = mxl111sf_tuner_get_status,
486 	.get_rf_strength   = mxl111sf_get_rf_strength,
487 	.get_frequency     = mxl111sf_tuner_get_frequency,
488 	.get_bandwidth     = mxl111sf_tuner_get_bandwidth,
489 	.get_if_frequency  = mxl111sf_tuner_get_if_frequency,
490 	.release           = mxl111sf_tuner_release,
491 };
492 
493 struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
494 					   struct mxl111sf_state *mxl_state,
495 					   struct mxl111sf_tuner_config *cfg)
496 {
497 	struct mxl111sf_tuner_state *state = NULL;
498 
499 	mxl_dbg("()");
500 
501 	state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
502 	if (state == NULL)
503 		return NULL;
504 
505 	state->mxl_state = mxl_state;
506 	state->cfg = cfg;
507 
508 	memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
509 	       sizeof(struct dvb_tuner_ops));
510 
511 	fe->tuner_priv = state;
512 	return fe;
513 }
514 EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
515 
516 MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
517 MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
518 MODULE_LICENSE("GPL");
519 MODULE_VERSION("0.1");
520 
521 /*
522  * Overrides for Emacs so that we follow Linus's tabbing style.
523  * ---------------------------------------------------------------------------
524  * Local variables:
525  * c-basic-offset: 8
526  * End:
527  */
528