1af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110 - Single Chip Satellite Channel Receiver driver module 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4a8d995c99ef56a3dbcdbe291bb71658bf00e9ad6Johannes Stezenbach Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds work 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dvb_frontend.h" 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "cx24110.h" 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cx24110_state { 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_adapter* i2c; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct cx24110_config* config; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dvb_frontend frontend; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 lastber; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 lastbler; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 lastesn0; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dprintk(args...) \ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { \ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (debug) printk(KERN_DEBUG "cx24110: " args); \ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (0) 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct {u8 reg; u8 data;} cx24110_regdata[]= 549101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* Comments beginning with @ denote this value should 5550c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky be the default */ 569101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {{0x09,0x01}, /* SoftResetAll */ 579101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x09,0x00}, /* release reset */ 589101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x01,0xe8}, /* MSB of code rate 27.5MS/s */ 599101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x02,0x17}, /* middle byte " */ 609101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x03,0x29}, /* LSB " */ 619101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x05,0x03}, /* @ DVB mode, standard code rate 3/4 */ 629101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x06,0xa5}, /* @ PLL 60MHz */ 639101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */ 649101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x0a,0x00}, /* @ partial chip disables, do not set */ 659101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x0b,0x01}, /* set output clock in gapped mode, start signal low 6650c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky active for first byte */ 679101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x0c,0x11}, /* no parity bytes, large hold time, serial data out */ 689101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */ 699101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1 7050c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky to avoid starting the BER counter. Reset the 7150c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky CRC test bit. Finite counting selected */ 729101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x15,0xff}, /* @ size of the limited time window for RS BER 7350c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky estimation. It is <value>*256 RS blocks, this 7450c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */ 759101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x16,0x00}, /* @ enable all RS output ports */ 769101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x17,0x04}, /* @ time window allowed for the RS to sync */ 779101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x18,0xae}, /* @ allow all standard DVB code rates to be scanned 7850c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky for automatically */ 799101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* leave the current code rate and normalization 8050c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky registers as they are after reset... */ 819101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x21,0x10}, /* @ during AutoAcq, search each viterbi setting 8250c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky only once */ 839101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x23,0x18}, /* @ size of the limited time window for Viterbi BER 8450c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky estimation. It is <value>*65536 channel bits, i.e. 8550c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky approx. 38ms at 27.5MS/s, rate 3/4 */ 869101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */ 879101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* leave front-end AGC parameters at default values */ 889101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* leave decimation AGC parameters at default values */ 899101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x35,0x40}, /* disable all interrupts. They are not connected anyway */ 909101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x36,0xff}, /* clear all interrupt pending flags */ 919101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x37,0x00}, /* @ fully enable AutoAcqq state machine */ 929101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x38,0x07}, /* @ enable fade recovery, but not autostart AutoAcq */ 939101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* leave the equalizer parameters on their default values */ 949101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* leave the final AGC parameters on their default values */ 959101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x41,0x00}, /* @ MSB of front-end derotator frequency */ 969101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x42,0x00}, /* @ middle bytes " */ 979101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x43,0x00}, /* @ LSB " */ 989101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* leave the carrier tracking loop parameters on default */ 99af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa /* leave the bit timing loop parameters at default */ 1009101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x56,0x4d}, /* set the filtune voltage to 2.7V, as recommended by */ 1019101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* the cx24108 data sheet for symbol rates above 15MS/s */ 1029101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x57,0x00}, /* @ Filter sigma delta enabled, positive */ 1039101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x61,0x95}, /* GPIO pins 1-4 have special function */ 1049101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x62,0x05}, /* GPIO pin 5 has special function, pin 6 is GPIO */ 1059101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x63,0x00}, /* All GPIO pins use CMOS output characteristics */ 1069101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x64,0x20}, /* GPIO 6 is input, all others are outputs */ 1079101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x6d,0x30}, /* tuner auto mode clock freq 62kHz */ 1089101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x70,0x15}, /* use auto mode, tuner word is 21 bits long */ 1099101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x73,0x00}, /* @ disable several demod bypasses */ 1109101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x74,0x00}, /* @ " */ 1119101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab {0x75,0x00} /* @ " */ 1129101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* the remaining registers are for SEC */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_writereg (struct cx24110_state* state, int reg, int data) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1189101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab u8 buf [] = { reg, data }; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1229101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk ("%s: writereg error (err == %i, reg == 0x%02x," 124271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison " data == 0x%02x)\n", __func__, err, reg, data); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EREMOTEIO; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1289101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab return 0; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_readreg (struct cx24110_state* state, u8 reg) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 b0 [] = { reg }; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 b1 [] = { 0 }; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = i2c_transfer(state->i2c, msg, 2); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret != 2) return ret; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return b1[0]; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_set_inversion (struct cx24110_state* state, fe_spectral_inversion_t inversion) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fixme (low): error handling */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (inversion) { 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case INVERSION_OFF: 1529101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x1); 1539101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* AcqSpectrInvDis on. No idea why someone should want this */ 1549101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x5,cx24110_readreg(state,0x5)&0xf7); 1559101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* Initial value 0 at start of acq */ 1569101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x22,cx24110_readreg(state,0x22)&0xef); 1579101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* current value 0 */ 1589101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* The cx24110 manual tells us this reg is read-only. 1599101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab But what the heck... set it ayways */ 1609101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab break; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case INVERSION_ON: 1629101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x1); 1639101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* AcqSpectrInvDis on. No idea why someone should want this */ 1649101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x5,cx24110_readreg(state,0x5)|0x08); 1659101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* Initial value 1 at start of acq */ 1669101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x22,cx24110_readreg(state,0x22)|0x10); 1679101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* current value 1 */ 1689101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab break; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case INVERSION_AUTO: 1709101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xfe); 1719101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* AcqSpectrInvDis off. Leave initial & current states as is */ 1729101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab break; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fixme (low): error handling */ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1849101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab static const int rate[]={-1,1,2,3,5,7,-1}; 1859101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab static const int g1[]={-1,0x01,0x02,0x05,0x15,0x45,-1}; 1869101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab static const int g2[]={-1,0x01,0x03,0x06,0x1a,0x7a,-1}; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1889101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* Well, the AutoAcq engine of the cx24106 and 24110 automatically 1899101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab searches all enabled viterbi rates, and can handle non-standard 1909101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab rates as well. */ 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1929101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab if (fec>FEC_AUTO) 1939101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab fec=FEC_AUTO; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1959101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab if (fec==FEC_AUTO) { /* (re-)establish AutoAcq behaviour */ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xdf); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* clear AcqVitDis bit */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x18,0xae); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allow all DVB standard code rates */ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|0x3); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set nominal Viterbi rate 3/4 */ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|0x3); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set current Viterbi rate 3/4 */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x1a,0x05); cx24110_writereg(state,0x1b,0x06); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the puncture registers for code rate 3/4 */ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2079101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab } else { 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x20); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set AcqVitDis bit */ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(rate[fec]>0) { 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|rate[fec]); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set nominal Viterbi rate */ 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|rate[fec]); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set current Viterbi rate */ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x1a,g1[fec]); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x1b,g2[fec]); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* not sure if this is the right way: I always used AutoAcq mode */ 2189101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab } else 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fixme (low): which is the correct return code? */ 2219101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab }; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic fe_code_rate_t cx24110_get_fec (struct cx24110_state* state) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i=cx24110_readreg(state,0x22)&0x0f; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!(i&0x08)) { 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FEC_1_2 + i - 1; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fixme (low): a special code rate has been selected. In theory, we need to 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return a denominator value, a numerator value, and a pair of puncture 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maps to correctly describe this mode. But this should never happen in 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds practice, because it cannot be set by cx24110_get_fec. */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FEC_NONE; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fixme (low): add error handling */ 2449101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab u32 ratio; 2459101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab u32 tmp, fclk, BDRI; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2479101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab static const u32 bands[]={5000000UL,15000000UL,90999000UL/2}; 2489101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab int i; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 250271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate); 2519101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab if (srate>90999000UL/2) 2529101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab srate=90999000UL/2; 2539101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab if (srate<500000) 2549101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab srate=500000; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2560496daa7d88d117fab4dd190c7f6e7c4a5aa15cdAhmed S. Darwish for(i = 0; (i < ARRAY_SIZE(bands)) && (srate>bands[i]); i++) 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ; 2589101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz, 2599101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult, 2609101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab R06[3:0] PLLphaseDetGain */ 2619101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab tmp=cx24110_readreg(state,0x07)&0xfc; 2629101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab if(srate<90999000UL/4) { /* sample rate 45MHz*/ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x07,tmp); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x06,0x78); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fclk=90999000UL/2; 2669101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab } else if(srate<60666000UL/2) { /* sample rate 60MHz */ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x07,tmp|0x1); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x06,0xa5); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fclk=60666000UL; 2709101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab } else if(srate<80888000UL/2) { /* sample rate 80MHz */ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x07,tmp|0x2); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x06,0x87); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fclk=80888000UL; 2749101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab } else { /* sample rate 90MHz */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x07,tmp|0x3); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x06,0x78); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fclk=90999000UL; 2789101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab }; 2799101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab dprintk("cx24110 debug: fclk %d Hz\n",fclk); 2809101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* we need to divide two integers with approx. 27 bits in 32 bit 2819101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab arithmetic giving a 25 bit result */ 2829101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* the maximum dividend is 90999000/2, 0x02b6446c, this number is 2839101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab also the most complex divisor. Hence, the dividend has, 2849101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab assuming 32bit unsigned arithmetic, 6 clear bits on top, the 2859101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab divisor 2 unused bits at the bottom. Also, the quotient is 2869101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab always less than 1/2. Borrowed from VES1893.c, of course */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2889101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab tmp=srate<<6; 2899101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab BDRI=fclk>>2; 2909101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab ratio=(tmp/BDRI); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2929101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab tmp=(tmp%BDRI)<<8; 2939101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab ratio=(ratio<<8)+(tmp/BDRI); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2959101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab tmp=(tmp%BDRI)<<8; 2969101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab ratio=(ratio<<8)+(tmp/BDRI); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2989101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab tmp=(tmp%BDRI)<<1; 2999101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab ratio=(ratio<<1)+(tmp/BDRI); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3019101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab dprintk("srate= %d (range %d, up to %d)\n", srate,i,bands[i]); 3029101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab dprintk("fclk = %d\n", fclk); 3039101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab dprintk("ratio= %08x\n", ratio); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3059101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state, 0x1, (ratio>>16)&0xff); 3069101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state, 0x2, (ratio>>8)&0xff); 3079101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state, 0x3, (ratio)&0xff); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3099101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab return 0; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3132e4e98e788d8fbe30892bee3375067a4937155dalawrence ruststatic int _cx24110_pll_write (struct dvb_frontend* fe, const u8 buf[], int len) 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 315b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 317c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey if (len != 3) 318c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey return -EINVAL; 319c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tuner data is 21 bits long, must be left-aligned in data */ 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FIXME (low): add error handling, avoid infinite loops if HW fails... */ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3249101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */ 3259101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3279101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* if the auto tuner writer is still busy, clear it out */ 3289101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab while (cx24110_readreg(state,0x6d)&0x80) 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x72,0); 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3319101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* write the topmost 8 bits */ 332c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey cx24110_writereg(state,0x72,buf[0]); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3349101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* wait for the send to be completed */ 3359101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3389101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* send another 8 bytes */ 339c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey cx24110_writereg(state,0x72,buf[1]); 3409101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3439101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* and the topmost 5 bits of this byte */ 344c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey cx24110_writereg(state,0x72,buf[2]); 3459101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3489101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab /* now strobe the enable line once */ 3499101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x6d,0x32); 3509101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab cx24110_writereg(state,0x6d,0x30); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3529101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab return 0; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_initfe(struct dvb_frontend* fe) 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 357b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fixme (low): error handling */ 3599101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab int i; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: init chip\n", __func__); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3630496daa7d88d117fab4dd190c7f6e7c4a5aa15cdAhmed S. Darwish for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) { 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data); 3659101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab }; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 367e7ac46469c247a931f760354deaed9cf10b75fdeManu Abraham return 0; 368e7ac46469c247a931f760354deaed9cf10b75fdeManu Abraham} 369e7ac46469c247a931f760354deaed9cf10b75fdeManu Abraham 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 372b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (voltage) { 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEC_VOLTAGE_13: 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0xc0); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEC_VOLTAGE_18: 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0x40); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 384b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbachstatic int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 386c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach int rv, bit; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cx24110_state *state = fe->demodulator_priv; 388c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach unsigned long timeout; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (burst == SEC_MINI_A) 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bit = 0x00; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (burst == SEC_MINI_B) 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bit = 0x08; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = cx24110_readreg(state, 0x77); 398296c786a0d2122b1e47c80ca717d8a8ac36402c1Adam Szalkowski if (!(rv & 0x04)) 399296c786a0d2122b1e47c80ca717d8a8ac36402c1Adam Szalkowski cx24110_writereg(state, 0x77, rv | 0x04); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = cx24110_readreg(state, 0x76); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit)); 403c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach timeout = jiffies + msecs_to_jiffies(100); 404c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40)) 405c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach ; /* wait for LNB ready */ 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_send_diseqc_msg(struct dvb_frontend* fe, 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dvb_diseqc_master_cmd *cmd) 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, rv; 414b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 415c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach unsigned long timeout; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171e7eb89ba936fc1db54e247a336f3f55bdbc644dManu Abraham if (cmd->msg_len < 3 || cmd->msg_len > 6) 4181e7eb89ba936fc1db54e247a336f3f55bdbc644dManu Abraham return -EINVAL; /* not implemented */ 4191e7eb89ba936fc1db54e247a336f3f55bdbc644dManu Abraham 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < cmd->msg_len; i++) 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state, 0x79 + i, cmd->msg[i]); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = cx24110_readreg(state, 0x77); 424296c786a0d2122b1e47c80ca717d8a8ac36402c1Adam Szalkowski if (rv & 0x04) { 425296c786a0d2122b1e47c80ca717d8a8ac36402c1Adam Szalkowski cx24110_writereg(state, 0x77, rv & ~0x04); 426296c786a0d2122b1e47c80ca717d8a8ac36402c1Adam Szalkowski msleep(30); /* reportedly fixes switching problems */ 427296c786a0d2122b1e47c80ca717d8a8ac36402c1Adam Szalkowski } 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = cx24110_readreg(state, 0x76); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); 432c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach timeout = jiffies + msecs_to_jiffies(100); 433c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40)) 434c589ebfce79834a9617c44d7ec0f608fa70eb42dJohannes Stezenbach ; /* wait for LNB ready */ 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status) 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 441b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sync = cx24110_readreg (state, 0x55); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status = 0; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sync & 0x10) 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status |= FE_HAS_SIGNAL; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sync & 0x08) 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status |= FE_HAS_CARRIER; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sync = cx24110_readreg (state, 0x08); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sync & 0x40) 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status |= FE_HAS_VITERBI; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sync & 0x20) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status |= FE_HAS_SYNC; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sync & 0x60) == 0x60) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status |= FE_HAS_LOCK; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_read_ber(struct dvb_frontend* fe, u32* ber) 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 469b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fixme (maybe): value range is 16 bit. Scale? */ 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(cx24110_readreg(state,0x24)&0x10) { 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the Viterbi error counter has finished one counting window */ 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x24,0x04); /* select the ber reg */ 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->lastber=cx24110_readreg(state,0x25)| 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cx24110_readreg(state,0x26)<<8); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x24,0x04); /* start new count window */ 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x24,0x14); 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ber = state->lastber; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 487b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 signal = cx24110_readreg (state, 0x27)+128; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *signal_strength = (signal << 8) | signal; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_read_snr(struct dvb_frontend* fe, u16* snr) 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 498b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(cx24110_readreg(state,0x6a)&0x80) { 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the Es/N0 error counter has finished one counting window */ 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->lastesn0=cx24110_readreg(state,0x69)| 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cx24110_readreg(state,0x68)<<8); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x6a,0x84); /* start new count window */ 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *snr = state->lastesn0; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 514b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 lastbyer; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(cx24110_readreg(state,0x10)&0x40) { 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the RS error counter has finished one counting window */ 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x10,0x60); /* select the byer reg */ 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lastbyer=cx24110_readreg(state,0x12)| 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cx24110_readreg(state,0x13)<<8)| 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cx24110_readreg(state,0x14)<<16); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x10,0x70); /* select the bler reg */ 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->lastbler=cx24110_readreg(state,0x12)| 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cx24110_readreg(state,0x13)<<8)| 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cx24110_readreg(state,0x14)<<16); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cx24110_writereg(state,0x10,0x20); /* start new count window */ 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ucblocks = state->lastbler; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5344be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehabstatic int cx24110_set_frontend(struct dvb_frontend *fe) 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 536b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 5374be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehab struct dtv_frontend_properties *p = &fe->dtv_property_cache; 53881d8a8da8233eb63f783eb3241805ab629b15907Andrew de Quincey 539dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher if (fe->ops.tuner_ops.set_params) { 54014d24d148c7521b2b88b396652e36f55d061e195Mauro Carvalho Chehab fe->ops.tuner_ops.set_params(fe); 541dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); 54281d8a8da8233eb63f783eb3241805ab629b15907Andrew de Quincey } 54381d8a8da8233eb63f783eb3241805ab629b15907Andrew de Quincey 5444be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehab cx24110_set_inversion(state, p->inversion); 5454be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehab cx24110_set_fec(state, p->fec_inner); 5464be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehab cx24110_set_symbolrate(state, p->symbol_rate); 54725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi cx24110_writereg(state,0x04,0x05); /* start acquisition */ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5527c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehabstatic int cx24110_get_frontend(struct dvb_frontend *fe) 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5547c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehab struct dtv_frontend_properties *p = &fe->dtv_property_cache; 555b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s32 afc; unsigned sclk; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* cannot read back tuner settings (freq). Need to have some private storage */ 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclk = cx24110_readreg (state, 0x07) & 0x03; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz. 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Need 64 bit arithmetic. Is thiss possible in the kernel? */ 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sclk==0) sclk=90999000L/2L; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (sclk==1) sclk=60666000L; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (sclk==2) sclk=80888000L; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else sclk=90999000L; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclk>>=8; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds afc = sclk*(cx24110_readreg (state, 0x44)&0x1f)+ 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((sclk*cx24110_readreg (state, 0x45))>>8)+ 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((sclk*cx24110_readreg (state, 0x46))>>16); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->frequency += afc; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ? 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INVERSION_ON : INVERSION_OFF; 5754be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehab p->fec_inner = cx24110_get_fec(state); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 582b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state *state = fe->demodulator_priv; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0)); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cx24110_release(struct dvb_frontend* fe) 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 589b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach struct cx24110_state* state = fe->demodulator_priv; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(state); 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dvb_frontend_ops cx24110_ops; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dvb_frontend* cx24110_attach(const struct cx24110_config* config, 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_adapter* i2c) 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cx24110_state* state = NULL; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate memory for the internal state */ 602084e24acc906c162c92de7df807190856ae60928Matthias Schwarzott state = kzalloc(sizeof(struct cx24110_state), GFP_KERNEL); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state == NULL) goto error; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* setup the state */ 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->config = config; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->i2c = i2c; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->lastber = 0; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->lastbler = 0; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->lastesn0 = 0; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if the demod is there */ 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = cx24110_readreg(state, 0x00); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ret != 0x5a) && (ret != 0x69)) goto error; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* create dvb_frontend */ 617dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops)); 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state->frontend.demodulator_priv = state; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &state->frontend; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror: 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(state); 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dvb_frontend_ops cx24110_ops = { 6274be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehab .delsys = { SYS_DVBS }, 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .info = { 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "Conexant CX24110 DVB-S", 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_min = 950000, 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_max = 2150000, 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_stepsize = 1011, /* kHz for QPSK frontends */ 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_tolerance = 29500, 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .symbol_rate_min = 1000000, 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .symbol_rate_max = 45000000, 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .caps = FE_CAN_INVERSION_AUTO | 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_QPSK | FE_CAN_RECOVER 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = cx24110_release, 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init = cx24110_initfe, 645c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey .write = _cx24110_pll_write, 6464be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehab .set_frontend = cx24110_set_frontend, 6474be325c9668f6af89baa52e092e054632658e850Mauro Carvalho Chehab .get_frontend = cx24110_get_frontend, 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_status = cx24110_read_status, 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_ber = cx24110_read_ber, 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_signal_strength = cx24110_read_signal_strength, 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_snr = cx24110_read_snr, 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_ucblocks = cx24110_read_ucblocks, 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .diseqc_send_master_cmd = cx24110_send_diseqc_msg, 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_tone = cx24110_set_tone, 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_voltage = cx24110_set_voltage, 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .diseqc_send_burst = cx24110_diseqc_send_burst, 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0644); 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Conexant CX24110 DVB-S Demodulator driver"); 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Peter Hettkamp"); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(cx24110_attach); 668