11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Driver for Philips tda1004xh OFDM Demodulator 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (c) 2003, 2004 Andrew de Quincey & Robert Schlabbach 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver needs external firmware. Please use the commands 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045", 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to 2612e66f6573beda52a434b757df5b7a5a05b9ebd2Ville Skytt\� * download/extract them, and then copy them to /usr/lib/hotplug/firmware 2712e66f6573beda52a434b757df5b7a5a05b9ebd2Ville Skytt\� * or /lib/firmware (depending on configuration of firmware hotplug). 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw" 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw" 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h> 354e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/jiffies.h> 364e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h> 374e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h> 384e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dvb_frontend.h" 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tda1004x.h" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dprintk(args...) \ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { \ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (debug) printk(KERN_DEBUG "tda1004x: " args); \ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (0) 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CHIPID 0x00 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_AUTO 0x01 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_IN_CONF1 0x02 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_IN_CONF2 0x03 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_OUT_CONF1 0x04 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_OUT_CONF2 0x05 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_STATUS_CD 0x06 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CONFC4 0x07 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_DSSPARE2 0x0C 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_CODE_IN 0x0D 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_FWPAGE 0x0E 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_SCAN_CPT 0x10 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_DSP_CMD 0x11 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_DSP_ARG 0x12 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_DSP_DATA1 0x13 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_DSP_DATA2 0x14 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CONFADC1 0x15 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CONFC1 0x16 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_S_AGC 0x1a 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_AGC_TUN_LEVEL 0x1a 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_SNR 0x1c 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CONF_TS1 0x1e 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CONF_TS2 0x1f 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CBER_RESET 0x20 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CBER_MSB 0x21 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CBER_LSB 0x22 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CVBER_LUT 0x23 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_VBER_MSB 0x24 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_VBER_MID 0x25 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_VBER_LSB 0x26 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_UNCOR 0x27 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_CONFPLL_P 0x2D 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_CONFPLL_M_MSB 0x2E 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_CONFPLL_M_LSB 0x2F 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_CONFPLL_N 0x30 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CONFPLL1 0x2D 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CONFPLL2 0x2F 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CONFPLL3 0x30 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_TIME_WREF1 0x31 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_TIME_WREF2 0x32 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_TIME_WREF3 0x33 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_TIME_WREF4 0x34 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_TIME_WREF5 0x35 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_UNSURW_MSB 0x31 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_UNSURW_LSB 0x32 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_WREF_MSB 0x33 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_WREF_MID 0x34 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_WREF_LSB 0x35 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_MUXOUT 0x36 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA1004X_CONFADC2 0x37 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10045H_IOFFSET 0x38 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CONF_TRISTATE1 0x3B 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CONF_TRISTATE2 0x3C 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CONF_POLARITY 0x3D 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_FREQ_OFFSET 0x3E 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_GPIO_OUT_SEL 0x41 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_GPIO_SELECT 0x42 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_AGC_CONF 0x43 111f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann#define TDA10046H_AGC_THR 0x44 112f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann#define TDA10046H_AGC_RENORM 0x45 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_AGC_GAINS 0x46 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_AGC_TUN_MIN 0x47 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_AGC_TUN_MAX 0x48 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_AGC_IF_MIN 0x49 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_AGC_IF_MAX 0x4A 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_FREQ_PHY2_MSB 0x4D 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_FREQ_PHY2_LSB 0x4E 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CVBER_CTRL 0x4F 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_AGC_IF_LEVEL 0x52 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CODE_CPT 0x57 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TDA10046H_CODE_IN 0x58 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 buf[] = { reg, data }; 1327f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msg.addr = state->config->demod_address; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = i2c_transfer(state->i2c, &msg, 1); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret != 1) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", 141271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison __func__, reg, data, ret); 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 143271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__, 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg, data, ret); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (ret != 1) ? -1 : 0; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_read_byte(struct tda1004x_state *state, int reg) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 b0[] = { reg }; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 b1[] = { 0 }; 1537f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 }, 1547f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach { .flags = I2C_M_RD, .buf = b1, .len = 1 }}; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 156271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: reg=0x%x\n", __func__, reg); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msg[0].addr = state->config->demod_address; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msg[1].addr = state->config->demod_address; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = i2c_transfer(state->i2c, msg, 2); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret != 2) { 163271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret); 165517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab return -EINVAL; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 168271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__, 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg, b1[0], ret); 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return b1[0]; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val; 176271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg, 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask, data); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // read a byte and check 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = tda1004x_read_byte(state, reg); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val < 0) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // mask if off 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = val & ~mask; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= data & 0xff; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // write it out again 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return tda1004x_write_byteI(state, reg, val); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned char *buf, int len) 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 197271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = 0; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < len; i++) { 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = tda1004x_write_byteI(state, reg + i, buf[i]); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result != 0) 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_enable_tuner_i2c(struct tda1004x_state *state) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 212271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2); 2150eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann msleep(20); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_disable_tuner_i2c(struct tda1004x_state *state) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 221271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda10045h_set_bandwidth(struct tda1004x_state *state, 2275f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab u32 bandwidth) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb }; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 }; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (bandwidth) { 2345f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab case 6000000: 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2385f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab case 7000000: 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2425f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab case 8000000: 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA10045H_IOFFSET, 0); 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda10046h_set_bandwidth(struct tda1004x_state *state, 2565f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab u32 bandwidth) 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2588a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 }; 2598a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f }; 2608a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d }; 2618a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann 2628a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 }; 2638a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab }; 2648a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 }; 2658a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann int tda10046_clk53m; 2668a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann 2678a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann if ((state->config->if_freq == TDA10046_FREQ_045) || 2688a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann (state->config->if_freq == TDA10046_FREQ_052)) 2698a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda10046_clk53m = 0; 2708a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann else 2718a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda10046_clk53m = 1; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (bandwidth) { 2735f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab case 6000000: 2748a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann if (tda10046_clk53m) 2758a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M, 27650c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky sizeof(bandwidth_6mhz_53M)); 2778a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann else 2788a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M, 27950c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky sizeof(bandwidth_6mhz_48M)); 280f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann if (state->config->if_freq == TDA10046_FREQ_045) { 2818a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a); 2828a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab); 283f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann } 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2865f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab case 7000000: 2878a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann if (tda10046_clk53m) 2888a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M, 28950c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky sizeof(bandwidth_7mhz_53M)); 2908a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann else 2918a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M, 29250c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky sizeof(bandwidth_7mhz_48M)); 293f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann if (state->config->if_freq == TDA10046_FREQ_045) { 2948a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c); 2958a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00); 296f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann } 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2995f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab case 8000000: 3008a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann if (tda10046_clk53m) 3018a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M, 30250c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky sizeof(bandwidth_8mhz_53M)); 3038a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann else 3048a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M, 30550c25fff5385c6baf3114f7c369b0f75a29ac1e8Michael Krufky sizeof(bandwidth_8mhz_48M)); 306f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann if (state->config->if_freq == TDA10046_FREQ_045) { 3078a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d); 3088a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55); 309f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann } 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_do_upload(struct tda1004x_state *state, 320bc179153ae2334efe28cf4f3300e024da7d83753David Woodhouse const unsigned char *mem, unsigned int len, 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 dspCodeCounterReg, u8 dspCodeInReg) 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 buf[65]; 3247f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach struct i2c_msg fw_msg = { .flags = 0, .buf = buf, .len = 0 }; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tx_size; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pos = 0; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* clear code counter */ 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, dspCodeCounterReg, 0); 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fw_msg.addr = state->config->demod_address; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = dspCodeInReg; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (pos != len) { 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // work out how much to send this time 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_size = len - pos; 3367f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (tx_size > 0x10) 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_size = 0x10; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // send the chunk 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(buf + 1, mem + pos, tx_size); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fw_msg.len = tx_size + 1; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) { 343ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann printk(KERN_ERR "tda1004x: Error during firmware upload\n"); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos += tx_size; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 348271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: fw_pos=0x%x\n", __func__, pos); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 350ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann // give the DSP a chance to settle 03/10/05 Hac 351ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann msleep(100); 3527f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 356ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmannstatic int tda1004x_check_upload_ok(struct tda1004x_state *state) 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 data1, data2; 359ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann unsigned long timeout; 360ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann 361ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann if (state->demod_type == TDA1004X_DEMOD_TDA10046) { 362ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann timeout = jiffies + 2 * HZ; 363ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) { 364ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann if (time_after(jiffies, timeout)) { 365ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann printk(KERN_ERR "tda1004x: timeout waiting for DSP ready\n"); 366ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann break; 367ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann } 368ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann msleep(1); 369ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann } 370ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann } else 371ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann msleep(100); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // check upload was OK 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA1004X_DSP_CMD, 0x67); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data1 = tda1004x_read_byte(state, TDA1004X_DSP_DATA1); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data2 = tda1004x_read_byte(state, TDA1004X_DSP_DATA2); 3793faadbb0fde3c53e1c4f13eabb478c0c7cb1e4ddHartmut Hackmann if (data1 != 0x67 || data2 < 0x20 || data2 > 0x2e) { 380ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann printk(KERN_INFO "tda1004x: found firmware revision %x -- invalid\n", data2); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 382ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann } 383ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann printk(KERN_INFO "tda1004x: found firmware revision %x -- ok\n", data2); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda10045_fwupload(struct dvb_frontend* fe) 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct firmware *fw; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't re-upload unless necessary */ 394ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann if (tda1004x_check_upload_ok(state) == 0) 3957f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return 0; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* request the firmware, this will block until someone uploads it */ 398ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann printk(KERN_INFO "tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 401ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset chip */ 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set parameters */ 4125f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab tda10045h_set_bandwidth(state, 8000000); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN); 4150c744b010078bd65724477e75261e51712d290a0Anssi Hannula release_firmware(fw); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 418ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann printk(KERN_INFO "tda1004x: firmware upload complete\n"); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* wait for DSP to initialise */ 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* DSPREADY doesn't seem to work on the TDA10045H */ 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(100); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 424ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann return tda1004x_check_upload_ok(state); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 427ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmannstatic void tda10046_init_plls(struct dvb_frontend* fe) 42871e3420111530273f2b26fabfac4d021c2a2b79fJohannes Stezenbach{ 429ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann struct tda1004x_state* state = fe->demodulator_priv; 4308a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann int tda10046_clk53m; 4318a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann 4328a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann if ((state->config->if_freq == TDA10046_FREQ_045) || 4338a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann (state->config->if_freq == TDA10046_FREQ_052)) 4348a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda10046_clk53m = 0; 4358a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann else 4368a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda10046_clk53m = 1; 43771e3420111530273f2b26fabfac4d021c2a2b79fJohannes Stezenbach 438ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0); 4398a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann if(tda10046_clk53m) { 4408a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n"); 4418a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8 4428a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann } else { 4438a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n"); 4448a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3 4458a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann } 446ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann if (state->config->xtal_freq == TDA10046_XTAL_4M ) { 447271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__); 448ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 449ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann } else { 450271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__); 451ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3 452ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann } 4538a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann if(tda10046_clk53m) 4548a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67); 4558a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann else 4568a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72); 4578a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann /* Note clock frequency is handled implicitly */ 458ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann switch (state->config->if_freq) { 459f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann case TDA10046_FREQ_045: 4608a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c); 4618a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00); 462f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann break; 463f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann case TDA10046_FREQ_052: 4648a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d); 4658a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7); 4668a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann break; 4678a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann case TDA10046_FREQ_3617: 4688a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7); 4698a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59); 4708a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann break; 4718a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann case TDA10046_FREQ_3613: 4728a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7); 4738a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f); 474f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann break; 475ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann } 4765f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab tda10046h_set_bandwidth(state, 8000000); /* default bandwidth 8 MHz */ 4778a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann /* let the PLLs settle */ 4788a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann msleep(120); 47971e3420111530273f2b26fabfac4d021c2a2b79fJohannes Stezenbach} 48071e3420111530273f2b26fabfac4d021c2a2b79fJohannes Stezenbach 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda10046_fwupload(struct dvb_frontend* fe) 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 484517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab int ret, confc4; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct firmware *fw; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset + wake up chip */ 4880eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann if (state->config->xtal_freq == TDA10046_XTAL_4M) { 489517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab confc4 = 0; 4900eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann } else { 491271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__); 492517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab confc4 = 0x80; 4930eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann } 494517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab tda1004x_write_byteI(state, TDA1004X_CONFC4, confc4); 495517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); 4971bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann /* set GPIO 1 and 3 */ 4981bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann if (state->config->gpio_config != TDA10046_GPTRI) { 4991bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0x33); 5001bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, state->config->gpio_config &0x0f); 5011bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann } 502ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann /* let the clocks recover from sleep */ 5031bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann msleep(10); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5058a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann /* The PLLs need to be reprogrammed after sleep */ 5068a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda10046_init_plls(fe); 50768717583557341874b2eea4dea36635256e932b6Hartmut Hackmann tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0); 5088a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't re-upload unless necessary */ 510ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann if (tda1004x_check_upload_ok(state) == 0) 5117f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return 0; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 513517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab /* 514517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab For i2c normal work, we need to slow down the bus speed. 515517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab However, the slow down breaks the eeprom firmware load. 516517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab So, use normal speed for eeprom booting and then restore the 517517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab i2c speed after that. Tested with MSI TV @nyware A/D board, 518517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab that comes with firmware version 29 inside their eeprom. 519517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab 520517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab It should also be noticed that no other I2C transfer should 521517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab be in course while booting from eeprom, otherwise, tda10046 522517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab goes into an instable state. So, proper locking are needed 523517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab at the i2c bus master. 524517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab */ 5251bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann printk(KERN_INFO "tda1004x: trying to boot from eeprom\n"); 526517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab tda1004x_write_byteI(state, TDA1004X_CONFC4, 4); 5271bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann msleep(300); 528517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab tda1004x_write_byteI(state, TDA1004X_CONFC4, confc4); 529517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab 530517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab /* Checks if eeprom firmware went without troubles */ 5311bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann if (tda1004x_check_upload_ok(state) == 0) 5321bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann return 0; 5331bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann 534517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab /* eeprom firmware didn't work. Load one manually. */ 535517efa89acef3ac440e6e1ca10252d407ba51abfMauro Carvalho Chehab 536f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann if (state->config->request_firmware != NULL) { 537f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann /* request the firmware, this will block until someone uploads it */ 538f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); 539f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); 540ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann if (ret) { 541f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann /* remain compatible to old bug: try to load with tda10045 image name */ 542f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); 543f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann if (ret) { 544f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n"); 545f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann return ret; 546f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann } else { 547f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n", 548f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann TDA10046_DEFAULT_FIRMWARE); 549f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann } 550f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann } 551f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann } else { 552f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann printk(KERN_ERR "tda1004x: no request function defined, can't upload from file\n"); 553f4546e702a89d2e483570f0f16c5155bb781cc38Hartmut Hackmann return -EIO; 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5551bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST 5561bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN); 5571bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann release_firmware(fw); 558ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann return tda1004x_check_upload_ok(state); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_encode_fec(int fec) 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // convert known FEC values 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fec) { 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FEC_1_2: 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FEC_2_3: 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FEC_3_4: 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FEC_5_6: 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 3; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FEC_7_8: 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 4; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // unsupported 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_decode_fec(int tdafec) 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // convert known FEC values 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (tdafec) { 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FEC_1_2; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FEC_2_3; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FEC_3_4; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 3: 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FEC_5_6; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FEC_7_8; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // unsupported 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6012e4e98e788d8fbe30892bee3375067a4937155dalawrence ruststatic int tda1004x_write(struct dvb_frontend* fe, const u8 buf[], int len) 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 605c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey if (len != 2) 606c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey return -EINVAL; 607c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey 608c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey return tda1004x_write_byteI(state, buf[0], buf[1]); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda10045_init(struct dvb_frontend* fe) 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 615271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tda10045_fwupload(fe)) { 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("tda1004x: firmware upload failed\n"); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // tda setup 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0); // set polarity of VAGC signal 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda10046_init(struct dvb_frontend* fe) 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 645271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tda10046_fwupload(fe)) { 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("tda1004x: firmware upload failed\n"); 649ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann return -EIO; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // tda setup 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer 6548a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream 6550eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann tda1004x_write_byteI(state, TDA1004X_CONFC1, 0x88); // enable pulse killer 656ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann 657ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann switch (state->config->agc_config) { 658ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann case TDA10046_AGC_DEFAULT: 659ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup 6601bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities 661ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann break; 662ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann case TDA10046_AGC_IFO_AUTO_NEG: 663ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup 6641bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities 665ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann break; 666f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann case TDA10046_AGC_IFO_AUTO_POS: 667f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup 6681bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x00); // set AGC polarities 6690eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann break; 6701bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann case TDA10046_AGC_TDA827X: 671550a9a5e5f8086ae410832f134a5d80b9bd7fdb6Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup 672550a9a5e5f8086ae410832f134a5d80b9bd7fdb6Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold 673550a9a5e5f8086ae410832f134a5d80b9bd7fdb6Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize 6741bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities 675550a9a5e5f8086ae410832f134a5d80b9bd7fdb6Hartmut Hackmann break; 676ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann } 67708cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann if (state->config->ts_mode == 0) { 67808cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x40); 67908cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); 68008cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann } else { 68108cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x80); 68208cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x10, 68308cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann state->config->invert_oclk << 4); 68408cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann } 6858a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); 68608cdf94c076121cd0214ef9ea18ae3fbb9ace684Hartmut Hackmann tda1004x_write_mask (state, TDA10046H_CONF_TRISTATE1, 0x3e, 0x38); // Turn IF AGC output on 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // } 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // } 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // } 6918a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1 692ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config 694ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config 6950eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann // tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes 696ecb60deb9d5bbcbab6c87ee5fde6f8368197fcacHartmut Hackmann 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7005f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehabstatic int tda1004x_set_fe(struct dvb_frontend *fe) 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7025f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tmp; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int inversion; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 707271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->demod_type == TDA1004X_DEMOD_TDA10046) { 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // setup auto offset 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x80, 0); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // disable agc_conf[2] 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 0); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set frequency 720dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher if (fe->ops.tuner_ops.set_params) { 72114d24d148c7521b2b88b396652e36f55d061e195Mauro Carvalho Chehab fe->ops.tuner_ops.set_params(fe); 722ede2200d79777d461cf2f0fd19cf7a17f633d3a4Hartmut Hackmann if (fe->ops.i2c_gate_ctrl) 723ede2200d79777d461cf2f0fd19cf7a17f633d3a4Hartmut Hackmann fe->ops.i2c_gate_ctrl(fe, 0); 724634623d3ba6146e13d06d3f36188c189c8a58a23Hartmut Hackmann } 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Hardcoded to use auto as much as possible on the TDA10045 as it 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // is very unreliable if AUTO mode is _not_ used. 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state->demod_type == TDA1004X_DEMOD_TDA10045) { 7295f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->code_rate_HP = FEC_AUTO; 7305f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->guard_interval = GUARD_INTERVAL_AUTO; 7315f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->transmission_mode = TRANSMISSION_MODE_AUTO; 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Set standard params.. or put them to auto 7355f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab if ((fe_params->code_rate_HP == FEC_AUTO) || 7365f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab (fe_params->code_rate_LP == FEC_AUTO) || 7375f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab (fe_params->modulation == QAM_AUTO) || 7385f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab (fe_params->hierarchy == HIERARCHY_AUTO)) { 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto 7405f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); /* turn off modulation bits */ 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0); // disable auto 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set HP FEC 7475f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab tmp = tda1004x_encode_fec(fe_params->code_rate_HP); 7487f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (tmp < 0) 7497f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return tmp; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set LP FEC 7535f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab tmp = tda1004x_encode_fec(fe_params->code_rate_LP); 7547f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (tmp < 0) 7557f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return tmp; 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3); 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7585f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab /* set modulation */ 7595f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab switch (fe_params->modulation) { 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case QPSK: 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0); 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case QAM_16: 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 1); 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case QAM_64: 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 2); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set hierarchy 7775f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab switch (fe_params->hierarchy) { 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HIERARCHY_NONE: 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HIERARCHY_1: 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 1 << 5); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HIERARCHY_2: 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 2 << 5); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HIERARCHY_4: 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 3 << 5); 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set bandwidth 8007f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach switch (state->demod_type) { 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10045: 8025f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab tda10045h_set_bandwidth(state, fe_params->bandwidth_hz); 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10046: 8065f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab tda10046h_set_bandwidth(state, fe_params->bandwidth_hz); 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set inversion 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inversion = fe_params->inversion; 8127f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (state->config->invert) 8137f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach inversion = inversion ? INVERSION_OFF : INVERSION_ON; 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (inversion) { 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case INVERSION_OFF: 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0); 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case INVERSION_ON: 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0x20); 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set guard interval 8285f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab switch (fe_params->guard_interval) { 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GUARD_INTERVAL_1_32: 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GUARD_INTERVAL_1_16: 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GUARD_INTERVAL_1_8: 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GUARD_INTERVAL_1_4: 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GUARD_INTERVAL_AUTO: 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 2, 2); 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set transmission mode 8595f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab switch (fe_params->transmission_mode) { 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TRANSMISSION_MODE_2K: 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0); 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4); 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TRANSMISSION_MODE_8K: 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0); 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 1 << 4); 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TRANSMISSION_MODE_AUTO: 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 4, 4); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0); 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // start the lock 8807f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach switch (state->demod_type) { 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10045: 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10046: 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40); 888634623d3ba6146e13d06d3f36188c189c8a58a23Hartmut Hackmann msleep(1); 889634623d3ba6146e13d06d3f36188c189c8a58a23Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 1); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8937f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach msleep(10); 8947f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8987c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehabstatic int tda1004x_get_fe(struct dvb_frontend *fe) 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9007c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehab struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 9028a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann 903271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // inversion status 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fe_params->inversion = INVERSION_OFF; 9077f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20) 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fe_params->inversion = INVERSION_ON; 9097f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (state->config->invert) 9107f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // bandwidth 9137f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach switch (state->demod_type) { 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10045: 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) { 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x14: 9175f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->bandwidth_hz = 8000000; 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xdb: 9205f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->bandwidth_hz = 7000000; 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x4f: 9235f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->bandwidth_hz = 6000000; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10046: 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) { 9298a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann case 0x5c: 9308a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann case 0x54: 9315f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->bandwidth_hz = 8000000; 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9338a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann case 0x6a: 9348a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann case 0x60: 9355f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->bandwidth_hz = 7000000; 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9378a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann case 0x7b: 9388a8e9c281de5dd63cdcbbafc0252fe0d8c758294Hartmut Hackmann case 0x70: 9395f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->bandwidth_hz = 6000000; 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // FEC 9465f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->code_rate_HP = 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7); 9485f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->code_rate_LP = 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7); 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9515f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab /* modulation */ 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) { 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 9545f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->modulation = QPSK; 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 9575f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->modulation = QAM_16; 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 9605f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->modulation = QAM_64; 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // transmission mode 9655f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->transmission_mode = TRANSMISSION_MODE_2K; 9667f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10) 9675f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->transmission_mode = TRANSMISSION_MODE_8K; 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // guard interval 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 9725f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->guard_interval = GUARD_INTERVAL_1_32; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 9755f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->guard_interval = GUARD_INTERVAL_1_16; 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 9785f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->guard_interval = GUARD_INTERVAL_1_8; 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 3: 9815f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->guard_interval = GUARD_INTERVAL_1_4; 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // hierarchy 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 9885f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->hierarchy = HIERARCHY_NONE; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 9915f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->hierarchy = HIERARCHY_1; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 9945f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->hierarchy = HIERARCHY_2; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 3: 9975f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab fe_params->hierarchy = HIERARCHY_4; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status) 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cber; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int vber; 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // read status 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = tda1004x_read_byte(state, TDA1004X_STATUS_CD); 10157f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (status == -1) 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // decode 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fe_status = 0; 10207f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (status & 4) 10217f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach *fe_status |= FE_HAS_SIGNAL; 10227f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (status & 2) 10237f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach *fe_status |= FE_HAS_CARRIER; 10247f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (status & 8) 10257f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // is getting anything valid 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(*fe_status & FE_HAS_VITERBI)) { 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // read the CBER 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB); 10327f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (cber == -1) 10337f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return -EIO; 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = tda1004x_read_byte(state, TDA1004X_CBER_MSB); 10357f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (status == -1) 10367f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return -EIO; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cber |= (status << 8); 10380eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann // The address 0x20 should be read to cope with a TDA10046 bug 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_read_byte(state, TDA1004X_CBER_RESET); 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10417f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (cber != 65535) 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fe_status |= FE_HAS_VITERBI; 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // if we DO have some valid VITERBI output, but don't already have SYNC 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid. 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) { 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // read the VBER 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB); 10507f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (vber == -1) 10517f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return -EIO; 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = tda1004x_read_byte(state, TDA1004X_VBER_MID); 10537f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (status == -1) 10547f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return -EIO; 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vber |= (status << 8); 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = tda1004x_read_byte(state, TDA1004X_VBER_MSB); 10577f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (status == -1) 10587f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return -EIO; 10590eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann vber |= (status & 0x0f) << 16; 10600eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann // The CVBER_LUT should be read to cope with TDA10046 hardware bug 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_read_byte(state, TDA1004X_CVBER_LUT); 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // if RS has passed some valid TS packets, then we must be 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // getting some SYNC bytes 10657f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (vber < 16632) 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *fe_status |= FE_HAS_SYNC; 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // success 1070271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: fe_status=0x%x\n", __func__, *fe_status); 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal) 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tmp; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int reg = 0; 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1080271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // determine the register to use 10837f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach switch (state->demod_type) { 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10045: 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = TDA10045H_S_AGC; 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10046: 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = TDA10046H_AGC_IF_LEVEL; 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // read it 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = tda1004x_read_byte(state, reg); 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp < 0) 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *signal = (tmp << 8) | tmp; 1099271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: signal=0x%x\n", __func__, *signal); 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr) 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tmp; 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1108271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // read it 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = tda1004x_read_byte(state, TDA1004X_SNR); 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp < 0) 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 1114c2026b3af0c8ad33ef253a950c271f2d0da111b6Andrew de Quincey tmp = 255 - tmp; 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *snr = ((tmp << 8) | tmp); 1117271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: snr=0x%x\n", __func__, *snr); 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tmp; 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tmp2; 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int counter; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1128271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // read the UCBLOCKS and reset 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds counter = 0; 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = tda1004x_read_byte(state, TDA1004X_UNCOR); 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp < 0) 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp &= 0x7f; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (counter++ < 5) { 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp2 = tda1004x_read_byte(state, TDA1004X_UNCOR); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp2 < 0) 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp2 &= 0x7f; 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((tmp2 < tmp) || (tmp2 == 0)) 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11497f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (tmp != 0x7f) 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ucblocks = tmp; 11517f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach else 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ucblocks = 0xffffffff; 11537f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 1154271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks); 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tmp; 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1163271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s\n", __func__); 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // read it in 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB); 11677f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (tmp < 0) 11687f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return -EIO; 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ber = tmp << 1; 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB); 11717f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach if (tmp < 0) 11727f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return -EIO; 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ber |= (tmp << 9); 11740eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann // The address 0x20 should be read to cope with a TDA10046 bug 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_read_byte(state, TDA1004X_CBER_RESET); 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1177271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison dprintk("%s: ber=0x%x\n", __func__, *ber); 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_sleep(struct dvb_frontend* fe) 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tda1004x_state* state = fe->demodulator_priv; 11841bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann int gpio_conf; 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11867f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach switch (state->demod_type) { 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10045: 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10); 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TDA1004X_DEMOD_TDA10046: 11920eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann /* set outputs to tristate */ 11930eb3de20a1cec67547951cebc4fcddc701e7428bHartmut Hackmann tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff); 11941bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann /* invert GPIO 1 and 3 if desired*/ 11951bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann gpio_conf = state->config->gpio_config; 11961bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann if (gpio_conf >= TDA10046_GP00_I) 11971bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, 11981bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann (gpio_conf & 0x0f) ^ 0x0a); 11991bb0e8667fab773d6c5a3d7caf506001deaeb7f5Hartmut Hackmann 120068717583557341874b2eea4dea36635256e932b6Hartmut Hackmann tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0xc0); 1201f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 120874349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quinceystatic int tda1004x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) 120974349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey{ 121074349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey struct tda1004x_state* state = fe->demodulator_priv; 121174349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey 121274349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey if (enable) { 121374349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey return tda1004x_enable_tuner_i2c(state); 121474349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey } else { 121574349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey return tda1004x_disable_tuner_i2c(state); 121674349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey } 121774349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey} 121874349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fesettings->min_delay_ms = 800; 1222f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann /* Drift compensation makes no sense for DVB-T */ 1223f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann fesettings->step_size = 0; 1224f03cbea36ab9412dcea58e953be4933b36c9b7beHartmut Hackmann fesettings->max_drift = 0; 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12282a514dea5fda67958c79f5137d4dcb272f8561e8Andrew de Quinceystatic void tda1004x_release(struct dvb_frontend* fe) 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12307f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach struct tda1004x_state *state = fe->demodulator_priv; 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(state); 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dvb_frontend_ops tda10045_ops = { 12355f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab .delsys = { SYS_DVBT }, 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .info = { 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "Philips TDA10045H DVB-T", 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_min = 51000000, 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_max = 858000000, 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_stepsize = 166667, 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .caps = 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12482a514dea5fda67958c79f5137d4dcb272f8561e8Andrew de Quincey .release = tda1004x_release, 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init = tda10045_init, 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sleep = tda1004x_sleep, 1252c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey .write = tda1004x_write, 125374349bef1a5b5a287721a42bec08c226b095e8b0Andrew de Quincey .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl, 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12555f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab .set_frontend = tda1004x_set_fe, 12565f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab .get_frontend = tda1004x_get_fe, 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_tune_settings = tda1004x_get_tune_settings, 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_status = tda1004x_read_status, 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_ber = tda1004x_read_ber, 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_signal_strength = tda1004x_read_signal_strength, 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_snr = tda1004x_read_snr, 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_ucblocks = tda1004x_read_ucblocks, 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12667f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbachstruct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, 12677f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach struct i2c_adapter* i2c) 12687f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach{ 12697f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach struct tda1004x_state *state; 12700e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab int id; 12717f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 12727f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach /* allocate memory for the internal state */ 1273084e24acc906c162c92de7df807190856ae60928Matthias Schwarzott state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); 1274bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab if (!state) { 12753472a2caa49b55c2923e7c876aa84f13eb4b8863Masanari Iida printk(KERN_ERR "Can't allocate memory for tda10045 state\n"); 12767f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return NULL; 1277bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab } 12787f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 12797f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach /* setup the state */ 12807f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach state->config = config; 12817f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach state->i2c = i2c; 12827f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach state->demod_type = TDA1004X_DEMOD_TDA10045; 12837f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 12847f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach /* check if the demod is there */ 1285bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab id = tda1004x_read_byte(state, TDA1004X_CHIPID); 12860e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab if (id < 0) { 12870e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab printk(KERN_ERR "tda10045: chip is not answering. Giving up.\n"); 12880e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab kfree(state); 12890e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab return NULL; 12900e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab } 12910e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab 1292bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab if (id != 0x25) { 1293bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id); 12947f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach kfree(state); 12957f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return NULL; 12967f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach } 12977f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 12987f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach /* create dvb_frontend */ 1299dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher memcpy(&state->frontend.ops, &tda10045_ops, sizeof(struct dvb_frontend_ops)); 13007f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach state->frontend.demodulator_priv = state; 13017f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return &state->frontend; 13027f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach} 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13047f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbachstatic struct dvb_frontend_ops tda10046_ops = { 13055f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab .delsys = { SYS_DVBT }, 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .info = { 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "Philips TDA10046H DVB-T", 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_min = 51000000, 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_max = 858000000, 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .frequency_stepsize = 166667, 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .caps = 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13182a514dea5fda67958c79f5137d4dcb272f8561e8Andrew de Quincey .release = tda1004x_release, 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init = tda10046_init, 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sleep = tda1004x_sleep, 1322c10d14d62d7b7596fd5c7bb8aad3f2b56f8640e6Andrew de Quincey .write = tda1004x_write, 1323159f8a6eda8c2ee359bb87bf62be70da2da14918Andrew de Quincey .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl, 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13255f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab .set_frontend = tda1004x_set_fe, 13265f82e6b18cb48e261f0a15a7f12c843b488234a5Mauro Carvalho Chehab .get_frontend = tda1004x_get_fe, 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_tune_settings = tda1004x_get_tune_settings, 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_status = tda1004x_read_status, 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_ber = tda1004x_read_ber, 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_signal_strength = tda1004x_read_signal_strength, 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_snr = tda1004x_read_snr, 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read_ucblocks = tda1004x_read_ucblocks, 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13367f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbachstruct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, 13377f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach struct i2c_adapter* i2c) 13387f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach{ 13397f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach struct tda1004x_state *state; 13400e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab int id; 13417f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 13427f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach /* allocate memory for the internal state */ 1343084e24acc906c162c92de7df807190856ae60928Matthias Schwarzott state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); 1344bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab if (!state) { 13453472a2caa49b55c2923e7c876aa84f13eb4b8863Masanari Iida printk(KERN_ERR "Can't allocate memory for tda10046 state\n"); 13467f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return NULL; 1347bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab } 13487f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 13497f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach /* setup the state */ 13507f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach state->config = config; 13517f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach state->i2c = i2c; 13527f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach state->demod_type = TDA1004X_DEMOD_TDA10046; 13537f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 13547f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach /* check if the demod is there */ 1355bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab id = tda1004x_read_byte(state, TDA1004X_CHIPID); 13560e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab if (id < 0) { 13570e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab printk(KERN_ERR "tda10046: chip is not answering. Giving up.\n"); 13580e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab kfree(state); 13590e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab return NULL; 13600e7830b50b20fcc25f21f79b7734102284d7c8f9Mauro Carvalho Chehab } 1361bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab if (id != 0x46) { 1362bc36ec746409e4e4719b94a86dc0d8cbeb6f439fMauro Carvalho Chehab printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id); 13637f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach kfree(state); 13647f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return NULL; 13657f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach } 13667f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 13677f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach /* create dvb_frontend */ 1368dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher memcpy(&state->frontend.ops, &tda10046_ops, sizeof(struct dvb_frontend_ops)); 13697f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach state->frontend.demodulator_priv = state; 13707f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach return &state->frontend; 13717f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach} 13727f5e02db4a39c36e68878a14fae1fe7ee6dd6fcfJohannes Stezenbach 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0644); 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Demodulator"); 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach"); 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(tda10045_attach); 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(tda10046_attach); 1382