blob: 7142b9c51dd2460e3b2c65ec91bddf08d877f8b0 [file] [log] [blame]
Mac Michaelsd8667cb2005-07-07 17:58:29 -07001/*
Michael Krufky1963c902005-08-08 09:22:43 -07002 * Support for LGDT3302 and LGDT3303 - VSB/QAM
Mac Michaelsd8667cb2005-07-07 17:58:29 -07003 *
4 * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
5 *
Mac Michaelsd8667cb2005-07-07 17:58:29 -07006 * 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 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22/*
23 * NOTES ABOUT THIS DRIVER
24 *
Michael Krufky1963c902005-08-08 09:22:43 -070025 * This Linux driver supports:
26 * DViCO FusionHDTV 3 Gold-Q
27 * DViCO FusionHDTV 3 Gold-T
28 * DViCO FusionHDTV 5 Gold
Mac Michaelsd8667cb2005-07-07 17:58:29 -070029 *
30 * TODO:
Michael Krufky1963c902005-08-08 09:22:43 -070031 * signal strength always returns 0.
Mac Michaelsd8667cb2005-07-07 17:58:29 -070032 *
33 */
34
Mac Michaelsd8667cb2005-07-07 17:58:29 -070035#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/moduleparam.h>
38#include <linux/init.h>
39#include <linux/delay.h>
40#include <asm/byteorder.h>
41
42#include "dvb_frontend.h"
Michael Krufky6ddcc912005-07-27 11:46:00 -070043#include "lgdt330x_priv.h"
44#include "lgdt330x.h"
Mac Michaelsd8667cb2005-07-07 17:58:29 -070045
46static int debug = 0;
47module_param(debug, int, 0644);
Michael Krufky6ddcc912005-07-27 11:46:00 -070048MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
Mac Michaelsd8667cb2005-07-07 17:58:29 -070049#define dprintk(args...) \
50do { \
Michael Krufky6ddcc912005-07-27 11:46:00 -070051if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
Mac Michaelsd8667cb2005-07-07 17:58:29 -070052} while (0)
53
Michael Krufky6ddcc912005-07-27 11:46:00 -070054struct lgdt330x_state
Mac Michaelsd8667cb2005-07-07 17:58:29 -070055{
56 struct i2c_adapter* i2c;
57 struct dvb_frontend_ops ops;
58
59 /* Configuration settings */
Michael Krufky6ddcc912005-07-27 11:46:00 -070060 const struct lgdt330x_config* config;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070061
62 struct dvb_frontend frontend;
63
64 /* Demodulator private data */
65 fe_modulation_t current_modulation;
66
67 /* Tuner private data */
68 u32 current_frequency;
69};
70
Michael Krufky1963c902005-08-08 09:22:43 -070071static int i2c_write_demod_bytes (struct lgdt330x_state* state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -070072 u8 *buf, /* data bytes to send */
73 int len /* number of bytes to send */ )
Mac Michaelsd8667cb2005-07-07 17:58:29 -070074{
Michael Krufkyb6aef072005-07-27 11:45:54 -070075 struct i2c_msg msg =
Michael Krufky1963c902005-08-08 09:22:43 -070076 { .addr = state->config->demod_address,
77 .flags = 0,
78 .buf = buf,
79 .len = 2 };
Michael Krufkyb6aef072005-07-27 11:45:54 -070080 int i;
Michael Krufky1963c902005-08-08 09:22:43 -070081 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070082
Michael Krufky1963c902005-08-08 09:22:43 -070083 for (i=0; i<len-1; i+=2){
Mac Michaelsd8667cb2005-07-07 17:58:29 -070084 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
Michael Krufky1963c902005-08-08 09:22:43 -070085 printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
Michael Krufky58ba0062005-07-12 13:58:37 -070086 if (err < 0)
87 return err;
88 else
89 return -EREMOTEIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070090 }
Michael Krufky1963c902005-08-08 09:22:43 -070091 msg.buf += 2;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070092 }
93 return 0;
94}
Michael Krufkyb6aef072005-07-27 11:45:54 -070095
Mac Michaelsd8667cb2005-07-07 17:58:29 -070096/*
97 * This routine writes the register (reg) to the demod bus
98 * then reads the data returned for (len) bytes.
99 */
100
Michael Krufky1963c902005-08-08 09:22:43 -0700101static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700102 enum I2C_REG reg, u8* buf, int len)
103{
104 u8 wr [] = { reg };
105 struct i2c_msg msg [] = {
106 { .addr = state->config->demod_address,
107 .flags = 0, .buf = wr, .len = 1 },
108 { .addr = state->config->demod_address,
109 .flags = I2C_M_RD, .buf = buf, .len = len },
110 };
111 int ret;
112 ret = i2c_transfer(state->i2c, msg, 2);
113 if (ret != 2) {
Michael Krufky6ddcc912005-07-27 11:46:00 -0700114 printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700115 } else {
116 ret = 0;
117 }
118 return ret;
119}
120
121/* Software reset */
Michael Krufky1963c902005-08-08 09:22:43 -0700122static int lgdt3302_SwReset(struct lgdt330x_state* state)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700123{
124 u8 ret;
125 u8 reset[] = {
126 IRQ_MASK,
127 0x00 /* bit 6 is active low software reset
128 * bits 5-0 are 1 to mask interrupts */
129 };
130
Michael Krufky1963c902005-08-08 09:22:43 -0700131 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700132 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700133 if (ret == 0) {
Michael Krufky1963c902005-08-08 09:22:43 -0700134
135 /* force reset high (inactive) and unmask interrupts */
136 reset[1] = 0x7f;
137 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700138 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700139 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700140 return ret;
141}
142
Michael Krufky1963c902005-08-08 09:22:43 -0700143static int lgdt3303_SwReset(struct lgdt330x_state* state)
144{
145 u8 ret;
146 u8 reset[] = {
147 0x02,
148 0x00 /* bit 0 is active low software reset */
149 };
150
151 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700152 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700153 if (ret == 0) {
154
155 /* force reset high (inactive) */
156 reset[1] = 0x01;
157 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700158 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700159 }
160 return ret;
161}
162
163static int lgdt330x_SwReset(struct lgdt330x_state* state)
164{
165 switch (state->config->demod_chip) {
166 case LGDT3302:
167 return lgdt3302_SwReset(state);
168 case LGDT3303:
169 return lgdt3303_SwReset(state);
170 default:
171 return -ENODEV;
172 }
173}
174
Michael Krufky6ddcc912005-07-27 11:46:00 -0700175static int lgdt330x_init(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700176{
177 /* Hardware reset is done using gpio[0] of cx23880x chip.
178 * I'd like to do it here, but don't know how to find chip address.
179 * cx88-cards.c arranges for the reset bit to be inactive (high).
180 * Maybe there needs to be a callable function in cx88-core or
181 * the caller of this function needs to do it. */
182
Michael Krufky1963c902005-08-08 09:22:43 -0700183 /*
184 * Array of byte pairs <address, value>
185 * to initialize each different chip
186 */
187 static u8 lgdt3302_init_data[] = {
188 /* Use 50MHz parameter values from spec sheet since xtal is 50 */
189 /* Change the value of NCOCTFV[25:0] of carrier
190 recovery center frequency register */
191 VSB_CARRIER_FREQ0, 0x00,
192 VSB_CARRIER_FREQ1, 0x87,
193 VSB_CARRIER_FREQ2, 0x8e,
194 VSB_CARRIER_FREQ3, 0x01,
195 /* Change the TPCLK pin polarity
196 data is valid on falling clock */
197 DEMUX_CONTROL, 0xfb,
198 /* Change the value of IFBW[11:0] of
199 AGC IF/RF loop filter bandwidth register */
200 AGC_RF_BANDWIDTH0, 0x40,
201 AGC_RF_BANDWIDTH1, 0x93,
202 AGC_RF_BANDWIDTH2, 0x00,
203 /* Change the value of bit 6, 'nINAGCBY' and
204 'NSSEL[1:0] of ACG function control register 2 */
205 AGC_FUNC_CTRL2, 0xc6,
206 /* Change the value of bit 6 'RFFIX'
207 of AGC function control register 3 */
208 AGC_FUNC_CTRL3, 0x40,
209 /* Set the value of 'INLVTHD' register 0x2a/0x2c
210 to 0x7fe */
211 AGC_DELAY0, 0x07,
212 AGC_DELAY2, 0xfe,
213 /* Change the value of IAGCBW[15:8]
214 of inner AGC loop filter bandwith */
215 AGC_LOOP_BANDWIDTH0, 0x08,
216 AGC_LOOP_BANDWIDTH1, 0x9a
217 };
218
219 static u8 lgdt3303_init_data[] = {
220 0x4c, 0x14
221 };
222
223 struct lgdt330x_state* state = fe->demodulator_priv;
224 char *chip_name;
225 int err;
226
227 switch (state->config->demod_chip) {
228 case LGDT3302:
229 chip_name = "LGDT3302";
230 err = i2c_write_demod_bytes(state, lgdt3302_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700231 sizeof(lgdt3302_init_data));
232 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700233 case LGDT3303:
234 chip_name = "LGDT3303";
235 err = i2c_write_demod_bytes(state, lgdt3303_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700236 sizeof(lgdt3303_init_data));
237 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700238 default:
239 chip_name = "undefined";
240 printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
241 err = -ENODEV;
242 }
243 dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
244 if (err < 0)
245 return err;
246 return lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700247}
248
Michael Krufky6ddcc912005-07-27 11:46:00 -0700249static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700250{
Michael Krufky1963c902005-08-08 09:22:43 -0700251 *ber = 0; /* Not supplied by the demod chips */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700252 return 0;
253}
254
Michael Krufky6ddcc912005-07-27 11:46:00 -0700255static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700256{
Michael Krufky1963c902005-08-08 09:22:43 -0700257 struct lgdt330x_state* state = fe->demodulator_priv;
258 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700259 u8 buf[2];
260
Michael Krufky1963c902005-08-08 09:22:43 -0700261 switch (state->config->demod_chip) {
262 case LGDT3302:
263 err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700264 buf, sizeof(buf));
265 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700266 case LGDT3303:
267 err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700268 buf, sizeof(buf));
269 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700270 default:
271 printk(KERN_WARNING
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700272 "Only LGDT3302 and LGDT3303 are supported chips.\n");
Michael Krufky1963c902005-08-08 09:22:43 -0700273 err = -ENODEV;
274 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700275
276 *ucblocks = (buf[0] << 8) | buf[1];
277 return 0;
278}
279
Michael Krufky6ddcc912005-07-27 11:46:00 -0700280static int lgdt330x_set_parameters(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700281 struct dvb_frontend_parameters *param)
282{
Michael Krufky1963c902005-08-08 09:22:43 -0700283 /*
284 * Array of byte pairs <address, value>
285 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
286 */
287 static u8 lgdt3303_8vsb_44_data[] = {
288 0x04, 0x00,
289 0x0d, 0x40,
290 0x0e, 0x87,
291 0x0f, 0x8e,
292 0x10, 0x01,
293 0x47, 0x8b };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700294
Michael Krufky1963c902005-08-08 09:22:43 -0700295 /*
296 * Array of byte pairs <address, value>
297 * to initialize QAM for lgdt3303 chip
298 */
299 static u8 lgdt3303_qam_data[] = {
300 0x04, 0x00,
301 0x0d, 0x00,
302 0x0e, 0x00,
303 0x0f, 0x00,
304 0x10, 0x00,
305 0x51, 0x63,
306 0x47, 0x66,
307 0x48, 0x66,
308 0x4d, 0x1a,
309 0x49, 0x08,
310 0x4a, 0x9b };
311
312 struct lgdt330x_state* state = fe->demodulator_priv;
313
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700314 static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700315
Michael Krufky1963c902005-08-08 09:22:43 -0700316 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700317 /* Change only if we are actually changing the modulation */
318 if (state->current_modulation != param->u.vsb.modulation) {
319 switch(param->u.vsb.modulation) {
320 case VSB_8:
321 dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
322
Michael Krufky1963c902005-08-08 09:22:43 -0700323 /* Select VSB mode */
324 top_ctrl_cfg[1] = 0x03;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700325
326 /* Select ANT connector if supported by card */
327 if (state->config->pll_rf_set)
328 state->config->pll_rf_set(fe, 1);
Michael Krufky1963c902005-08-08 09:22:43 -0700329
330 if (state->config->demod_chip == LGDT3303) {
331 err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700332 sizeof(lgdt3303_8vsb_44_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700333 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700334 break;
335
336 case QAM_64:
337 dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
338
Michael Krufky1963c902005-08-08 09:22:43 -0700339 /* Select QAM_64 mode */
340 top_ctrl_cfg[1] = 0x00;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700341
342 /* Select CABLE connector if supported by card */
343 if (state->config->pll_rf_set)
344 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700345
346 if (state->config->demod_chip == LGDT3303) {
347 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
348 sizeof(lgdt3303_qam_data));
349 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700350 break;
351
352 case QAM_256:
353 dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
354
Michael Krufky1963c902005-08-08 09:22:43 -0700355 /* Select QAM_256 mode */
356 top_ctrl_cfg[1] = 0x01;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700357
358 /* Select CABLE connector if supported by card */
359 if (state->config->pll_rf_set)
360 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700361
362 if (state->config->demod_chip == LGDT3303) {
363 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
364 sizeof(lgdt3303_qam_data));
365 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700366 break;
367 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700368 printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700369 return -1;
370 }
Michael Krufky1963c902005-08-08 09:22:43 -0700371 /*
372 * select serial or parallel MPEG harware interface
373 * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
374 * Parallel: 0x00
375 */
376 top_ctrl_cfg[1] |= state->config->serial_mpeg;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700377
378 /* Select the requested mode */
Michael Krufky1963c902005-08-08 09:22:43 -0700379 i2c_write_demod_bytes(state, top_ctrl_cfg,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700380 sizeof(top_ctrl_cfg));
381 if (state->config->set_ts_params)
382 state->config->set_ts_params(fe, 0);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700383 state->current_modulation = param->u.vsb.modulation;
384 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700385
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700386 /* Tune to the specified frequency */
387 if (state->config->pll_set)
Michael Krufky1963c902005-08-08 09:22:43 -0700388 state->config->pll_set(fe, param);
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700389
390 /* Keep track of the new frequency */
391 state->current_frequency = param->frequency;
392
Michael Krufky6ddcc912005-07-27 11:46:00 -0700393 lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700394 return 0;
395}
396
Michael Krufky6ddcc912005-07-27 11:46:00 -0700397static int lgdt330x_get_frontend(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700398 struct dvb_frontend_parameters* param)
399{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700400 struct lgdt330x_state *state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700401 param->frequency = state->current_frequency;
402 return 0;
403}
404
Michael Krufky1963c902005-08-08 09:22:43 -0700405static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700406{
Michael Krufky1963c902005-08-08 09:22:43 -0700407 struct lgdt330x_state* state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700408 u8 buf[3];
409
410 *status = 0; /* Reset status result */
411
Michael Krufky08d80522005-07-07 17:58:43 -0700412 /* AGC status register */
Michael Krufky1963c902005-08-08 09:22:43 -0700413 i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
Michael Krufky08d80522005-07-07 17:58:43 -0700414 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
415 if ((buf[0] & 0x0c) == 0x8){
416 /* Test signal does not exist flag */
417 /* as well as the AGC lock flag. */
418 *status |= FE_HAS_SIGNAL;
419 } else {
420 /* Without a signal all other status bits are meaningless */
421 return 0;
422 }
423
Michael Krufky1963c902005-08-08 09:22:43 -0700424 /*
425 * You must set the Mask bits to 1 in the IRQ_MASK in order
426 * to see that status bit in the IRQ_STATUS register.
427 * This is done in SwReset();
428 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700429 /* signal status */
Michael Krufky1963c902005-08-08 09:22:43 -0700430 i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700431 dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
Michael Krufky08d80522005-07-07 17:58:43 -0700432
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700433
434 /* sync status */
435 if ((buf[2] & 0x03) == 0x01) {
436 *status |= FE_HAS_SYNC;
437 }
438
439 /* FEC error status */
440 if ((buf[2] & 0x0c) == 0x08) {
441 *status |= FE_HAS_LOCK;
442 *status |= FE_HAS_VITERBI;
443 }
444
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700445 /* Carrier Recovery Lock Status Register */
Michael Krufky1963c902005-08-08 09:22:43 -0700446 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700447 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
448 switch (state->current_modulation) {
449 case QAM_256:
450 case QAM_64:
451 /* Need to undestand why there are 3 lock levels here */
452 if ((buf[0] & 0x07) == 0x07)
453 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700454 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700455 case VSB_8:
456 if ((buf[0] & 0x80) == 0x80)
457 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700458 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700459 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700460 printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700461 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700462
463 return 0;
464}
465
Michael Krufky1963c902005-08-08 09:22:43 -0700466static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700467{
Michael Krufky1963c902005-08-08 09:22:43 -0700468 struct lgdt330x_state* state = fe->demodulator_priv;
469 int err;
470 u8 buf[3];
471
472 *status = 0; /* Reset status result */
473
474 /* lgdt3303 AGC status register */
475 err = i2c_read_demod_bytes(state, 0x58, buf, 1);
476 if (err < 0)
477 return err;
478
479 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
480 if ((buf[0] & 0x21) == 0x01){
481 /* Test input signal does not exist flag */
482 /* as well as the AGC lock flag. */
483 *status |= FE_HAS_SIGNAL;
484 } else {
485 /* Without a signal all other status bits are meaningless */
486 return 0;
487 }
488
489 /* Carrier Recovery Lock Status Register */
490 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
491 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
492 switch (state->current_modulation) {
493 case QAM_256:
494 case QAM_64:
495 /* Need to undestand why there are 3 lock levels here */
496 if ((buf[0] & 0x07) == 0x07)
497 *status |= FE_HAS_CARRIER;
498 else
499 break;
500 i2c_read_demod_bytes(state, 0x8a, buf, 1);
501 if ((buf[0] & 0x04) == 0x04)
502 *status |= FE_HAS_SYNC;
503 if ((buf[0] & 0x01) == 0x01)
504 *status |= FE_HAS_LOCK;
505 if ((buf[0] & 0x08) == 0x08)
506 *status |= FE_HAS_VITERBI;
507 break;
508 case VSB_8:
509 if ((buf[0] & 0x80) == 0x80)
510 *status |= FE_HAS_CARRIER;
511 else
512 break;
513 i2c_read_demod_bytes(state, 0x38, buf, 1);
514 if ((buf[0] & 0x02) == 0x00)
515 *status |= FE_HAS_SYNC;
516 if ((buf[0] & 0x01) == 0x01) {
517 *status |= FE_HAS_LOCK;
518 *status |= FE_HAS_VITERBI;
519 }
520 break;
521 default:
522 printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
523 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700524 return 0;
525}
526
Michael Krufky1963c902005-08-08 09:22:43 -0700527static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
528{
529 /* not directly available. */
530 *strength = 0;
531 return 0;
532}
533
534static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700535{
536#ifdef SNR_IN_DB
537 /*
538 * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
539 * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
540 * respectively. The following tables are built on these formulas.
541 * The usual definition is SNR = 20 log10(signal/noise)
542 * If the specification is wrong the value retuned is 1/2 the actual SNR in db.
543 *
544 * This table is a an ordered list of noise values computed by the
545 * formula from the spec sheet such that the index into the table
546 * starting at 43 or 45 is the SNR value in db. There are duplicate noise
547 * value entries at the beginning because the SNR varies more than
548 * 1 db for a change of 1 digit in noise at very small values of noise.
549 *
550 * Examples from SNR_EQ table:
551 * noise SNR
552 * 0 43
553 * 1 42
554 * 2 39
555 * 3 37
556 * 4 36
557 * 5 35
558 * 6 34
559 * 7 33
560 * 8 33
561 * 9 32
562 * 10 32
563 * 11 31
564 * 12 31
565 * 13 30
566 */
567
568 static const u32 SNR_EQ[] =
569 { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7,
570 9, 11, 13, 17, 21, 26, 33, 41, 52, 65,
571 81, 102, 129, 162, 204, 257, 323, 406, 511, 644,
572 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433,
573 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323,
574 80978, 101945, 128341, 161571, 203406, 256073, 0x40000
575 };
576
577 static const u32 SNR_PH[] =
578 { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8,
579 10, 12, 15, 19, 23, 29, 37, 46, 58, 73,
580 91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
581 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
582 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
Michael Krufky1963c902005-08-08 09:22:43 -0700583 90833, 114351, 143960, 181235, 228161, 0x080000
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700584 };
585
586 static u8 buf[5];/* read data buffer */
587 static u32 noise; /* noise value */
588 static u32 snr_db; /* index into SNR_EQ[] */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700589 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700590
Michael Krufky1963c902005-08-08 09:22:43 -0700591 /* read both equalizer and phase tracker noise data */
592 i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700593
594 if (state->current_modulation == VSB_8) {
595 /* Equalizer Mean-Square Error Register for VSB */
596 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
597
598 /*
599 * Look up noise value in table.
600 * A better search algorithm could be used...
601 * watch out there are duplicate entries.
602 */
603 for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
604 if (noise < SNR_EQ[snr_db]) {
605 *snr = 43 - snr_db;
606 break;
607 }
608 }
609 } else {
610 /* Phase Tracker Mean-Square Error Register for QAM */
611 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
612
613 /* Look up noise value in table. */
614 for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
615 if (noise < SNR_PH[snr_db]) {
616 *snr = 45 - snr_db;
617 break;
618 }
619 }
620 }
621#else
622 /* Return the raw noise value */
623 static u8 buf[5];/* read data buffer */
624 static u32 noise; /* noise value */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700625 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700626
627 /* read both equalizer and pase tracker noise data */
Michael Krufky1963c902005-08-08 09:22:43 -0700628 i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700629
630 if (state->current_modulation == VSB_8) {
Michael Krufky1963c902005-08-08 09:22:43 -0700631 /* Phase Tracker Mean-Square Error Register for VSB */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700632 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
Michael Krufky1963c902005-08-08 09:22:43 -0700633 } else {
634
635 /* Carrier Recovery Mean-Square Error for QAM */
636 i2c_read_demod_bytes(state, 0x1a, buf, 2);
637 noise = ((buf[0] & 3) << 8) | buf[1];
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700638 }
639
640 /* Small values for noise mean signal is better so invert noise */
Michael Krufky1963c902005-08-08 09:22:43 -0700641 *snr = ~noise;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700642#endif
643
644 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
645
646 return 0;
647}
648
Michael Krufky1963c902005-08-08 09:22:43 -0700649static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
650{
651 /* Return the raw noise value */
652 static u8 buf[5];/* read data buffer */
653 static u32 noise; /* noise value */
654 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
655
656 if (state->current_modulation == VSB_8) {
657
658 /* Phase Tracker Mean-Square Error Register for VSB */
659 noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
660 } else {
661
662 /* Carrier Recovery Mean-Square Error for QAM */
663 i2c_read_demod_bytes(state, 0x1a, buf, 2);
664 noise = (buf[0] << 8) | buf[1];
665 }
666
667 /* Small values for noise mean signal is better so invert noise */
668 *snr = ~noise;
669
670 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
671
672 return 0;
673}
674
Michael Krufky6ddcc912005-07-27 11:46:00 -0700675static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700676{
677 /* I have no idea about this - it may not be needed */
678 fe_tune_settings->min_delay_ms = 500;
679 fe_tune_settings->step_size = 0;
680 fe_tune_settings->max_drift = 0;
681 return 0;
682}
683
Michael Krufky6ddcc912005-07-27 11:46:00 -0700684static void lgdt330x_release(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700685{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700686 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700687 kfree(state);
688}
689
Michael Krufky1963c902005-08-08 09:22:43 -0700690static struct dvb_frontend_ops lgdt3302_ops;
691static struct dvb_frontend_ops lgdt3303_ops;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700692
Michael Krufky6ddcc912005-07-27 11:46:00 -0700693struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700694 struct i2c_adapter* i2c)
695{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700696 struct lgdt330x_state* state = NULL;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700697 u8 buf[1];
698
699 /* Allocate memory for the internal state */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700700 state = (struct lgdt330x_state*) kmalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700701 if (state == NULL)
702 goto error;
703 memset(state,0,sizeof(*state));
704
705 /* Setup the state */
706 state->config = config;
707 state->i2c = i2c;
Michael Krufky1963c902005-08-08 09:22:43 -0700708 switch (config->demod_chip) {
709 case LGDT3302:
710 memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
711 break;
712 case LGDT3303:
713 memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
714 break;
715 default:
716 goto error;
717 }
718
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700719 /* Verify communication with demod chip */
Michael Krufky1963c902005-08-08 09:22:43 -0700720 if (i2c_read_demod_bytes(state, 2, buf, 1))
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700721 goto error;
722
723 state->current_frequency = -1;
724 state->current_modulation = -1;
725
726 /* Create dvb_frontend */
727 state->frontend.ops = &state->ops;
728 state->frontend.demodulator_priv = state;
729 return &state->frontend;
730
731error:
732 if (state)
733 kfree(state);
734 dprintk("%s: ERROR\n",__FUNCTION__);
735 return NULL;
736}
737
Michael Krufky1963c902005-08-08 09:22:43 -0700738static struct dvb_frontend_ops lgdt3302_ops = {
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700739 .info = {
Michael Krufkye179d8b2005-08-09 17:48:54 -0700740 .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700741 .type = FE_ATSC,
742 .frequency_min= 54000000,
743 .frequency_max= 858000000,
744 .frequency_stepsize= 62500,
745 /* Symbol rate is for all VSB modes need to check QAM */
746 .symbol_rate_min = 10762000,
747 .symbol_rate_max = 10762000,
748 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
749 },
Michael Krufky6ddcc912005-07-27 11:46:00 -0700750 .init = lgdt330x_init,
751 .set_frontend = lgdt330x_set_parameters,
752 .get_frontend = lgdt330x_get_frontend,
753 .get_tune_settings = lgdt330x_get_tune_settings,
Michael Krufky1963c902005-08-08 09:22:43 -0700754 .read_status = lgdt3302_read_status,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700755 .read_ber = lgdt330x_read_ber,
756 .read_signal_strength = lgdt330x_read_signal_strength,
Michael Krufky1963c902005-08-08 09:22:43 -0700757 .read_snr = lgdt3302_read_snr,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700758 .read_ucblocks = lgdt330x_read_ucblocks,
759 .release = lgdt330x_release,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700760};
761
Michael Krufky1963c902005-08-08 09:22:43 -0700762static struct dvb_frontend_ops lgdt3303_ops = {
763 .info = {
764 .name= "LG Electronics LGDT3303 VSB/QAM Frontend",
765 .type = FE_ATSC,
766 .frequency_min= 54000000,
767 .frequency_max= 858000000,
768 .frequency_stepsize= 62500,
769 /* Symbol rate is for all VSB modes need to check QAM */
770 .symbol_rate_min = 10762000,
771 .symbol_rate_max = 10762000,
772 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
773 },
774 .init = lgdt330x_init,
775 .set_frontend = lgdt330x_set_parameters,
776 .get_frontend = lgdt330x_get_frontend,
777 .get_tune_settings = lgdt330x_get_tune_settings,
778 .read_status = lgdt3303_read_status,
779 .read_ber = lgdt330x_read_ber,
780 .read_signal_strength = lgdt330x_read_signal_strength,
781 .read_snr = lgdt3303_read_snr,
782 .read_ucblocks = lgdt330x_read_ucblocks,
783 .release = lgdt330x_release,
784};
785
786MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700787MODULE_AUTHOR("Wilson Michaels");
788MODULE_LICENSE("GPL");
789
Michael Krufky6ddcc912005-07-27 11:46:00 -0700790EXPORT_SYMBOL(lgdt330x_attach);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700791
792/*
793 * Local variables:
794 * c-basic-offset: 8
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700795 * End:
796 */