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