11541Srgrimes// SPDX-License-Identifier: GPL-2.0-or-later
21541Srgrimes/*
31541Srgrimes    driver for LSI L64781 COFDM demodulator
41541Srgrimes
51541Srgrimes    Copyright (C) 2001 Holger Waechtler for Convergence Integrated Media GmbH
61541Srgrimes		       Marko Kohtala <marko.kohtala@luukku.com>
71541Srgrimes
81541Srgrimes
91541Srgrimes*/
101541Srgrimes
111541Srgrimes#include <linux/init.h>
121541Srgrimes#include <linux/kernel.h>
131541Srgrimes#include <linux/module.h>
141541Srgrimes#include <linux/string.h>
151541Srgrimes#include <linux/slab.h>
161541Srgrimes#include <media/dvb_frontend.h>
171541Srgrimes#include "l64781.h"
181541Srgrimes
191541Srgrimes
201541Srgrimesstruct l64781_state {
211541Srgrimes	struct i2c_adapter* i2c;
221541Srgrimes	const struct l64781_config* config;
231541Srgrimes	struct dvb_frontend frontend;
241541Srgrimes
251541Srgrimes	/* private demodulator data */
261541Srgrimes	unsigned int first:1;
271541Srgrimes};
281541Srgrimes
291541Srgrimes#define dprintk(args...) \
301541Srgrimes	do { \
311541Srgrimes		if (debug) printk(KERN_DEBUG "l64781: " args); \
321541Srgrimes	} while (0)
331541Srgrimes
3450477Speterstatic int debug;
351541Srgrimes
361541Srgrimesmodule_param(debug, int, 0644);
3733756SdysonMODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
3833756Sdyson
391541Srgrimes
401549Srgrimesstatic int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
411541Srgrimes{
4276166Smarkm	int ret;
431541Srgrimes	u8 buf [] = { reg, data };
4413702Sdg	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
4567354Sjhb
4612662Sdg	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
4771337Sjake		dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
4894729Sjeff			 __func__, reg, ret);
4966281Sjasone
501541Srgrimes	return (ret != 1) ? -1 : 0;
5112662Sdg}
521541Srgrimes
5312662Sdgstatic int l64781_readreg (struct l64781_state* state, u8 reg)
5427899Sdyson{
5527899Sdyson	int ret;
5692654Sjeff	u8 b0 [] = { reg };
5792654Sjeff	u8 b1 [] = { 0 };
5895771Sjeff	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
591541Srgrimes			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
6051401Sphk
6151401Sphk	ret = i2c_transfer(state->i2c, msg, 2);
6251401Sphk
6351401Sphk	if (ret != 2) return ret;
6492194Sarchie
6592194Sarchie	return b1[0];
6692194Sarchie}
6792194Sarchie
6892194Sarchiestatic void apply_tps (struct l64781_state* state)
6992194Sarchie{
7092194Sarchie	l64781_writereg (state, 0x2a, 0x00);
7192194Sarchie	l64781_writereg (state, 0x2a, 0x01);
7292194Sarchie
7392194Sarchie	/* This here is a little bit questionable because it enables
7451906Sphk	   the automatic update of TPS registers. I think we'd need to
7551167Sbde	   handle the IRQ from FE to update some other registers as
7651167Sbde	   well, or at least implement some magic to tuning to correct
7751167Sbde	   to the TPS received from transmission. */
7853541Sshin	l64781_writereg (state, 0x2a, 0x02);
7953541Sshin}
8053541Sshin
8192723Salfred
8210358Sjulianstatic void reset_afc (struct l64781_state* state)
8310358Sjulian{
8430354Sphk	/* Set AFC stall for the AFC_INIT_FRQ setting, TIM_STALL for
8530354Sphk	   timing offset */
8641054Speter	l64781_writereg (state, 0x07, 0x9e); /* stall AFC */
8730278Sphk	l64781_writereg (state, 0x08, 0);    /* AFC INIT FREQ */
8829508Sbde	l64781_writereg (state, 0x09, 0);
8929508Sbde	l64781_writereg (state, 0x0a, 0);
9092654Sjeff	l64781_writereg (state, 0x07, 0x8e);
9192654Sjeff	l64781_writereg (state, 0x0e, 0);    /* AGC gain to zero in beginning */
9292654Sjeff	l64781_writereg (state, 0x11, 0x80); /* stall TIM */
9365710Sjasone	l64781_writereg (state, 0x10, 0);    /* TIM_OFFSET_LSB */
9495742Srwatson	l64781_writereg (state, 0x12, 0);
9592654Sjeff	l64781_writereg (state, 0x13, 0);
9694729Sjeff	l64781_writereg (state, 0x11, 0x00);
9757263Sdillon}
9892654Sjeff
9992654Sjeffstatic int reset_and_configure (struct l64781_state* state)
10094729Sjeff{
10194729Sjeff	u8 buf [] = { 0x06 };
10294729Sjeff	struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 };
10394729Sjeff	// NOTE: this is correct in writing to address 0x00
10494729Sjeff
10594729Sjeff	return (i2c_transfer(state->i2c, &msg, 1) == 1) ? 0 : -ENODEV;
10694729Sjeff}
10794729Sjeff
10894729Sjeffstatic int apply_frontend_param(struct dvb_frontend *fe)
10994729Sjeff{
11094729Sjeff	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
11194729Sjeff	struct l64781_state* state = fe->demodulator_priv;
11294729Sjeff	/* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
11394729Sjeff	static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
11495743Srwatson	/* QPSK, QAM_16, QAM_64 */
11595742Srwatson	static const u8 qam_tab [] = { 2, 4, 0, 6 };
11695742Srwatson	static const u8 guard_tab [] = { 1, 2, 4, 8 };
11792654Sjeff	/* The Grundig 29504-401.04 Tuner comes with 18.432MHz crystal. */
1181541Srgrimes	static const u32 ppm = 8000;
1191541Srgrimes	u32 ddfs_offset_fixed;
12094729Sjeff/*	u32 ddfs_offset_variable = 0x6000-((1000000UL+ppm)/ */
12192654Sjeff/*			bw_tab[p->bandWidth]<<10)/15625; */
1221541Srgrimes	u32 init_freq;
12394730Sjeff	u32 spi_bias;
12494730Sjeff	u8 val0x04;
12594730Sjeff	u8 val0x05;
12694730Sjeff	u8 val0x06;
12794730Sjeff	int bw;
12894730Sjeff
12994729Sjeff	switch (p->bandwidth_hz) {
1301541Srgrimes	case 8000000:
1311541Srgrimes		bw = 8;
13242957Sdillon		break;
13342957Sdillon	case 7000000:
13442957Sdillon		bw = 7;
13542957Sdillon		break;
13642957Sdillon	case 6000000:
13742957Sdillon		bw = 6;
1381541Srgrimes		break;
1391541Srgrimes	default:
1401541Srgrimes		return -EINVAL;
1411541Srgrimes	}
14230281Sphk
14330278Sphk	if (fe->ops.tuner_ops.set_params) {
1441541Srgrimes		fe->ops.tuner_ops.set_params(fe);
14594729Sjeff		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
14692654Sjeff	}
14792654Sjeff
14830281Sphk	if (p->inversion != INVERSION_ON &&
1491541Srgrimes	    p->inversion != INVERSION_OFF)
15095319Sphk		return -EINVAL;
15195319Sphk
15295319Sphk	if (p->code_rate_HP != FEC_1_2 && p->code_rate_HP != FEC_2_3 &&
15395319Sphk	    p->code_rate_HP != FEC_3_4 && p->code_rate_HP != FEC_5_6 &&
15471707Speter	    p->code_rate_HP != FEC_7_8)
15551401Sphk		return -EINVAL;
15683366Sjulian
15751401Sphk	if (p->hierarchy != HIERARCHY_NONE &&
15851401Sphk	    (p->code_rate_LP != FEC_1_2 && p->code_rate_LP != FEC_2_3 &&
15992654Sjeff	     p->code_rate_LP != FEC_3_4 && p->code_rate_LP != FEC_5_6 &&
16094729Sjeff	     p->code_rate_LP != FEC_7_8))
16194729Sjeff		return -EINVAL;
16294729Sjeff
16394729Sjeff	if (p->modulation != QPSK && p->modulation != QAM_16 &&
16494729Sjeff	    p->modulation != QAM_64)
16594729Sjeff		return -EINVAL;
16694729Sjeff
16792654Sjeff	if (p->transmission_mode != TRANSMISSION_MODE_2K &&
16894729Sjeff	    p->transmission_mode != TRANSMISSION_MODE_8K)
16992654Sjeff		return -EINVAL;
17094729Sjeff
17194729Sjeff	if ((int)p->guard_interval < GUARD_INTERVAL_1_32 ||
17294729Sjeff	    p->guard_interval > GUARD_INTERVAL_1_4)
17392654Sjeff		return -EINVAL;
17494729Sjeff
17592654Sjeff	if ((int)p->hierarchy < HIERARCHY_NONE ||
17692654Sjeff	    p->hierarchy > HIERARCHY_4)
17794729Sjeff		return -EINVAL;
1781541Srgrimes
1791541Srgrimes	ddfs_offset_fixed = 0x4000-(ppm<<16)/bw/1000000;
18094729Sjeff
18192654Sjeff	/* This works up to 20000 ppm, it overflows if too large ppm! */
1821541Srgrimes	init_freq = (((8UL<<25) + (8UL<<19) / 25*ppm / (15625/25)) /
1831541Srgrimes			bw & 0xFFFFFF);
1841541Srgrimes
1851541Srgrimes	/* SPI bias calculation is slightly modified to fit in 32bit */
18694729Sjeff	/* will work for high ppm only... */
1871541Srgrimes	spi_bias = 378 * (1 << 10);
1881541Srgrimes	spi_bias *= 16;
1891541Srgrimes	spi_bias *= bw;
1901541Srgrimes	spi_bias *= qam_tab[p->modulation];
19142957Sdillon	spi_bias /= p->code_rate_HP + 1;
19242957Sdillon	spi_bias /= (guard_tab[p->guard_interval] + 32);
19342957Sdillon	spi_bias *= 1000;
19442957Sdillon	spi_bias /= 1000 + ppm/1000;
19542957Sdillon	spi_bias *= p->code_rate_HP;
1961541Srgrimes
1971541Srgrimes	val0x04 = (p->transmission_mode << 2) | p->guard_interval;
1981541Srgrimes	val0x05 = fec_tab[p->code_rate_HP];
1991541Srgrimes
20030281Sphk	if (p->hierarchy != HIERARCHY_NONE)
2011541Srgrimes		val0x05 |= (p->code_rate_LP - FEC_1_2) << 3;
20292654Sjeff
20392654Sjeff	val0x06 = (p->hierarchy << 2) | p->modulation;
20492654Sjeff
20530281Sphk	l64781_writereg (state, 0x04, val0x04);
2061541Srgrimes	l64781_writereg (state, 0x05, val0x05);
20792194Sarchie	l64781_writereg (state, 0x06, val0x06);
20892194Sarchie
20992194Sarchie	reset_afc (state);
21092194Sarchie
21195319Sphk	/* Technical manual section 2.6.1, TIM_IIR_GAIN optimal values */
21295319Sphk	l64781_writereg (state, 0x15,
21395319Sphk			 p->transmission_mode == TRANSMISSION_MODE_2K ? 1 : 3);
21495319Sphk	l64781_writereg (state, 0x16, init_freq & 0xff);
21595319Sphk	l64781_writereg (state, 0x17, (init_freq >> 8) & 0xff);
21695319Sphk	l64781_writereg (state, 0x18, (init_freq >> 16) & 0xff);
21792654Sjeff
21865710Sjasone	l64781_writereg (state, 0x1b, spi_bias & 0xff);
21992654Sjeff	l64781_writereg (state, 0x1c, (spi_bias >> 8) & 0xff);
22092654Sjeff	l64781_writereg (state, 0x1d, ((spi_bias >> 16) & 0x7f) |
22192654Sjeff		(p->inversion == INVERSION_ON ? 0x80 : 0x00));
22292654Sjeff
22394729Sjeff	l64781_writereg (state, 0x22, ddfs_offset_fixed & 0xff);
22494729Sjeff	l64781_writereg (state, 0x23, (ddfs_offset_fixed >> 8) & 0x3f);
22592654Sjeff
22692654Sjeff	l64781_readreg (state, 0x00);  /*  clear interrupt registers... */
22792654Sjeff	l64781_readreg (state, 0x01);  /*  dto. */
22892654Sjeff
22992654Sjeff	apply_tps (state);
23092654Sjeff
23192654Sjeff	return 0;
2321541Srgrimes}
2331541Srgrimes
2341541Srgrimesstatic int get_frontend(struct dvb_frontend *fe,
2351541Srgrimes			struct dtv_frontend_properties *p)
2361541Srgrimes{
2371541Srgrimes	struct l64781_state* state = fe->demodulator_priv;
23892194Sarchie	int tmp;
23992194Sarchie
24092194Sarchie
24192194Sarchie	tmp = l64781_readreg(state, 0x04);
24292194Sarchie	switch(tmp & 3) {
24392194Sarchie	case 0:
24492194Sarchie		p->guard_interval = GUARD_INTERVAL_1_32;
24592194Sarchie		break;
24692194Sarchie	case 1:
24792654Sjeff		p->guard_interval = GUARD_INTERVAL_1_16;
24892194Sarchie		break;
24992194Sarchie	case 2:
25092194Sarchie		p->guard_interval = GUARD_INTERVAL_1_8;
25192194Sarchie		break;
25292194Sarchie	case 3:
25392194Sarchie		p->guard_interval = GUARD_INTERVAL_1_4;
25492194Sarchie		break;
25592654Sjeff	}
25692654Sjeff	switch((tmp >> 2) & 3) {
25792654Sjeff	case 0:
25892194Sarchie		p->transmission_mode = TRANSMISSION_MODE_2K;
25992654Sjeff		break;
26092194Sarchie	case 1:
26192194Sarchie		p->transmission_mode = TRANSMISSION_MODE_8K;
26292194Sarchie		break;
26392654Sjeff	default:
26492654Sjeff		printk(KERN_WARNING "Unexpected value for transmission_mode\n");
26592654Sjeff	}
26692654Sjeff
26792194Sarchie	tmp = l64781_readreg(state, 0x05);
26892194Sarchie	switch(tmp & 7) {
26992194Sarchie	case 0:
27092194Sarchie		p->code_rate_HP = FEC_1_2;
27192194Sarchie		break;
27292194Sarchie	case 1:
27392194Sarchie		p->code_rate_HP = FEC_2_3;
27492194Sarchie		break;
27592194Sarchie	case 2:
27692194Sarchie		p->code_rate_HP = FEC_3_4;
27792194Sarchie		break;
27892194Sarchie	case 3:
27992194Sarchie		p->code_rate_HP = FEC_5_6;
28092194Sarchie		break;
28192194Sarchie	case 4:
28292194Sarchie		p->code_rate_HP = FEC_7_8;
28392194Sarchie		break;
28492194Sarchie	default:
28592194Sarchie		printk("Unexpected value for code_rate_HP\n");
28692194Sarchie	}
28792194Sarchie	switch((tmp >> 3) & 7) {
28892194Sarchie	case 0:
28992194Sarchie		p->code_rate_LP = FEC_1_2;
29092194Sarchie		break;
29192194Sarchie	case 1:
29292194Sarchie		p->code_rate_LP = FEC_2_3;
29392194Sarchie		break;
29492194Sarchie	case 2:
29592194Sarchie		p->code_rate_LP = FEC_3_4;
29692194Sarchie		break;
29792194Sarchie	case 3:
29892194Sarchie		p->code_rate_LP = FEC_5_6;
29992194Sarchie		break;
30092194Sarchie	case 4:
3011541Srgrimes		p->code_rate_LP = FEC_7_8;
3021541Srgrimes		break;
30310358Sjulian	default:
30410358Sjulian		printk("Unexpected value for code_rate_LP\n");
30512569Sbde	}
30612569Sbde
3071541Srgrimes	tmp = l64781_readreg(state, 0x06);
30894729Sjeff	switch(tmp & 3) {
30956720Sdg	case 0:
31056720Sdg		p->modulation = QPSK;
31192654Sjeff		break;
31292654Sjeff	case 1:
31392654Sjeff		p->modulation = QAM_16;
31492654Sjeff		break;
31592654Sjeff	case 2:
31694729Sjeff		p->modulation = QAM_64;
31793818Sjhb		break;
31865710Sjasone	default:
31933756Sdyson		printk(KERN_WARNING "Unexpected value for modulation\n");
32033756Sdyson	}
32133756Sdyson	switch((tmp >> 2) & 7) {
32233756Sdyson	case 0:
32333756Sdyson		p->hierarchy = HIERARCHY_NONE;
32433756Sdyson		break;
32533756Sdyson	case 1:
32633756Sdyson		p->hierarchy = HIERARCHY_1;
32733756Sdyson		break;
32833756Sdyson	case 2:
32933756Sdyson		p->hierarchy = HIERARCHY_2;
33033756Sdyson		break;
33177843Speter	case 3:
33233756Sdyson		p->hierarchy = HIERARCHY_4;
33333756Sdyson		break;
33433756Sdyson	default:
33577843Speter		printk("Unexpected value for hierarchy\n");
33677843Speter	}
33733756Sdyson
33833756Sdyson
33933756Sdyson	tmp = l64781_readreg (state, 0x1d);
34077843Speter	p->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
34177843Speter
34233756Sdyson	tmp = (int) (l64781_readreg (state, 0x08) |
34333756Sdyson		     (l64781_readreg (state, 0x09) << 8) |
34443012Smsmith		     (l64781_readreg (state, 0x0a) << 16));
34577900Speter	p->frequency += tmp;
34643012Smsmith
34756720Sdg	return 0;
34856720Sdg}
34956720Sdg
35056720Sdgstatic int l64781_read_status(struct dvb_frontend *fe, enum fe_status *status)
35156720Sdg{
35256720Sdg	struct l64781_state* state = fe->demodulator_priv;
35356720Sdg	int sync = l64781_readreg (state, 0x32);
35456720Sdg	int gain = l64781_readreg (state, 0x0e);
35533756Sdyson
35678592Sbmilekic	l64781_readreg (state, 0x00);  /*  clear interrupt registers... */
35781089Sbmilekic	l64781_readreg (state, 0x01);  /*  dto. */
35878592Sbmilekic
35978592Sbmilekic	*status = 0;
36078592Sbmilekic
36178592Sbmilekic	if (gain > 5)
36278592Sbmilekic		*status |= FE_HAS_SIGNAL;
36375686Sbmilekic
36478592Sbmilekic	if (sync & 0x02) /* VCXO locked, this criteria should be ok */
3658876Srgrimes		*status |= FE_HAS_CARRIER;
3661541Srgrimes
36732702Sdyson	if (sync & 0x20)
36827899Sdyson		*status |= FE_HAS_VITERBI;
36992654Sjeff
37092654Sjeff	if (sync & 0x40)
37192654Sjeff		*status |= FE_HAS_SYNC;
37292654Sjeff
37392654Sjeff	if (sync == 0x7f)
37492654Sjeff		*status |= FE_HAS_LOCK;
37592654Sjeff
37692654Sjeff	return 0;
37792654Sjeff}
37892654Sjeff
37992654Sjeffstatic int l64781_read_ber(struct dvb_frontend* fe, u32* ber)
38092654Sjeff{
38192654Sjeff	struct l64781_state* state = fe->demodulator_priv;
38292654Sjeff
38392654Sjeff	/*   XXX FIXME: set up counting period (reg 0x26...0x28)
38492654Sjeff	 */
38592654Sjeff	*ber = l64781_readreg (state, 0x39)
38694729Sjeff	    | (l64781_readreg (state, 0x3a) << 8);
38794729Sjeff
38894729Sjeff	return 0;
38992654Sjeff}
39095771Sjeff
39195771Sjeffstatic int l64781_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
39295771Sjeff{
39395771Sjeff	struct l64781_state* state = fe->demodulator_priv;
39495771Sjeff
39595771Sjeff	u8 gain = l64781_readreg (state, 0x0e);
39695771Sjeff	*signal_strength = (gain << 8) | gain;
39794729Sjeff
39892654Sjeff	return 0;
39994729Sjeff}
40092654Sjeff
4011541Srgrimesstatic int l64781_read_snr(struct dvb_frontend* fe, u16* snr)
40230278Sphk{
40330278Sphk	struct l64781_state* state = fe->demodulator_priv;
40441054Speter
40541054Speter	u8 avg_quality = 0xff - l64781_readreg (state, 0x33);
40641054Speter	*snr = (avg_quality << 8) | avg_quality; /* not exact, but...*/
40730278Sphk
40841054Speter	return 0;
40930278Sphk}
41094729Sjeff
41153541Sshinstatic int l64781_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
41230817Sphk{
41330817Sphk	struct l64781_state* state = fe->demodulator_priv;
41431549Sdyson
41531549Sdyson	*ucblocks = l64781_readreg (state, 0x37)
41631549Sdyson	   | (l64781_readreg (state, 0x38) << 8);
41794729Sjeff
41894729Sjeff	return 0;
41994729Sjeff}
42030278Sphk
42130278Sphkstatic int l64781_sleep(struct dvb_frontend* fe)
42294729Sjeff{
4231541Srgrimes	struct l64781_state* state = fe->demodulator_priv;
42441054Speter
42541054Speter	/* Power down */
42641054Speter	return l64781_writereg (state, 0x3e, 0x5a);
42741054Speter}
42841054Speter
42941054Speterstatic int l64781_init(struct dvb_frontend* fe)
43041054Speter{
43141054Speter	struct l64781_state* state = fe->demodulator_priv;
43294729Sjeff
43353541Sshin	reset_and_configure (state);
43441054Speter
43541054Speter	/* Power up */
43641054Speter	l64781_writereg (state, 0x3e, 0xa5);
43741054Speter
43841054Speter	/* Reset hard */
43941054Speter	l64781_writereg (state, 0x2a, 0x04);
44041054Speter	l64781_writereg (state, 0x2a, 0x00);
44141054Speter
44241054Speter	/* Set tuner specific things */
44341054Speter	/* AFC_POL, set also in reset_afc */
44441054Speter	l64781_writereg (state, 0x07, 0x8e);
44541054Speter
44641054Speter	/* Use internal ADC */
44741054Speter	l64781_writereg (state, 0x0b, 0x81);
44841054Speter
44947067Sbde	/* AGC loop gain, and polarity is positive */
45094729Sjeff	l64781_writereg (state, 0x0c, 0x84);
45141054Speter
45294729Sjeff	/* Internal ADC outputs two's complement */
45394729Sjeff	l64781_writereg (state, 0x0d, 0x8c);
45494729Sjeff
45594729Sjeff	/* With ppm=8000, it seems the DTR_SENSITIVITY will result in
45694729Sjeff	   value of 2 with all possible bandwidths and guard
45794729Sjeff	   intervals, which is the initial value anyway. */
45894729Sjeff	/*l64781_writereg (state, 0x19, 0x92);*/
45994729Sjeff
46094729Sjeff	/* Everything is two's complement, soft bit and CSI_OUT too */
46194729Sjeff	l64781_writereg (state, 0x1e, 0x09);
46294729Sjeff
46394729Sjeff	/* delay a bit after first init attempt */
46494729Sjeff	if (state->first) {
46594729Sjeff		state->first = 0;
46694729Sjeff		msleep(200);
46794729Sjeff	}
46894729Sjeff
46994729Sjeff	return 0;
47094729Sjeff}
47194729Sjeff
47294729Sjeffstatic int l64781_get_tune_settings(struct dvb_frontend* fe,
47394729Sjeff				    struct dvb_frontend_tune_settings* fesettings)
47494729Sjeff{
47594729Sjeff	fesettings->min_delay_ms = 4000;
47694729Sjeff	fesettings->step_size = 0;
47794729Sjeff	fesettings->max_drift = 0;
47894729Sjeff	return 0;
47994729Sjeff}
48094729Sjeff
48194729Sjeffstatic void l64781_release(struct dvb_frontend* fe)
48294729Sjeff{
48394729Sjeff	struct l64781_state* state = fe->demodulator_priv;
48494729Sjeff	kfree(state);
48594729Sjeff}
48694729Sjeff
48794729Sjeffstatic const struct dvb_frontend_ops l64781_ops;
48894729Sjeff
48994729Sjeffstruct dvb_frontend* l64781_attach(const struct l64781_config* config,
49094729Sjeff				   struct i2c_adapter* i2c)
49194729Sjeff{
49294729Sjeff	struct l64781_state* state = NULL;
49394729Sjeff	int reg0x3e = -1;
49494729Sjeff	u8 b0 [] = { 0x1a };
49594729Sjeff	u8 b1 [] = { 0x00 };
49694729Sjeff	struct i2c_msg msg [] = { { .addr = config->demod_address, .flags = 0, .buf = b0, .len = 1 },
49794730Sjeff			   { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
49894729Sjeff
49994729Sjeff	/* allocate memory for the internal state */
50094729Sjeff	state = kzalloc(sizeof(struct l64781_state), GFP_KERNEL);
50194729Sjeff	if (state == NULL) goto error;
50294729Sjeff
50394729Sjeff	/* setup the state */
50494729Sjeff	state->config = config;
50594729Sjeff	state->i2c = i2c;
50694729Sjeff	state->first = 1;
50794729Sjeff
50894729Sjeff	/*
50994729Sjeff	 *  the L64781 won't show up before we send the reset_and_configure()
51094729Sjeff	 *  broadcast. If nothing responds there is no L64781 on the bus...
51194729Sjeff	 */
51294729Sjeff	if (reset_and_configure(state) < 0) {
51394729Sjeff		dprintk("No response to reset and configure broadcast...\n");
51494729Sjeff		goto error;
51594729Sjeff	}
51694729Sjeff
51794729Sjeff	/* The chip always responds to reads */
51894729Sjeff	if (i2c_transfer(state->i2c, msg, 2) != 2) {
51994729Sjeff		dprintk("No response to read on I2C bus\n");
52094729Sjeff		goto error;
52194729Sjeff	}
52294729Sjeff
52394729Sjeff	/* Save current register contents for bailout */
52494729Sjeff	reg0x3e = l64781_readreg(state, 0x3e);
52594729Sjeff
52694729Sjeff	/* Reading the POWER_DOWN register always returns 0 */
52794730Sjeff	if (reg0x3e != 0) {
52894730Sjeff		dprintk("Device doesn't look like L64781\n");
52994730Sjeff		goto error;
53094730Sjeff	}
53194730Sjeff
53294730Sjeff	/* Turn the chip off */
53394730Sjeff	l64781_writereg (state, 0x3e, 0x5a);
53494730Sjeff
53594730Sjeff	/* Responds to all reads with 0 */
53694730Sjeff	if (l64781_readreg(state, 0x1a) != 0) {
53794730Sjeff		dprintk("Read 1 returned unexpected value\n");
53894730Sjeff		goto error;
53994730Sjeff	}
54094730Sjeff
54194730Sjeff	/* Turn the chip on */
54294730Sjeff	l64781_writereg (state, 0x3e, 0xa5);
54394730Sjeff
54494730Sjeff	/* Responds with register default value */
54594730Sjeff	if (l64781_readreg(state, 0x1a) != 0xa1) {
54694730Sjeff		dprintk("Read 2 returned unexpected value\n");
54794730Sjeff		goto error;
54894730Sjeff	}
54994730Sjeff
55094730Sjeff	/* create dvb_frontend */
55194730Sjeff	memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
55294730Sjeff	state->frontend.demodulator_priv = state;
55394730Sjeff	return &state->frontend;
55494730Sjeff
55594730Sjefferror:
55694730Sjeff	if (reg0x3e >= 0)
55794730Sjeff		l64781_writereg (state, 0x3e, reg0x3e);  /* restore reg 0x3e */
55894730Sjeff	kfree(state);
55994730Sjeff	return NULL;
56094730Sjeff}
56194730Sjeff
56294730Sjeffstatic const struct dvb_frontend_ops l64781_ops = {
56394730Sjeff	.delsys = { SYS_DVBT },
56494730Sjeff	.info = {
56594730Sjeff		.name = "LSI L64781 DVB-T",
56694730Sjeff	/*	.frequency_min_hz = ???,*/
56794730Sjeff	/*	.frequency_max_hz = ???,*/
56894730Sjeff		.frequency_stepsize_hz = 166666,
56994730Sjeff	/*      .symbol_rate_tolerance = ???,*/
57094730Sjeff		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
57194730Sjeff		      FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
57294730Sjeff		      FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
57394730Sjeff		      FE_CAN_MUTE_TS
57494730Sjeff	},
57594730Sjeff
57694730Sjeff	.release = l64781_release,
57794730Sjeff
57894730Sjeff	.init = l64781_init,
57994730Sjeff	.sleep = l64781_sleep,
58094730Sjeff
58194730Sjeff	.set_frontend = apply_frontend_param,
58294730Sjeff	.get_frontend = get_frontend,
58394730Sjeff	.get_tune_settings = l64781_get_tune_settings,
58494730Sjeff
58594730Sjeff	.read_status = l64781_read_status,
58694730Sjeff	.read_ber = l64781_read_ber,
587	.read_signal_strength = l64781_read_signal_strength,
588	.read_snr = l64781_read_snr,
589	.read_ucblocks = l64781_read_ucblocks,
590};
591
592MODULE_DESCRIPTION("LSI L64781 DVB-T Demodulator driver");
593MODULE_AUTHOR("Holger Waechtler, Marko Kohtala");
594MODULE_LICENSE("GPL");
595
596EXPORT_SYMBOL_GPL(l64781_attach);
597