blob: f6731738b07313c317e0badf7be94c9ab49ddae1 [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 *
Mac Michaelsd8667cb2005-07-07 17:58:29 -070016 */
17
18/*
19 * NOTES ABOUT THIS DRIVER
20 *
Michael Krufky1963c902005-08-08 09:22:43 -070021 * This Linux driver supports:
22 * DViCO FusionHDTV 3 Gold-Q
23 * DViCO FusionHDTV 3 Gold-T
24 * DViCO FusionHDTV 5 Gold
Michael Krufky3cff00d2005-11-08 21:35:12 -080025 * DViCO FusionHDTV 5 Lite
Michael Krufkyd8e6acf2006-01-09 15:32:42 -020026 * DViCO FusionHDTV 5 USB Gold
Michael Krufkyc0b11b92005-11-08 21:35:32 -080027 * Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
Michael Krufky20fe4f652006-04-10 09:40:40 -030028 * pcHDTV HD5500
Mac Michaelsd8667cb2005-07-07 17:58:29 -070029 *
Mac Michaelsd8667cb2005-07-07 17:58:29 -070030 */
31
Mac Michaelsd8667cb2005-07-07 17:58:29 -070032#include <linux/kernel.h>
33#include <linux/module.h>
Mac Michaelsd8667cb2005-07-07 17:58:29 -070034#include <linux/init.h>
35#include <linux/delay.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080036#include <linux/string.h>
37#include <linux/slab.h>
Mac Michaelsd8667cb2005-07-07 17:58:29 -070038#include <asm/byteorder.h>
39
Mauro Carvalho Chehabfada1932017-12-28 13:03:51 -050040#include <media/dvb_frontend.h>
41#include <media/dvb_math.h>
Michael Krufky6ddcc912005-07-27 11:46:00 -070042#include "lgdt330x_priv.h"
43#include "lgdt330x.h"
Mac Michaelsd8667cb2005-07-07 17:58:29 -070044
Trent Piepho19be6852006-10-29 13:35:39 -030045/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
46/* #define USE_EQMSE */
47
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030048static int debug;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070049module_param(debug, int, 0644);
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050050MODULE_PARM_DESC(debug, "Turn on/off lgdt330x frontend debugging (default:off).");
Mauro Carvalho Chehab6752c792018-03-09 10:53:28 -050051
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050052#define dprintk(state, fmt, arg...) do { \
Mauro Carvalho Chehab6752c792018-03-09 10:53:28 -050053 if (debug) \
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050054 dev_printk(KERN_DEBUG, &state->client->dev, fmt, ##arg);\
Mac Michaelsd8667cb2005-07-07 17:58:29 -070055} while (0)
56
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050057struct lgdt330x_state {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050058 struct i2c_client *client;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070059
60 /* Configuration settings */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050061 struct lgdt330x_config config;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070062
63 struct dvb_frontend frontend;
64
65 /* Demodulator private data */
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -030066 enum fe_modulation current_modulation;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -050067 u32 snr; /* Result of last SNR calculation */
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -050068 u16 ucblocks;
69 unsigned long last_stats_time;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070070
71 /* Tuner private data */
72 u32 current_frequency;
73};
74
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050075static int i2c_write_demod_bytes(struct lgdt330x_state *state,
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050076 const u8 *buf, /* data bytes to send */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050077 int len /* number of bytes to send */)
Mac Michaelsd8667cb2005-07-07 17:58:29 -070078{
Michael Krufkyb6aef072005-07-27 11:45:54 -070079 int i;
Michael Krufky1963c902005-08-08 09:22:43 -070080 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070081
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050082 for (i = 0; i < len - 1; i += 2) {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050083 err = i2c_master_send(state->client, buf, 2);
84 if (err != 2) {
85 dev_warn(&state->client->dev,
86 "%s: error (addr %02x <- %02x, err = %i)\n",
87 __func__, buf[0], 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 }
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050093 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 */
Xi Wang34817172012-02-14 14:32:41 -0300102static int i2c_read_demod_bytes(struct lgdt330x_state *state,
103 enum I2C_REG reg, u8 *buf, int len)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700104{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500105 u8 wr[] = { reg };
106 struct i2c_msg msg[] = {
107 {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500108 .addr = state->client->addr,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500109 .flags = 0,
110 .buf = wr,
111 .len = 1
112 }, {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500113 .addr = state->client->addr,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500114 .flags = I2C_M_RD,
115 .buf = buf,
116 .len = len
117 },
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700118 };
119 int ret;
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500120
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500121 ret = i2c_transfer(state->client->adapter, msg, 2);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700122 if (ret != 2) {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500123 dev_warn(&state->client->dev,
124 "%s: addr 0x%02x select 0x%02x error (ret == %i)\n",
125 __func__, state->client->addr, reg, ret);
Xi Wang34817172012-02-14 14:32:41 -0300126 if (ret >= 0)
127 ret = -EIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700128 } else {
129 ret = 0;
130 }
131 return ret;
132}
133
134/* Software reset */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500135static int lgdt3302_sw_reset(struct lgdt330x_state *state)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700136{
137 u8 ret;
138 u8 reset[] = {
139 IRQ_MASK,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500140 /*
141 * bit 6 is active low software reset
142 * bits 5-0 are 1 to mask interrupts
143 */
144 0x00
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700145 };
146
Michael Krufky1963c902005-08-08 09:22:43 -0700147 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700148 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700149 if (ret == 0) {
Michael Krufky1963c902005-08-08 09:22:43 -0700150 /* force reset high (inactive) and unmask interrupts */
151 reset[1] = 0x7f;
152 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700153 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700154 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700155 return ret;
156}
157
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500158static int lgdt3303_sw_reset(struct lgdt330x_state *state)
Michael Krufky1963c902005-08-08 09:22:43 -0700159{
160 u8 ret;
161 u8 reset[] = {
162 0x02,
163 0x00 /* bit 0 is active low software reset */
164 };
165
166 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700167 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700168 if (ret == 0) {
Michael Krufky1963c902005-08-08 09:22:43 -0700169 /* force reset high (inactive) */
170 reset[1] = 0x01;
171 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700172 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700173 }
174 return ret;
175}
176
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500177static int lgdt330x_sw_reset(struct lgdt330x_state *state)
Michael Krufky1963c902005-08-08 09:22:43 -0700178{
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500179 switch (state->config.demod_chip) {
Michael Krufky1963c902005-08-08 09:22:43 -0700180 case LGDT3302:
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500181 return lgdt3302_sw_reset(state);
Michael Krufky1963c902005-08-08 09:22:43 -0700182 case LGDT3303:
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500183 return lgdt3303_sw_reset(state);
Michael Krufky1963c902005-08-08 09:22:43 -0700184 default:
185 return -ENODEV;
186 }
187}
188
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500189static int lgdt330x_init(struct dvb_frontend *fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700190{
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500191 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500192 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500193 char *chip_name;
194 int err;
Michael Krufky1963c902005-08-08 09:22:43 -0700195 /*
196 * Array of byte pairs <address, value>
197 * to initialize each different chip
198 */
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500199 static const u8 lgdt3302_init_data[] = {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500200 /* Use 50MHz param values from spec sheet since xtal is 50 */
201 /*
202 * Change the value of NCOCTFV[25:0] of carrier
203 * recovery center frequency register
204 */
Michael Krufky1963c902005-08-08 09:22:43 -0700205 VSB_CARRIER_FREQ0, 0x00,
206 VSB_CARRIER_FREQ1, 0x87,
207 VSB_CARRIER_FREQ2, 0x8e,
208 VSB_CARRIER_FREQ3, 0x01,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500209 /*
210 * Change the TPCLK pin polarity
211 * data is valid on falling clock
212 */
Michael Krufky1963c902005-08-08 09:22:43 -0700213 DEMUX_CONTROL, 0xfb,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500214 /*
215 * Change the value of IFBW[11:0] of
216 * AGC IF/RF loop filter bandwidth register
217 */
Michael Krufky1963c902005-08-08 09:22:43 -0700218 AGC_RF_BANDWIDTH0, 0x40,
219 AGC_RF_BANDWIDTH1, 0x93,
220 AGC_RF_BANDWIDTH2, 0x00,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500221 /*
222 * Change the value of bit 6, 'nINAGCBY' and
223 * 'NSSEL[1:0] of ACG function control register 2
224 */
Michael Krufky1963c902005-08-08 09:22:43 -0700225 AGC_FUNC_CTRL2, 0xc6,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500226 /*
227 * Change the value of bit 6 'RFFIX'
228 * of AGC function control register 3
229 */
Michael Krufky1963c902005-08-08 09:22:43 -0700230 AGC_FUNC_CTRL3, 0x40,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500231 /*
232 * Set the value of 'INLVTHD' register 0x2a/0x2c
233 * to 0x7fe
234 */
Michael Krufky1963c902005-08-08 09:22:43 -0700235 AGC_DELAY0, 0x07,
236 AGC_DELAY2, 0xfe,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500237 /*
238 * Change the value of IAGCBW[15:8]
239 * of inner AGC loop filter bandwidth
240 */
Michael Krufky1963c902005-08-08 09:22:43 -0700241 AGC_LOOP_BANDWIDTH0, 0x08,
242 AGC_LOOP_BANDWIDTH1, 0x9a
243 };
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500244 static const u8 lgdt3303_init_data[] = {
Michael Krufky1963c902005-08-08 09:22:43 -0700245 0x4c, 0x14
246 };
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500247 static const u8 flip_1_lgdt3303_init_data[] = {
Michael Krufkyc0b11b92005-11-08 21:35:32 -0800248 0x4c, 0x14,
249 0x87, 0xf3
250 };
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500251 static const u8 flip_2_lgdt3303_init_data[] = {
Michael Krufkyc0f4c0a2008-06-28 02:06:50 -0300252 0x4c, 0x14,
253 0x87, 0xda
254 };
255
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500256 /*
257 * Hardware reset is done using gpio[0] of cx23880x chip.
258 * I'd like to do it here, but don't know how to find chip address.
259 * cx88-cards.c arranges for the reset bit to be inactive (high).
260 * Maybe there needs to be a callable function in cx88-core or
261 * the caller of this function needs to do it.
262 */
Michael Krufky1963c902005-08-08 09:22:43 -0700263
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500264 switch (state->config.demod_chip) {
Michael Krufky1963c902005-08-08 09:22:43 -0700265 case LGDT3302:
266 chip_name = "LGDT3302";
267 err = i2c_write_demod_bytes(state, lgdt3302_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700268 sizeof(lgdt3302_init_data));
269 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700270 case LGDT3303:
271 chip_name = "LGDT3303";
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500272 switch (state->config.clock_polarity_flip) {
Michael Krufkyc0f4c0a2008-06-28 02:06:50 -0300273 case 2:
274 err = i2c_write_demod_bytes(state,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500275 flip_2_lgdt3303_init_data,
276 sizeof(flip_2_lgdt3303_init_data));
Michael Krufkyc0f4c0a2008-06-28 02:06:50 -0300277 break;
278 case 1:
279 err = i2c_write_demod_bytes(state,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500280 flip_1_lgdt3303_init_data,
281 sizeof(flip_1_lgdt3303_init_data));
Michael Krufkyc0f4c0a2008-06-28 02:06:50 -0300282 break;
283 case 0:
284 default:
Michael Krufkyc0b11b92005-11-08 21:35:32 -0800285 err = i2c_write_demod_bytes(state, lgdt3303_init_data,
286 sizeof(lgdt3303_init_data));
287 }
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700288 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700289 default:
290 chip_name = "undefined";
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500291 dev_warn(&state->client->dev,
292 "Only LGDT3302 and LGDT3303 are supported chips.\n");
Michael Krufky1963c902005-08-08 09:22:43 -0700293 err = -ENODEV;
294 }
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500295 dprintk(state, "Initialized the %s chip\n", chip_name);
Michael Krufky1963c902005-08-08 09:22:43 -0700296 if (err < 0)
297 return err;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500298
299 p->cnr.len = 1;
300 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500301 p->block_error.len = 1;
302 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
303 p->block_count.len = 1;
304 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
305 state->last_stats_time = 0;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500306
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500307 return lgdt330x_sw_reset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700308}
309
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500310static int lgdt330x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700311{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500312 struct lgdt330x_state *state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700313
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500314 *ucblocks = state->ucblocks;
Michael Krufky26110da2011-12-15 10:16:09 -0300315
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700316 return 0;
317}
318
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300319static int lgdt330x_set_parameters(struct dvb_frontend *fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700320{
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300321 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500322 struct lgdt330x_state *state = fe->demodulator_priv;
Michael Krufky1963c902005-08-08 09:22:43 -0700323 /*
324 * Array of byte pairs <address, value>
325 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
326 */
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500327 static const u8 lgdt3303_8vsb_44_data[] = {
Michael Krufky1963c902005-08-08 09:22:43 -0700328 0x04, 0x00,
329 0x0d, 0x40,
Michael Krufky0b6389f2006-11-28 02:35:02 -0300330 0x0e, 0x87,
331 0x0f, 0x8e,
332 0x10, 0x01,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500333 0x47, 0x8b
334 };
Michael Krufky1963c902005-08-08 09:22:43 -0700335 /*
336 * Array of byte pairs <address, value>
337 * to initialize QAM for lgdt3303 chip
338 */
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500339 static const u8 lgdt3303_qam_data[] = {
Michael Krufky1963c902005-08-08 09:22:43 -0700340 0x04, 0x00,
341 0x0d, 0x00,
342 0x0e, 0x00,
343 0x0f, 0x00,
344 0x10, 0x00,
345 0x51, 0x63,
346 0x47, 0x66,
347 0x48, 0x66,
348 0x4d, 0x1a,
349 0x49, 0x08,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500350 0x4a, 0x9b
351 };
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500352 u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700353
Michael Krufky54828d12011-12-15 10:30:38 -0300354 int err = 0;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700355 /* Change only if we are actually changing the modulation */
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300356 if (state->current_modulation != p->modulation) {
357 switch (p->modulation) {
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700358 case VSB_8:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500359 dprintk(state, "VSB_8 MODE\n");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700360
Michael Krufky1963c902005-08-08 09:22:43 -0700361 /* Select VSB mode */
362 top_ctrl_cfg[1] = 0x03;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700363
364 /* Select ANT connector if supported by card */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500365 if (state->config.pll_rf_set)
366 state->config.pll_rf_set(fe, 1);
Michael Krufky1963c902005-08-08 09:22:43 -0700367
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500368 if (state->config.demod_chip == LGDT3303) {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500369 err = i2c_write_demod_bytes(state,
370 lgdt3303_8vsb_44_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700371 sizeof(lgdt3303_8vsb_44_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700372 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700373 break;
374
375 case QAM_64:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500376 dprintk(state, "QAM_64 MODE\n");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700377
Michael Krufky1963c902005-08-08 09:22:43 -0700378 /* Select QAM_64 mode */
379 top_ctrl_cfg[1] = 0x00;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700380
381 /* Select CABLE connector if supported by card */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500382 if (state->config.pll_rf_set)
383 state->config.pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700384
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500385 if (state->config.demod_chip == LGDT3303) {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500386 err = i2c_write_demod_bytes(state,
387 lgdt3303_qam_data,
388 sizeof(lgdt3303_qam_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700389 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700390 break;
391
392 case QAM_256:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500393 dprintk(state, "QAM_256 MODE\n");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700394
Michael Krufky1963c902005-08-08 09:22:43 -0700395 /* Select QAM_256 mode */
396 top_ctrl_cfg[1] = 0x01;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700397
398 /* Select CABLE connector if supported by card */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500399 if (state->config.pll_rf_set)
400 state->config.pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700401
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500402 if (state->config.demod_chip == LGDT3303) {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500403 err = i2c_write_demod_bytes(state,
404 lgdt3303_qam_data,
405 sizeof(lgdt3303_qam_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700406 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700407 break;
408 default:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500409 dev_warn(&state->client->dev,
410 "%s: Modulation type(%d) UNSUPPORTED\n",
411 __func__, p->modulation);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700412 return -1;
413 }
Michael Krufky54828d12011-12-15 10:30:38 -0300414 if (err < 0)
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500415 dev_warn(&state->client->dev,
416 "%s: error blasting bytes to lgdt3303 for modulation type(%d)\n",
417 __func__, p->modulation);
Michael Krufky54828d12011-12-15 10:30:38 -0300418
Michael Krufky1963c902005-08-08 09:22:43 -0700419 /*
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500420 * select serial or parallel MPEG hardware interface
Michael Krufky1963c902005-08-08 09:22:43 -0700421 * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
422 * Parallel: 0x00
423 */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500424 top_ctrl_cfg[1] |= state->config.serial_mpeg;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700425
426 /* Select the requested mode */
Michael Krufky1963c902005-08-08 09:22:43 -0700427 i2c_write_demod_bytes(state, top_ctrl_cfg,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700428 sizeof(top_ctrl_cfg));
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500429 if (state->config.set_ts_params)
430 state->config.set_ts_params(fe, 0);
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300431 state->current_modulation = p->modulation;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700432 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700433
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700434 /* Tune to the specified frequency */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300435 if (fe->ops.tuner_ops.set_params) {
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -0300436 fe->ops.tuner_ops.set_params(fe);
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500437 if (fe->ops.i2c_gate_ctrl)
438 fe->ops.i2c_gate_ctrl(fe, 0);
Andrew de Quincey02269f32006-04-18 17:47:11 -0300439 }
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700440
441 /* Keep track of the new frequency */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500442 /*
443 * FIXME this is the wrong way to do this...
444 * The tuner is shared with the video4linux analog API
445 */
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300446 state->current_frequency = p->frequency;
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700447
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500448 lgdt330x_sw_reset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700449 return 0;
450}
451
Mauro Carvalho Chehab7e3e68b2016-02-04 12:58:30 -0200452static int lgdt330x_get_frontend(struct dvb_frontend *fe,
453 struct dtv_frontend_properties *p)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700454{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700455 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab7e3e68b2016-02-04 12:58:30 -0200456
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300457 p->frequency = state->current_frequency;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700458 return 0;
459}
460
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500461/*
462 * Calculate SNR estimation (scaled by 2^24)
463 *
464 * 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
465 * equations from LGDT3303 datasheet. VSB is the same between the '02
466 * and '03, so maybe QAM is too? Perhaps someone with a newer datasheet
467 * that has QAM information could verify?
468 *
469 * For 8-VSB: (two ways, take your pick)
470 * LGDT3302:
471 * SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
472 * LGDT3303:
473 * SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
474 * LGDT3302 & LGDT3303:
475 * SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one)
476 * For 64-QAM:
477 * SNR = 10 * log10( 688128 / MSEQAM)
478 * For 256-QAM:
479 * SNR = 10 * log10( 696320 / MSEQAM)
480 *
481 * We re-write the snr equation as:
482 * SNR * 2^24 = 10*(c - intlog10(MSE))
483 * Where for 256-QAM, c = log10(696320) * 2^24, and so on.
484 */
Trent Piepho19be6852006-10-29 13:35:39 -0300485static u32 calculate_snr(u32 mse, u32 c)
Michael Krufky1963c902005-08-08 09:22:43 -0700486{
Trent Piepho19be6852006-10-29 13:35:39 -0300487 if (mse == 0) /* No signal */
488 return 0;
489
490 mse = intlog10(mse);
491 if (mse > c) {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500492 /*
493 * Negative SNR, which is possible, but realisticly the
494 * demod will lose lock before the signal gets this bad.
495 * The API only allows for unsigned values, so just return 0
496 */
Trent Piepho19be6852006-10-29 13:35:39 -0300497 return 0;
498 }
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500499 return 10 * (c - mse);
Michael Krufky1963c902005-08-08 09:22:43 -0700500}
501
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500502static int lgdt3302_read_snr(struct dvb_frontend *fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700503{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500504 struct lgdt330x_state *state = fe->demodulator_priv;
Trent Piepho19be6852006-10-29 13:35:39 -0300505 u8 buf[5]; /* read data buffer */
506 u32 noise; /* noise value */
507 u32 c; /* per-modulation SNR calculation constant */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700508
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500509 switch (state->current_modulation) {
Trent Piepho19be6852006-10-29 13:35:39 -0300510 case VSB_8:
511 i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
512#ifdef USE_EQMSE
513 /* Use Equalizer Mean-Square Error Register */
514 /* SNR for ranges from -15.61 to +41.58 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700515 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
Trent Piepho19be6852006-10-29 13:35:39 -0300516 c = 69765745; /* log10(25*24^2)*2^24 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700517#else
Trent Piepho19be6852006-10-29 13:35:39 -0300518 /* Use Phase Tracker Mean-Square Error Register */
519 /* SNR for ranges from -13.11 to +44.08 */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500520 noise = ((buf[0] & 7 << 3) << 13) | (buf[3] << 8) | buf[4];
Trent Piepho19be6852006-10-29 13:35:39 -0300521 c = 73957994; /* log10(25*32^2)*2^24 */
522#endif
523 break;
524 case QAM_64:
525 case QAM_256:
526 i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
Michael Krufky1963c902005-08-08 09:22:43 -0700527 noise = ((buf[0] & 3) << 8) | buf[1];
Trent Piepho19be6852006-10-29 13:35:39 -0300528 c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
529 /* log10(688128)*2^24 and log10(696320)*2^24 */
530 break;
531 default:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500532 dev_err(&state->client->dev,
533 "%s: Modulation set to unsupported value\n",
534 __func__);
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500535
536 state->snr = 0;
537
Trent Piepho19be6852006-10-29 13:35:39 -0300538 return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700539 }
540
Trent Piepho19be6852006-10-29 13:35:39 -0300541 state->snr = calculate_snr(noise, c);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700542
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500543 dprintk(state, "noise = 0x%08x, snr = %d.%02d dB\n", noise,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500544 state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700545
546 return 0;
547}
548
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500549static int lgdt3303_read_snr(struct dvb_frontend *fe)
Michael Krufky1963c902005-08-08 09:22:43 -0700550{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500551 struct lgdt330x_state *state = fe->demodulator_priv;
Trent Piepho19be6852006-10-29 13:35:39 -0300552 u8 buf[5]; /* read data buffer */
553 u32 noise; /* noise value */
554 u32 c; /* per-modulation SNR calculation constant */
Michael Krufky1963c902005-08-08 09:22:43 -0700555
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500556 switch (state->current_modulation) {
Trent Piepho19be6852006-10-29 13:35:39 -0300557 case VSB_8:
558 i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
559#ifdef USE_EQMSE
560 /* Use Equalizer Mean-Square Error Register */
561 /* SNR for ranges from -16.12 to +44.08 */
562 noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
563 c = 73957994; /* log10(25*32^2)*2^24 */
564#else
565 /* Use Phase Tracker Mean-Square Error Register */
566 /* SNR for ranges from -13.11 to +44.08 */
Michael Krufky1963c902005-08-08 09:22:43 -0700567 noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
Trent Piepho19be6852006-10-29 13:35:39 -0300568 c = 73957994; /* log10(25*32^2)*2^24 */
569#endif
570 break;
571 case QAM_64:
572 case QAM_256:
573 i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
Michael Krufky1963c902005-08-08 09:22:43 -0700574 noise = (buf[0] << 8) | buf[1];
Trent Piepho19be6852006-10-29 13:35:39 -0300575 c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
576 /* log10(688128)*2^24 and log10(696320)*2^24 */
577 break;
578 default:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500579 dev_err(&state->client->dev,
580 "%s: Modulation set to unsupported value\n",
581 __func__);
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500582 state->snr = 0;
Trent Piepho19be6852006-10-29 13:35:39 -0300583 return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
Michael Krufky1963c902005-08-08 09:22:43 -0700584 }
585
Trent Piepho19be6852006-10-29 13:35:39 -0300586 state->snr = calculate_snr(noise, c);
Michael Krufky1963c902005-08-08 09:22:43 -0700587
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500588 dprintk(state, "noise = 0x%08x, snr = %d.%02d dB\n", noise,
Trent Piepho19be6852006-10-29 13:35:39 -0300589 state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
590
591 return 0;
592}
593
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500594static int lgdt330x_read_snr(struct dvb_frontend *fe, u16 *snr)
595{
596 struct lgdt330x_state *state = fe->demodulator_priv;
597
598 *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
599
600 return 0;
601}
602
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500603static int lgdt330x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
Trent Piepho19be6852006-10-29 13:35:39 -0300604{
605 /* Calculate Strength from SNR up to 35dB */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500606 /*
607 * Even though the SNR can go higher than 35dB, there is some comfort
608 * factor in having a range of strong signals that can show at 100%
609 */
610 struct lgdt330x_state *state = fe->demodulator_priv;
Trent Piepho19be6852006-10-29 13:35:39 -0300611 u16 snr;
612 int ret;
613
614 ret = fe->ops.read_snr(fe, &snr);
615 if (ret != 0)
616 return ret;
617 /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
618 /* scale the range 0 - 35*2^24 into 0 - 65535 */
619 if (state->snr >= 8960 * 0x10000)
620 *strength = 0xffff;
621 else
622 *strength = state->snr / 8960;
Michael Krufky1963c902005-08-08 09:22:43 -0700623
624 return 0;
625}
626
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500627
628static int lgdt3302_read_status(struct dvb_frontend *fe,
629 enum fe_status *status)
630{
631 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500632 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500633 u8 buf[3];
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500634 int err;
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500635
636 *status = 0; /* Reset status result */
637
638 /* AGC status register */
639 i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
640 dprintk(state, "AGC_STATUS = 0x%02x\n", buf[0]);
641 if ((buf[0] & 0x0c) == 0x8) {
642 /*
643 * Test signal does not exist flag
644 * as well as the AGC lock flag.
645 */
646 *status |= FE_HAS_SIGNAL;
647 }
648
649 /*
650 * You must set the Mask bits to 1 in the IRQ_MASK in order
651 * to see that status bit in the IRQ_STATUS register.
652 * This is done in SwReset();
653 */
654
655 /* signal status */
656 i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
657 dprintk(state,
658 "TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n",
659 buf[0], buf[1], buf[2]);
660
661 /* sync status */
662 if ((buf[2] & 0x03) == 0x01)
663 *status |= FE_HAS_SYNC;
664
665 /* FEC error status */
666 if ((buf[2] & 0x0c) == 0x08)
667 *status |= FE_HAS_LOCK | FE_HAS_VITERBI;
668
669 /* Carrier Recovery Lock Status Register */
670 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
671 dprintk(state, "CARRIER_LOCK = 0x%02x\n", buf[0]);
672 switch (state->current_modulation) {
673 case QAM_256:
674 case QAM_64:
675 /* Need to understand why there are 3 lock levels here */
676 if ((buf[0] & 0x07) == 0x07)
677 *status |= FE_HAS_CARRIER;
678 break;
679 case VSB_8:
680 if ((buf[0] & 0x80) == 0x80)
681 *status |= FE_HAS_CARRIER;
682 break;
683 default:
684 dev_warn(&state->client->dev,
685 "%s: Modulation set to unsupported value\n",
686 __func__);
687 }
688
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500689 if (!(*status & FE_HAS_LOCK)) {
690 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
691 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
692 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
693 return 0;
694 }
695
696 if (state->last_stats_time &&
697 time_is_after_jiffies(state->last_stats_time))
698 return 0;
699
700 state->last_stats_time = jiffies + msecs_to_jiffies(1000);
701
702 err = lgdt3302_read_snr(fe);
703 if (!err) {
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500704 p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
705 p->cnr.stat[0].svalue = (((u64)state->snr) * 1000) >> 24;
706 } else {
707 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
708 }
709
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500710 err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
711 buf, sizeof(buf));
712 if (!err) {
713 state->ucblocks = (buf[0] << 8) | buf[1];
714
715 dprintk(state, "UCB = 0x%02x\n", state->ucblocks);
716
717 p->block_error.stat[0].uvalue += state->ucblocks;
718 /* FIXME: what's the basis for block count */
719 p->block_count.stat[0].uvalue += 10000;
720
721 p->block_error.stat[0].scale = FE_SCALE_COUNTER;
722 p->block_count.stat[0].scale = FE_SCALE_COUNTER;
723 } else {
724 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
725 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
726 }
727
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500728 return 0;
729}
730
731static int lgdt3303_read_status(struct dvb_frontend *fe,
732 enum fe_status *status)
733{
734 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500735 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500736 u8 buf[3];
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500737 int err;
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500738
739 *status = 0; /* Reset status result */
740
741 /* lgdt3303 AGC status register */
742 err = i2c_read_demod_bytes(state, 0x58, buf, 1);
743 if (err < 0)
744 return err;
745
746 dprintk(state, "AGC_STATUS = 0x%02x\n", buf[0]);
747 if ((buf[0] & 0x21) == 0x01) {
748 /*
749 * Test input signal does not exist flag
750 * as well as the AGC lock flag.
751 */
752 *status |= FE_HAS_SIGNAL;
753 }
754
755 /* Carrier Recovery Lock Status Register */
756 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
757 dprintk(state, "CARRIER_LOCK = 0x%02x\n", buf[0]);
758 switch (state->current_modulation) {
759 case QAM_256:
760 case QAM_64:
761 /* Need to understand why there are 3 lock levels here */
762 if ((buf[0] & 0x07) == 0x07)
763 *status |= FE_HAS_CARRIER;
764 else
765 break;
766 i2c_read_demod_bytes(state, 0x8a, buf, 1);
767 dprintk(state, "QAM LOCK = 0x%02x\n", buf[0]);
768
769 if ((buf[0] & 0x04) == 0x04)
770 *status |= FE_HAS_SYNC;
771 if ((buf[0] & 0x01) == 0x01)
772 *status |= FE_HAS_LOCK;
773 if ((buf[0] & 0x08) == 0x08)
774 *status |= FE_HAS_VITERBI;
775 break;
776 case VSB_8:
777 if ((buf[0] & 0x80) == 0x80)
778 *status |= FE_HAS_CARRIER;
779 else
780 break;
781 i2c_read_demod_bytes(state, 0x38, buf, 1);
782 dprintk(state, "8-VSB LOCK = 0x%02x\n", buf[0]);
783
784 if ((buf[0] & 0x02) == 0x00)
785 *status |= FE_HAS_SYNC;
786 if ((buf[0] & 0xfd) == 0x01)
787 *status |= FE_HAS_VITERBI | FE_HAS_LOCK;
788 break;
789 default:
790 dev_warn(&state->client->dev,
791 "%s: Modulation set to unsupported value\n",
792 __func__);
793 }
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500794
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500795 if (!(*status & FE_HAS_LOCK)) {
796 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
797 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
798 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
799 return 0;
800 }
801
802 if (state->last_stats_time &&
803 time_is_after_jiffies(state->last_stats_time))
804 return 0;
805
806 state->last_stats_time = jiffies + msecs_to_jiffies(1000);
807
808 err = lgdt3303_read_snr(fe);
809 if (!err) {
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500810 p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
811 p->cnr.stat[0].svalue = (((u64)state->snr) * 1000) >> 24;
812 } else {
813 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
814 }
815
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500816 err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
817 buf, sizeof(buf));
818 if (!err) {
819 state->ucblocks = (buf[0] << 8) | buf[1];
820
821 dprintk(state, "UCB = 0x%02x\n", state->ucblocks);
822
823 p->block_error.stat[0].uvalue += state->ucblocks;
824 /* FIXME: what's the basis for block count */
825 p->block_count.stat[0].uvalue += 10000;
826
827 p->block_error.stat[0].scale = FE_SCALE_COUNTER;
828 p->block_count.stat[0].scale = FE_SCALE_COUNTER;
829 } else {
830 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
831 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
832 }
833
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500834 return 0;
835}
836
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500837static int
838lgdt330x_get_tune_settings(struct dvb_frontend *fe,
839 struct dvb_frontend_tune_settings *fe_tune_settings)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700840{
841 /* I have no idea about this - it may not be needed */
842 fe_tune_settings->min_delay_ms = 500;
843 fe_tune_settings->step_size = 0;
844 fe_tune_settings->max_drift = 0;
845 return 0;
846}
847
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500848static void lgdt330x_release(struct dvb_frontend *fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700849{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500850 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500851 struct i2c_client *client = state->client;
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500852
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500853 dev_dbg(&client->dev, "\n");
854
855 i2c_unregister_device(client);
856}
857
858static struct dvb_frontend *lgdt330x_get_dvb_frontend(struct i2c_client *client)
859{
860 struct lgdt330x_state *state = i2c_get_clientdata(client);
861
862 dev_dbg(&client->dev, "\n");
863
864 return &state->frontend;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700865}
866
Max Kellermannbd336e62016-08-09 18:32:21 -0300867static const struct dvb_frontend_ops lgdt3302_ops;
868static const struct dvb_frontend_ops lgdt3303_ops;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700869
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500870static int lgdt330x_probe(struct i2c_client *client,
871 const struct i2c_device_id *id)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700872{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500873 struct lgdt330x_state *state = NULL;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700874 u8 buf[1];
875
876 /* Allocate memory for the internal state */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500877 state = kzalloc(sizeof(*state), GFP_KERNEL);
878 if (!state)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700879 goto error;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700880
881 /* Setup the state */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500882 memcpy(&state->config, client->dev.platform_data,
883 sizeof(state->config));
884 i2c_set_clientdata(client, state);
885 state->client = client;
Patrick Boettcherdea74862006-05-14 05:01:31 -0300886
887 /* Create dvb_frontend */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500888 switch (state->config.demod_chip) {
Michael Krufky1963c902005-08-08 09:22:43 -0700889 case LGDT3302:
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500890 memcpy(&state->frontend.ops, &lgdt3302_ops,
891 sizeof(struct dvb_frontend_ops));
Michael Krufky1963c902005-08-08 09:22:43 -0700892 break;
893 case LGDT3303:
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500894 memcpy(&state->frontend.ops, &lgdt3303_ops,
895 sizeof(struct dvb_frontend_ops));
Michael Krufky1963c902005-08-08 09:22:43 -0700896 break;
897 default:
898 goto error;
899 }
Patrick Boettcherdea74862006-05-14 05:01:31 -0300900 state->frontend.demodulator_priv = state;
Michael Krufky1963c902005-08-08 09:22:43 -0700901
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500902 /* Setup get frontend callback */
903 state->config.get_dvb_frontend = lgdt330x_get_dvb_frontend;
904
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700905 /* Verify communication with demod chip */
Michael Krufky1963c902005-08-08 09:22:43 -0700906 if (i2c_read_demod_bytes(state, 2, buf, 1))
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700907 goto error;
908
909 state->current_frequency = -1;
910 state->current_modulation = -1;
911
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500912 dev_info(&state->client->dev,
913 "Demod loaded for LGDT330%s chip\n",
914 state->config.demod_chip == LGDT3302 ? "2" : "3");
Mauro Carvalho Chehabff093612018-03-09 10:53:29 -0500915
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500916 return 0;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700917
918error:
Jesper Juhl2ea75332005-11-07 01:01:31 -0800919 kfree(state);
Mauro Carvalho Chehab89eaaf22018-05-04 11:16:49 -0400920 if (debug)
921 dev_printk(KERN_DEBUG, &client->dev, "Error loading lgdt330x driver\n");
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500922 return -ENODEV;
923}
924struct dvb_frontend *lgdt330x_attach(const struct lgdt330x_config *_config,
925 u8 demod_address,
926 struct i2c_adapter *i2c)
927{
928 struct i2c_client *client;
929 struct i2c_board_info board_info = {};
930 struct lgdt330x_config config = *_config;
931
932 strlcpy(board_info.type, "lgdt330x", sizeof(board_info.type));
933 board_info.addr = demod_address;
934 board_info.platform_data = &config;
935 client = i2c_new_device(i2c, &board_info);
936 if (!client || !client->dev.driver)
937 return NULL;
938
939 return lgdt330x_get_dvb_frontend(client);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700940}
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500941EXPORT_SYMBOL(lgdt330x_attach);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700942
Max Kellermannbd336e62016-08-09 18:32:21 -0300943static const struct dvb_frontend_ops lgdt3302_ops = {
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300944 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700945 .info = {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500946 .name = "LG Electronics LGDT3302 VSB/QAM Frontend",
947 .frequency_min = 54000000,
948 .frequency_max = 858000000,
949 .frequency_stepsize = 62500,
Michael Krufky66944e92005-11-08 21:35:55 -0800950 .symbol_rate_min = 5056941, /* QAM 64 */
951 .symbol_rate_max = 10762000, /* VSB 8 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700952 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
953 },
Michael Krufky6ddcc912005-07-27 11:46:00 -0700954 .init = lgdt330x_init,
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300955 .set_frontend = lgdt330x_set_parameters,
956 .get_frontend = lgdt330x_get_frontend,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700957 .get_tune_settings = lgdt330x_get_tune_settings,
Michael Krufky1963c902005-08-08 09:22:43 -0700958 .read_status = lgdt3302_read_status,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700959 .read_signal_strength = lgdt330x_read_signal_strength,
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500960 .read_snr = lgdt330x_read_snr,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700961 .read_ucblocks = lgdt330x_read_ucblocks,
962 .release = lgdt330x_release,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700963};
964
Max Kellermannbd336e62016-08-09 18:32:21 -0300965static const struct dvb_frontend_ops lgdt3303_ops = {
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300966 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
Michael Krufky1963c902005-08-08 09:22:43 -0700967 .info = {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500968 .name = "LG Electronics LGDT3303 VSB/QAM Frontend",
969 .frequency_min = 54000000,
970 .frequency_max = 858000000,
971 .frequency_stepsize = 62500,
Michael Krufky66944e92005-11-08 21:35:55 -0800972 .symbol_rate_min = 5056941, /* QAM 64 */
973 .symbol_rate_max = 10762000, /* VSB 8 */
Michael Krufky1963c902005-08-08 09:22:43 -0700974 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
975 },
976 .init = lgdt330x_init,
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300977 .set_frontend = lgdt330x_set_parameters,
978 .get_frontend = lgdt330x_get_frontend,
Michael Krufky1963c902005-08-08 09:22:43 -0700979 .get_tune_settings = lgdt330x_get_tune_settings,
980 .read_status = lgdt3303_read_status,
Michael Krufky1963c902005-08-08 09:22:43 -0700981 .read_signal_strength = lgdt330x_read_signal_strength,
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500982 .read_snr = lgdt330x_read_snr,
Michael Krufky1963c902005-08-08 09:22:43 -0700983 .read_ucblocks = lgdt330x_read_ucblocks,
984 .release = lgdt330x_release,
985};
986
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500987static int lgdt330x_remove(struct i2c_client *client)
988{
989 struct lgdt330x_state *state = i2c_get_clientdata(client);
990
991 dev_dbg(&client->dev, "\n");
992
993 kfree(state);
994
995 return 0;
996}
997
998static const struct i2c_device_id lgdt330x_id_table[] = {
999 {"lgdt330x", 0},
1000 {}
1001};
1002MODULE_DEVICE_TABLE(i2c, lgdt330x_id_table);
1003
1004static struct i2c_driver lgdt330x_driver = {
1005 .driver = {
1006 .name = "lgdt330x",
1007 .suppress_bind_attrs = true,
1008 },
1009 .probe = lgdt330x_probe,
1010 .remove = lgdt330x_remove,
1011 .id_table = lgdt330x_id_table,
1012};
1013
1014module_i2c_driver(lgdt330x_driver);
1015
1016
Michael Krufky1963c902005-08-08 09:22:43 -07001017MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
Mac Michaelsd8667cb2005-07-07 17:58:29 -07001018MODULE_AUTHOR("Wilson Michaels");
1019MODULE_LICENSE("GPL");