blob: 145918877d2f7601a1106e732a8614022d14ab3d [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
Michael Krufky3cff00d2005-11-08 21:35:12 -080029 * DViCO FusionHDTV 5 Lite
Mac Michaelsd8667cb2005-07-07 17:58:29 -070030 *
31 * TODO:
Michael Krufky1963c902005-08-08 09:22:43 -070032 * signal strength always returns 0.
Mac Michaelsd8667cb2005-07-07 17:58:29 -070033 *
34 */
35
Mac Michaelsd8667cb2005-07-07 17:58:29 -070036#include <linux/kernel.h>
37#include <linux/module.h>
38#include <linux/moduleparam.h>
39#include <linux/init.h>
40#include <linux/delay.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080041#include <linux/string.h>
42#include <linux/slab.h>
Mac Michaelsd8667cb2005-07-07 17:58:29 -070043#include <asm/byteorder.h>
44
45#include "dvb_frontend.h"
Michael Krufky6ddcc912005-07-27 11:46:00 -070046#include "lgdt330x_priv.h"
47#include "lgdt330x.h"
Mac Michaelsd8667cb2005-07-07 17:58:29 -070048
49static int debug = 0;
50module_param(debug, int, 0644);
Michael Krufky6ddcc912005-07-27 11:46:00 -070051MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
Mac Michaelsd8667cb2005-07-07 17:58:29 -070052#define dprintk(args...) \
53do { \
Michael Krufky6ddcc912005-07-27 11:46:00 -070054if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
Mac Michaelsd8667cb2005-07-07 17:58:29 -070055} while (0)
56
Michael Krufky6ddcc912005-07-27 11:46:00 -070057struct lgdt330x_state
Mac Michaelsd8667cb2005-07-07 17:58:29 -070058{
59 struct i2c_adapter* i2c;
60 struct dvb_frontend_ops ops;
61
62 /* Configuration settings */
Michael Krufky6ddcc912005-07-27 11:46:00 -070063 const struct lgdt330x_config* config;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070064
65 struct dvb_frontend frontend;
66
67 /* Demodulator private data */
68 fe_modulation_t current_modulation;
69
70 /* Tuner private data */
71 u32 current_frequency;
72};
73
Michael Krufky1963c902005-08-08 09:22:43 -070074static int i2c_write_demod_bytes (struct lgdt330x_state* state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -070075 u8 *buf, /* data bytes to send */
76 int len /* number of bytes to send */ )
Mac Michaelsd8667cb2005-07-07 17:58:29 -070077{
Michael Krufkyb6aef072005-07-27 11:45:54 -070078 struct i2c_msg msg =
Michael Krufky1963c902005-08-08 09:22:43 -070079 { .addr = state->config->demod_address,
80 .flags = 0,
81 .buf = buf,
82 .len = 2 };
Michael Krufkyb6aef072005-07-27 11:45:54 -070083 int i;
Michael Krufky1963c902005-08-08 09:22:43 -070084 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070085
Michael Krufky1963c902005-08-08 09:22:43 -070086 for (i=0; i<len-1; i+=2){
Mac Michaelsd8667cb2005-07-07 17:58:29 -070087 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
Michael Krufky1963c902005-08-08 09:22:43 -070088 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 -070089 if (err < 0)
90 return err;
91 else
92 return -EREMOTEIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070093 }
Michael Krufky1963c902005-08-08 09:22:43 -070094 msg.buf += 2;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070095 }
96 return 0;
97}
Michael Krufkyb6aef072005-07-27 11:45:54 -070098
Mac Michaelsd8667cb2005-07-07 17:58:29 -070099/*
100 * This routine writes the register (reg) to the demod bus
101 * then reads the data returned for (len) bytes.
102 */
103
Michael Krufky1963c902005-08-08 09:22:43 -0700104static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700105 enum I2C_REG reg, u8* buf, int len)
106{
107 u8 wr [] = { reg };
108 struct i2c_msg msg [] = {
109 { .addr = state->config->demod_address,
110 .flags = 0, .buf = wr, .len = 1 },
111 { .addr = state->config->demod_address,
112 .flags = I2C_M_RD, .buf = buf, .len = len },
113 };
114 int ret;
115 ret = i2c_transfer(state->i2c, msg, 2);
116 if (ret != 2) {
Michael Krufky6ddcc912005-07-27 11:46:00 -0700117 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 -0700118 } else {
119 ret = 0;
120 }
121 return ret;
122}
123
124/* Software reset */
Michael Krufky1963c902005-08-08 09:22:43 -0700125static int lgdt3302_SwReset(struct lgdt330x_state* state)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700126{
127 u8 ret;
128 u8 reset[] = {
129 IRQ_MASK,
130 0x00 /* bit 6 is active low software reset
131 * bits 5-0 are 1 to mask interrupts */
132 };
133
Michael Krufky1963c902005-08-08 09:22:43 -0700134 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700135 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700136 if (ret == 0) {
Michael Krufky1963c902005-08-08 09:22:43 -0700137
138 /* force reset high (inactive) and unmask interrupts */
139 reset[1] = 0x7f;
140 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700141 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700142 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700143 return ret;
144}
145
Michael Krufky1963c902005-08-08 09:22:43 -0700146static int lgdt3303_SwReset(struct lgdt330x_state* state)
147{
148 u8 ret;
149 u8 reset[] = {
150 0x02,
151 0x00 /* bit 0 is active low software reset */
152 };
153
154 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700155 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700156 if (ret == 0) {
157
158 /* force reset high (inactive) */
159 reset[1] = 0x01;
160 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700161 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700162 }
163 return ret;
164}
165
166static int lgdt330x_SwReset(struct lgdt330x_state* state)
167{
168 switch (state->config->demod_chip) {
169 case LGDT3302:
170 return lgdt3302_SwReset(state);
171 case LGDT3303:
172 return lgdt3303_SwReset(state);
173 default:
174 return -ENODEV;
175 }
176}
177
Michael Krufky6ddcc912005-07-27 11:46:00 -0700178static int lgdt330x_init(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700179{
180 /* Hardware reset is done using gpio[0] of cx23880x chip.
181 * I'd like to do it here, but don't know how to find chip address.
182 * cx88-cards.c arranges for the reset bit to be inactive (high).
183 * Maybe there needs to be a callable function in cx88-core or
184 * the caller of this function needs to do it. */
185
Michael Krufky1963c902005-08-08 09:22:43 -0700186 /*
187 * Array of byte pairs <address, value>
188 * to initialize each different chip
189 */
190 static u8 lgdt3302_init_data[] = {
191 /* Use 50MHz parameter values from spec sheet since xtal is 50 */
192 /* Change the value of NCOCTFV[25:0] of carrier
193 recovery center frequency register */
194 VSB_CARRIER_FREQ0, 0x00,
195 VSB_CARRIER_FREQ1, 0x87,
196 VSB_CARRIER_FREQ2, 0x8e,
197 VSB_CARRIER_FREQ3, 0x01,
198 /* Change the TPCLK pin polarity
199 data is valid on falling clock */
200 DEMUX_CONTROL, 0xfb,
201 /* Change the value of IFBW[11:0] of
202 AGC IF/RF loop filter bandwidth register */
203 AGC_RF_BANDWIDTH0, 0x40,
204 AGC_RF_BANDWIDTH1, 0x93,
205 AGC_RF_BANDWIDTH2, 0x00,
206 /* Change the value of bit 6, 'nINAGCBY' and
207 'NSSEL[1:0] of ACG function control register 2 */
208 AGC_FUNC_CTRL2, 0xc6,
209 /* Change the value of bit 6 'RFFIX'
210 of AGC function control register 3 */
211 AGC_FUNC_CTRL3, 0x40,
212 /* Set the value of 'INLVTHD' register 0x2a/0x2c
213 to 0x7fe */
214 AGC_DELAY0, 0x07,
215 AGC_DELAY2, 0xfe,
216 /* Change the value of IAGCBW[15:8]
217 of inner AGC loop filter bandwith */
218 AGC_LOOP_BANDWIDTH0, 0x08,
219 AGC_LOOP_BANDWIDTH1, 0x9a
220 };
221
222 static u8 lgdt3303_init_data[] = {
223 0x4c, 0x14
224 };
225
226 struct lgdt330x_state* state = fe->demodulator_priv;
227 char *chip_name;
228 int err;
229
230 switch (state->config->demod_chip) {
231 case LGDT3302:
232 chip_name = "LGDT3302";
233 err = i2c_write_demod_bytes(state, lgdt3302_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700234 sizeof(lgdt3302_init_data));
235 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700236 case LGDT3303:
237 chip_name = "LGDT3303";
238 err = i2c_write_demod_bytes(state, lgdt3303_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700239 sizeof(lgdt3303_init_data));
240 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700241 default:
242 chip_name = "undefined";
243 printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
244 err = -ENODEV;
245 }
246 dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
247 if (err < 0)
248 return err;
249 return lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700250}
251
Michael Krufky6ddcc912005-07-27 11:46:00 -0700252static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700253{
Michael Krufky1963c902005-08-08 09:22:43 -0700254 *ber = 0; /* Not supplied by the demod chips */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700255 return 0;
256}
257
Michael Krufky6ddcc912005-07-27 11:46:00 -0700258static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700259{
Michael Krufky1963c902005-08-08 09:22:43 -0700260 struct lgdt330x_state* state = fe->demodulator_priv;
261 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700262 u8 buf[2];
263
Michael Krufky1963c902005-08-08 09:22:43 -0700264 switch (state->config->demod_chip) {
265 case LGDT3302:
266 err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700267 buf, sizeof(buf));
268 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700269 case LGDT3303:
270 err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700271 buf, sizeof(buf));
272 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700273 default:
274 printk(KERN_WARNING
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700275 "Only LGDT3302 and LGDT3303 are supported chips.\n");
Michael Krufky1963c902005-08-08 09:22:43 -0700276 err = -ENODEV;
277 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700278
279 *ucblocks = (buf[0] << 8) | buf[1];
280 return 0;
281}
282
Michael Krufky6ddcc912005-07-27 11:46:00 -0700283static int lgdt330x_set_parameters(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700284 struct dvb_frontend_parameters *param)
285{
Michael Krufky1963c902005-08-08 09:22:43 -0700286 /*
287 * Array of byte pairs <address, value>
288 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
289 */
290 static u8 lgdt3303_8vsb_44_data[] = {
291 0x04, 0x00,
292 0x0d, 0x40,
293 0x0e, 0x87,
294 0x0f, 0x8e,
295 0x10, 0x01,
296 0x47, 0x8b };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700297
Michael Krufky1963c902005-08-08 09:22:43 -0700298 /*
299 * Array of byte pairs <address, value>
300 * to initialize QAM for lgdt3303 chip
301 */
302 static u8 lgdt3303_qam_data[] = {
303 0x04, 0x00,
304 0x0d, 0x00,
305 0x0e, 0x00,
306 0x0f, 0x00,
307 0x10, 0x00,
308 0x51, 0x63,
309 0x47, 0x66,
310 0x48, 0x66,
311 0x4d, 0x1a,
312 0x49, 0x08,
313 0x4a, 0x9b };
314
315 struct lgdt330x_state* state = fe->demodulator_priv;
316
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700317 static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700318
Michael Krufky1963c902005-08-08 09:22:43 -0700319 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700320 /* Change only if we are actually changing the modulation */
321 if (state->current_modulation != param->u.vsb.modulation) {
322 switch(param->u.vsb.modulation) {
323 case VSB_8:
324 dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
325
Michael Krufky1963c902005-08-08 09:22:43 -0700326 /* Select VSB mode */
327 top_ctrl_cfg[1] = 0x03;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700328
329 /* Select ANT connector if supported by card */
330 if (state->config->pll_rf_set)
331 state->config->pll_rf_set(fe, 1);
Michael Krufky1963c902005-08-08 09:22:43 -0700332
333 if (state->config->demod_chip == LGDT3303) {
334 err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700335 sizeof(lgdt3303_8vsb_44_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700336 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700337 break;
338
339 case QAM_64:
340 dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
341
Michael Krufky1963c902005-08-08 09:22:43 -0700342 /* Select QAM_64 mode */
343 top_ctrl_cfg[1] = 0x00;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700344
345 /* Select CABLE connector if supported by card */
346 if (state->config->pll_rf_set)
347 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700348
349 if (state->config->demod_chip == LGDT3303) {
350 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
351 sizeof(lgdt3303_qam_data));
352 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700353 break;
354
355 case QAM_256:
356 dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
357
Michael Krufky1963c902005-08-08 09:22:43 -0700358 /* Select QAM_256 mode */
359 top_ctrl_cfg[1] = 0x01;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700360
361 /* Select CABLE connector if supported by card */
362 if (state->config->pll_rf_set)
363 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700364
365 if (state->config->demod_chip == LGDT3303) {
366 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
367 sizeof(lgdt3303_qam_data));
368 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700369 break;
370 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700371 printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700372 return -1;
373 }
Michael Krufky1963c902005-08-08 09:22:43 -0700374 /*
375 * select serial or parallel MPEG harware interface
376 * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
377 * Parallel: 0x00
378 */
379 top_ctrl_cfg[1] |= state->config->serial_mpeg;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700380
381 /* Select the requested mode */
Michael Krufky1963c902005-08-08 09:22:43 -0700382 i2c_write_demod_bytes(state, top_ctrl_cfg,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700383 sizeof(top_ctrl_cfg));
384 if (state->config->set_ts_params)
385 state->config->set_ts_params(fe, 0);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700386 state->current_modulation = param->u.vsb.modulation;
387 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700388
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700389 /* Tune to the specified frequency */
390 if (state->config->pll_set)
Michael Krufky1963c902005-08-08 09:22:43 -0700391 state->config->pll_set(fe, param);
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700392
393 /* Keep track of the new frequency */
394 state->current_frequency = param->frequency;
395
Michael Krufky6ddcc912005-07-27 11:46:00 -0700396 lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700397 return 0;
398}
399
Michael Krufky6ddcc912005-07-27 11:46:00 -0700400static int lgdt330x_get_frontend(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700401 struct dvb_frontend_parameters* param)
402{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700403 struct lgdt330x_state *state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700404 param->frequency = state->current_frequency;
405 return 0;
406}
407
Michael Krufky1963c902005-08-08 09:22:43 -0700408static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700409{
Michael Krufky1963c902005-08-08 09:22:43 -0700410 struct lgdt330x_state* state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700411 u8 buf[3];
412
413 *status = 0; /* Reset status result */
414
Michael Krufky08d80522005-07-07 17:58:43 -0700415 /* AGC status register */
Michael Krufky1963c902005-08-08 09:22:43 -0700416 i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
Michael Krufky08d80522005-07-07 17:58:43 -0700417 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
418 if ((buf[0] & 0x0c) == 0x8){
419 /* Test signal does not exist flag */
420 /* as well as the AGC lock flag. */
421 *status |= FE_HAS_SIGNAL;
422 } else {
423 /* Without a signal all other status bits are meaningless */
424 return 0;
425 }
426
Michael Krufky1963c902005-08-08 09:22:43 -0700427 /*
428 * You must set the Mask bits to 1 in the IRQ_MASK in order
429 * to see that status bit in the IRQ_STATUS register.
430 * This is done in SwReset();
431 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700432 /* signal status */
Michael Krufky1963c902005-08-08 09:22:43 -0700433 i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700434 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 -0700435
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700436
437 /* sync status */
438 if ((buf[2] & 0x03) == 0x01) {
439 *status |= FE_HAS_SYNC;
440 }
441
442 /* FEC error status */
443 if ((buf[2] & 0x0c) == 0x08) {
444 *status |= FE_HAS_LOCK;
445 *status |= FE_HAS_VITERBI;
446 }
447
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700448 /* Carrier Recovery Lock Status Register */
Michael Krufky1963c902005-08-08 09:22:43 -0700449 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700450 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
451 switch (state->current_modulation) {
452 case QAM_256:
453 case QAM_64:
454 /* Need to undestand why there are 3 lock levels here */
455 if ((buf[0] & 0x07) == 0x07)
456 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700457 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700458 case VSB_8:
459 if ((buf[0] & 0x80) == 0x80)
460 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700461 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700462 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700463 printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700464 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700465
466 return 0;
467}
468
Michael Krufky1963c902005-08-08 09:22:43 -0700469static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700470{
Michael Krufky1963c902005-08-08 09:22:43 -0700471 struct lgdt330x_state* state = fe->demodulator_priv;
472 int err;
473 u8 buf[3];
474
475 *status = 0; /* Reset status result */
476
477 /* lgdt3303 AGC status register */
478 err = i2c_read_demod_bytes(state, 0x58, buf, 1);
479 if (err < 0)
480 return err;
481
482 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
483 if ((buf[0] & 0x21) == 0x01){
484 /* Test input signal does not exist flag */
485 /* as well as the AGC lock flag. */
486 *status |= FE_HAS_SIGNAL;
487 } else {
488 /* Without a signal all other status bits are meaningless */
489 return 0;
490 }
491
492 /* Carrier Recovery Lock Status Register */
493 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
494 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
495 switch (state->current_modulation) {
496 case QAM_256:
497 case QAM_64:
498 /* Need to undestand why there are 3 lock levels here */
499 if ((buf[0] & 0x07) == 0x07)
500 *status |= FE_HAS_CARRIER;
501 else
502 break;
503 i2c_read_demod_bytes(state, 0x8a, buf, 1);
504 if ((buf[0] & 0x04) == 0x04)
505 *status |= FE_HAS_SYNC;
506 if ((buf[0] & 0x01) == 0x01)
507 *status |= FE_HAS_LOCK;
508 if ((buf[0] & 0x08) == 0x08)
509 *status |= FE_HAS_VITERBI;
510 break;
511 case VSB_8:
512 if ((buf[0] & 0x80) == 0x80)
513 *status |= FE_HAS_CARRIER;
514 else
515 break;
516 i2c_read_demod_bytes(state, 0x38, buf, 1);
517 if ((buf[0] & 0x02) == 0x00)
518 *status |= FE_HAS_SYNC;
519 if ((buf[0] & 0x01) == 0x01) {
520 *status |= FE_HAS_LOCK;
521 *status |= FE_HAS_VITERBI;
522 }
523 break;
524 default:
525 printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
526 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700527 return 0;
528}
529
Michael Krufky1963c902005-08-08 09:22:43 -0700530static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
531{
532 /* not directly available. */
533 *strength = 0;
534 return 0;
535}
536
537static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700538{
539#ifdef SNR_IN_DB
540 /*
541 * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
542 * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
543 * respectively. The following tables are built on these formulas.
544 * The usual definition is SNR = 20 log10(signal/noise)
545 * If the specification is wrong the value retuned is 1/2 the actual SNR in db.
546 *
547 * This table is a an ordered list of noise values computed by the
548 * formula from the spec sheet such that the index into the table
549 * starting at 43 or 45 is the SNR value in db. There are duplicate noise
550 * value entries at the beginning because the SNR varies more than
551 * 1 db for a change of 1 digit in noise at very small values of noise.
552 *
553 * Examples from SNR_EQ table:
554 * noise SNR
555 * 0 43
556 * 1 42
557 * 2 39
558 * 3 37
559 * 4 36
560 * 5 35
561 * 6 34
562 * 7 33
563 * 8 33
564 * 9 32
565 * 10 32
566 * 11 31
567 * 12 31
568 * 13 30
569 */
570
571 static const u32 SNR_EQ[] =
572 { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7,
573 9, 11, 13, 17, 21, 26, 33, 41, 52, 65,
574 81, 102, 129, 162, 204, 257, 323, 406, 511, 644,
575 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433,
576 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323,
577 80978, 101945, 128341, 161571, 203406, 256073, 0x40000
578 };
579
580 static const u32 SNR_PH[] =
581 { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8,
582 10, 12, 15, 19, 23, 29, 37, 46, 58, 73,
583 91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
584 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
585 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
Michael Krufky1963c902005-08-08 09:22:43 -0700586 90833, 114351, 143960, 181235, 228161, 0x080000
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700587 };
588
589 static u8 buf[5];/* read data buffer */
590 static u32 noise; /* noise value */
591 static u32 snr_db; /* index into SNR_EQ[] */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700592 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700593
Michael Krufky1963c902005-08-08 09:22:43 -0700594 /* read both equalizer and phase tracker noise data */
595 i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700596
597 if (state->current_modulation == VSB_8) {
598 /* Equalizer Mean-Square Error Register for VSB */
599 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
600
601 /*
602 * Look up noise value in table.
603 * A better search algorithm could be used...
604 * watch out there are duplicate entries.
605 */
606 for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
607 if (noise < SNR_EQ[snr_db]) {
608 *snr = 43 - snr_db;
609 break;
610 }
611 }
612 } else {
613 /* Phase Tracker Mean-Square Error Register for QAM */
614 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
615
616 /* Look up noise value in table. */
617 for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
618 if (noise < SNR_PH[snr_db]) {
619 *snr = 45 - snr_db;
620 break;
621 }
622 }
623 }
624#else
625 /* Return the raw noise value */
626 static u8 buf[5];/* read data buffer */
627 static u32 noise; /* noise value */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700628 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700629
630 /* read both equalizer and pase tracker noise data */
Michael Krufky1963c902005-08-08 09:22:43 -0700631 i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700632
633 if (state->current_modulation == VSB_8) {
Michael Krufky1963c902005-08-08 09:22:43 -0700634 /* Phase Tracker Mean-Square Error Register for VSB */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700635 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
Michael Krufky1963c902005-08-08 09:22:43 -0700636 } else {
637
638 /* Carrier Recovery Mean-Square Error for QAM */
639 i2c_read_demod_bytes(state, 0x1a, buf, 2);
640 noise = ((buf[0] & 3) << 8) | buf[1];
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700641 }
642
643 /* Small values for noise mean signal is better so invert noise */
Michael Krufky1963c902005-08-08 09:22:43 -0700644 *snr = ~noise;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700645#endif
646
647 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
648
649 return 0;
650}
651
Michael Krufky1963c902005-08-08 09:22:43 -0700652static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
653{
654 /* Return the raw noise value */
655 static u8 buf[5];/* read data buffer */
656 static u32 noise; /* noise value */
657 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
658
659 if (state->current_modulation == VSB_8) {
660
661 /* Phase Tracker Mean-Square Error Register for VSB */
662 noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
663 } else {
664
665 /* Carrier Recovery Mean-Square Error for QAM */
666 i2c_read_demod_bytes(state, 0x1a, buf, 2);
667 noise = (buf[0] << 8) | buf[1];
668 }
669
670 /* Small values for noise mean signal is better so invert noise */
671 *snr = ~noise;
672
673 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
674
675 return 0;
676}
677
Michael Krufky6ddcc912005-07-27 11:46:00 -0700678static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700679{
680 /* I have no idea about this - it may not be needed */
681 fe_tune_settings->min_delay_ms = 500;
682 fe_tune_settings->step_size = 0;
683 fe_tune_settings->max_drift = 0;
684 return 0;
685}
686
Michael Krufky6ddcc912005-07-27 11:46:00 -0700687static void lgdt330x_release(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700688{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700689 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700690 kfree(state);
691}
692
Michael Krufky1963c902005-08-08 09:22:43 -0700693static struct dvb_frontend_ops lgdt3302_ops;
694static struct dvb_frontend_ops lgdt3303_ops;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700695
Michael Krufky6ddcc912005-07-27 11:46:00 -0700696struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700697 struct i2c_adapter* i2c)
698{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700699 struct lgdt330x_state* state = NULL;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700700 u8 buf[1];
701
702 /* Allocate memory for the internal state */
Michael Krufky6ddcc912005-07-27 11:46:00 -0700703 state = (struct lgdt330x_state*) kmalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700704 if (state == NULL)
705 goto error;
706 memset(state,0,sizeof(*state));
707
708 /* Setup the state */
709 state->config = config;
710 state->i2c = i2c;
Michael Krufky1963c902005-08-08 09:22:43 -0700711 switch (config->demod_chip) {
712 case LGDT3302:
713 memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
714 break;
715 case LGDT3303:
716 memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
717 break;
718 default:
719 goto error;
720 }
721
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700722 /* Verify communication with demod chip */
Michael Krufky1963c902005-08-08 09:22:43 -0700723 if (i2c_read_demod_bytes(state, 2, buf, 1))
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700724 goto error;
725
726 state->current_frequency = -1;
727 state->current_modulation = -1;
728
729 /* Create dvb_frontend */
730 state->frontend.ops = &state->ops;
731 state->frontend.demodulator_priv = state;
732 return &state->frontend;
733
734error:
Jesper Juhl2ea75332005-11-07 01:01:31 -0800735 kfree(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700736 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 */