blob: fe5b659a9e6b20cd91a9654acd722d34c5e96921 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001 /*
2 Driver for Philips tda1004xh OFDM Demodulator
3
4 (c) 2003, 2004 Andrew de Quincey & Robert Schlabbach
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 */
22/*
23 * This driver needs external firmware. Please use the commands
24 * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
25 * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
Ville Skytt\รค12e66f62006-01-09 15:25:38 -020026 * download/extract them, and then copy them to /usr/lib/hotplug/firmware
27 * or /lib/firmware (depending on configuration of firmware hotplug).
Linus Torvalds1da177e2005-04-16 15:20:36 -070028 */
29#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
30#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw"
31
32#include <linux/init.h>
33#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/device.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080035#include <linux/jiffies.h>
36#include <linux/string.h>
37#include <linux/slab.h>
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include "dvb_frontend.h"
40#include "tda1004x.h"
41
Linus Torvalds1da177e2005-04-16 15:20:36 -070042static int debug;
43#define dprintk(args...) \
44 do { \
45 if (debug) printk(KERN_DEBUG "tda1004x: " args); \
46 } while (0)
47
48#define TDA1004X_CHIPID 0x00
49#define TDA1004X_AUTO 0x01
50#define TDA1004X_IN_CONF1 0x02
51#define TDA1004X_IN_CONF2 0x03
52#define TDA1004X_OUT_CONF1 0x04
53#define TDA1004X_OUT_CONF2 0x05
54#define TDA1004X_STATUS_CD 0x06
55#define TDA1004X_CONFC4 0x07
56#define TDA1004X_DSSPARE2 0x0C
57#define TDA10045H_CODE_IN 0x0D
58#define TDA10045H_FWPAGE 0x0E
59#define TDA1004X_SCAN_CPT 0x10
60#define TDA1004X_DSP_CMD 0x11
61#define TDA1004X_DSP_ARG 0x12
62#define TDA1004X_DSP_DATA1 0x13
63#define TDA1004X_DSP_DATA2 0x14
64#define TDA1004X_CONFADC1 0x15
65#define TDA1004X_CONFC1 0x16
66#define TDA10045H_S_AGC 0x1a
67#define TDA10046H_AGC_TUN_LEVEL 0x1a
68#define TDA1004X_SNR 0x1c
69#define TDA1004X_CONF_TS1 0x1e
70#define TDA1004X_CONF_TS2 0x1f
71#define TDA1004X_CBER_RESET 0x20
72#define TDA1004X_CBER_MSB 0x21
73#define TDA1004X_CBER_LSB 0x22
74#define TDA1004X_CVBER_LUT 0x23
75#define TDA1004X_VBER_MSB 0x24
76#define TDA1004X_VBER_MID 0x25
77#define TDA1004X_VBER_LSB 0x26
78#define TDA1004X_UNCOR 0x27
79
80#define TDA10045H_CONFPLL_P 0x2D
81#define TDA10045H_CONFPLL_M_MSB 0x2E
82#define TDA10045H_CONFPLL_M_LSB 0x2F
83#define TDA10045H_CONFPLL_N 0x30
84
85#define TDA10046H_CONFPLL1 0x2D
86#define TDA10046H_CONFPLL2 0x2F
87#define TDA10046H_CONFPLL3 0x30
88#define TDA10046H_TIME_WREF1 0x31
89#define TDA10046H_TIME_WREF2 0x32
90#define TDA10046H_TIME_WREF3 0x33
91#define TDA10046H_TIME_WREF4 0x34
92#define TDA10046H_TIME_WREF5 0x35
93
94#define TDA10045H_UNSURW_MSB 0x31
95#define TDA10045H_UNSURW_LSB 0x32
96#define TDA10045H_WREF_MSB 0x33
97#define TDA10045H_WREF_MID 0x34
98#define TDA10045H_WREF_LSB 0x35
99#define TDA10045H_MUXOUT 0x36
100#define TDA1004X_CONFADC2 0x37
101
102#define TDA10045H_IOFFSET 0x38
103
104#define TDA10046H_CONF_TRISTATE1 0x3B
105#define TDA10046H_CONF_TRISTATE2 0x3C
106#define TDA10046H_CONF_POLARITY 0x3D
107#define TDA10046H_FREQ_OFFSET 0x3E
108#define TDA10046H_GPIO_OUT_SEL 0x41
109#define TDA10046H_GPIO_SELECT 0x42
110#define TDA10046H_AGC_CONF 0x43
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700111#define TDA10046H_AGC_THR 0x44
112#define TDA10046H_AGC_RENORM 0x45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113#define TDA10046H_AGC_GAINS 0x46
114#define TDA10046H_AGC_TUN_MIN 0x47
115#define TDA10046H_AGC_TUN_MAX 0x48
116#define TDA10046H_AGC_IF_MIN 0x49
117#define TDA10046H_AGC_IF_MAX 0x4A
118
119#define TDA10046H_FREQ_PHY2_MSB 0x4D
120#define TDA10046H_FREQ_PHY2_LSB 0x4E
121
122#define TDA10046H_CVBER_CTRL 0x4F
123#define TDA10046H_AGC_IF_LEVEL 0x52
124#define TDA10046H_CODE_CPT 0x57
125#define TDA10046H_CODE_IN 0x58
126
127
128static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
129{
130 int ret;
131 u8 buf[] = { reg, data };
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700132 struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300134 dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
136 msg.addr = state->config->demod_address;
137 ret = i2c_transfer(state->i2c, &msg, 1);
138
139 if (ret != 1)
140 dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300141 __func__, reg, data, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300143 dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 reg, data, ret);
145 return (ret != 1) ? -1 : 0;
146}
147
148static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
149{
150 int ret;
151 u8 b0[] = { reg };
152 u8 b1[] = { 0 };
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700153 struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
154 { .flags = I2C_M_RD, .buf = b1, .len = 1 }};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300156 dprintk("%s: reg=0x%x\n", __func__, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
158 msg[0].addr = state->config->demod_address;
159 msg[1].addr = state->config->demod_address;
160 ret = i2c_transfer(state->i2c, msg, 2);
161
162 if (ret != 2) {
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300163 dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 ret);
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300165 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 }
167
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300168 dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 reg, b1[0], ret);
170 return b1[0];
171}
172
173static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data)
174{
175 int val;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300176 dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 mask, data);
178
179 // read a byte and check
180 val = tda1004x_read_byte(state, reg);
181 if (val < 0)
182 return val;
183
184 // mask if off
185 val = val & ~mask;
186 val |= data & 0xff;
187
188 // write it out again
189 return tda1004x_write_byteI(state, reg, val);
190}
191
192static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned char *buf, int len)
193{
194 int i;
195 int result;
196
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300197 dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
199 result = 0;
200 for (i = 0; i < len; i++) {
201 result = tda1004x_write_byteI(state, reg + i, buf[i]);
202 if (result != 0)
203 break;
204 }
205
206 return result;
207}
208
209static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
210{
211 int result;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300212 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
214 result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2);
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -0200215 msleep(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 return result;
217}
218
219static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
220{
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300221 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
223 return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0);
224}
225
226static int tda10045h_set_bandwidth(struct tda1004x_state *state,
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300227 u32 bandwidth)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228{
229 static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f };
230 static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb };
231 static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 };
232
233 switch (bandwidth) {
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300234 case 6000000:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz));
236 break;
237
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300238 case 7000000:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz));
240 break;
241
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300242 case 8000000:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz));
244 break;
245
246 default:
247 return -EINVAL;
248 }
249
250 tda1004x_write_byteI(state, TDA10045H_IOFFSET, 0);
251
252 return 0;
253}
254
255static int tda10046h_set_bandwidth(struct tda1004x_state *state,
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300256 u32 bandwidth)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257{
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200258 static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
259 static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
260 static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200262 static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 };
263 static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab };
264 static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 };
265 int tda10046_clk53m;
266
267 if ((state->config->if_freq == TDA10046_FREQ_045) ||
268 (state->config->if_freq == TDA10046_FREQ_052))
269 tda10046_clk53m = 0;
270 else
271 tda10046_clk53m = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 switch (bandwidth) {
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300273 case 6000000:
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200274 if (tda10046_clk53m)
275 tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
Michael Krufky50c25ff2006-01-09 15:25:34 -0200276 sizeof(bandwidth_6mhz_53M));
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200277 else
278 tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M,
Michael Krufky50c25ff2006-01-09 15:25:34 -0200279 sizeof(bandwidth_6mhz_48M));
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700280 if (state->config->if_freq == TDA10046_FREQ_045) {
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200281 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
282 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab);
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 break;
285
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300286 case 7000000:
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200287 if (tda10046_clk53m)
288 tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
Michael Krufky50c25ff2006-01-09 15:25:34 -0200289 sizeof(bandwidth_7mhz_53M));
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200290 else
291 tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M,
Michael Krufky50c25ff2006-01-09 15:25:34 -0200292 sizeof(bandwidth_7mhz_48M));
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700293 if (state->config->if_freq == TDA10046_FREQ_045) {
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200294 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
295 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 break;
298
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300299 case 8000000:
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200300 if (tda10046_clk53m)
301 tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
Michael Krufky50c25ff2006-01-09 15:25:34 -0200302 sizeof(bandwidth_8mhz_53M));
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200303 else
304 tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M,
Michael Krufky50c25ff2006-01-09 15:25:34 -0200305 sizeof(bandwidth_8mhz_48M));
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700306 if (state->config->if_freq == TDA10046_FREQ_045) {
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200307 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
308 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55);
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 break;
311
312 default:
313 return -EINVAL;
314 }
315
316 return 0;
317}
318
319static int tda1004x_do_upload(struct tda1004x_state *state,
David Woodhousebc179152008-05-24 00:12:23 +0100320 const unsigned char *mem, unsigned int len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 u8 dspCodeCounterReg, u8 dspCodeInReg)
322{
323 u8 buf[65];
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700324 struct i2c_msg fw_msg = { .flags = 0, .buf = buf, .len = 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 int tx_size;
326 int pos = 0;
327
328 /* clear code counter */
329 tda1004x_write_byteI(state, dspCodeCounterReg, 0);
330 fw_msg.addr = state->config->demod_address;
331
332 buf[0] = dspCodeInReg;
333 while (pos != len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 // work out how much to send this time
335 tx_size = len - pos;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700336 if (tx_size > 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 tx_size = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
339 // send the chunk
340 memcpy(buf + 1, mem + pos, tx_size);
341 fw_msg.len = tx_size + 1;
342 if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700343 printk(KERN_ERR "tda1004x: Error during firmware upload\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 return -EIO;
345 }
346 pos += tx_size;
347
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300348 dprintk("%s: fw_pos=0x%x\n", __func__, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 }
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700350 // give the DSP a chance to settle 03/10/05 Hac
351 msleep(100);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 return 0;
354}
355
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700356static int tda1004x_check_upload_ok(struct tda1004x_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
358 u8 data1, data2;
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700359 unsigned long timeout;
360
361 if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
362 timeout = jiffies + 2 * HZ;
363 while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
364 if (time_after(jiffies, timeout)) {
365 printk(KERN_ERR "tda1004x: timeout waiting for DSP ready\n");
366 break;
367 }
368 msleep(1);
369 }
370 } else
371 msleep(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
373 // check upload was OK
374 tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP
375 tda1004x_write_byteI(state, TDA1004X_DSP_CMD, 0x67);
376
377 data1 = tda1004x_read_byte(state, TDA1004X_DSP_DATA1);
378 data2 = tda1004x_read_byte(state, TDA1004X_DSP_DATA2);
Hartmut Hackmann3faadbb2005-07-07 17:57:42 -0700379 if (data1 != 0x67 || data2 < 0x20 || data2 > 0x2e) {
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700380 printk(KERN_INFO "tda1004x: found firmware revision %x -- invalid\n", data2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 return -EIO;
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700382 }
383 printk(KERN_INFO "tda1004x: found firmware revision %x -- ok\n", data2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 return 0;
385}
386
387static int tda10045_fwupload(struct dvb_frontend* fe)
388{
389 struct tda1004x_state* state = fe->demodulator_priv;
390 int ret;
391 const struct firmware *fw;
392
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 /* don't re-upload unless necessary */
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700394 if (tda1004x_check_upload_ok(state) == 0)
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700395 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 /* request the firmware, this will block until someone uploads it */
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700398 printk(KERN_INFO "tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
400 if (ret) {
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700401 printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 return ret;
403 }
404
405 /* reset chip */
406 tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0);
407 tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8);
408 tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0);
409 msleep(10);
410
411 /* set parameters */
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300412 tda10045h_set_bandwidth(state, 8000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
414 ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN);
Anssi Hannula0c744b02005-07-07 17:57:42 -0700415 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 if (ret)
417 return ret;
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700418 printk(KERN_INFO "tda1004x: firmware upload complete\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
420 /* wait for DSP to initialise */
421 /* DSPREADY doesn't seem to work on the TDA10045H */
422 msleep(100);
423
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700424 return tda1004x_check_upload_ok(state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425}
426
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700427static void tda10046_init_plls(struct dvb_frontend* fe)
Johannes Stezenbach71e34202005-05-16 21:54:36 -0700428{
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700429 struct tda1004x_state* state = fe->demodulator_priv;
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200430 int tda10046_clk53m;
431
432 if ((state->config->if_freq == TDA10046_FREQ_045) ||
433 (state->config->if_freq == TDA10046_FREQ_052))
434 tda10046_clk53m = 0;
435 else
436 tda10046_clk53m = 1;
Johannes Stezenbach71e34202005-05-16 21:54:36 -0700437
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700438 tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200439 if(tda10046_clk53m) {
440 printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n");
441 tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8
442 } else {
443 printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n");
444 tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
445 }
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700446 if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300447 dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__);
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700448 tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
449 } else {
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300450 dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__);
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700451 tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
Johannes Stezenbach71e34202005-05-16 21:54:36 -0700452 }
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200453 if(tda10046_clk53m)
454 tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67);
455 else
456 tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72);
457 /* Note clock frequency is handled implicitly */
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700458 switch (state->config->if_freq) {
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700459 case TDA10046_FREQ_045:
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200460 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
461 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700462 break;
463 case TDA10046_FREQ_052:
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200464 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
465 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7);
466 break;
467 case TDA10046_FREQ_3617:
468 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
469 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59);
470 break;
471 case TDA10046_FREQ_3613:
472 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
473 tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700474 break;
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700475 }
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300476 tda10046h_set_bandwidth(state, 8000000); /* default bandwidth 8 MHz */
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200477 /* let the PLLs settle */
478 msleep(120);
Johannes Stezenbach71e34202005-05-16 21:54:36 -0700479}
480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481static int tda10046_fwupload(struct dvb_frontend* fe)
482{
483 struct tda1004x_state* state = fe->demodulator_priv;
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300484 int ret, confc4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 const struct firmware *fw;
486
487 /* reset + wake up chip */
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -0200488 if (state->config->xtal_freq == TDA10046_XTAL_4M) {
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300489 confc4 = 0;
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -0200490 } else {
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300491 dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300492 confc4 = 0x80;
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -0200493 }
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300494 tda1004x_write_byteI(state, TDA1004X_CONFC4, confc4);
495
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300497 /* set GPIO 1 and 3 */
498 if (state->config->gpio_config != TDA10046_GPTRI) {
499 tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0x33);
500 tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, state->config->gpio_config &0x0f);
501 }
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700502 /* let the clocks recover from sleep */
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300503 msleep(10);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200505 /* The PLLs need to be reprogrammed after sleep */
506 tda10046_init_plls(fe);
Hartmut Hackmann68717582007-04-27 12:31:15 -0300507 tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0);
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200508
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 /* don't re-upload unless necessary */
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700510 if (tda1004x_check_upload_ok(state) == 0)
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700511 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300513 /*
514 For i2c normal work, we need to slow down the bus speed.
515 However, the slow down breaks the eeprom firmware load.
516 So, use normal speed for eeprom booting and then restore the
517 i2c speed after that. Tested with MSI TV @nyware A/D board,
518 that comes with firmware version 29 inside their eeprom.
519
520 It should also be noticed that no other I2C transfer should
521 be in course while booting from eeprom, otherwise, tda10046
522 goes into an instable state. So, proper locking are needed
523 at the i2c bus master.
524 */
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300525 printk(KERN_INFO "tda1004x: trying to boot from eeprom\n");
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300526 tda1004x_write_byteI(state, TDA1004X_CONFC4, 4);
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300527 msleep(300);
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300528 tda1004x_write_byteI(state, TDA1004X_CONFC4, confc4);
529
530 /* Checks if eeprom firmware went without troubles */
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300531 if (tda1004x_check_upload_ok(state) == 0)
532 return 0;
533
Mauro Carvalho Chehab517efa82009-02-09 13:12:41 -0300534 /* eeprom firmware didn't work. Load one manually. */
535
Hartmut Hackmannf4546e72007-04-27 12:31:13 -0300536 if (state->config->request_firmware != NULL) {
537 /* request the firmware, this will block until someone uploads it */
538 printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
539 ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE);
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700540 if (ret) {
Hartmut Hackmannf4546e72007-04-27 12:31:13 -0300541 /* remain compatible to old bug: try to load with tda10045 image name */
542 ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
543 if (ret) {
544 printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
545 return ret;
546 } else {
547 printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n",
548 TDA10046_DEFAULT_FIRMWARE);
549 }
550 }
551 } else {
552 printk(KERN_ERR "tda1004x: no request function defined, can't upload from file\n");
553 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 }
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300555 tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
556 ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN);
557 release_firmware(fw);
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700558 return tda1004x_check_upload_ok(state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559}
560
561static int tda1004x_encode_fec(int fec)
562{
563 // convert known FEC values
564 switch (fec) {
565 case FEC_1_2:
566 return 0;
567 case FEC_2_3:
568 return 1;
569 case FEC_3_4:
570 return 2;
571 case FEC_5_6:
572 return 3;
573 case FEC_7_8:
574 return 4;
575 }
576
577 // unsupported
578 return -EINVAL;
579}
580
581static int tda1004x_decode_fec(int tdafec)
582{
583 // convert known FEC values
584 switch (tdafec) {
585 case 0:
586 return FEC_1_2;
587 case 1:
588 return FEC_2_3;
589 case 2:
590 return FEC_3_4;
591 case 3:
592 return FEC_5_6;
593 case 4:
594 return FEC_7_8;
595 }
596
597 // unsupported
598 return -1;
599}
600
lawrence rust2e4e98e2010-08-25 09:50:20 -0300601static int tda1004x_write(struct dvb_frontend* fe, const u8 buf[], int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
603 struct tda1004x_state* state = fe->demodulator_priv;
604
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300605 if (len != 2)
606 return -EINVAL;
607
608 return tda1004x_write_byteI(state, buf[0], buf[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609}
610
611static int tda10045_init(struct dvb_frontend* fe)
612{
613 struct tda1004x_state* state = fe->demodulator_priv;
614
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300615 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 if (tda10045_fwupload(fe)) {
618 printk("tda1004x: firmware upload failed\n");
619 return -EIO;
620 }
621
622 tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
623
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 // tda setup
625 tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
626 tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream
627 tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0); // set polarity of VAGC signal
628 tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer
629 tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset
630 tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset
631 tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface
632 tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface
633 tda1004x_write_mask(state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits
634 tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity
635 tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e);
636
637 tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk);
638
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 return 0;
640}
641
642static int tda10046_init(struct dvb_frontend* fe)
643{
644 struct tda1004x_state* state = fe->demodulator_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300645 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 if (tda10046_fwupload(fe)) {
648 printk("tda1004x: firmware upload failed\n");
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700649 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 }
651
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 // tda setup
653 tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200654 tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -0200655 tda1004x_write_byteI(state, TDA1004X_CONFC1, 0x88); // enable pulse killer
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700656
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700657 switch (state->config->agc_config) {
658 case TDA10046_AGC_DEFAULT:
659 tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300660 tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700661 break;
662 case TDA10046_AGC_IFO_AUTO_NEG:
663 tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300664 tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700665 break;
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700666 case TDA10046_AGC_IFO_AUTO_POS:
667 tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300668 tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x00); // set AGC polarities
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700669 break;
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300670 case TDA10046_AGC_TDA827X:
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -0700671 tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
672 tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200673 tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -0300674 tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60); // set AGC polarities
Hartmut Hackmann550a9a52006-11-15 21:31:54 -0300675 break;
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700676 }
Hartmut Hackmann08cdf942007-03-18 19:23:20 -0300677 if (state->config->ts_mode == 0) {
678 tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x40);
679 tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
680 } else {
681 tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x80);
682 tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x10,
683 state->config->invert_oclk << 4);
684 }
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200685 tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
Hartmut Hackmann08cdf942007-03-18 19:23:20 -0300686 tda1004x_write_mask (state, TDA10046H_CONF_TRISTATE1, 0x3e, 0x38); // Turn IF AGC output on
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // }
688 tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
689 tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // }
690 tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // }
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200691 tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700692 tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700694 tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -0200695 // tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700696
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 return 0;
698}
699
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300700static int tda1004x_set_fe(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300702 struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 struct tda1004x_state* state = fe->demodulator_priv;
704 int tmp;
705 int inversion;
706
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300707 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
710 // setup auto offset
711 tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10);
712 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x80, 0);
713 tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0);
714
715 // disable agc_conf[2]
716 tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 0);
717 }
718
719 // set frequency
Patrick Boettcherdea74862006-05-14 05:01:31 -0300720 if (fe->ops.tuner_ops.set_params) {
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -0300721 fe->ops.tuner_ops.set_params(fe);
Hartmut Hackmannede22002007-04-27 12:31:32 -0300722 if (fe->ops.i2c_gate_ctrl)
723 fe->ops.i2c_gate_ctrl(fe, 0);
Hartmut Hackmann634623d2005-11-08 21:35:13 -0800724 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 // Hardcoded to use auto as much as possible on the TDA10045 as it
727 // is very unreliable if AUTO mode is _not_ used.
728 if (state->demod_type == TDA1004X_DEMOD_TDA10045) {
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300729 fe_params->code_rate_HP = FEC_AUTO;
730 fe_params->guard_interval = GUARD_INTERVAL_AUTO;
731 fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 }
733
734 // Set standard params.. or put them to auto
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300735 if ((fe_params->code_rate_HP == FEC_AUTO) ||
736 (fe_params->code_rate_LP == FEC_AUTO) ||
737 (fe_params->modulation == QAM_AUTO) ||
738 (fe_params->hierarchy == HIERARCHY_AUTO)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300740 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); /* turn off modulation bits */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits
742 tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits
743 } else {
744 tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0); // disable auto
745
746 // set HP FEC
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300747 tmp = tda1004x_encode_fec(fe_params->code_rate_HP);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700748 if (tmp < 0)
749 return tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp);
751
752 // set LP FEC
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300753 tmp = tda1004x_encode_fec(fe_params->code_rate_LP);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700754 if (tmp < 0)
755 return tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3);
757
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300758 /* set modulation */
759 switch (fe_params->modulation) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 case QPSK:
761 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0);
762 break;
763
764 case QAM_16:
765 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 1);
766 break;
767
768 case QAM_64:
769 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 2);
770 break;
771
772 default:
773 return -EINVAL;
774 }
775
776 // set hierarchy
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300777 switch (fe_params->hierarchy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 case HIERARCHY_NONE:
779 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5);
780 break;
781
782 case HIERARCHY_1:
783 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 1 << 5);
784 break;
785
786 case HIERARCHY_2:
787 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 2 << 5);
788 break;
789
790 case HIERARCHY_4:
791 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 3 << 5);
792 break;
793
794 default:
795 return -EINVAL;
796 }
797 }
798
799 // set bandwidth
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700800 switch (state->demod_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 case TDA1004X_DEMOD_TDA10045:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300802 tda10045h_set_bandwidth(state, fe_params->bandwidth_hz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 break;
804
805 case TDA1004X_DEMOD_TDA10046:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300806 tda10046h_set_bandwidth(state, fe_params->bandwidth_hz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 break;
808 }
809
810 // set inversion
811 inversion = fe_params->inversion;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700812 if (state->config->invert)
813 inversion = inversion ? INVERSION_OFF : INVERSION_ON;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 switch (inversion) {
815 case INVERSION_OFF:
816 tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0);
817 break;
818
819 case INVERSION_ON:
820 tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0x20);
821 break;
822
823 default:
824 return -EINVAL;
825 }
826
827 // set guard interval
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300828 switch (fe_params->guard_interval) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 case GUARD_INTERVAL_1_32:
830 tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
831 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
832 break;
833
834 case GUARD_INTERVAL_1_16:
835 tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
836 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 1 << 2);
837 break;
838
839 case GUARD_INTERVAL_1_8:
840 tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
841 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 2 << 2);
842 break;
843
844 case GUARD_INTERVAL_1_4:
845 tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
846 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 3 << 2);
847 break;
848
849 case GUARD_INTERVAL_AUTO:
850 tda1004x_write_mask(state, TDA1004X_AUTO, 2, 2);
851 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
852 break;
853
854 default:
855 return -EINVAL;
856 }
857
858 // set transmission mode
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300859 switch (fe_params->transmission_mode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 case TRANSMISSION_MODE_2K:
861 tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0);
862 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4);
863 break;
864
865 case TRANSMISSION_MODE_8K:
866 tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0);
867 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 1 << 4);
868 break;
869
870 case TRANSMISSION_MODE_AUTO:
871 tda1004x_write_mask(state, TDA1004X_AUTO, 4, 4);
872 tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0);
873 break;
874
875 default:
876 return -EINVAL;
877 }
878
879 // start the lock
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700880 switch (state->demod_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 case TDA1004X_DEMOD_TDA10045:
882 tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8);
883 tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 break;
885
886 case TDA1004X_DEMOD_TDA10046:
887 tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40);
Hartmut Hackmann634623d2005-11-08 21:35:13 -0800888 msleep(1);
889 tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 break;
891 }
892
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700893 msleep(10);
894
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 return 0;
896}
897
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300898static int tda1004x_get_fe(struct dvb_frontend *fe, struct dtv_frontend_properties *fe_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899{
900 struct tda1004x_state* state = fe->demodulator_priv;
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200901
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300902 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
904 // inversion status
905 fe_params->inversion = INVERSION_OFF;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700906 if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 fe_params->inversion = INVERSION_ON;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700908 if (state->config->invert)
909 fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910
911 // bandwidth
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700912 switch (state->demod_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 case TDA1004X_DEMOD_TDA10045:
914 switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) {
915 case 0x14:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300916 fe_params->bandwidth_hz = 8000000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 break;
918 case 0xdb:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300919 fe_params->bandwidth_hz = 7000000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 break;
921 case 0x4f:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300922 fe_params->bandwidth_hz = 6000000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 break;
924 }
925 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 case TDA1004X_DEMOD_TDA10046:
927 switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200928 case 0x5c:
929 case 0x54:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300930 fe_params->bandwidth_hz = 8000000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 break;
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200932 case 0x6a:
933 case 0x60:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300934 fe_params->bandwidth_hz = 7000000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 break;
Hartmut Hackmann8a8e9c22006-01-09 15:25:04 -0200936 case 0x7b:
937 case 0x70:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300938 fe_params->bandwidth_hz = 6000000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 break;
940 }
941 break;
942 }
943
944 // FEC
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300945 fe_params->code_rate_HP =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7);
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300947 fe_params->code_rate_LP =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7);
949
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300950 /* modulation */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) {
952 case 0:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300953 fe_params->modulation = QPSK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 break;
955 case 1:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300956 fe_params->modulation = QAM_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 break;
958 case 2:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300959 fe_params->modulation = QAM_64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 break;
961 }
962
963 // transmission mode
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300964 fe_params->transmission_mode = TRANSMISSION_MODE_2K;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -0700965 if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10)
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300966 fe_params->transmission_mode = TRANSMISSION_MODE_8K;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
968 // guard interval
969 switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {
970 case 0:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300971 fe_params->guard_interval = GUARD_INTERVAL_1_32;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 break;
973 case 1:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300974 fe_params->guard_interval = GUARD_INTERVAL_1_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 break;
976 case 2:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300977 fe_params->guard_interval = GUARD_INTERVAL_1_8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 break;
979 case 3:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300980 fe_params->guard_interval = GUARD_INTERVAL_1_4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 break;
982 }
983
984 // hierarchy
985 switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) {
986 case 0:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300987 fe_params->hierarchy = HIERARCHY_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 break;
989 case 1:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300990 fe_params->hierarchy = HIERARCHY_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 break;
992 case 2:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300993 fe_params->hierarchy = HIERARCHY_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 break;
995 case 3:
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -0300996 fe_params->hierarchy = HIERARCHY_4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 break;
998 }
999
1000 return 0;
1001}
1002
1003static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status)
1004{
1005 struct tda1004x_state* state = fe->demodulator_priv;
1006 int status;
1007 int cber;
1008 int vber;
1009
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001010 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
1012 // read status
1013 status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001014 if (status == -1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016
1017 // decode
1018 *fe_status = 0;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001019 if (status & 4)
1020 *fe_status |= FE_HAS_SIGNAL;
1021 if (status & 2)
1022 *fe_status |= FE_HAS_CARRIER;
1023 if (status & 8)
1024 *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
1026 // if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi
1027 // is getting anything valid
1028 if (!(*fe_status & FE_HAS_VITERBI)) {
1029 // read the CBER
1030 cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001031 if (cber == -1)
1032 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 status = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001034 if (status == -1)
1035 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 cber |= (status << 8);
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -02001037 // The address 0x20 should be read to cope with a TDA10046 bug
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 tda1004x_read_byte(state, TDA1004X_CBER_RESET);
1039
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001040 if (cber != 65535)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 *fe_status |= FE_HAS_VITERBI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 }
1043
1044 // if we DO have some valid VITERBI output, but don't already have SYNC
1045 // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid.
1046 if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) {
1047 // read the VBER
1048 vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001049 if (vber == -1)
1050 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 status = tda1004x_read_byte(state, TDA1004X_VBER_MID);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001052 if (status == -1)
1053 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 vber |= (status << 8);
1055 status = tda1004x_read_byte(state, TDA1004X_VBER_MSB);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001056 if (status == -1)
1057 return -EIO;
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -02001058 vber |= (status & 0x0f) << 16;
1059 // The CVBER_LUT should be read to cope with TDA10046 hardware bug
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 tda1004x_read_byte(state, TDA1004X_CVBER_LUT);
1061
1062 // if RS has passed some valid TS packets, then we must be
1063 // getting some SYNC bytes
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001064 if (vber < 16632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 *fe_status |= FE_HAS_SYNC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067
1068 // success
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001069 dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 return 0;
1071}
1072
1073static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
1074{
1075 struct tda1004x_state* state = fe->demodulator_priv;
1076 int tmp;
1077 int reg = 0;
1078
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001079 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
1081 // determine the register to use
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001082 switch (state->demod_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 case TDA1004X_DEMOD_TDA10045:
1084 reg = TDA10045H_S_AGC;
1085 break;
1086
1087 case TDA1004X_DEMOD_TDA10046:
1088 reg = TDA10046H_AGC_IF_LEVEL;
1089 break;
1090 }
1091
1092 // read it
1093 tmp = tda1004x_read_byte(state, reg);
1094 if (tmp < 0)
1095 return -EIO;
1096
1097 *signal = (tmp << 8) | tmp;
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001098 dprintk("%s: signal=0x%x\n", __func__, *signal);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 return 0;
1100}
1101
1102static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
1103{
1104 struct tda1004x_state* state = fe->demodulator_priv;
1105 int tmp;
1106
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001107 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
1109 // read it
1110 tmp = tda1004x_read_byte(state, TDA1004X_SNR);
1111 if (tmp < 0)
1112 return -EIO;
Andrew de Quinceyc2026b32005-09-09 13:02:33 -07001113 tmp = 255 - tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
1115 *snr = ((tmp << 8) | tmp);
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001116 dprintk("%s: snr=0x%x\n", __func__, *snr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 return 0;
1118}
1119
1120static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
1121{
1122 struct tda1004x_state* state = fe->demodulator_priv;
1123 int tmp;
1124 int tmp2;
1125 int counter;
1126
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001127 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
1129 // read the UCBLOCKS and reset
1130 counter = 0;
1131 tmp = tda1004x_read_byte(state, TDA1004X_UNCOR);
1132 if (tmp < 0)
1133 return -EIO;
1134 tmp &= 0x7f;
1135 while (counter++ < 5) {
1136 tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
1137 tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
1138 tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
1139
1140 tmp2 = tda1004x_read_byte(state, TDA1004X_UNCOR);
1141 if (tmp2 < 0)
1142 return -EIO;
1143 tmp2 &= 0x7f;
1144 if ((tmp2 < tmp) || (tmp2 == 0))
1145 break;
1146 }
1147
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001148 if (tmp != 0x7f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 *ucblocks = tmp;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001150 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 *ucblocks = 0xffffffff;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001152
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001153 dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 return 0;
1155}
1156
1157static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
1158{
1159 struct tda1004x_state* state = fe->demodulator_priv;
1160 int tmp;
1161
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001162 dprintk("%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
1164 // read it in
1165 tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001166 if (tmp < 0)
1167 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 *ber = tmp << 1;
1169 tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001170 if (tmp < 0)
1171 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 *ber |= (tmp << 9);
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -02001173 // The address 0x20 should be read to cope with a TDA10046 bug
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 tda1004x_read_byte(state, TDA1004X_CBER_RESET);
1175
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001176 dprintk("%s: ber=0x%x\n", __func__, *ber);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 return 0;
1178}
1179
1180static int tda1004x_sleep(struct dvb_frontend* fe)
1181{
1182 struct tda1004x_state* state = fe->demodulator_priv;
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -03001183 int gpio_conf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001185 switch (state->demod_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 case TDA1004X_DEMOD_TDA10045:
1187 tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10);
1188 break;
1189
1190 case TDA1004X_DEMOD_TDA10046:
Hartmut Hackmann0eb3de22006-02-07 06:49:10 -02001191 /* set outputs to tristate */
1192 tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff);
Hartmut Hackmann1bb0e862007-04-27 12:31:10 -03001193 /* invert GPIO 1 and 3 if desired*/
1194 gpio_conf = state->config->gpio_config;
1195 if (gpio_conf >= TDA10046_GP00_I)
1196 tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f,
1197 (gpio_conf & 0x0f) ^ 0x0a);
1198
Hartmut Hackmann68717582007-04-27 12:31:15 -03001199 tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0xc0);
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -07001200 tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 break;
1202 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
1204 return 0;
1205}
1206
Andrew de Quincey74349bef2006-04-18 17:47:10 -03001207static int tda1004x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
1208{
1209 struct tda1004x_state* state = fe->demodulator_priv;
1210
1211 if (enable) {
1212 return tda1004x_enable_tuner_i2c(state);
1213 } else {
1214 return tda1004x_disable_tuner_i2c(state);
1215 }
1216}
1217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
1219{
1220 fesettings->min_delay_ms = 800;
Hartmut Hackmannf03cbea2005-07-07 17:57:43 -07001221 /* Drift compensation makes no sense for DVB-T */
1222 fesettings->step_size = 0;
1223 fesettings->max_drift = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 return 0;
1225}
1226
Andrew de Quincey2a514de2006-08-08 09:10:09 -03001227static void tda1004x_release(struct dvb_frontend* fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228{
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001229 struct tda1004x_state *state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 kfree(state);
1231}
1232
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233static struct dvb_frontend_ops tda10045_ops = {
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -03001234 .delsys = { SYS_DVBT },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 .info = {
1236 .name = "Philips TDA10045H DVB-T",
1237 .type = FE_OFDM,
1238 .frequency_min = 51000000,
1239 .frequency_max = 858000000,
1240 .frequency_stepsize = 166667,
1241 .caps =
1242 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1243 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1244 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1245 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
1246 },
1247
Andrew de Quincey2a514de2006-08-08 09:10:09 -03001248 .release = tda1004x_release,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
1250 .init = tda10045_init,
1251 .sleep = tda1004x_sleep,
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -03001252 .write = tda1004x_write,
Andrew de Quincey74349bef2006-04-18 17:47:10 -03001253 .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -03001255 .set_frontend = tda1004x_set_fe,
1256 .get_frontend = tda1004x_get_fe,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 .get_tune_settings = tda1004x_get_tune_settings,
1258
1259 .read_status = tda1004x_read_status,
1260 .read_ber = tda1004x_read_ber,
1261 .read_signal_strength = tda1004x_read_signal_strength,
1262 .read_snr = tda1004x_read_snr,
1263 .read_ucblocks = tda1004x_read_ucblocks,
1264};
1265
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001266struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
1267 struct i2c_adapter* i2c)
1268{
1269 struct tda1004x_state *state;
Mauro Carvalho Chehab0e7830b2008-06-14 11:27:34 -03001270 int id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001272 /* allocate memory for the internal state */
Matthias Schwarzott084e24a2009-08-10 22:51:01 -03001273 state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
Mauro Carvalho Chehabbc36ec72008-06-14 10:44:04 -03001274 if (!state) {
1275 printk(KERN_ERR "Can't alocate memory for tda10045 state\n");
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001276 return NULL;
Mauro Carvalho Chehabbc36ec72008-06-14 10:44:04 -03001277 }
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001278
1279 /* setup the state */
1280 state->config = config;
1281 state->i2c = i2c;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001282 state->demod_type = TDA1004X_DEMOD_TDA10045;
1283
1284 /* check if the demod is there */
Mauro Carvalho Chehabbc36ec72008-06-14 10:44:04 -03001285 id = tda1004x_read_byte(state, TDA1004X_CHIPID);
Mauro Carvalho Chehab0e7830b2008-06-14 11:27:34 -03001286 if (id < 0) {
1287 printk(KERN_ERR "tda10045: chip is not answering. Giving up.\n");
1288 kfree(state);
1289 return NULL;
1290 }
1291
Mauro Carvalho Chehabbc36ec72008-06-14 10:44:04 -03001292 if (id != 0x25) {
1293 printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001294 kfree(state);
1295 return NULL;
1296 }
1297
1298 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -03001299 memcpy(&state->frontend.ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001300 state->frontend.demodulator_priv = state;
1301 return &state->frontend;
1302}
1303
1304static struct dvb_frontend_ops tda10046_ops = {
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -03001305 .delsys = { SYS_DVBT },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 .info = {
1307 .name = "Philips TDA10046H DVB-T",
1308 .type = FE_OFDM,
1309 .frequency_min = 51000000,
1310 .frequency_max = 858000000,
1311 .frequency_stepsize = 166667,
1312 .caps =
1313 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1314 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1315 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1316 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
1317 },
1318
Andrew de Quincey2a514de2006-08-08 09:10:09 -03001319 .release = tda1004x_release,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
1321 .init = tda10046_init,
1322 .sleep = tda1004x_sleep,
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -03001323 .write = tda1004x_write,
Andrew de Quincey159f8a62006-04-19 18:31:03 -03001324 .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
Mauro Carvalho Chehab5f82e6b2011-12-26 13:19:48 -03001326 .set_frontend = tda1004x_set_fe,
1327 .get_frontend = tda1004x_get_fe,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 .get_tune_settings = tda1004x_get_tune_settings,
1329
1330 .read_status = tda1004x_read_status,
1331 .read_ber = tda1004x_read_ber,
1332 .read_signal_strength = tda1004x_read_signal_strength,
1333 .read_snr = tda1004x_read_snr,
1334 .read_ucblocks = tda1004x_read_ucblocks,
1335};
1336
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001337struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
1338 struct i2c_adapter* i2c)
1339{
1340 struct tda1004x_state *state;
Mauro Carvalho Chehab0e7830b2008-06-14 11:27:34 -03001341 int id;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001342
1343 /* allocate memory for the internal state */
Matthias Schwarzott084e24a2009-08-10 22:51:01 -03001344 state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
Mauro Carvalho Chehabbc36ec72008-06-14 10:44:04 -03001345 if (!state) {
1346 printk(KERN_ERR "Can't alocate memory for tda10046 state\n");
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001347 return NULL;
Mauro Carvalho Chehabbc36ec72008-06-14 10:44:04 -03001348 }
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001349
1350 /* setup the state */
1351 state->config = config;
1352 state->i2c = i2c;
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001353 state->demod_type = TDA1004X_DEMOD_TDA10046;
1354
1355 /* check if the demod is there */
Mauro Carvalho Chehabbc36ec72008-06-14 10:44:04 -03001356 id = tda1004x_read_byte(state, TDA1004X_CHIPID);
Mauro Carvalho Chehab0e7830b2008-06-14 11:27:34 -03001357 if (id < 0) {
1358 printk(KERN_ERR "tda10046: chip is not answering. Giving up.\n");
1359 kfree(state);
1360 return NULL;
1361 }
Mauro Carvalho Chehabbc36ec72008-06-14 10:44:04 -03001362 if (id != 0x46) {
1363 printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001364 kfree(state);
1365 return NULL;
1366 }
1367
1368 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -03001369 memcpy(&state->frontend.ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
Johannes Stezenbach7f5e02d2005-05-16 21:54:30 -07001370 state->frontend.demodulator_priv = state;
1371 return &state->frontend;
1372}
1373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374module_param(debug, int, 0644);
1375MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
1376
1377MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Demodulator");
1378MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach");
1379MODULE_LICENSE("GPL");
1380
1381EXPORT_SYMBOL(tda10045_attach);
1382EXPORT_SYMBOL(tda10046_attach);