blob: 1f1cd7a8d500846c07e8fd4fa49c0d8335cd7443 [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,
Mac Michaelsd8667cb2005-07-07 17:58:29 -070072 u8 *buf, /* data bytes to send */
73 int len /* number of bytes to send */ )
74{
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,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700132 reset, sizeof(reset));
133 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,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700138 reset, sizeof(reset));
139 }
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,
152 reset, sizeof(reset));
153 if (ret == 0) {
154
155 /* force reset high (inactive) */
156 reset[1] = 0x01;
157 ret = i2c_write_demod_bytes(state,
158 reset, sizeof(reset));
159 }
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 Krufky1963c902005-08-08 09:22:43 -0700175
Michael Krufky6ddcc912005-07-27 11:46:00 -0700176static int lgdt330x_init(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700177{
178 /* Hardware reset is done using gpio[0] of cx23880x chip.
179 * I'd like to do it here, but don't know how to find chip address.
180 * cx88-cards.c arranges for the reset bit to be inactive (high).
181 * Maybe there needs to be a callable function in cx88-core or
182 * the caller of this function needs to do it. */
183
Michael Krufky1963c902005-08-08 09:22:43 -0700184 /*
185 * Array of byte pairs <address, value>
186 * to initialize each different chip
187 */
188 static u8 lgdt3302_init_data[] = {
189 /* Use 50MHz parameter values from spec sheet since xtal is 50 */
190 /* Change the value of NCOCTFV[25:0] of carrier
191 recovery center frequency register */
192 VSB_CARRIER_FREQ0, 0x00,
193 VSB_CARRIER_FREQ1, 0x87,
194 VSB_CARRIER_FREQ2, 0x8e,
195 VSB_CARRIER_FREQ3, 0x01,
196 /* Change the TPCLK pin polarity
197 data is valid on falling clock */
198 DEMUX_CONTROL, 0xfb,
199 /* Change the value of IFBW[11:0] of
200 AGC IF/RF loop filter bandwidth register */
201 AGC_RF_BANDWIDTH0, 0x40,
202 AGC_RF_BANDWIDTH1, 0x93,
203 AGC_RF_BANDWIDTH2, 0x00,
204 /* Change the value of bit 6, 'nINAGCBY' and
205 'NSSEL[1:0] of ACG function control register 2 */
206 AGC_FUNC_CTRL2, 0xc6,
207 /* Change the value of bit 6 'RFFIX'
208 of AGC function control register 3 */
209 AGC_FUNC_CTRL3, 0x40,
210 /* Set the value of 'INLVTHD' register 0x2a/0x2c
211 to 0x7fe */
212 AGC_DELAY0, 0x07,
213 AGC_DELAY2, 0xfe,
214 /* Change the value of IAGCBW[15:8]
215 of inner AGC loop filter bandwith */
216 AGC_LOOP_BANDWIDTH0, 0x08,
217 AGC_LOOP_BANDWIDTH1, 0x9a
218 };
219
220 static u8 lgdt3303_init_data[] = {
221 0x4c, 0x14
222 };
223
224 struct lgdt330x_state* state = fe->demodulator_priv;
225 char *chip_name;
226 int err;
227
228 switch (state->config->demod_chip) {
229 case LGDT3302:
230 chip_name = "LGDT3302";
231 err = i2c_write_demod_bytes(state, lgdt3302_init_data,
232 sizeof(lgdt3302_init_data));
233 break;
234 case LGDT3303:
235 chip_name = "LGDT3303";
236 err = i2c_write_demod_bytes(state, lgdt3303_init_data,
237 sizeof(lgdt3303_init_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700238 break;
239 default:
240 chip_name = "undefined";
241 printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
242 err = -ENODEV;
243 }
244 dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
245 if (err < 0)
246 return err;
247 return lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700248}
249
Michael Krufky6ddcc912005-07-27 11:46:00 -0700250static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700251{
Michael Krufky1963c902005-08-08 09:22:43 -0700252 *ber = 0; /* Not supplied by the demod chips */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700253 return 0;
254}
255
Michael Krufky6ddcc912005-07-27 11:46:00 -0700256static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700257{
Michael Krufky1963c902005-08-08 09:22:43 -0700258 struct lgdt330x_state* state = fe->demodulator_priv;
259 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700260 u8 buf[2];
261
Michael Krufky1963c902005-08-08 09:22:43 -0700262 switch (state->config->demod_chip) {
263 case LGDT3302:
264 err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
265 buf, sizeof(buf));
266 break;
267 case LGDT3303:
268 err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
269 buf, sizeof(buf));
270 break;
271 default:
272 printk(KERN_WARNING
273 "Only LGDT3302 and LGDT3303 are supported chips.\n");
274 err = -ENODEV;
275 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700276
277 *ucblocks = (buf[0] << 8) | buf[1];
278 return 0;
279}
280
Michael Krufky6ddcc912005-07-27 11:46:00 -0700281static int lgdt330x_set_parameters(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700282 struct dvb_frontend_parameters *param)
283{
Michael Krufky1963c902005-08-08 09:22:43 -0700284 /*
285 * Array of byte pairs <address, value>
286 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
287 */
288 static u8 lgdt3303_8vsb_44_data[] = {
289 0x04, 0x00,
290 0x0d, 0x40,
291 0x0e, 0x87,
292 0x0f, 0x8e,
293 0x10, 0x01,
294 0x47, 0x8b };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700295
Michael Krufky1963c902005-08-08 09:22:43 -0700296 /*
297 * Array of byte pairs <address, value>
298 * to initialize QAM for lgdt3303 chip
299 */
300 static u8 lgdt3303_qam_data[] = {
301 0x04, 0x00,
302 0x0d, 0x00,
303 0x0e, 0x00,
304 0x0f, 0x00,
305 0x10, 0x00,
306 0x51, 0x63,
307 0x47, 0x66,
308 0x48, 0x66,
309 0x4d, 0x1a,
310 0x49, 0x08,
311 0x4a, 0x9b };
312
313 struct lgdt330x_state* state = fe->demodulator_priv;
314
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700315 static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700316
Michael Krufky1963c902005-08-08 09:22:43 -0700317 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700318 /* Change only if we are actually changing the modulation */
319 if (state->current_modulation != param->u.vsb.modulation) {
320 switch(param->u.vsb.modulation) {
321 case VSB_8:
322 dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
323
Michael Krufky1963c902005-08-08 09:22:43 -0700324 /* Select VSB mode */
325 top_ctrl_cfg[1] = 0x03;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700326
327 /* Select ANT connector if supported by card */
328 if (state->config->pll_rf_set)
329 state->config->pll_rf_set(fe, 1);
Michael Krufky1963c902005-08-08 09:22:43 -0700330
331 if (state->config->demod_chip == LGDT3303) {
332 err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
333 sizeof(lgdt3303_8vsb_44_data));
334 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700335 break;
336
337 case QAM_64:
338 dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
339
Michael Krufky1963c902005-08-08 09:22:43 -0700340 /* Select QAM_64 mode */
341 top_ctrl_cfg[1] = 0x00;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700342
343 /* Select CABLE connector if supported by card */
344 if (state->config->pll_rf_set)
345 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700346
347 if (state->config->demod_chip == LGDT3303) {
348 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
349 sizeof(lgdt3303_qam_data));
350 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700351 break;
352
353 case QAM_256:
354 dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
355
Michael Krufky1963c902005-08-08 09:22:43 -0700356 /* Select QAM_256 mode */
357 top_ctrl_cfg[1] = 0x01;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700358
359 /* Select CABLE connector if supported by card */
360 if (state->config->pll_rf_set)
361 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700362
363 if (state->config->demod_chip == LGDT3303) {
364 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
365 sizeof(lgdt3303_qam_data));
366 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700367 break;
368 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700369 printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700370 return -1;
371 }
Michael Krufky1963c902005-08-08 09:22:43 -0700372 /*
373 * select serial or parallel MPEG harware interface
374 * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
375 * Parallel: 0x00
376 */
377 top_ctrl_cfg[1] |= state->config->serial_mpeg;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700378
379 /* Select the requested mode */
Michael Krufky1963c902005-08-08 09:22:43 -0700380 i2c_write_demod_bytes(state, top_ctrl_cfg,
381 sizeof(top_ctrl_cfg));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700382 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
386 /* Change only if we are actually changing the channel */
387 if (state->current_frequency != param->frequency) {
Michael Krufky1963c902005-08-08 09:22:43 -0700388 /* Tune to the new frequency */
389 state->config->pll_set(fe, param);
390 /* Keep track of the new frequency */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700391 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 */