• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/media/dvb/frontends/
1/*
2 * Driver for
3 *    Samsung S5H1420 and
4 *    PnpNetwork PN1010 QPSK Demodulator
5 *
6 * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
7 * Copyright (C) 2005-8 Patrick Boettcher <pb@linuxtv.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/string.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
31#include <linux/jiffies.h>
32#include <asm/div64.h>
33
34#include <linux/i2c.h>
35
36
37#include "dvb_frontend.h"
38#include "s5h1420.h"
39#include "s5h1420_priv.h"
40
41#define TONE_FREQ 22000
42
43struct s5h1420_state {
44	struct i2c_adapter* i2c;
45	const struct s5h1420_config* config;
46
47	struct dvb_frontend frontend;
48	struct i2c_adapter tuner_i2c_adapter;
49
50	u8 CON_1_val;
51
52	u8 postlocked:1;
53	u32 fclk;
54	u32 tunedfreq;
55	fe_code_rate_t fec_inner;
56	u32 symbol_rate;
57
58	u8 shadow[256];
59};
60
61static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
62static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
63				     struct dvb_frontend_tune_settings* fesettings);
64
65
66static int debug;
67module_param(debug, int, 0644);
68MODULE_PARM_DESC(debug, "enable debugging");
69
70#define dprintk(x...) do { \
71	if (debug) \
72		printk(KERN_DEBUG "S5H1420: " x); \
73} while (0)
74
75static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
76{
77	int ret;
78	u8 b[2];
79	struct i2c_msg msg[] = {
80		{ .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
81		{ .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
82		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
83	};
84
85	b[0] = (reg - 1) & 0xff;
86	b[1] = state->shadow[(reg - 1) & 0xff];
87
88	if (state->config->repeated_start_workaround) {
89		ret = i2c_transfer(state->i2c, msg, 3);
90		if (ret != 3)
91			return ret;
92	} else {
93		ret = i2c_transfer(state->i2c, &msg[1], 1);
94		if (ret != 1)
95			return ret;
96		ret = i2c_transfer(state->i2c, &msg[2], 1);
97		if (ret != 1)
98			return ret;
99	}
100
101	/* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
102
103	return b[0];
104}
105
106static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
107{
108	u8 buf[] = { reg, data };
109	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
110	int err;
111
112	/* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
113	err = i2c_transfer(state->i2c, &msg, 1);
114	if (err != 1) {
115		dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
116		return -EREMOTEIO;
117	}
118	state->shadow[reg] = data;
119
120	return 0;
121}
122
123static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
124{
125	struct s5h1420_state* state = fe->demodulator_priv;
126
127	dprintk("enter %s\n", __func__);
128
129	switch(voltage) {
130	case SEC_VOLTAGE_13:
131		s5h1420_writereg(state, 0x3c,
132				 (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
133		break;
134
135	case SEC_VOLTAGE_18:
136		s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) | 0x03);
137		break;
138
139	case SEC_VOLTAGE_OFF:
140		s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) & 0xfd);
141		break;
142	}
143
144	dprintk("leave %s\n", __func__);
145	return 0;
146}
147
148static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
149{
150	struct s5h1420_state* state = fe->demodulator_priv;
151
152	dprintk("enter %s\n", __func__);
153	switch(tone) {
154	case SEC_TONE_ON:
155		s5h1420_writereg(state, 0x3b,
156				 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
157		break;
158
159	case SEC_TONE_OFF:
160		s5h1420_writereg(state, 0x3b,
161				 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
162		break;
163	}
164	dprintk("leave %s\n", __func__);
165
166	return 0;
167}
168
169static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
170				    struct dvb_diseqc_master_cmd* cmd)
171{
172	struct s5h1420_state* state = fe->demodulator_priv;
173	u8 val;
174	int i;
175	unsigned long timeout;
176	int result = 0;
177
178	dprintk("enter %s\n", __func__);
179	if (cmd->msg_len > 8)
180		return -EINVAL;
181
182	/* setup for DISEQC */
183	val = s5h1420_readreg(state, 0x3b);
184	s5h1420_writereg(state, 0x3b, 0x02);
185	msleep(15);
186
187	/* write the DISEQC command bytes */
188	for(i=0; i< cmd->msg_len; i++) {
189		s5h1420_writereg(state, 0x3d + i, cmd->msg[i]);
190	}
191
192	/* kick off transmission */
193	s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) |
194				      ((cmd->msg_len-1) << 4) | 0x08);
195
196	/* wait for transmission to complete */
197	timeout = jiffies + ((100*HZ) / 1000);
198	while(time_before(jiffies, timeout)) {
199		if (!(s5h1420_readreg(state, 0x3b) & 0x08))
200			break;
201
202		msleep(5);
203	}
204	if (time_after(jiffies, timeout))
205		result = -ETIMEDOUT;
206
207	/* restore original settings */
208	s5h1420_writereg(state, 0x3b, val);
209	msleep(15);
210	dprintk("leave %s\n", __func__);
211	return result;
212}
213
214static int s5h1420_recv_slave_reply (struct dvb_frontend* fe,
215				     struct dvb_diseqc_slave_reply* reply)
216{
217	struct s5h1420_state* state = fe->demodulator_priv;
218	u8 val;
219	int i;
220	int length;
221	unsigned long timeout;
222	int result = 0;
223
224	/* setup for DISEQC recieve */
225	val = s5h1420_readreg(state, 0x3b);
226	s5h1420_writereg(state, 0x3b, 0x82);
227	msleep(15);
228
229	/* wait for reception to complete */
230	timeout = jiffies + ((reply->timeout*HZ) / 1000);
231	while(time_before(jiffies, timeout)) {
232		if (!(s5h1420_readreg(state, 0x3b) & 0x80))
233			break;
234
235		msleep(5);
236	}
237	if (time_after(jiffies, timeout)) {
238		result = -ETIMEDOUT;
239		goto exit;
240	}
241
242	if (s5h1420_readreg(state, 0x49)) {
243		result = -EIO;
244		goto exit;
245	}
246
247	/* check length */
248	length = (s5h1420_readreg(state, 0x3b) & 0x70) >> 4;
249	if (length > sizeof(reply->msg)) {
250		result = -EOVERFLOW;
251		goto exit;
252	}
253	reply->msg_len = length;
254
255	/* extract data */
256	for(i=0; i< length; i++) {
257		reply->msg[i] = s5h1420_readreg(state, 0x3d + i);
258	}
259
260exit:
261	/* restore original settings */
262	s5h1420_writereg(state, 0x3b, val);
263	msleep(15);
264	return result;
265}
266
267static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
268{
269	struct s5h1420_state* state = fe->demodulator_priv;
270	u8 val;
271	int result = 0;
272	unsigned long timeout;
273
274	/* setup for tone burst */
275	val = s5h1420_readreg(state, 0x3b);
276	s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x70) | 0x01);
277
278	/* set value for B position if requested */
279	if (minicmd == SEC_MINI_B) {
280		s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x04);
281	}
282	msleep(15);
283
284	/* start transmission */
285	s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08);
286
287	/* wait for transmission to complete */
288	timeout = jiffies + ((100*HZ) / 1000);
289	while(time_before(jiffies, timeout)) {
290		if (!(s5h1420_readreg(state, 0x3b) & 0x08))
291			break;
292
293		msleep(5);
294	}
295	if (time_after(jiffies, timeout))
296		result = -ETIMEDOUT;
297
298	/* restore original settings */
299	s5h1420_writereg(state, 0x3b, val);
300	msleep(15);
301	return result;
302}
303
304static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
305{
306	u8 val;
307	fe_status_t status = 0;
308
309	val = s5h1420_readreg(state, 0x14);
310	if (val & 0x02)
311		status |=  FE_HAS_SIGNAL;
312	if (val & 0x01)
313		status |=  FE_HAS_CARRIER;
314	val = s5h1420_readreg(state, 0x36);
315	if (val & 0x01)
316		status |=  FE_HAS_VITERBI;
317	if (val & 0x20)
318		status |=  FE_HAS_SYNC;
319	if (status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|FE_HAS_SYNC))
320		status |=  FE_HAS_LOCK;
321
322	return status;
323}
324
325static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
326{
327	struct s5h1420_state* state = fe->demodulator_priv;
328	u8 val;
329
330	dprintk("enter %s\n", __func__);
331
332	if (status == NULL)
333		return -EINVAL;
334
335	/* determine lock state */
336	*status = s5h1420_get_status_bits(state);
337
338	/* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
339	the inversion, wait a bit and check again */
340	if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
341		val = s5h1420_readreg(state, Vit10);
342		if ((val & 0x07) == 0x03) {
343			if (val & 0x08)
344				s5h1420_writereg(state, Vit09, 0x13);
345			else
346				s5h1420_writereg(state, Vit09, 0x1b);
347
348			/* wait a bit then update lock status */
349			mdelay(200);
350			*status = s5h1420_get_status_bits(state);
351		}
352	}
353
354	/* perform post lock setup */
355	if ((*status & FE_HAS_LOCK) && !state->postlocked) {
356
357		/* calculate the data rate */
358		u32 tmp = s5h1420_getsymbolrate(state);
359		switch (s5h1420_readreg(state, Vit10) & 0x07) {
360		case 0: tmp = (tmp * 2 * 1) / 2; break;
361		case 1: tmp = (tmp * 2 * 2) / 3; break;
362		case 2: tmp = (tmp * 2 * 3) / 4; break;
363		case 3: tmp = (tmp * 2 * 5) / 6; break;
364		case 4: tmp = (tmp * 2 * 6) / 7; break;
365		case 5: tmp = (tmp * 2 * 7) / 8; break;
366		}
367
368		if (tmp == 0) {
369			printk(KERN_ERR "s5h1420: avoided division by 0\n");
370			tmp = 1;
371		}
372		tmp = state->fclk / tmp;
373
374
375		/* set the MPEG_CLK_INTL for the calculated data rate */
376		if (tmp < 2)
377			val = 0x00;
378		else if (tmp < 5)
379			val = 0x01;
380		else if (tmp < 9)
381			val = 0x02;
382		else if (tmp < 13)
383			val = 0x03;
384		else if (tmp < 17)
385			val = 0x04;
386		else if (tmp < 25)
387			val = 0x05;
388		else if (tmp < 33)
389			val = 0x06;
390		else
391			val = 0x07;
392		dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
393
394		s5h1420_writereg(state, FEC01, 0x18);
395		s5h1420_writereg(state, FEC01, 0x10);
396		s5h1420_writereg(state, FEC01, val);
397
398		/* Enable "MPEG_Out" */
399		val = s5h1420_readreg(state, Mpeg02);
400		s5h1420_writereg(state, Mpeg02, val | (1 << 6));
401
402		/* kicker disable */
403		val = s5h1420_readreg(state, QPSK01) & 0x7f;
404		s5h1420_writereg(state, QPSK01, val);
405
406		/* DC freeze TODO it was never activated by default or it can stay activated */
407
408		if (s5h1420_getsymbolrate(state) >= 20000000) {
409			s5h1420_writereg(state, Loop04, 0x8a);
410			s5h1420_writereg(state, Loop05, 0x6a);
411		} else {
412			s5h1420_writereg(state, Loop04, 0x58);
413			s5h1420_writereg(state, Loop05, 0x27);
414		}
415
416		/* post-lock processing has been done! */
417		state->postlocked = 1;
418	}
419
420	dprintk("leave %s\n", __func__);
421
422	return 0;
423}
424
425static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber)
426{
427	struct s5h1420_state* state = fe->demodulator_priv;
428
429	s5h1420_writereg(state, 0x46, 0x1d);
430	mdelay(25);
431
432	*ber = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
433
434	return 0;
435}
436
437static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength)
438{
439	struct s5h1420_state* state = fe->demodulator_priv;
440
441	u8 val = s5h1420_readreg(state, 0x15);
442
443	*strength =  (u16) ((val << 8) | val);
444
445	return 0;
446}
447
448static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
449{
450	struct s5h1420_state* state = fe->demodulator_priv;
451
452	s5h1420_writereg(state, 0x46, 0x1f);
453	mdelay(25);
454
455	*ucblocks = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
456
457	return 0;
458}
459
460static void s5h1420_reset(struct s5h1420_state* state)
461{
462	dprintk("%s\n", __func__);
463	s5h1420_writereg (state, 0x01, 0x08);
464	s5h1420_writereg (state, 0x01, 0x00);
465	udelay(10);
466}
467
468static void s5h1420_setsymbolrate(struct s5h1420_state* state,
469				  struct dvb_frontend_parameters *p)
470{
471	u8 v;
472	u64 val;
473
474	dprintk("enter %s\n", __func__);
475
476	val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
477	if (p->u.qpsk.symbol_rate < 29000000)
478		val *= 2;
479	do_div(val, (state->fclk / 1000));
480
481	dprintk("symbol rate register: %06llx\n", (unsigned long long)val);
482
483	v = s5h1420_readreg(state, Loop01);
484	s5h1420_writereg(state, Loop01, v & 0x7f);
485	s5h1420_writereg(state, Tnco01, val >> 16);
486	s5h1420_writereg(state, Tnco02, val >> 8);
487	s5h1420_writereg(state, Tnco03, val & 0xff);
488	s5h1420_writereg(state, Loop01,  v | 0x80);
489	dprintk("leave %s\n", __func__);
490}
491
492static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
493{
494	return state->symbol_rate;
495}
496
497static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
498{
499	int val;
500	u8 v;
501
502	dprintk("enter %s\n", __func__);
503
504	/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
505	 * divide fclk by 1000000 to get the correct value. */
506	val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
507
508	dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
509
510	v = s5h1420_readreg(state, Loop01);
511	s5h1420_writereg(state, Loop01, v & 0xbf);
512	s5h1420_writereg(state, Pnco01, val >> 16);
513	s5h1420_writereg(state, Pnco02, val >> 8);
514	s5h1420_writereg(state, Pnco03, val & 0xff);
515	s5h1420_writereg(state, Loop01, v | 0x40);
516	dprintk("leave %s\n", __func__);
517}
518
519static int s5h1420_getfreqoffset(struct s5h1420_state* state)
520{
521	int val;
522
523	s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
524	val  = s5h1420_readreg(state, 0x0e) << 16;
525	val |= s5h1420_readreg(state, 0x0f) << 8;
526	val |= s5h1420_readreg(state, 0x10);
527	s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
528
529	if (val & 0x800000)
530		val |= 0xff000000;
531
532	/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
533	 * divide fclk by 1000000 to get the correct value. */
534	val = (((-val) * (state->fclk/1000000)) / (1<<24));
535
536	return val;
537}
538
539static void s5h1420_setfec_inversion(struct s5h1420_state* state,
540				     struct dvb_frontend_parameters *p)
541{
542	u8 inversion = 0;
543	u8 vit08, vit09;
544
545	dprintk("enter %s\n", __func__);
546
547	if (p->inversion == INVERSION_OFF)
548		inversion = state->config->invert ? 0x08 : 0;
549	else if (p->inversion == INVERSION_ON)
550		inversion = state->config->invert ? 0 : 0x08;
551
552	if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
553		vit08 = 0x3f;
554		vit09 = 0;
555	} else {
556		switch(p->u.qpsk.fec_inner) {
557		case FEC_1_2:
558			vit08 = 0x01; vit09 = 0x10;
559			break;
560
561		case FEC_2_3:
562			vit08 = 0x02; vit09 = 0x11;
563			break;
564
565		case FEC_3_4:
566			vit08 = 0x04; vit09 = 0x12;
567			break;
568
569		case FEC_5_6:
570			vit08 = 0x08; vit09 = 0x13;
571			break;
572
573		case FEC_6_7:
574			vit08 = 0x10; vit09 = 0x14;
575			break;
576
577		case FEC_7_8:
578			vit08 = 0x20; vit09 = 0x15;
579			break;
580
581		default:
582			return;
583		}
584	}
585	vit09 |= inversion;
586	dprintk("fec: %02x %02x\n", vit08, vit09);
587	s5h1420_writereg(state, Vit08, vit08);
588	s5h1420_writereg(state, Vit09, vit09);
589	dprintk("leave %s\n", __func__);
590}
591
592static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
593{
594	switch(s5h1420_readreg(state, 0x32) & 0x07) {
595	case 0:
596		return FEC_1_2;
597
598	case 1:
599		return FEC_2_3;
600
601	case 2:
602		return FEC_3_4;
603
604	case 3:
605		return FEC_5_6;
606
607	case 4:
608		return FEC_6_7;
609
610	case 5:
611		return FEC_7_8;
612	}
613
614	return FEC_NONE;
615}
616
617static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
618{
619	if (s5h1420_readreg(state, 0x32) & 0x08)
620		return INVERSION_ON;
621
622	return INVERSION_OFF;
623}
624
625static int s5h1420_set_frontend(struct dvb_frontend* fe,
626				struct dvb_frontend_parameters *p)
627{
628	struct s5h1420_state* state = fe->demodulator_priv;
629	int frequency_delta;
630	struct dvb_frontend_tune_settings fesettings;
631	uint8_t clock_settting;
632
633	dprintk("enter %s\n", __func__);
634
635	/* check if we should do a fast-tune */
636	memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
637	s5h1420_get_tune_settings(fe, &fesettings);
638	frequency_delta = p->frequency - state->tunedfreq;
639	if ((frequency_delta > -fesettings.max_drift) &&
640			(frequency_delta < fesettings.max_drift) &&
641			(frequency_delta != 0) &&
642			(state->fec_inner == p->u.qpsk.fec_inner) &&
643			(state->symbol_rate == p->u.qpsk.symbol_rate)) {
644
645		if (fe->ops.tuner_ops.set_params) {
646			fe->ops.tuner_ops.set_params(fe, p);
647			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
648		}
649		if (fe->ops.tuner_ops.get_frequency) {
650			u32 tmp;
651			fe->ops.tuner_ops.get_frequency(fe, &tmp);
652			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
653			s5h1420_setfreqoffset(state, p->frequency - tmp);
654		} else {
655			s5h1420_setfreqoffset(state, 0);
656		}
657		dprintk("simple tune\n");
658		return 0;
659	}
660	dprintk("tuning demod\n");
661
662	/* first of all, software reset */
663	s5h1420_reset(state);
664
665	/* set s5h1420 fclk PLL according to desired symbol rate */
666	if (p->u.qpsk.symbol_rate > 33000000)
667		state->fclk = 80000000;
668	else if (p->u.qpsk.symbol_rate > 28500000)
669		state->fclk = 59000000;
670	else if (p->u.qpsk.symbol_rate > 25000000)
671		state->fclk = 86000000;
672	else if (p->u.qpsk.symbol_rate > 1900000)
673		state->fclk = 88000000;
674	else
675		state->fclk = 44000000;
676
677	/* Clock */
678	switch (state->fclk) {
679	default:
680	case 88000000:
681		clock_settting = 80;
682		break;
683	case 86000000:
684		clock_settting = 78;
685		break;
686	case 80000000:
687		clock_settting = 72;
688		break;
689	case 59000000:
690		clock_settting = 51;
691		break;
692	case 44000000:
693		clock_settting = 36;
694		break;
695	}
696	dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
697	s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
698	s5h1420_writereg(state, PLL02, 0x40);
699	s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
700
701	/* TODO DC offset removal, config parameter ? */
702	if (p->u.qpsk.symbol_rate > 29000000)
703		s5h1420_writereg(state, QPSK01, 0xae | 0x10);
704	else
705		s5h1420_writereg(state, QPSK01, 0xac | 0x10);
706
707	/* set misc registers */
708	s5h1420_writereg(state, CON_1, 0x00);
709	s5h1420_writereg(state, QPSK02, 0x00);
710	s5h1420_writereg(state, Pre01, 0xb0);
711
712	s5h1420_writereg(state, Loop01, 0xF0);
713	s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
714	s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
715	if (p->u.qpsk.symbol_rate > 20000000)
716		s5h1420_writereg(state, Loop04, 0x79);
717	else
718		s5h1420_writereg(state, Loop04, 0x58);
719	s5h1420_writereg(state, Loop05, 0x6b);
720
721	if (p->u.qpsk.symbol_rate >= 8000000)
722		s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
723	else if (p->u.qpsk.symbol_rate >= 4000000)
724		s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
725	else
726		s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
727
728	s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
729
730	s5h1420_writereg(state, Sync01, 0x33);
731	s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
732	s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
733	s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
734
735	s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
736	s5h1420_writereg(state, DiS03, 0x00);
737	s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
738
739	/* set tuner PLL */
740	if (fe->ops.tuner_ops.set_params) {
741		fe->ops.tuner_ops.set_params(fe, p);
742		if (fe->ops.i2c_gate_ctrl)
743			fe->ops.i2c_gate_ctrl(fe, 0);
744		s5h1420_setfreqoffset(state, 0);
745	}
746
747	/* set the reset of the parameters */
748	s5h1420_setsymbolrate(state, p);
749	s5h1420_setfec_inversion(state, p);
750
751	/* start QPSK */
752	s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
753
754	state->fec_inner = p->u.qpsk.fec_inner;
755	state->symbol_rate = p->u.qpsk.symbol_rate;
756	state->postlocked = 0;
757	state->tunedfreq = p->frequency;
758
759	dprintk("leave %s\n", __func__);
760	return 0;
761}
762
763static int s5h1420_get_frontend(struct dvb_frontend* fe,
764				struct dvb_frontend_parameters *p)
765{
766	struct s5h1420_state* state = fe->demodulator_priv;
767
768	p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state);
769	p->inversion = s5h1420_getinversion(state);
770	p->u.qpsk.symbol_rate = s5h1420_getsymbolrate(state);
771	p->u.qpsk.fec_inner = s5h1420_getfec(state);
772
773	return 0;
774}
775
776static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
777				     struct dvb_frontend_tune_settings* fesettings)
778{
779	if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
780		fesettings->min_delay_ms = 50;
781		fesettings->step_size = 2000;
782		fesettings->max_drift = 8000;
783	} else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
784		fesettings->min_delay_ms = 100;
785		fesettings->step_size = 1500;
786		fesettings->max_drift = 9000;
787	} else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
788		fesettings->min_delay_ms = 100;
789		fesettings->step_size = 1000;
790		fesettings->max_drift = 8000;
791	} else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
792		fesettings->min_delay_ms = 100;
793		fesettings->step_size = 500;
794		fesettings->max_drift = 7000;
795	} else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
796		fesettings->min_delay_ms = 200;
797		fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
798		fesettings->max_drift = 14 * fesettings->step_size;
799	} else {
800		fesettings->min_delay_ms = 200;
801		fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
802		fesettings->max_drift = 18 * fesettings->step_size;
803	}
804
805	return 0;
806}
807
808static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
809{
810	struct s5h1420_state* state = fe->demodulator_priv;
811
812	if (enable)
813		return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
814	else
815		return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
816}
817
818static int s5h1420_init (struct dvb_frontend* fe)
819{
820	struct s5h1420_state* state = fe->demodulator_priv;
821
822	/* disable power down and do reset */
823	state->CON_1_val = state->config->serial_mpeg << 4;
824	s5h1420_writereg(state, 0x02, state->CON_1_val);
825	msleep(10);
826	s5h1420_reset(state);
827
828	return 0;
829}
830
831static int s5h1420_sleep(struct dvb_frontend* fe)
832{
833	struct s5h1420_state* state = fe->demodulator_priv;
834	state->CON_1_val = 0x12;
835	return s5h1420_writereg(state, 0x02, state->CON_1_val);
836}
837
838static void s5h1420_release(struct dvb_frontend* fe)
839{
840	struct s5h1420_state* state = fe->demodulator_priv;
841	i2c_del_adapter(&state->tuner_i2c_adapter);
842	kfree(state);
843}
844
845static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
846{
847	return I2C_FUNC_I2C;
848}
849
850static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
851{
852	struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
853	struct i2c_msg m[1 + num];
854	u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
855
856	memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
857
858	m[0].addr = state->config->demod_address;
859	m[0].buf  = tx_open;
860	m[0].len  = 2;
861
862	memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
863
864	return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
865}
866
867static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
868	.master_xfer   = s5h1420_tuner_i2c_tuner_xfer,
869	.functionality = s5h1420_tuner_i2c_func,
870};
871
872struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
873{
874	struct s5h1420_state *state = fe->demodulator_priv;
875	return &state->tuner_i2c_adapter;
876}
877EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
878
879static struct dvb_frontend_ops s5h1420_ops;
880
881struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
882				    struct i2c_adapter *i2c)
883{
884	/* allocate memory for the internal state */
885	struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
886	u8 i;
887
888	if (state == NULL)
889		goto error;
890
891	/* setup the state */
892	state->config = config;
893	state->i2c = i2c;
894	state->postlocked = 0;
895	state->fclk = 88000000;
896	state->tunedfreq = 0;
897	state->fec_inner = FEC_NONE;
898	state->symbol_rate = 0;
899
900	/* check if the demod is there + identify it */
901	i = s5h1420_readreg(state, ID01);
902	if (i != 0x03)
903		goto error;
904
905	memset(state->shadow, 0xff, sizeof(state->shadow));
906
907	for (i = 0; i < 0x50; i++)
908		state->shadow[i] = s5h1420_readreg(state, i);
909
910	/* create dvb_frontend */
911	memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
912	state->frontend.demodulator_priv = state;
913
914	/* create tuner i2c adapter */
915	strlcpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus",
916		sizeof(state->tuner_i2c_adapter.name));
917	state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
918	state->tuner_i2c_adapter.algo      = &s5h1420_tuner_i2c_algo;
919	state->tuner_i2c_adapter.algo_data = NULL;
920	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
921	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
922		printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
923		goto error;
924	}
925
926	return &state->frontend;
927
928error:
929	kfree(state);
930	return NULL;
931}
932EXPORT_SYMBOL(s5h1420_attach);
933
934static struct dvb_frontend_ops s5h1420_ops = {
935
936	.info = {
937		.name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
938		.type     = FE_QPSK,
939		.frequency_min    = 950000,
940		.frequency_max    = 2150000,
941		.frequency_stepsize = 125,     /* kHz for QPSK frontends */
942		.frequency_tolerance  = 29500,
943		.symbol_rate_min  = 1000000,
944		.symbol_rate_max  = 45000000,
945		/*  .symbol_rate_tolerance  = ???,*/
946		.caps = FE_CAN_INVERSION_AUTO |
947		FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
948		FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
949		FE_CAN_QPSK
950	},
951
952	.release = s5h1420_release,
953
954	.init = s5h1420_init,
955	.sleep = s5h1420_sleep,
956	.i2c_gate_ctrl = s5h1420_i2c_gate_ctrl,
957
958	.set_frontend = s5h1420_set_frontend,
959	.get_frontend = s5h1420_get_frontend,
960	.get_tune_settings = s5h1420_get_tune_settings,
961
962	.read_status = s5h1420_read_status,
963	.read_ber = s5h1420_read_ber,
964	.read_signal_strength = s5h1420_read_signal_strength,
965	.read_ucblocks = s5h1420_read_ucblocks,
966
967	.diseqc_send_master_cmd = s5h1420_send_master_cmd,
968	.diseqc_recv_slave_reply = s5h1420_recv_slave_reply,
969	.diseqc_send_burst = s5h1420_send_burst,
970	.set_tone = s5h1420_set_tone,
971	.set_voltage = s5h1420_set_voltage,
972};
973
974MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
975MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
976MODULE_LICENSE("GPL");
977