blob: db3ef58dafba4bad96a89fe6b3e9e9dd52fe80e1 [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
Michael Krufkyd8e6acf2006-01-09 15:32:42 -020030 * DViCO FusionHDTV 5 USB Gold
Michael Krufkyc0b11b92005-11-08 21:35:32 -080031 * Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
Michael Krufky20fe4f652006-04-10 09:40:40 -030032 * pcHDTV HD5500
Mac Michaelsd8667cb2005-07-07 17:58:29 -070033 *
Mac Michaelsd8667cb2005-07-07 17:58:29 -070034 */
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"
Trent Piepho19be6852006-10-29 13:35:39 -030046#include "dvb_math.h"
Michael Krufky6ddcc912005-07-27 11:46:00 -070047#include "lgdt330x_priv.h"
48#include "lgdt330x.h"
Mac Michaelsd8667cb2005-07-07 17:58:29 -070049
Trent Piepho19be6852006-10-29 13:35:39 -030050/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
51/* #define USE_EQMSE */
52
Mac Michaelsd8667cb2005-07-07 17:58:29 -070053static int debug = 0;
54module_param(debug, int, 0644);
Michael Krufky6ddcc912005-07-27 11:46:00 -070055MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
Mac Michaelsd8667cb2005-07-07 17:58:29 -070056#define dprintk(args...) \
57do { \
Michael Krufky6ddcc912005-07-27 11:46:00 -070058if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
Mac Michaelsd8667cb2005-07-07 17:58:29 -070059} while (0)
60
Michael Krufky6ddcc912005-07-27 11:46:00 -070061struct lgdt330x_state
Mac Michaelsd8667cb2005-07-07 17:58:29 -070062{
63 struct i2c_adapter* i2c;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070064
65 /* Configuration settings */
Michael Krufky6ddcc912005-07-27 11:46:00 -070066 const struct lgdt330x_config* config;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070067
68 struct dvb_frontend frontend;
69
70 /* Demodulator private data */
71 fe_modulation_t current_modulation;
Trent Piepho19be6852006-10-29 13:35:39 -030072 u32 snr; /* Result of last SNR calculation */
Mac Michaelsd8667cb2005-07-07 17:58:29 -070073
74 /* Tuner private data */
75 u32 current_frequency;
76};
77
Michael Krufky1963c902005-08-08 09:22:43 -070078static int i2c_write_demod_bytes (struct lgdt330x_state* state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -070079 u8 *buf, /* data bytes to send */
80 int len /* number of bytes to send */ )
Mac Michaelsd8667cb2005-07-07 17:58:29 -070081{
Michael Krufkyb6aef072005-07-27 11:45:54 -070082 struct i2c_msg msg =
Michael Krufky1963c902005-08-08 09:22:43 -070083 { .addr = state->config->demod_address,
84 .flags = 0,
85 .buf = buf,
86 .len = 2 };
Michael Krufkyb6aef072005-07-27 11:45:54 -070087 int i;
Michael Krufky1963c902005-08-08 09:22:43 -070088 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070089
Michael Krufky1963c902005-08-08 09:22:43 -070090 for (i=0; i<len-1; i+=2){
Mac Michaelsd8667cb2005-07-07 17:58:29 -070091 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
Michael Krufky1963c902005-08-08 09:22:43 -070092 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 -070093 if (err < 0)
94 return err;
95 else
96 return -EREMOTEIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070097 }
Michael Krufky1963c902005-08-08 09:22:43 -070098 msg.buf += 2;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070099 }
100 return 0;
101}
Michael Krufkyb6aef072005-07-27 11:45:54 -0700102
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700103/*
104 * This routine writes the register (reg) to the demod bus
105 * then reads the data returned for (len) bytes.
106 */
107
Michael Krufky1963c902005-08-08 09:22:43 -0700108static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700109 enum I2C_REG reg, u8* buf, int len)
110{
111 u8 wr [] = { reg };
112 struct i2c_msg msg [] = {
113 { .addr = state->config->demod_address,
114 .flags = 0, .buf = wr, .len = 1 },
115 { .addr = state->config->demod_address,
116 .flags = I2C_M_RD, .buf = buf, .len = len },
117 };
118 int ret;
119 ret = i2c_transfer(state->i2c, msg, 2);
120 if (ret != 2) {
Michael Krufky6ddcc912005-07-27 11:46:00 -0700121 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 -0700122 } else {
123 ret = 0;
124 }
125 return ret;
126}
127
128/* Software reset */
Michael Krufky1963c902005-08-08 09:22:43 -0700129static int lgdt3302_SwReset(struct lgdt330x_state* state)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700130{
131 u8 ret;
132 u8 reset[] = {
133 IRQ_MASK,
134 0x00 /* bit 6 is active low software reset
135 * bits 5-0 are 1 to mask interrupts */
136 };
137
Michael Krufky1963c902005-08-08 09:22:43 -0700138 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700139 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700140 if (ret == 0) {
Michael Krufky1963c902005-08-08 09:22:43 -0700141
142 /* force reset high (inactive) and unmask interrupts */
143 reset[1] = 0x7f;
144 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700145 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700146 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700147 return ret;
148}
149
Michael Krufky1963c902005-08-08 09:22:43 -0700150static int lgdt3303_SwReset(struct lgdt330x_state* state)
151{
152 u8 ret;
153 u8 reset[] = {
154 0x02,
155 0x00 /* bit 0 is active low software reset */
156 };
157
158 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700159 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700160 if (ret == 0) {
161
162 /* force reset high (inactive) */
163 reset[1] = 0x01;
164 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700165 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700166 }
167 return ret;
168}
169
170static int lgdt330x_SwReset(struct lgdt330x_state* state)
171{
172 switch (state->config->demod_chip) {
173 case LGDT3302:
174 return lgdt3302_SwReset(state);
175 case LGDT3303:
176 return lgdt3303_SwReset(state);
177 default:
178 return -ENODEV;
179 }
180}
181
Michael Krufky6ddcc912005-07-27 11:46:00 -0700182static int lgdt330x_init(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700183{
184 /* Hardware reset is done using gpio[0] of cx23880x chip.
185 * I'd like to do it here, but don't know how to find chip address.
186 * cx88-cards.c arranges for the reset bit to be inactive (high).
187 * Maybe there needs to be a callable function in cx88-core or
188 * the caller of this function needs to do it. */
189
Michael Krufky1963c902005-08-08 09:22:43 -0700190 /*
191 * Array of byte pairs <address, value>
192 * to initialize each different chip
193 */
194 static u8 lgdt3302_init_data[] = {
195 /* Use 50MHz parameter values from spec sheet since xtal is 50 */
196 /* Change the value of NCOCTFV[25:0] of carrier
197 recovery center frequency register */
198 VSB_CARRIER_FREQ0, 0x00,
199 VSB_CARRIER_FREQ1, 0x87,
200 VSB_CARRIER_FREQ2, 0x8e,
201 VSB_CARRIER_FREQ3, 0x01,
202 /* Change the TPCLK pin polarity
203 data is valid on falling clock */
204 DEMUX_CONTROL, 0xfb,
205 /* Change the value of IFBW[11:0] of
206 AGC IF/RF loop filter bandwidth register */
207 AGC_RF_BANDWIDTH0, 0x40,
208 AGC_RF_BANDWIDTH1, 0x93,
209 AGC_RF_BANDWIDTH2, 0x00,
210 /* Change the value of bit 6, 'nINAGCBY' and
211 'NSSEL[1:0] of ACG function control register 2 */
212 AGC_FUNC_CTRL2, 0xc6,
213 /* Change the value of bit 6 'RFFIX'
214 of AGC function control register 3 */
215 AGC_FUNC_CTRL3, 0x40,
216 /* Set the value of 'INLVTHD' register 0x2a/0x2c
217 to 0x7fe */
218 AGC_DELAY0, 0x07,
219 AGC_DELAY2, 0xfe,
220 /* Change the value of IAGCBW[15:8]
Adrian Bunk9aaeded2006-06-30 18:19:55 +0200221 of inner AGC loop filter bandwidth */
Michael Krufky1963c902005-08-08 09:22:43 -0700222 AGC_LOOP_BANDWIDTH0, 0x08,
223 AGC_LOOP_BANDWIDTH1, 0x9a
224 };
225
226 static u8 lgdt3303_init_data[] = {
227 0x4c, 0x14
228 };
229
Michael Krufkyc0b11b92005-11-08 21:35:32 -0800230 static u8 flip_lgdt3303_init_data[] = {
231 0x4c, 0x14,
232 0x87, 0xf3
233 };
234
Michael Krufky1963c902005-08-08 09:22:43 -0700235 struct lgdt330x_state* state = fe->demodulator_priv;
236 char *chip_name;
237 int err;
238
239 switch (state->config->demod_chip) {
240 case LGDT3302:
241 chip_name = "LGDT3302";
242 err = i2c_write_demod_bytes(state, lgdt3302_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700243 sizeof(lgdt3302_init_data));
244 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700245 case LGDT3303:
246 chip_name = "LGDT3303";
Michael Krufkyc0b11b92005-11-08 21:35:32 -0800247 if (state->config->clock_polarity_flip) {
248 err = i2c_write_demod_bytes(state, flip_lgdt3303_init_data,
249 sizeof(flip_lgdt3303_init_data));
250 } else {
251 err = i2c_write_demod_bytes(state, lgdt3303_init_data,
252 sizeof(lgdt3303_init_data));
253 }
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700254 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700255 default:
256 chip_name = "undefined";
257 printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
258 err = -ENODEV;
259 }
260 dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
261 if (err < 0)
262 return err;
263 return lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700264}
265
Michael Krufky6ddcc912005-07-27 11:46:00 -0700266static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700267{
Michael Krufky1963c902005-08-08 09:22:43 -0700268 *ber = 0; /* Not supplied by the demod chips */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700269 return 0;
270}
271
Michael Krufky6ddcc912005-07-27 11:46:00 -0700272static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700273{
Michael Krufky1963c902005-08-08 09:22:43 -0700274 struct lgdt330x_state* state = fe->demodulator_priv;
275 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700276 u8 buf[2];
277
Michael Krufky1963c902005-08-08 09:22:43 -0700278 switch (state->config->demod_chip) {
279 case LGDT3302:
280 err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700281 buf, sizeof(buf));
282 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700283 case LGDT3303:
284 err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700285 buf, sizeof(buf));
286 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700287 default:
288 printk(KERN_WARNING
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700289 "Only LGDT3302 and LGDT3303 are supported chips.\n");
Michael Krufky1963c902005-08-08 09:22:43 -0700290 err = -ENODEV;
291 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700292
293 *ucblocks = (buf[0] << 8) | buf[1];
294 return 0;
295}
296
Michael Krufky6ddcc912005-07-27 11:46:00 -0700297static int lgdt330x_set_parameters(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700298 struct dvb_frontend_parameters *param)
299{
Michael Krufky1963c902005-08-08 09:22:43 -0700300 /*
301 * Array of byte pairs <address, value>
302 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
303 */
304 static u8 lgdt3303_8vsb_44_data[] = {
305 0x04, 0x00,
306 0x0d, 0x40,
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800307 0x0e, 0x87,
308 0x0f, 0x8e,
309 0x10, 0x01,
310 0x47, 0x8b };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700311
Michael Krufky1963c902005-08-08 09:22:43 -0700312 /*
313 * Array of byte pairs <address, value>
314 * to initialize QAM for lgdt3303 chip
315 */
316 static u8 lgdt3303_qam_data[] = {
317 0x04, 0x00,
318 0x0d, 0x00,
319 0x0e, 0x00,
320 0x0f, 0x00,
321 0x10, 0x00,
322 0x51, 0x63,
323 0x47, 0x66,
324 0x48, 0x66,
325 0x4d, 0x1a,
326 0x49, 0x08,
327 0x4a, 0x9b };
328
329 struct lgdt330x_state* state = fe->demodulator_priv;
330
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700331 static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700332
Michael Krufky1963c902005-08-08 09:22:43 -0700333 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700334 /* Change only if we are actually changing the modulation */
335 if (state->current_modulation != param->u.vsb.modulation) {
336 switch(param->u.vsb.modulation) {
337 case VSB_8:
338 dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
339
Michael Krufky1963c902005-08-08 09:22:43 -0700340 /* Select VSB mode */
341 top_ctrl_cfg[1] = 0x03;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700342
343 /* Select ANT connector if supported by card */
344 if (state->config->pll_rf_set)
345 state->config->pll_rf_set(fe, 1);
Michael Krufky1963c902005-08-08 09:22:43 -0700346
347 if (state->config->demod_chip == LGDT3303) {
348 err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700349 sizeof(lgdt3303_8vsb_44_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700350 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700351 break;
352
353 case QAM_64:
354 dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
355
Michael Krufky1963c902005-08-08 09:22:43 -0700356 /* Select QAM_64 mode */
357 top_ctrl_cfg[1] = 0x00;
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
369 case QAM_256:
370 dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
371
Michael Krufky1963c902005-08-08 09:22:43 -0700372 /* Select QAM_256 mode */
373 top_ctrl_cfg[1] = 0x01;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700374
375 /* Select CABLE connector if supported by card */
376 if (state->config->pll_rf_set)
377 state->config->pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700378
379 if (state->config->demod_chip == LGDT3303) {
380 err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
381 sizeof(lgdt3303_qam_data));
382 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700383 break;
384 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700385 printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700386 return -1;
387 }
Michael Krufky1963c902005-08-08 09:22:43 -0700388 /*
389 * select serial or parallel MPEG harware interface
390 * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
391 * Parallel: 0x00
392 */
393 top_ctrl_cfg[1] |= state->config->serial_mpeg;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700394
395 /* Select the requested mode */
Michael Krufky1963c902005-08-08 09:22:43 -0700396 i2c_write_demod_bytes(state, top_ctrl_cfg,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700397 sizeof(top_ctrl_cfg));
398 if (state->config->set_ts_params)
399 state->config->set_ts_params(fe, 0);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700400 state->current_modulation = param->u.vsb.modulation;
401 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700402
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700403 /* Tune to the specified frequency */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300404 if (fe->ops.tuner_ops.set_params) {
405 fe->ops.tuner_ops.set_params(fe, param);
406 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
Andrew de Quincey02269f32006-04-18 17:47:11 -0300407 }
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700408
409 /* Keep track of the new frequency */
Mauro Carvalho Chehab4302c152006-01-09 15:25:22 -0200410 /* FIXME this is the wrong way to do this... */
411 /* The tuner is shared with the video4linux analog API */
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700412 state->current_frequency = param->frequency;
413
Michael Krufky6ddcc912005-07-27 11:46:00 -0700414 lgdt330x_SwReset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700415 return 0;
416}
417
Michael Krufky6ddcc912005-07-27 11:46:00 -0700418static int lgdt330x_get_frontend(struct dvb_frontend* fe,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700419 struct dvb_frontend_parameters* param)
420{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700421 struct lgdt330x_state *state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700422 param->frequency = state->current_frequency;
423 return 0;
424}
425
Michael Krufky1963c902005-08-08 09:22:43 -0700426static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700427{
Michael Krufky1963c902005-08-08 09:22:43 -0700428 struct lgdt330x_state* state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700429 u8 buf[3];
430
431 *status = 0; /* Reset status result */
432
Michael Krufky08d80522005-07-07 17:58:43 -0700433 /* AGC status register */
Michael Krufky1963c902005-08-08 09:22:43 -0700434 i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
Michael Krufky08d80522005-07-07 17:58:43 -0700435 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
436 if ((buf[0] & 0x0c) == 0x8){
437 /* Test signal does not exist flag */
438 /* as well as the AGC lock flag. */
439 *status |= FE_HAS_SIGNAL;
440 } else {
441 /* Without a signal all other status bits are meaningless */
442 return 0;
443 }
444
Michael Krufky1963c902005-08-08 09:22:43 -0700445 /*
446 * You must set the Mask bits to 1 in the IRQ_MASK in order
447 * to see that status bit in the IRQ_STATUS register.
448 * This is done in SwReset();
449 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700450 /* signal status */
Michael Krufky1963c902005-08-08 09:22:43 -0700451 i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700452 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 -0700453
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700454
455 /* sync status */
456 if ((buf[2] & 0x03) == 0x01) {
457 *status |= FE_HAS_SYNC;
458 }
459
460 /* FEC error status */
461 if ((buf[2] & 0x0c) == 0x08) {
462 *status |= FE_HAS_LOCK;
463 *status |= FE_HAS_VITERBI;
464 }
465
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700466 /* Carrier Recovery Lock Status Register */
Michael Krufky1963c902005-08-08 09:22:43 -0700467 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700468 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
469 switch (state->current_modulation) {
470 case QAM_256:
471 case QAM_64:
472 /* Need to undestand why there are 3 lock levels here */
473 if ((buf[0] & 0x07) == 0x07)
474 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700475 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700476 case VSB_8:
477 if ((buf[0] & 0x80) == 0x80)
478 *status |= FE_HAS_CARRIER;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700479 break;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700480 default:
Michael Krufky6ddcc912005-07-27 11:46:00 -0700481 printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700482 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700483
484 return 0;
485}
486
Michael Krufky1963c902005-08-08 09:22:43 -0700487static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700488{
Michael Krufky1963c902005-08-08 09:22:43 -0700489 struct lgdt330x_state* state = fe->demodulator_priv;
490 int err;
491 u8 buf[3];
492
493 *status = 0; /* Reset status result */
494
495 /* lgdt3303 AGC status register */
496 err = i2c_read_demod_bytes(state, 0x58, buf, 1);
497 if (err < 0)
498 return err;
499
500 dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
501 if ((buf[0] & 0x21) == 0x01){
502 /* Test input signal does not exist flag */
503 /* as well as the AGC lock flag. */
504 *status |= FE_HAS_SIGNAL;
505 } else {
506 /* Without a signal all other status bits are meaningless */
507 return 0;
508 }
509
510 /* Carrier Recovery Lock Status Register */
511 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
512 dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
513 switch (state->current_modulation) {
514 case QAM_256:
515 case QAM_64:
516 /* Need to undestand why there are 3 lock levels here */
517 if ((buf[0] & 0x07) == 0x07)
518 *status |= FE_HAS_CARRIER;
519 else
520 break;
521 i2c_read_demod_bytes(state, 0x8a, buf, 1);
522 if ((buf[0] & 0x04) == 0x04)
523 *status |= FE_HAS_SYNC;
524 if ((buf[0] & 0x01) == 0x01)
525 *status |= FE_HAS_LOCK;
526 if ((buf[0] & 0x08) == 0x08)
527 *status |= FE_HAS_VITERBI;
528 break;
529 case VSB_8:
530 if ((buf[0] & 0x80) == 0x80)
531 *status |= FE_HAS_CARRIER;
532 else
533 break;
534 i2c_read_demod_bytes(state, 0x38, buf, 1);
535 if ((buf[0] & 0x02) == 0x00)
536 *status |= FE_HAS_SYNC;
537 if ((buf[0] & 0x01) == 0x01) {
538 *status |= FE_HAS_LOCK;
539 *status |= FE_HAS_VITERBI;
540 }
541 break;
542 default:
543 printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
544 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700545 return 0;
546}
547
Trent Piepho19be6852006-10-29 13:35:39 -0300548/* Calculate SNR estimation (scaled by 2^24)
549
550 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
551 equations from LGDT3303 datasheet. VSB is the same between the '02
552 and '03, so maybe QAM is too? Perhaps someone with a newer datasheet
553 that has QAM information could verify?
554
555 For 8-VSB: (two ways, take your pick)
556 LGDT3302:
557 SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
558 LGDT3303:
559 SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
560 LGDT3302 & LGDT3303:
561 SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one)
562 For 64-QAM:
563 SNR = 10 * log10( 688128 / MSEQAM)
564 For 256-QAM:
565 SNR = 10 * log10( 696320 / MSEQAM)
566
567 We re-write the snr equation as:
568 SNR * 2^24 = 10*(c - intlog10(MSE))
569 Where for 256-QAM, c = log10(696320) * 2^24, and so on. */
570
571static u32 calculate_snr(u32 mse, u32 c)
Michael Krufky1963c902005-08-08 09:22:43 -0700572{
Trent Piepho19be6852006-10-29 13:35:39 -0300573 if (mse == 0) /* No signal */
574 return 0;
575
576 mse = intlog10(mse);
577 if (mse > c) {
578 /* Negative SNR, which is possible, but realisticly the
579 demod will lose lock before the signal gets this bad. The
580 API only allows for unsigned values, so just return 0 */
581 return 0;
582 }
583 return 10*(c - mse);
Michael Krufky1963c902005-08-08 09:22:43 -0700584}
585
586static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700587{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700588 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Trent Piepho19be6852006-10-29 13:35:39 -0300589 u8 buf[5]; /* read data buffer */
590 u32 noise; /* noise value */
591 u32 c; /* per-modulation SNR calculation constant */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700592
Trent Piepho19be6852006-10-29 13:35:39 -0300593 switch(state->current_modulation) {
594 case VSB_8:
595 i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
596#ifdef USE_EQMSE
597 /* Use Equalizer Mean-Square Error Register */
598 /* SNR for ranges from -15.61 to +41.58 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700599 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
Trent Piepho19be6852006-10-29 13:35:39 -0300600 c = 69765745; /* log10(25*24^2)*2^24 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700601#else
Trent Piepho19be6852006-10-29 13:35:39 -0300602 /* Use Phase Tracker Mean-Square Error Register */
603 /* SNR for ranges from -13.11 to +44.08 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700604 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
Trent Piepho19be6852006-10-29 13:35:39 -0300605 c = 73957994; /* log10(25*32^2)*2^24 */
606#endif
607 break;
608 case QAM_64:
609 case QAM_256:
610 i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
Michael Krufky1963c902005-08-08 09:22:43 -0700611 noise = ((buf[0] & 3) << 8) | buf[1];
Trent Piepho19be6852006-10-29 13:35:39 -0300612 c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
613 /* log10(688128)*2^24 and log10(696320)*2^24 */
614 break;
615 default:
616 printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
617 __FUNCTION__);
618 return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700619 }
620
Trent Piepho19be6852006-10-29 13:35:39 -0300621 state->snr = calculate_snr(noise, c);
622 *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700623
Trent Piepho19be6852006-10-29 13:35:39 -0300624 dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
625 state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700626
627 return 0;
628}
629
Michael Krufky1963c902005-08-08 09:22:43 -0700630static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
631{
Michael Krufky1963c902005-08-08 09:22:43 -0700632 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Trent Piepho19be6852006-10-29 13:35:39 -0300633 u8 buf[5]; /* read data buffer */
634 u32 noise; /* noise value */
635 u32 c; /* per-modulation SNR calculation constant */
Michael Krufky1963c902005-08-08 09:22:43 -0700636
Trent Piepho19be6852006-10-29 13:35:39 -0300637 switch(state->current_modulation) {
638 case VSB_8:
639 i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
640#ifdef USE_EQMSE
641 /* Use Equalizer Mean-Square Error Register */
642 /* SNR for ranges from -16.12 to +44.08 */
643 noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
644 c = 73957994; /* log10(25*32^2)*2^24 */
645#else
646 /* Use Phase Tracker Mean-Square Error Register */
647 /* SNR for ranges from -13.11 to +44.08 */
Michael Krufky1963c902005-08-08 09:22:43 -0700648 noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
Trent Piepho19be6852006-10-29 13:35:39 -0300649 c = 73957994; /* log10(25*32^2)*2^24 */
650#endif
651 break;
652 case QAM_64:
653 case QAM_256:
654 i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
Michael Krufky1963c902005-08-08 09:22:43 -0700655 noise = (buf[0] << 8) | buf[1];
Trent Piepho19be6852006-10-29 13:35:39 -0300656 c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
657 /* log10(688128)*2^24 and log10(696320)*2^24 */
658 break;
659 default:
660 printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
661 __FUNCTION__);
662 return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
Michael Krufky1963c902005-08-08 09:22:43 -0700663 }
664
Trent Piepho19be6852006-10-29 13:35:39 -0300665 state->snr = calculate_snr(noise, c);
666 *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
Michael Krufky1963c902005-08-08 09:22:43 -0700667
Trent Piepho19be6852006-10-29 13:35:39 -0300668 dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
669 state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
670
671 return 0;
672}
673
674static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
675{
676 /* Calculate Strength from SNR up to 35dB */
677 /* Even though the SNR can go higher than 35dB, there is some comfort */
678 /* factor in having a range of strong signals that can show at 100% */
679 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
680 u16 snr;
681 int ret;
682
683 ret = fe->ops.read_snr(fe, &snr);
684 if (ret != 0)
685 return ret;
686 /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
687 /* scale the range 0 - 35*2^24 into 0 - 65535 */
688 if (state->snr >= 8960 * 0x10000)
689 *strength = 0xffff;
690 else
691 *strength = state->snr / 8960;
Michael Krufky1963c902005-08-08 09:22:43 -0700692
693 return 0;
694}
695
Michael Krufky6ddcc912005-07-27 11:46:00 -0700696static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700697{
698 /* I have no idea about this - it may not be needed */
699 fe_tune_settings->min_delay_ms = 500;
700 fe_tune_settings->step_size = 0;
701 fe_tune_settings->max_drift = 0;
702 return 0;
703}
704
Michael Krufky6ddcc912005-07-27 11:46:00 -0700705static void lgdt330x_release(struct dvb_frontend* fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700706{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700707 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700708 kfree(state);
709}
710
Michael Krufky1963c902005-08-08 09:22:43 -0700711static struct dvb_frontend_ops lgdt3302_ops;
712static struct dvb_frontend_ops lgdt3303_ops;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700713
Michael Krufky6ddcc912005-07-27 11:46:00 -0700714struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700715 struct i2c_adapter* i2c)
716{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700717 struct lgdt330x_state* state = NULL;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700718 u8 buf[1];
719
720 /* Allocate memory for the internal state */
Panagiotis Issaris74081872006-01-11 19:40:56 -0200721 state = kzalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700722 if (state == NULL)
723 goto error;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700724
725 /* Setup the state */
726 state->config = config;
727 state->i2c = i2c;
Patrick Boettcherdea74862006-05-14 05:01:31 -0300728
729 /* Create dvb_frontend */
Michael Krufky1963c902005-08-08 09:22:43 -0700730 switch (config->demod_chip) {
731 case LGDT3302:
Patrick Boettcherdea74862006-05-14 05:01:31 -0300732 memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
Michael Krufky1963c902005-08-08 09:22:43 -0700733 break;
734 case LGDT3303:
Patrick Boettcherdea74862006-05-14 05:01:31 -0300735 memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
Michael Krufky1963c902005-08-08 09:22:43 -0700736 break;
737 default:
738 goto error;
739 }
Patrick Boettcherdea74862006-05-14 05:01:31 -0300740 state->frontend.demodulator_priv = state;
Michael Krufky1963c902005-08-08 09:22:43 -0700741
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700742 /* Verify communication with demod chip */
Michael Krufky1963c902005-08-08 09:22:43 -0700743 if (i2c_read_demod_bytes(state, 2, buf, 1))
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700744 goto error;
745
746 state->current_frequency = -1;
747 state->current_modulation = -1;
748
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700749 return &state->frontend;
750
751error:
Jesper Juhl2ea75332005-11-07 01:01:31 -0800752 kfree(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700753 dprintk("%s: ERROR\n",__FUNCTION__);
754 return NULL;
755}
756
Michael Krufky1963c902005-08-08 09:22:43 -0700757static struct dvb_frontend_ops lgdt3302_ops = {
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700758 .info = {
Michael Krufkye179d8b2005-08-09 17:48:54 -0700759 .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700760 .type = FE_ATSC,
761 .frequency_min= 54000000,
762 .frequency_max= 858000000,
763 .frequency_stepsize= 62500,
Michael Krufky66944e92005-11-08 21:35:55 -0800764 .symbol_rate_min = 5056941, /* QAM 64 */
765 .symbol_rate_max = 10762000, /* VSB 8 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700766 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
767 },
Michael Krufky6ddcc912005-07-27 11:46:00 -0700768 .init = lgdt330x_init,
769 .set_frontend = lgdt330x_set_parameters,
770 .get_frontend = lgdt330x_get_frontend,
771 .get_tune_settings = lgdt330x_get_tune_settings,
Michael Krufky1963c902005-08-08 09:22:43 -0700772 .read_status = lgdt3302_read_status,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700773 .read_ber = lgdt330x_read_ber,
774 .read_signal_strength = lgdt330x_read_signal_strength,
Michael Krufky1963c902005-08-08 09:22:43 -0700775 .read_snr = lgdt3302_read_snr,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700776 .read_ucblocks = lgdt330x_read_ucblocks,
777 .release = lgdt330x_release,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700778};
779
Michael Krufky1963c902005-08-08 09:22:43 -0700780static struct dvb_frontend_ops lgdt3303_ops = {
781 .info = {
782 .name= "LG Electronics LGDT3303 VSB/QAM Frontend",
783 .type = FE_ATSC,
784 .frequency_min= 54000000,
785 .frequency_max= 858000000,
786 .frequency_stepsize= 62500,
Michael Krufky66944e92005-11-08 21:35:55 -0800787 .symbol_rate_min = 5056941, /* QAM 64 */
788 .symbol_rate_max = 10762000, /* VSB 8 */
Michael Krufky1963c902005-08-08 09:22:43 -0700789 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
790 },
791 .init = lgdt330x_init,
792 .set_frontend = lgdt330x_set_parameters,
793 .get_frontend = lgdt330x_get_frontend,
794 .get_tune_settings = lgdt330x_get_tune_settings,
795 .read_status = lgdt3303_read_status,
796 .read_ber = lgdt330x_read_ber,
797 .read_signal_strength = lgdt330x_read_signal_strength,
798 .read_snr = lgdt3303_read_snr,
799 .read_ucblocks = lgdt330x_read_ucblocks,
800 .release = lgdt330x_release,
801};
802
803MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700804MODULE_AUTHOR("Wilson Michaels");
805MODULE_LICENSE("GPL");
806
Michael Krufky6ddcc912005-07-27 11:46:00 -0700807EXPORT_SYMBOL(lgdt330x_attach);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700808
809/*
810 * Local variables:
811 * c-basic-offset: 8
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700812 * End:
813 */