blob: 8dde72bd10461fb5997cf13e6748e73bfee43535 [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>
Tim Schmielau4e57b682005-10-30 15:03:48 -080040#include <linux/string.h>
41#include <linux/slab.h>
Mac Michaelsd8667cb2005-07-07 17:58:29 -070042#include <asm/byteorder.h>
43
44#include "dvb_frontend.h"
Michael Krufky6ddcc912005-07-27 11:46:00 -070045#include "lgdt330x_priv.h"
46#include "lgdt330x.h"
Mac Michaelsd8667cb2005-07-07 17:58:29 -070047
48static int debug = 0;
49module_param(debug, int, 0644);
Michael Krufky6ddcc912005-07-27 11:46:00 -070050MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
Mac Michaelsd8667cb2005-07-07 17:58:29 -070051#define dprintk(args...) \
52do { \
Michael Krufky6ddcc912005-07-27 11:46:00 -070053if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
Mac Michaelsd8667cb2005-07-07 17:58:29 -070054} while (0)
55
Michael Krufky6ddcc912005-07-27 11:46:00 -070056struct lgdt330x_state
Mac Michaelsd8667cb2005-07-07 17:58:29 -070057{
58 struct i2c_adapter* i2c;
59 struct dvb_frontend_ops ops;
60
61 /* Configuration settings */
Michael Krufky6ddcc912005-07-27 11:46:00 -070062 const struct lgdt330x_config* config;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070063
64 struct dvb_frontend frontend;
65
66 /* Demodulator private data */
67 fe_modulation_t current_modulation;
68
69 /* Tuner private data */
70 u32 current_frequency;
71};
72
Michael Krufky1963c902005-08-08 09:22:43 -070073static int i2c_write_demod_bytes (struct lgdt330x_state* state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -070074 u8 *buf, /* data bytes to send */
75 int len /* number of bytes to send */ )
Mac Michaelsd8667cb2005-07-07 17:58:29 -070076{
Michael Krufkyb6aef072005-07-27 11:45:54 -070077 struct i2c_msg msg =
Michael Krufky1963c902005-08-08 09:22:43 -070078 { .addr = state->config->demod_address,
79 .flags = 0,
80 .buf = buf,
81 .len = 2 };
Michael Krufkyb6aef072005-07-27 11:45:54 -070082 int i;
Michael Krufky1963c902005-08-08 09:22:43 -070083 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070084
Michael Krufky1963c902005-08-08 09:22:43 -070085 for (i=0; i<len-1; i+=2){
Mac Michaelsd8667cb2005-07-07 17:58:29 -070086 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
Michael Krufky1963c902005-08-08 09:22:43 -070087 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 -070088 if (err < 0)
89 return err;
90 else
91 return -EREMOTEIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070092 }
Michael Krufky1963c902005-08-08 09:22:43 -070093 msg.buf += 2;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070094 }
95 return 0;
96}
Michael Krufkyb6aef072005-07-27 11:45:54 -070097
Mac Michaelsd8667cb2005-07-07 17:58:29 -070098/*
99 * This routine writes the register (reg) to the demod bus
100 * then reads the data returned for (len) bytes.
101 */
102
Michael Krufky1963c902005-08-08 09:22:43 -0700103static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700104 enum I2C_REG reg, u8* buf, int len)
105{
106 u8 wr [] = { reg };
107 struct i2c_msg msg [] = {
108 { .addr = state->config->demod_address,
109 .flags = 0, .buf = wr, .len = 1 },
110 { .addr = state->config->demod_address,
111 .flags = I2C_M_RD, .buf = buf, .len = len },
112 };
113 int ret;
114 ret = i2c_transfer(state->i2c, msg, 2);
115 if (ret != 2) {
Michael Krufky6ddcc912005-07-27 11:46:00 -0700116 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 -0700117 } else {
118 ret = 0;
119 }
120 return ret;
121}
122
123/* Software reset */
Michael Krufky1963c902005-08-08 09:22:43 -0700124static int lgdt3302_SwReset(struct lgdt330x_state* state)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700125{
126 u8 ret;
127 u8 reset[] = {
128 IRQ_MASK,
129 0x00 /* bit 6 is active low software reset
130 * bits 5-0 are 1 to mask interrupts */
131 };
132
Michael Krufky1963c902005-08-08 09:22:43 -0700133 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700134 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700135 if (ret == 0) {
Michael Krufky1963c902005-08-08 09:22:43 -0700136
137 /* force reset high (inactive) and unmask interrupts */
138 reset[1] = 0x7f;
139 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700140 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700141 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700142 return ret;
143}
144
Michael Krufky1963c902005-08-08 09:22:43 -0700145static int lgdt3303_SwReset(struct lgdt330x_state* state)
146{
147 u8 ret;
148 u8 reset[] = {
149 0x02,
150 0x00 /* bit 0 is active low software reset */
151 };
152
153 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700154 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700155 if (ret == 0) {
156
157 /* force reset high (inactive) */
158 reset[1] = 0x01;
159 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700160 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700161 }
162 return ret;
163}
164
165static int lgdt330x_SwReset(struct lgdt330x_state* state)
166{
167 switch (state->config->demod_chip) {
168 case LGDT3302:
169 return lgdt3302_SwReset(state);
170 case LGDT3303:
171 return lgdt3303_SwReset(state);
172 default:
173 return -ENODEV;
174 }
175}
176
Michael Krufky6ddcc912005-07-27 11:46:00 -0700177static int lgdt330x_init(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700178{
179 /* Hardware reset is done using gpio[0] of cx23880x chip.
180 * I'd like to do it here, but don't know how to find chip address.
181 * cx88-cards.c arranges for the reset bit to be inactive (high).
182 * Maybe there needs to be a callable function in cx88-core or
183 * the caller of this function needs to do it. */
184
Michael Krufky1963c902005-08-08 09:22:43 -0700185 /*
186 * Array of byte pairs <address, value>
187 * to initialize each different chip
188 */
189 static u8 lgdt3302_init_data[] = {
190 /* Use 50MHz parameter values from spec sheet since xtal is 50 */
191 /* Change the value of NCOCTFV[25:0] of carrier
192 recovery center frequency register */
193 VSB_CARRIER_FREQ0, 0x00,
194 VSB_CARRIER_FREQ1, 0x87,
195 VSB_CARRIER_FREQ2, 0x8e,
196 VSB_CARRIER_FREQ3, 0x01,
197 /* Change the TPCLK pin polarity
198 data is valid on falling clock */
199 DEMUX_CONTROL, 0xfb,
200 /* Change the value of IFBW[11:0] of
201 AGC IF/RF loop filter bandwidth register */
202 AGC_RF_BANDWIDTH0, 0x40,
203 AGC_RF_BANDWIDTH1, 0x93,
204 AGC_RF_BANDWIDTH2, 0x00,
205 /* Change the value of bit 6, 'nINAGCBY' and
206 'NSSEL[1:0] of ACG function control register 2 */
207 AGC_FUNC_CTRL2, 0xc6,
208 /* Change the value of bit 6 'RFFIX'
209 of AGC function control register 3 */
210 AGC_FUNC_CTRL3, 0x40,
211 /* Set the value of 'INLVTHD' register 0x2a/0x2c
212 to 0x7fe */
213 AGC_DELAY0, 0x07,
214 AGC_DELAY2, 0xfe,
215 /* Change the value of IAGCBW[15:8]
216 of inner AGC loop filter bandwith */
217 AGC_LOOP_BANDWIDTH0, 0x08,
218 AGC_LOOP_BANDWIDTH1, 0x9a
219 };
220
221 static u8 lgdt3303_init_data[] = {
222 0x4c, 0x14
223 };
224
225 struct lgdt330x_state* state = fe->demodulator_priv;
226 char *chip_name;
227 int err;
228
229 switch (state->config->demod_chip) {
230 case LGDT3302:
231 chip_name = "LGDT3302";
232 err = i2c_write_demod_bytes(state, lgdt3302_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700233 sizeof(lgdt3302_init_data));
234 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700235 case LGDT3303:
236 chip_name = "LGDT3303";
237 err = i2c_write_demod_bytes(state, lgdt3303_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700238 sizeof(lgdt3303_init_data));
239 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700240 default:
241 chip_name = "undefined";
242 printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
243 err = -ENODEV;
244 }
245 dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
246 if (err < 0)
247 return err;
248 return lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700249}
250
Michael Krufky6ddcc912005-07-27 11:46:00 -0700251static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700252{
Michael Krufky1963c902005-08-08 09:22:43 -0700253 *ber = 0; /* Not supplied by the demod chips */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700254 return 0;
255}
256
Michael Krufky6ddcc912005-07-27 11:46:00 -0700257static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700258{
Michael Krufky1963c902005-08-08 09:22:43 -0700259 struct lgdt330x_state* state = fe->demodulator_priv;
260 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700261 u8 buf[2];
262
Michael Krufky1963c902005-08-08 09:22:43 -0700263 switch (state->config->demod_chip) {
264 case LGDT3302:
265 err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700266 buf, sizeof(buf));
267 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700268 case LGDT3303:
269 err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700270 buf, sizeof(buf));
271 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700272 default:
273 printk(KERN_WARNING
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700274 "Only LGDT3302 and LGDT3303 are supported chips.\n");
Michael Krufky1963c902005-08-08 09:22:43 -0700275 err = -ENODEV;
276 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700277
278 *ucblocks = (buf[0] << 8) | buf[1];
279 return 0;
280}
281
Michael Krufky6ddcc912005-07-27 11:46:00 -0700282static int lgdt330x_set_parameters(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700283 struct dvb_frontend_parameters *param)
284{
Michael Krufky1963c902005-08-08 09:22:43 -0700285 /*
286 * Array of byte pairs <address, value>
287 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
288 */
289 static u8 lgdt3303_8vsb_44_data[] = {
290 0x04, 0x00,
291 0x0d, 0x40,
292 0x0e, 0x87,
293 0x0f, 0x8e,
294 0x10, 0x01,
295 0x47, 0x8b };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700296
Michael Krufky1963c902005-08-08 09:22:43 -0700297 /*
298 * Array of byte pairs <address, value>
299 * to initialize QAM for lgdt3303 chip
300 */
301 static u8 lgdt3303_qam_data[] = {
302 0x04, 0x00,
303 0x0d, 0x00,
304 0x0e, 0x00,
305 0x0f, 0x00,
306 0x10, 0x00,
307 0x51, 0x63,
308 0x47, 0x66,
309 0x48, 0x66,
310 0x4d, 0x1a,
311 0x49, 0x08,
312 0x4a, 0x9b };
313
314 struct lgdt330x_state* state = fe->demodulator_priv;
315
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700316 static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700317
Michael Krufky1963c902005-08-08 09:22:43 -0700318 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700319 /* Change only if we are actually changing the modulation */
320 if (state->current_modulation != param->u.vsb.modulation) {
321 switch(param->u.vsb.modulation) {
322 case VSB_8:
323 dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
324
Michael Krufky1963c902005-08-08 09:22:43 -0700325 /* Select VSB mode */
326 top_ctrl_cfg[1] = 0x03;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700327
328 /* Select ANT connector if supported by card */
329 if (state->config->pll_rf_set)
330 state->config->pll_rf_set(fe, 1);
Michael Krufky1963c902005-08-08 09:22:43 -0700331
332 if (state->config->demod_chip == LGDT3303) {
333 err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700334 sizeof(lgdt3303_8vsb_44_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700335 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700336 break;
337
338 case QAM_64:
339 dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
340
Michael Krufky1963c902005-08-08 09:22:43 -0700341 /* Select QAM_64 mode */
342 top_ctrl_cfg[1] = 0x00;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700343
344 /* Select CABLE connector if supported by card */
345 if (state->config->pll_rf_set)
346 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700347
348 if (state->config->demod_chip == LGDT3303) {
349 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
350 sizeof(lgdt3303_qam_data));
351 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700352 break;
353
354 case QAM_256:
355 dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
356
Michael Krufky1963c902005-08-08 09:22:43 -0700357 /* Select QAM_256 mode */
358 top_ctrl_cfg[1] = 0x01;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700359
360 /* Select CABLE connector if supported by card */
361 if (state->config->pll_rf_set)
362 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700363
364 if (state->config->demod_chip == LGDT3303) {
365 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
366 sizeof(lgdt3303_qam_data));
367 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700368 break;
369 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700370 printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700371 return -1;
372 }
Michael Krufky1963c902005-08-08 09:22:43 -0700373 /*
374 * select serial or parallel MPEG harware interface
375 * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
376 * Parallel: 0x00
377 */
378 top_ctrl_cfg[1] |= state->config->serial_mpeg;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700379
380 /* Select the requested mode */
Michael Krufky1963c902005-08-08 09:22:43 -0700381 i2c_write_demod_bytes(state, top_ctrl_cfg,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700382 sizeof(top_ctrl_cfg));
383 if (state->config->set_ts_params)
384 state->config->set_ts_params(fe, 0);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700385 state->current_modulation = param->u.vsb.modulation;
386 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700387
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700388 /* Tune to the specified frequency */
389 if (state->config->pll_set)
Michael Krufky1963c902005-08-08 09:22:43 -0700390 state->config->pll_set(fe, param);
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700391
392 /* Keep track of the new frequency */
393 state->current_frequency = param->frequency;
394
Michael Krufky6ddcc912005-07-27 11:46:00 -0700395 lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700396 return 0;
397}
398
Michael Krufky6ddcc912005-07-27 11:46:00 -0700399static int lgdt330x_get_frontend(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700400 struct dvb_frontend_parameters* param)
401{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700402 struct lgdt330x_state *state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700403 param->frequency = state->current_frequency;
404 return 0;
405}
406
Michael Krufky1963c902005-08-08 09:22:43 -0700407static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700408{
Michael Krufky1963c902005-08-08 09:22:43 -0700409 struct lgdt330x_state* state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700410 u8 buf[3];
411
412 *status = 0; /* Reset status result */
413
Michael Krufky08d80522005-07-07 17:58:43 -0700414 /* AGC status register */
Michael Krufky1963c902005-08-08 09:22:43 -0700415 i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
Michael Krufky08d80522005-07-07 17:58:43 -0700416 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
417 if ((buf[0] & 0x0c) == 0x8){
418 /* Test signal does not exist flag */
419 /* as well as the AGC lock flag. */
420 *status |= FE_HAS_SIGNAL;
421 } else {
422 /* Without a signal all other status bits are meaningless */
423 return 0;
424 }
425
Michael Krufky1963c902005-08-08 09:22:43 -0700426 /*
427 * You must set the Mask bits to 1 in the IRQ_MASK in order
428 * to see that status bit in the IRQ_STATUS register.
429 * This is done in SwReset();
430 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700431 /* signal status */
Michael Krufky1963c902005-08-08 09:22:43 -0700432 i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700433 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 -0700434
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700435
436 /* sync status */
437 if ((buf[2] & 0x03) == 0x01) {
438 *status |= FE_HAS_SYNC;
439 }
440
441 /* FEC error status */
442 if ((buf[2] & 0x0c) == 0x08) {
443 *status |= FE_HAS_LOCK;
444 *status |= FE_HAS_VITERBI;
445 }
446
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700447 /* Carrier Recovery Lock Status Register */
Michael Krufky1963c902005-08-08 09:22:43 -0700448 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700449 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
450 switch (state->current_modulation) {
451 case QAM_256:
452 case QAM_64:
453 /* Need to undestand why there are 3 lock levels here */
454 if ((buf[0] & 0x07) == 0x07)
455 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700456 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700457 case VSB_8:
458 if ((buf[0] & 0x80) == 0x80)
459 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700460 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700461 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700462 printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700463 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700464
465 return 0;
466}
467
Michael Krufky1963c902005-08-08 09:22:43 -0700468static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700469{
Michael Krufky1963c902005-08-08 09:22:43 -0700470 struct lgdt330x_state* state = fe->demodulator_priv;
471 int err;
472 u8 buf[3];
473
474 *status = 0; /* Reset status result */
475
476 /* lgdt3303 AGC status register */
477 err = i2c_read_demod_bytes(state, 0x58, buf, 1);
478 if (err < 0)
479 return err;
480
481 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
482 if ((buf[0] & 0x21) == 0x01){
483 /* Test input signal does not exist flag */
484 /* as well as the AGC lock flag. */
485 *status |= FE_HAS_SIGNAL;
486 } else {
487 /* Without a signal all other status bits are meaningless */
488 return 0;
489 }
490
491 /* Carrier Recovery Lock Status Register */
492 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
493 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
494 switch (state->current_modulation) {
495 case QAM_256:
496 case QAM_64:
497 /* Need to undestand why there are 3 lock levels here */
498 if ((buf[0] & 0x07) == 0x07)
499 *status |= FE_HAS_CARRIER;
500 else
501 break;
502 i2c_read_demod_bytes(state, 0x8a, buf, 1);
503 if ((buf[0] & 0x04) == 0x04)
504 *status |= FE_HAS_SYNC;
505 if ((buf[0] & 0x01) == 0x01)
506 *status |= FE_HAS_LOCK;
507 if ((buf[0] & 0x08) == 0x08)
508 *status |= FE_HAS_VITERBI;
509 break;
510 case VSB_8:
511 if ((buf[0] & 0x80) == 0x80)
512 *status |= FE_HAS_CARRIER;
513 else
514 break;
515 i2c_read_demod_bytes(state, 0x38, buf, 1);
516 if ((buf[0] & 0x02) == 0x00)
517 *status |= FE_HAS_SYNC;
518 if ((buf[0] & 0x01) == 0x01) {
519 *status |= FE_HAS_LOCK;
520 *status |= FE_HAS_VITERBI;
521 }
522 break;
523 default:
524 printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
525 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700526 return 0;
527}
528
Michael Krufky1963c902005-08-08 09:22:43 -0700529static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
530{
531 /* not directly available. */
532 *strength = 0;
533 return 0;
534}
535
536static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700537{
538#ifdef SNR_IN_DB
539 /*
540 * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
541 * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
542 * respectively. The following tables are built on these formulas.
543 * The usual definition is SNR = 20 log10(signal/noise)
544 * If the specification is wrong the value retuned is 1/2 the actual SNR in db.
545 *
546 * This table is a an ordered list of noise values computed by the
547 * formula from the spec sheet such that the index into the table
548 * starting at 43 or 45 is the SNR value in db. There are duplicate noise
549 * value entries at the beginning because the SNR varies more than
550 * 1 db for a change of 1 digit in noise at very small values of noise.
551 *
552 * Examples from SNR_EQ table:
553 * noise SNR
554 * 0 43
555 * 1 42
556 * 2 39
557 * 3 37
558 * 4 36
559 * 5 35
560 * 6 34
561 * 7 33
562 * 8 33
563 * 9 32
564 * 10 32
565 * 11 31
566 * 12 31
567 * 13 30
568 */
569
570 static const u32 SNR_EQ[] =
571 { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7,
572 9, 11, 13, 17, 21, 26, 33, 41, 52, 65,
573 81, 102, 129, 162, 204, 257, 323, 406, 511, 644,
574 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433,
575 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323,
576 80978, 101945, 128341, 161571, 203406, 256073, 0x40000
577 };
578
579 static const u32 SNR_PH[] =
580 { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8,
581 10, 12, 15, 19, 23, 29, 37, 46, 58, 73,
582 91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
583 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
584 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
Michael Krufky1963c902005-08-08 09:22:43 -0700585 90833, 114351, 143960, 181235, 228161, 0x080000
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700586 };
587
588 static u8 buf[5];/* read data buffer */
589 static u32 noise; /* noise value */
590 static u32 snr_db; /* index into SNR_EQ[] */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700591 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700592
Michael Krufky1963c902005-08-08 09:22:43 -0700593 /* read both equalizer and phase tracker noise data */
594 i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700595
596 if (state->current_modulation == VSB_8) {
597 /* Equalizer Mean-Square Error Register for VSB */
598 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
599
600 /*
601 * Look up noise value in table.
602 * A better search algorithm could be used...
603 * watch out there are duplicate entries.
604 */
605 for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
606 if (noise < SNR_EQ[snr_db]) {
607 *snr = 43 - snr_db;
608 break;
609 }
610 }
611 } else {
612 /* Phase Tracker Mean-Square Error Register for QAM */
613 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
614
615 /* Look up noise value in table. */
616 for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
617 if (noise < SNR_PH[snr_db]) {
618 *snr = 45 - snr_db;
619 break;
620 }
621 }
622 }
623#else
624 /* Return the raw noise value */
625 static u8 buf[5];/* read data buffer */
626 static u32 noise; /* noise value */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700627 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700628
629 /* read both equalizer and pase tracker noise data */
Michael Krufky1963c902005-08-08 09:22:43 -0700630 i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700631
632 if (state->current_modulation == VSB_8) {
Michael Krufky1963c902005-08-08 09:22:43 -0700633 /* Phase Tracker Mean-Square Error Register for VSB */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700634 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
Michael Krufky1963c902005-08-08 09:22:43 -0700635 } else {
636
637 /* Carrier Recovery Mean-Square Error for QAM */
638 i2c_read_demod_bytes(state, 0x1a, buf, 2);
639 noise = ((buf[0] & 3) << 8) | buf[1];
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700640 }
641
642 /* Small values for noise mean signal is better so invert noise */
Michael Krufky1963c902005-08-08 09:22:43 -0700643 *snr = ~noise;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700644#endif
645
646 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
647
648 return 0;
649}
650
Michael Krufky1963c902005-08-08 09:22:43 -0700651static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
652{
653 /* Return the raw noise value */
654 static u8 buf[5];/* read data buffer */
655 static u32 noise; /* noise value */
656 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
657
658 if (state->current_modulation == VSB_8) {
659
660 /* Phase Tracker Mean-Square Error Register for VSB */
661 noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
662 } else {
663
664 /* Carrier Recovery Mean-Square Error for QAM */
665 i2c_read_demod_bytes(state, 0x1a, buf, 2);
666 noise = (buf[0] << 8) | buf[1];
667 }
668
669 /* Small values for noise mean signal is better so invert noise */
670 *snr = ~noise;
671
672 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
673
674 return 0;
675}
676
Michael Krufky6ddcc912005-07-27 11:46:00 -0700677static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700678{
679 /* I have no idea about this - it may not be needed */
680 fe_tune_settings->min_delay_ms = 500;
681 fe_tune_settings->step_size = 0;
682 fe_tune_settings->max_drift = 0;
683 return 0;
684}
685
Michael Krufky6ddcc912005-07-27 11:46:00 -0700686static void lgdt330x_release(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700687{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700688 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700689 kfree(state);
690}
691
Michael Krufky1963c902005-08-08 09:22:43 -0700692static struct dvb_frontend_ops lgdt3302_ops;
693static struct dvb_frontend_ops lgdt3303_ops;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700694
Michael Krufky6ddcc912005-07-27 11:46:00 -0700695struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700696 struct i2c_adapter* i2c)
697{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700698 struct lgdt330x_state* state = NULL;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700699 u8 buf[1];
700
701 /* Allocate memory for the internal state */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700702 state = (struct lgdt330x_state*) kmalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700703 if (state == NULL)
704 goto error;
705 memset(state,0,sizeof(*state));
706
707 /* Setup the state */
708 state->config = config;
709 state->i2c = i2c;
Michael Krufky1963c902005-08-08 09:22:43 -0700710 switch (config->demod_chip) {
711 case LGDT3302:
712 memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
713 break;
714 case LGDT3303:
715 memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
716 break;
717 default:
718 goto error;
719 }
720
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700721 /* Verify communication with demod chip */
Michael Krufky1963c902005-08-08 09:22:43 -0700722 if (i2c_read_demod_bytes(state, 2, buf, 1))
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700723 goto error;
724
725 state->current_frequency = -1;
726 state->current_modulation = -1;
727
728 /* Create dvb_frontend */
729 state->frontend.ops = &state->ops;
730 state->frontend.demodulator_priv = state;
731 return &state->frontend;
732
733error:
734 if (state)
735 kfree(state);
736 dprintk("%s: ERROR\n",__FUNCTION__);
737 return NULL;
738}
739
Michael Krufky1963c902005-08-08 09:22:43 -0700740static struct dvb_frontend_ops lgdt3302_ops = {
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700741 .info = {
Michael Krufkye179d8b2005-08-09 17:48:54 -0700742 .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700743 .type = FE_ATSC,
744 .frequency_min= 54000000,
745 .frequency_max= 858000000,
746 .frequency_stepsize= 62500,
747 /* Symbol rate is for all VSB modes need to check QAM */
748 .symbol_rate_min = 10762000,
749 .symbol_rate_max = 10762000,
750 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
751 },
Michael Krufky6ddcc912005-07-27 11:46:00 -0700752 .init = lgdt330x_init,
753 .set_frontend = lgdt330x_set_parameters,
754 .get_frontend = lgdt330x_get_frontend,
755 .get_tune_settings = lgdt330x_get_tune_settings,
Michael Krufky1963c902005-08-08 09:22:43 -0700756 .read_status = lgdt3302_read_status,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700757 .read_ber = lgdt330x_read_ber,
758 .read_signal_strength = lgdt330x_read_signal_strength,
Michael Krufky1963c902005-08-08 09:22:43 -0700759 .read_snr = lgdt3302_read_snr,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700760 .read_ucblocks = lgdt330x_read_ucblocks,
761 .release = lgdt330x_release,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700762};
763
Michael Krufky1963c902005-08-08 09:22:43 -0700764static struct dvb_frontend_ops lgdt3303_ops = {
765 .info = {
766 .name= "LG Electronics LGDT3303 VSB/QAM Frontend",
767 .type = FE_ATSC,
768 .frequency_min= 54000000,
769 .frequency_max= 858000000,
770 .frequency_stepsize= 62500,
771 /* Symbol rate is for all VSB modes need to check QAM */
772 .symbol_rate_min = 10762000,
773 .symbol_rate_max = 10762000,
774 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
775 },
776 .init = lgdt330x_init,
777 .set_frontend = lgdt330x_set_parameters,
778 .get_frontend = lgdt330x_get_frontend,
779 .get_tune_settings = lgdt330x_get_tune_settings,
780 .read_status = lgdt3303_read_status,
781 .read_ber = lgdt330x_read_ber,
782 .read_signal_strength = lgdt330x_read_signal_strength,
783 .read_snr = lgdt3303_read_snr,
784 .read_ucblocks = lgdt330x_read_ucblocks,
785 .release = lgdt330x_release,
786};
787
788MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700789MODULE_AUTHOR("Wilson Michaels");
790MODULE_LICENSE("GPL");
791
Michael Krufky6ddcc912005-07-27 11:46:00 -0700792EXPORT_SYMBOL(lgdt330x_attach);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700793
794/*
795 * Local variables:
796 * c-basic-offset: 8
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700797 * End:
798 */