blob: da3a8c5e18d8ed9204c5e3cb812642359cd92871 [file] [log] [blame]
Thomas Gleixnerc942fdd2019-05-27 08:55:06 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Mac Michaelsd8667cb2005-07-07 17:58:29 -07002/*
Michael Krufky1963c902005-08-08 09:22:43 -07003 * Support for LGDT3302 and LGDT3303 - VSB/QAM
Mac Michaelsd8667cb2005-07-07 17:58:29 -07004 *
5 * Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
Mac Michaelsd8667cb2005-07-07 17:58:29 -07006 */
7
8/*
9 * NOTES ABOUT THIS DRIVER
10 *
Michael Krufky1963c902005-08-08 09:22:43 -070011 * This Linux driver supports:
12 * DViCO FusionHDTV 3 Gold-Q
13 * DViCO FusionHDTV 3 Gold-T
14 * DViCO FusionHDTV 5 Gold
Michael Krufky3cff00d2005-11-08 21:35:12 -080015 * DViCO FusionHDTV 5 Lite
Michael Krufkyd8e6acf2006-01-09 15:32:42 -020016 * DViCO FusionHDTV 5 USB Gold
Michael Krufkyc0b11b92005-11-08 21:35:32 -080017 * Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
Michael Krufky20fe4f652006-04-10 09:40:40 -030018 * pcHDTV HD5500
Mac Michaelsd8667cb2005-07-07 17:58:29 -070019 *
Mac Michaelsd8667cb2005-07-07 17:58:29 -070020 */
21
Mac Michaelsd8667cb2005-07-07 17:58:29 -070022#include <linux/kernel.h>
23#include <linux/module.h>
Mac Michaelsd8667cb2005-07-07 17:58:29 -070024#include <linux/init.h>
25#include <linux/delay.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080026#include <linux/string.h>
27#include <linux/slab.h>
Mac Michaelsd8667cb2005-07-07 17:58:29 -070028#include <asm/byteorder.h>
29
Mauro Carvalho Chehabfada1932017-12-28 13:03:51 -050030#include <media/dvb_frontend.h>
31#include <media/dvb_math.h>
Michael Krufky6ddcc912005-07-27 11:46:00 -070032#include "lgdt330x_priv.h"
33#include "lgdt330x.h"
Mac Michaelsd8667cb2005-07-07 17:58:29 -070034
Trent Piepho19be6852006-10-29 13:35:39 -030035/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
36/* #define USE_EQMSE */
37
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030038static int debug;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070039module_param(debug, int, 0644);
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050040MODULE_PARM_DESC(debug, "Turn on/off lgdt330x frontend debugging (default:off).");
Mauro Carvalho Chehab6752c792018-03-09 10:53:28 -050041
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050042#define dprintk(state, fmt, arg...) do { \
Mauro Carvalho Chehab6752c792018-03-09 10:53:28 -050043 if (debug) \
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050044 dev_printk(KERN_DEBUG, &state->client->dev, fmt, ##arg);\
Mac Michaelsd8667cb2005-07-07 17:58:29 -070045} while (0)
46
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050047struct lgdt330x_state {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050048 struct i2c_client *client;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070049
50 /* Configuration settings */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050051 struct lgdt330x_config config;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070052
53 struct dvb_frontend frontend;
54
55 /* Demodulator private data */
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -030056 enum fe_modulation current_modulation;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -050057 u32 snr; /* Result of last SNR calculation */
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -050058 u16 ucblocks;
59 unsigned long last_stats_time;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070060
61 /* Tuner private data */
62 u32 current_frequency;
63};
64
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050065static int i2c_write_demod_bytes(struct lgdt330x_state *state,
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050066 const u8 *buf, /* data bytes to send */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050067 int len /* number of bytes to send */)
Mac Michaelsd8667cb2005-07-07 17:58:29 -070068{
Michael Krufkyb6aef072005-07-27 11:45:54 -070069 int i;
Michael Krufky1963c902005-08-08 09:22:43 -070070 int err;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070071
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050072 for (i = 0; i < len - 1; i += 2) {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050073 err = i2c_master_send(state->client, buf, 2);
74 if (err != 2) {
75 dev_warn(&state->client->dev,
76 "%s: error (addr %02x <- %02x, err = %i)\n",
77 __func__, buf[0], buf[1], err);
Michael Krufky58ba0062005-07-12 13:58:37 -070078 if (err < 0)
79 return err;
80 else
81 return -EREMOTEIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070082 }
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050083 buf += 2;
Mac Michaelsd8667cb2005-07-07 17:58:29 -070084 }
85 return 0;
86}
Michael Krufkyb6aef072005-07-27 11:45:54 -070087
Mac Michaelsd8667cb2005-07-07 17:58:29 -070088/*
89 * This routine writes the register (reg) to the demod bus
90 * then reads the data returned for (len) bytes.
91 */
Xi Wang34817172012-02-14 14:32:41 -030092static int i2c_read_demod_bytes(struct lgdt330x_state *state,
93 enum I2C_REG reg, u8 *buf, int len)
Mac Michaelsd8667cb2005-07-07 17:58:29 -070094{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050095 u8 wr[] = { reg };
96 struct i2c_msg msg[] = {
97 {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -050098 .addr = state->client->addr,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -050099 .flags = 0,
100 .buf = wr,
101 .len = 1
102 }, {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500103 .addr = state->client->addr,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500104 .flags = I2C_M_RD,
105 .buf = buf,
106 .len = len
107 },
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700108 };
109 int ret;
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500110
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500111 ret = i2c_transfer(state->client->adapter, msg, 2);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700112 if (ret != 2) {
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500113 dev_warn(&state->client->dev,
114 "%s: addr 0x%02x select 0x%02x error (ret == %i)\n",
115 __func__, state->client->addr, reg, ret);
Xi Wang34817172012-02-14 14:32:41 -0300116 if (ret >= 0)
117 ret = -EIO;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700118 } else {
119 ret = 0;
120 }
121 return ret;
122}
123
124/* Software reset */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500125static int lgdt3302_sw_reset(struct lgdt330x_state *state)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700126{
127 u8 ret;
128 u8 reset[] = {
129 IRQ_MASK,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500130 /*
131 * bit 6 is active low software reset
132 * bits 5-0 are 1 to mask interrupts
133 */
134 0x00
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700135 };
136
Michael Krufky1963c902005-08-08 09:22:43 -0700137 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700138 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700139 if (ret == 0) {
Michael Krufky1963c902005-08-08 09:22:43 -0700140 /* force reset high (inactive) and unmask interrupts */
141 reset[1] = 0x7f;
142 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700143 reset, sizeof(reset));
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700144 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700145 return ret;
146}
147
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500148static int lgdt3303_sw_reset(struct lgdt330x_state *state)
Michael Krufky1963c902005-08-08 09:22:43 -0700149{
150 u8 ret;
151 u8 reset[] = {
152 0x02,
153 0x00 /* bit 0 is active low software reset */
154 };
155
156 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700157 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700158 if (ret == 0) {
Michael Krufky1963c902005-08-08 09:22:43 -0700159 /* force reset high (inactive) */
160 reset[1] = 0x01;
161 ret = i2c_write_demod_bytes(state,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700162 reset, sizeof(reset));
Michael Krufky1963c902005-08-08 09:22:43 -0700163 }
164 return ret;
165}
166
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500167static int lgdt330x_sw_reset(struct lgdt330x_state *state)
Michael Krufky1963c902005-08-08 09:22:43 -0700168{
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500169 switch (state->config.demod_chip) {
Michael Krufky1963c902005-08-08 09:22:43 -0700170 case LGDT3302:
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500171 return lgdt3302_sw_reset(state);
Michael Krufky1963c902005-08-08 09:22:43 -0700172 case LGDT3303:
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500173 return lgdt3303_sw_reset(state);
Michael Krufky1963c902005-08-08 09:22:43 -0700174 default:
175 return -ENODEV;
176 }
177}
178
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500179static int lgdt330x_init(struct dvb_frontend *fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700180{
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500181 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500182 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500183 char *chip_name;
184 int err;
Michael Krufky1963c902005-08-08 09:22:43 -0700185 /*
186 * Array of byte pairs <address, value>
187 * to initialize each different chip
188 */
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500189 static const u8 lgdt3302_init_data[] = {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500190 /* Use 50MHz param values from spec sheet since xtal is 50 */
191 /*
192 * Change the value of NCOCTFV[25:0] of carrier
193 * recovery center frequency register
194 */
Michael Krufky1963c902005-08-08 09:22:43 -0700195 VSB_CARRIER_FREQ0, 0x00,
196 VSB_CARRIER_FREQ1, 0x87,
197 VSB_CARRIER_FREQ2, 0x8e,
198 VSB_CARRIER_FREQ3, 0x01,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500199 /*
200 * Change the TPCLK pin polarity
201 * data is valid on falling clock
202 */
Michael Krufky1963c902005-08-08 09:22:43 -0700203 DEMUX_CONTROL, 0xfb,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500204 /*
205 * Change the value of IFBW[11:0] of
206 * AGC IF/RF loop filter bandwidth register
207 */
Michael Krufky1963c902005-08-08 09:22:43 -0700208 AGC_RF_BANDWIDTH0, 0x40,
209 AGC_RF_BANDWIDTH1, 0x93,
210 AGC_RF_BANDWIDTH2, 0x00,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500211 /*
212 * Change the value of bit 6, 'nINAGCBY' and
213 * 'NSSEL[1:0] of ACG function control register 2
214 */
Michael Krufky1963c902005-08-08 09:22:43 -0700215 AGC_FUNC_CTRL2, 0xc6,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500216 /*
217 * Change the value of bit 6 'RFFIX'
218 * of AGC function control register 3
219 */
Michael Krufky1963c902005-08-08 09:22:43 -0700220 AGC_FUNC_CTRL3, 0x40,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500221 /*
222 * Set the value of 'INLVTHD' register 0x2a/0x2c
223 * to 0x7fe
224 */
Michael Krufky1963c902005-08-08 09:22:43 -0700225 AGC_DELAY0, 0x07,
226 AGC_DELAY2, 0xfe,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500227 /*
228 * Change the value of IAGCBW[15:8]
229 * of inner AGC loop filter bandwidth
230 */
Michael Krufky1963c902005-08-08 09:22:43 -0700231 AGC_LOOP_BANDWIDTH0, 0x08,
232 AGC_LOOP_BANDWIDTH1, 0x9a
233 };
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500234 static const u8 lgdt3303_init_data[] = {
Michael Krufky1963c902005-08-08 09:22:43 -0700235 0x4c, 0x14
236 };
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500237 static const u8 flip_1_lgdt3303_init_data[] = {
Michael Krufkyc0b11b92005-11-08 21:35:32 -0800238 0x4c, 0x14,
239 0x87, 0xf3
240 };
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500241 static const u8 flip_2_lgdt3303_init_data[] = {
Michael Krufkyc0f4c0a2008-06-28 02:06:50 -0300242 0x4c, 0x14,
243 0x87, 0xda
244 };
245
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500246 /*
247 * Hardware reset is done using gpio[0] of cx23880x chip.
248 * I'd like to do it here, but don't know how to find chip address.
249 * cx88-cards.c arranges for the reset bit to be inactive (high).
250 * Maybe there needs to be a callable function in cx88-core or
251 * the caller of this function needs to do it.
252 */
Michael Krufky1963c902005-08-08 09:22:43 -0700253
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500254 switch (state->config.demod_chip) {
Michael Krufky1963c902005-08-08 09:22:43 -0700255 case LGDT3302:
256 chip_name = "LGDT3302";
257 err = i2c_write_demod_bytes(state, lgdt3302_init_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700258 sizeof(lgdt3302_init_data));
259 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700260 case LGDT3303:
261 chip_name = "LGDT3303";
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500262 switch (state->config.clock_polarity_flip) {
Michael Krufkyc0f4c0a2008-06-28 02:06:50 -0300263 case 2:
264 err = i2c_write_demod_bytes(state,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500265 flip_2_lgdt3303_init_data,
266 sizeof(flip_2_lgdt3303_init_data));
Michael Krufkyc0f4c0a2008-06-28 02:06:50 -0300267 break;
268 case 1:
269 err = i2c_write_demod_bytes(state,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500270 flip_1_lgdt3303_init_data,
271 sizeof(flip_1_lgdt3303_init_data));
Michael Krufkyc0f4c0a2008-06-28 02:06:50 -0300272 break;
273 case 0:
274 default:
Michael Krufkyc0b11b92005-11-08 21:35:32 -0800275 err = i2c_write_demod_bytes(state, lgdt3303_init_data,
276 sizeof(lgdt3303_init_data));
277 }
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700278 break;
Michael Krufky1963c902005-08-08 09:22:43 -0700279 default:
280 chip_name = "undefined";
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500281 dev_warn(&state->client->dev,
282 "Only LGDT3302 and LGDT3303 are supported chips.\n");
Michael Krufky1963c902005-08-08 09:22:43 -0700283 err = -ENODEV;
284 }
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500285 dprintk(state, "Initialized the %s chip\n", chip_name);
Michael Krufky1963c902005-08-08 09:22:43 -0700286 if (err < 0)
287 return err;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500288
289 p->cnr.len = 1;
290 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500291 p->block_error.len = 1;
292 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
293 p->block_count.len = 1;
294 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
295 state->last_stats_time = 0;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500296
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500297 return lgdt330x_sw_reset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700298}
299
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500300static int lgdt330x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700301{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500302 struct lgdt330x_state *state = fe->demodulator_priv;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700303
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500304 *ucblocks = state->ucblocks;
Michael Krufky26110da2011-12-15 10:16:09 -0300305
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700306 return 0;
307}
308
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300309static int lgdt330x_set_parameters(struct dvb_frontend *fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700310{
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300311 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500312 struct lgdt330x_state *state = fe->demodulator_priv;
Michael Krufky1963c902005-08-08 09:22:43 -0700313 /*
314 * Array of byte pairs <address, value>
315 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
316 */
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500317 static const u8 lgdt3303_8vsb_44_data[] = {
Michael Krufky1963c902005-08-08 09:22:43 -0700318 0x04, 0x00,
319 0x0d, 0x40,
Michael Krufky0b6389f2006-11-28 02:35:02 -0300320 0x0e, 0x87,
321 0x0f, 0x8e,
322 0x10, 0x01,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500323 0x47, 0x8b
324 };
Michael Krufky1963c902005-08-08 09:22:43 -0700325 /*
326 * Array of byte pairs <address, value>
327 * to initialize QAM for lgdt3303 chip
328 */
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500329 static const u8 lgdt3303_qam_data[] = {
Michael Krufky1963c902005-08-08 09:22:43 -0700330 0x04, 0x00,
331 0x0d, 0x00,
332 0x0e, 0x00,
333 0x0f, 0x00,
334 0x10, 0x00,
335 0x51, 0x63,
336 0x47, 0x66,
337 0x48, 0x66,
338 0x4d, 0x1a,
339 0x49, 0x08,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500340 0x4a, 0x9b
341 };
Mauro Carvalho Chehab1334a7d2018-03-09 10:53:32 -0500342 u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700343
Michael Krufky54828d12011-12-15 10:30:38 -0300344 int err = 0;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700345 /* Change only if we are actually changing the modulation */
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300346 if (state->current_modulation != p->modulation) {
347 switch (p->modulation) {
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700348 case VSB_8:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500349 dprintk(state, "VSB_8 MODE\n");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700350
Michael Krufky1963c902005-08-08 09:22:43 -0700351 /* Select VSB mode */
352 top_ctrl_cfg[1] = 0x03;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700353
354 /* Select ANT connector if supported by card */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500355 if (state->config.pll_rf_set)
356 state->config.pll_rf_set(fe, 1);
Michael Krufky1963c902005-08-08 09:22:43 -0700357
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500358 if (state->config.demod_chip == LGDT3303) {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500359 err = i2c_write_demod_bytes(state,
360 lgdt3303_8vsb_44_data,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700361 sizeof(lgdt3303_8vsb_44_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700362 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700363 break;
364
365 case QAM_64:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500366 dprintk(state, "QAM_64 MODE\n");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700367
Michael Krufky1963c902005-08-08 09:22:43 -0700368 /* Select QAM_64 mode */
369 top_ctrl_cfg[1] = 0x00;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700370
371 /* Select CABLE connector if supported by card */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500372 if (state->config.pll_rf_set)
373 state->config.pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700374
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500375 if (state->config.demod_chip == LGDT3303) {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500376 err = i2c_write_demod_bytes(state,
377 lgdt3303_qam_data,
378 sizeof(lgdt3303_qam_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700379 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700380 break;
381
382 case QAM_256:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500383 dprintk(state, "QAM_256 MODE\n");
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700384
Michael Krufky1963c902005-08-08 09:22:43 -0700385 /* Select QAM_256 mode */
386 top_ctrl_cfg[1] = 0x01;
Michael Krufky0ccef6d2005-07-27 11:45:55 -0700387
388 /* Select CABLE connector if supported by card */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500389 if (state->config.pll_rf_set)
390 state->config.pll_rf_set(fe, 0);
Michael Krufky1963c902005-08-08 09:22:43 -0700391
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500392 if (state->config.demod_chip == LGDT3303) {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500393 err = i2c_write_demod_bytes(state,
394 lgdt3303_qam_data,
395 sizeof(lgdt3303_qam_data));
Michael Krufky1963c902005-08-08 09:22:43 -0700396 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700397 break;
398 default:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500399 dev_warn(&state->client->dev,
400 "%s: Modulation type(%d) UNSUPPORTED\n",
401 __func__, p->modulation);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700402 return -1;
403 }
Michael Krufky54828d12011-12-15 10:30:38 -0300404 if (err < 0)
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500405 dev_warn(&state->client->dev,
406 "%s: error blasting bytes to lgdt3303 for modulation type(%d)\n",
407 __func__, p->modulation);
Michael Krufky54828d12011-12-15 10:30:38 -0300408
Michael Krufky1963c902005-08-08 09:22:43 -0700409 /*
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500410 * select serial or parallel MPEG hardware interface
Michael Krufky1963c902005-08-08 09:22:43 -0700411 * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
412 * Parallel: 0x00
413 */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500414 top_ctrl_cfg[1] |= state->config.serial_mpeg;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700415
416 /* Select the requested mode */
Michael Krufky1963c902005-08-08 09:22:43 -0700417 i2c_write_demod_bytes(state, top_ctrl_cfg,
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700418 sizeof(top_ctrl_cfg));
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500419 if (state->config.set_ts_params)
420 state->config.set_ts_params(fe, 0);
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300421 state->current_modulation = p->modulation;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700422 }
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700423
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700424 /* Tune to the specified frequency */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300425 if (fe->ops.tuner_ops.set_params) {
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -0300426 fe->ops.tuner_ops.set_params(fe);
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500427 if (fe->ops.i2c_gate_ctrl)
428 fe->ops.i2c_gate_ctrl(fe, 0);
Andrew de Quincey02269f32006-04-18 17:47:11 -0300429 }
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700430
431 /* Keep track of the new frequency */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500432 /*
433 * FIXME this is the wrong way to do this...
434 * The tuner is shared with the video4linux analog API
435 */
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300436 state->current_frequency = p->frequency;
Michael Krufkydc9ca2a2005-09-06 15:19:40 -0700437
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500438 lgdt330x_sw_reset(state);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700439 return 0;
440}
441
Mauro Carvalho Chehab7e3e68b2016-02-04 12:58:30 -0200442static int lgdt330x_get_frontend(struct dvb_frontend *fe,
443 struct dtv_frontend_properties *p)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700444{
Michael Krufky6ddcc912005-07-27 11:46:00 -0700445 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab7e3e68b2016-02-04 12:58:30 -0200446
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300447 p->frequency = state->current_frequency;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700448 return 0;
449}
450
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500451/*
452 * Calculate SNR estimation (scaled by 2^24)
453 *
454 * 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
455 * equations from LGDT3303 datasheet. VSB is the same between the '02
456 * and '03, so maybe QAM is too? Perhaps someone with a newer datasheet
457 * that has QAM information could verify?
458 *
459 * For 8-VSB: (two ways, take your pick)
460 * LGDT3302:
461 * SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
462 * LGDT3303:
463 * SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
464 * LGDT3302 & LGDT3303:
465 * SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one)
466 * For 64-QAM:
467 * SNR = 10 * log10( 688128 / MSEQAM)
468 * For 256-QAM:
469 * SNR = 10 * log10( 696320 / MSEQAM)
470 *
471 * We re-write the snr equation as:
472 * SNR * 2^24 = 10*(c - intlog10(MSE))
473 * Where for 256-QAM, c = log10(696320) * 2^24, and so on.
474 */
Trent Piepho19be6852006-10-29 13:35:39 -0300475static u32 calculate_snr(u32 mse, u32 c)
Michael Krufky1963c902005-08-08 09:22:43 -0700476{
Trent Piepho19be6852006-10-29 13:35:39 -0300477 if (mse == 0) /* No signal */
478 return 0;
479
480 mse = intlog10(mse);
481 if (mse > c) {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500482 /*
483 * Negative SNR, which is possible, but realisticly the
484 * demod will lose lock before the signal gets this bad.
485 * The API only allows for unsigned values, so just return 0
486 */
Trent Piepho19be6852006-10-29 13:35:39 -0300487 return 0;
488 }
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500489 return 10 * (c - mse);
Michael Krufky1963c902005-08-08 09:22:43 -0700490}
491
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500492static int lgdt3302_read_snr(struct dvb_frontend *fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700493{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500494 struct lgdt330x_state *state = fe->demodulator_priv;
Trent Piepho19be6852006-10-29 13:35:39 -0300495 u8 buf[5]; /* read data buffer */
496 u32 noise; /* noise value */
497 u32 c; /* per-modulation SNR calculation constant */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700498
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500499 switch (state->current_modulation) {
Trent Piepho19be6852006-10-29 13:35:39 -0300500 case VSB_8:
501 i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
502#ifdef USE_EQMSE
503 /* Use Equalizer Mean-Square Error Register */
504 /* SNR for ranges from -15.61 to +41.58 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700505 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
Trent Piepho19be6852006-10-29 13:35:39 -0300506 c = 69765745; /* log10(25*24^2)*2^24 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700507#else
Trent Piepho19be6852006-10-29 13:35:39 -0300508 /* Use Phase Tracker Mean-Square Error Register */
509 /* SNR for ranges from -13.11 to +44.08 */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500510 noise = ((buf[0] & 7 << 3) << 13) | (buf[3] << 8) | buf[4];
Trent Piepho19be6852006-10-29 13:35:39 -0300511 c = 73957994; /* log10(25*32^2)*2^24 */
512#endif
513 break;
514 case QAM_64:
515 case QAM_256:
516 i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
Michael Krufky1963c902005-08-08 09:22:43 -0700517 noise = ((buf[0] & 3) << 8) | buf[1];
Trent Piepho19be6852006-10-29 13:35:39 -0300518 c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
519 /* log10(688128)*2^24 and log10(696320)*2^24 */
520 break;
521 default:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500522 dev_err(&state->client->dev,
523 "%s: Modulation set to unsupported value\n",
524 __func__);
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500525
526 state->snr = 0;
527
Trent Piepho19be6852006-10-29 13:35:39 -0300528 return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700529 }
530
Trent Piepho19be6852006-10-29 13:35:39 -0300531 state->snr = calculate_snr(noise, c);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700532
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500533 dprintk(state, "noise = 0x%08x, snr = %d.%02d dB\n", noise,
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500534 state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700535
536 return 0;
537}
538
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500539static int lgdt3303_read_snr(struct dvb_frontend *fe)
Michael Krufky1963c902005-08-08 09:22:43 -0700540{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500541 struct lgdt330x_state *state = fe->demodulator_priv;
Trent Piepho19be6852006-10-29 13:35:39 -0300542 u8 buf[5]; /* read data buffer */
543 u32 noise; /* noise value */
544 u32 c; /* per-modulation SNR calculation constant */
Michael Krufky1963c902005-08-08 09:22:43 -0700545
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500546 switch (state->current_modulation) {
Trent Piepho19be6852006-10-29 13:35:39 -0300547 case VSB_8:
548 i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
549#ifdef USE_EQMSE
550 /* Use Equalizer Mean-Square Error Register */
551 /* SNR for ranges from -16.12 to +44.08 */
552 noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
553 c = 73957994; /* log10(25*32^2)*2^24 */
554#else
555 /* Use Phase Tracker Mean-Square Error Register */
556 /* SNR for ranges from -13.11 to +44.08 */
Michael Krufky1963c902005-08-08 09:22:43 -0700557 noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
Trent Piepho19be6852006-10-29 13:35:39 -0300558 c = 73957994; /* log10(25*32^2)*2^24 */
559#endif
560 break;
561 case QAM_64:
562 case QAM_256:
563 i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
Michael Krufky1963c902005-08-08 09:22:43 -0700564 noise = (buf[0] << 8) | buf[1];
Trent Piepho19be6852006-10-29 13:35:39 -0300565 c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
566 /* log10(688128)*2^24 and log10(696320)*2^24 */
567 break;
568 default:
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500569 dev_err(&state->client->dev,
570 "%s: Modulation set to unsupported value\n",
571 __func__);
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500572 state->snr = 0;
Trent Piepho19be6852006-10-29 13:35:39 -0300573 return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
Michael Krufky1963c902005-08-08 09:22:43 -0700574 }
575
Trent Piepho19be6852006-10-29 13:35:39 -0300576 state->snr = calculate_snr(noise, c);
Michael Krufky1963c902005-08-08 09:22:43 -0700577
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500578 dprintk(state, "noise = 0x%08x, snr = %d.%02d dB\n", noise,
Trent Piepho19be6852006-10-29 13:35:39 -0300579 state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
580
581 return 0;
582}
583
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500584static int lgdt330x_read_snr(struct dvb_frontend *fe, u16 *snr)
585{
586 struct lgdt330x_state *state = fe->demodulator_priv;
587
588 *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
589
590 return 0;
591}
592
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500593static int lgdt330x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
Trent Piepho19be6852006-10-29 13:35:39 -0300594{
595 /* Calculate Strength from SNR up to 35dB */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500596 /*
597 * Even though the SNR can go higher than 35dB, there is some comfort
598 * factor in having a range of strong signals that can show at 100%
599 */
600 struct lgdt330x_state *state = fe->demodulator_priv;
Trent Piepho19be6852006-10-29 13:35:39 -0300601 u16 snr;
602 int ret;
603
604 ret = fe->ops.read_snr(fe, &snr);
605 if (ret != 0)
606 return ret;
607 /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
608 /* scale the range 0 - 35*2^24 into 0 - 65535 */
609 if (state->snr >= 8960 * 0x10000)
610 *strength = 0xffff;
611 else
612 *strength = state->snr / 8960;
Michael Krufky1963c902005-08-08 09:22:43 -0700613
614 return 0;
615}
616
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500617
618static int lgdt3302_read_status(struct dvb_frontend *fe,
619 enum fe_status *status)
620{
621 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500622 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500623 u8 buf[3];
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500624 int err;
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500625
626 *status = 0; /* Reset status result */
627
628 /* AGC status register */
629 i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
630 dprintk(state, "AGC_STATUS = 0x%02x\n", buf[0]);
631 if ((buf[0] & 0x0c) == 0x8) {
632 /*
633 * Test signal does not exist flag
634 * as well as the AGC lock flag.
635 */
636 *status |= FE_HAS_SIGNAL;
637 }
638
639 /*
640 * You must set the Mask bits to 1 in the IRQ_MASK in order
641 * to see that status bit in the IRQ_STATUS register.
642 * This is done in SwReset();
643 */
644
645 /* signal status */
646 i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
647 dprintk(state,
648 "TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n",
649 buf[0], buf[1], buf[2]);
650
651 /* sync status */
652 if ((buf[2] & 0x03) == 0x01)
653 *status |= FE_HAS_SYNC;
654
655 /* FEC error status */
656 if ((buf[2] & 0x0c) == 0x08)
657 *status |= FE_HAS_LOCK | FE_HAS_VITERBI;
658
659 /* Carrier Recovery Lock Status Register */
660 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
661 dprintk(state, "CARRIER_LOCK = 0x%02x\n", buf[0]);
662 switch (state->current_modulation) {
663 case QAM_256:
664 case QAM_64:
665 /* Need to understand why there are 3 lock levels here */
666 if ((buf[0] & 0x07) == 0x07)
667 *status |= FE_HAS_CARRIER;
668 break;
669 case VSB_8:
670 if ((buf[0] & 0x80) == 0x80)
671 *status |= FE_HAS_CARRIER;
672 break;
673 default:
674 dev_warn(&state->client->dev,
675 "%s: Modulation set to unsupported value\n",
676 __func__);
677 }
678
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500679 if (!(*status & FE_HAS_LOCK)) {
680 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
681 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
682 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
683 return 0;
684 }
685
686 if (state->last_stats_time &&
687 time_is_after_jiffies(state->last_stats_time))
688 return 0;
689
690 state->last_stats_time = jiffies + msecs_to_jiffies(1000);
691
692 err = lgdt3302_read_snr(fe);
693 if (!err) {
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500694 p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
695 p->cnr.stat[0].svalue = (((u64)state->snr) * 1000) >> 24;
696 } else {
697 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
698 }
699
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500700 err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
701 buf, sizeof(buf));
702 if (!err) {
703 state->ucblocks = (buf[0] << 8) | buf[1];
704
705 dprintk(state, "UCB = 0x%02x\n", state->ucblocks);
706
707 p->block_error.stat[0].uvalue += state->ucblocks;
708 /* FIXME: what's the basis for block count */
709 p->block_count.stat[0].uvalue += 10000;
710
711 p->block_error.stat[0].scale = FE_SCALE_COUNTER;
712 p->block_count.stat[0].scale = FE_SCALE_COUNTER;
713 } else {
714 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
715 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
716 }
717
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500718 return 0;
719}
720
721static int lgdt3303_read_status(struct dvb_frontend *fe,
722 enum fe_status *status)
723{
724 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500725 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500726 u8 buf[3];
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500727 int err;
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500728
729 *status = 0; /* Reset status result */
730
731 /* lgdt3303 AGC status register */
732 err = i2c_read_demod_bytes(state, 0x58, buf, 1);
733 if (err < 0)
734 return err;
735
736 dprintk(state, "AGC_STATUS = 0x%02x\n", buf[0]);
737 if ((buf[0] & 0x21) == 0x01) {
738 /*
739 * Test input signal does not exist flag
740 * as well as the AGC lock flag.
741 */
742 *status |= FE_HAS_SIGNAL;
743 }
744
745 /* Carrier Recovery Lock Status Register */
746 i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
747 dprintk(state, "CARRIER_LOCK = 0x%02x\n", buf[0]);
748 switch (state->current_modulation) {
749 case QAM_256:
750 case QAM_64:
751 /* Need to understand why there are 3 lock levels here */
752 if ((buf[0] & 0x07) == 0x07)
753 *status |= FE_HAS_CARRIER;
754 else
755 break;
756 i2c_read_demod_bytes(state, 0x8a, buf, 1);
757 dprintk(state, "QAM LOCK = 0x%02x\n", buf[0]);
758
759 if ((buf[0] & 0x04) == 0x04)
760 *status |= FE_HAS_SYNC;
761 if ((buf[0] & 0x01) == 0x01)
762 *status |= FE_HAS_LOCK;
763 if ((buf[0] & 0x08) == 0x08)
764 *status |= FE_HAS_VITERBI;
765 break;
766 case VSB_8:
767 if ((buf[0] & 0x80) == 0x80)
768 *status |= FE_HAS_CARRIER;
769 else
770 break;
771 i2c_read_demod_bytes(state, 0x38, buf, 1);
772 dprintk(state, "8-VSB LOCK = 0x%02x\n", buf[0]);
773
774 if ((buf[0] & 0x02) == 0x00)
775 *status |= FE_HAS_SYNC;
French, Nicholas A1b4fd9d2018-12-09 02:11:18 -0500776 if ((buf[0] & 0x01) == 0x01)
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500777 *status |= FE_HAS_VITERBI | FE_HAS_LOCK;
778 break;
779 default:
780 dev_warn(&state->client->dev,
781 "%s: Modulation set to unsupported value\n",
782 __func__);
783 }
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500784
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500785 if (!(*status & FE_HAS_LOCK)) {
786 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
787 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
788 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
789 return 0;
790 }
791
792 if (state->last_stats_time &&
793 time_is_after_jiffies(state->last_stats_time))
794 return 0;
795
796 state->last_stats_time = jiffies + msecs_to_jiffies(1000);
797
798 err = lgdt3303_read_snr(fe);
799 if (!err) {
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500800 p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
801 p->cnr.stat[0].svalue = (((u64)state->snr) * 1000) >> 24;
802 } else {
803 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
804 }
805
Mauro Carvalho Chehab5f939c32018-03-09 11:15:41 -0500806 err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
807 buf, sizeof(buf));
808 if (!err) {
809 state->ucblocks = (buf[0] << 8) | buf[1];
810
811 dprintk(state, "UCB = 0x%02x\n", state->ucblocks);
812
813 p->block_error.stat[0].uvalue += state->ucblocks;
814 /* FIXME: what's the basis for block count */
815 p->block_count.stat[0].uvalue += 10000;
816
817 p->block_error.stat[0].scale = FE_SCALE_COUNTER;
818 p->block_count.stat[0].scale = FE_SCALE_COUNTER;
819 } else {
820 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
821 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
822 }
823
Mauro Carvalho Chehab53d41722018-03-09 10:53:33 -0500824 return 0;
825}
826
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500827static int
828lgdt330x_get_tune_settings(struct dvb_frontend *fe,
829 struct dvb_frontend_tune_settings *fe_tune_settings)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700830{
831 /* I have no idea about this - it may not be needed */
832 fe_tune_settings->min_delay_ms = 500;
833 fe_tune_settings->step_size = 0;
834 fe_tune_settings->max_drift = 0;
835 return 0;
836}
837
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500838static void lgdt330x_release(struct dvb_frontend *fe)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700839{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500840 struct lgdt330x_state *state = fe->demodulator_priv;
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500841 struct i2c_client *client = state->client;
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500842
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500843 dev_dbg(&client->dev, "\n");
844
845 i2c_unregister_device(client);
846}
847
848static struct dvb_frontend *lgdt330x_get_dvb_frontend(struct i2c_client *client)
849{
850 struct lgdt330x_state *state = i2c_get_clientdata(client);
851
852 dev_dbg(&client->dev, "\n");
853
854 return &state->frontend;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700855}
856
Max Kellermannbd336e62016-08-09 18:32:21 -0300857static const struct dvb_frontend_ops lgdt3302_ops;
858static const struct dvb_frontend_ops lgdt3303_ops;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700859
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500860static int lgdt330x_probe(struct i2c_client *client,
861 const struct i2c_device_id *id)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700862{
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500863 struct lgdt330x_state *state = NULL;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700864 u8 buf[1];
865
866 /* Allocate memory for the internal state */
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500867 state = kzalloc(sizeof(*state), GFP_KERNEL);
868 if (!state)
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700869 goto error;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700870
871 /* Setup the state */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500872 memcpy(&state->config, client->dev.platform_data,
873 sizeof(state->config));
874 i2c_set_clientdata(client, state);
875 state->client = client;
Patrick Boettcherdea74862006-05-14 05:01:31 -0300876
877 /* Create dvb_frontend */
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500878 switch (state->config.demod_chip) {
Michael Krufky1963c902005-08-08 09:22:43 -0700879 case LGDT3302:
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500880 memcpy(&state->frontend.ops, &lgdt3302_ops,
881 sizeof(struct dvb_frontend_ops));
Michael Krufky1963c902005-08-08 09:22:43 -0700882 break;
883 case LGDT3303:
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500884 memcpy(&state->frontend.ops, &lgdt3303_ops,
885 sizeof(struct dvb_frontend_ops));
Michael Krufky1963c902005-08-08 09:22:43 -0700886 break;
887 default:
888 goto error;
889 }
Patrick Boettcherdea74862006-05-14 05:01:31 -0300890 state->frontend.demodulator_priv = state;
Michael Krufky1963c902005-08-08 09:22:43 -0700891
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500892 /* Setup get frontend callback */
893 state->config.get_dvb_frontend = lgdt330x_get_dvb_frontend;
894
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700895 /* Verify communication with demod chip */
Michael Krufky1963c902005-08-08 09:22:43 -0700896 if (i2c_read_demod_bytes(state, 2, buf, 1))
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700897 goto error;
898
899 state->current_frequency = -1;
900 state->current_modulation = -1;
901
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500902 dev_info(&state->client->dev,
903 "Demod loaded for LGDT330%s chip\n",
904 state->config.demod_chip == LGDT3302 ? "2" : "3");
Mauro Carvalho Chehabff093612018-03-09 10:53:29 -0500905
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500906 return 0;
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700907
908error:
Jesper Juhl2ea75332005-11-07 01:01:31 -0800909 kfree(state);
Mauro Carvalho Chehab89eaaf22018-05-04 11:16:49 -0400910 if (debug)
911 dev_printk(KERN_DEBUG, &client->dev, "Error loading lgdt330x driver\n");
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500912 return -ENODEV;
913}
914struct dvb_frontend *lgdt330x_attach(const struct lgdt330x_config *_config,
915 u8 demod_address,
916 struct i2c_adapter *i2c)
917{
918 struct i2c_client *client;
919 struct i2c_board_info board_info = {};
920 struct lgdt330x_config config = *_config;
921
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -0400922 strscpy(board_info.type, "lgdt330x", sizeof(board_info.type));
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500923 board_info.addr = demod_address;
924 board_info.platform_data = &config;
Wolfram Sang4f7f5e02019-12-16 16:51:30 +0100925 client = i2c_new_client_device(i2c, &board_info);
926 if (!i2c_client_has_driver(client))
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500927 return NULL;
928
929 return lgdt330x_get_dvb_frontend(client);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700930}
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500931EXPORT_SYMBOL(lgdt330x_attach);
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700932
Max Kellermannbd336e62016-08-09 18:32:21 -0300933static const struct dvb_frontend_ops lgdt3302_ops = {
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300934 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700935 .info = {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500936 .name = "LG Electronics LGDT3302 VSB/QAM Frontend",
Mauro Carvalho Chehabf1b1eab2018-07-05 18:59:36 -0400937 .frequency_min_hz = 54 * MHz,
938 .frequency_max_hz = 858 * MHz,
939 .frequency_stepsize_hz = 62500,
Michael Krufky66944e92005-11-08 21:35:55 -0800940 .symbol_rate_min = 5056941, /* QAM 64 */
941 .symbol_rate_max = 10762000, /* VSB 8 */
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700942 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
943 },
Michael Krufky6ddcc912005-07-27 11:46:00 -0700944 .init = lgdt330x_init,
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300945 .set_frontend = lgdt330x_set_parameters,
946 .get_frontend = lgdt330x_get_frontend,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700947 .get_tune_settings = lgdt330x_get_tune_settings,
Michael Krufky1963c902005-08-08 09:22:43 -0700948 .read_status = lgdt3302_read_status,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700949 .read_signal_strength = lgdt330x_read_signal_strength,
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500950 .read_snr = lgdt330x_read_snr,
Michael Krufky6ddcc912005-07-27 11:46:00 -0700951 .read_ucblocks = lgdt330x_read_ucblocks,
952 .release = lgdt330x_release,
Mac Michaelsd8667cb2005-07-07 17:58:29 -0700953};
954
Max Kellermannbd336e62016-08-09 18:32:21 -0300955static const struct dvb_frontend_ops lgdt3303_ops = {
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300956 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
Michael Krufky1963c902005-08-08 09:22:43 -0700957 .info = {
Mauro Carvalho Chehab467845a2018-03-09 10:53:27 -0500958 .name = "LG Electronics LGDT3303 VSB/QAM Frontend",
Mauro Carvalho Chehabf1b1eab2018-07-05 18:59:36 -0400959 .frequency_min_hz = 54 * MHz,
960 .frequency_max_hz = 858 * MHz,
961 .frequency_stepsize_hz = 62500,
Michael Krufky66944e92005-11-08 21:35:55 -0800962 .symbol_rate_min = 5056941, /* QAM 64 */
963 .symbol_rate_max = 10762000, /* VSB 8 */
Michael Krufky1963c902005-08-08 09:22:43 -0700964 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
965 },
966 .init = lgdt330x_init,
Mauro Carvalho Chehabca7072d2011-12-26 11:25:21 -0300967 .set_frontend = lgdt330x_set_parameters,
968 .get_frontend = lgdt330x_get_frontend,
Michael Krufky1963c902005-08-08 09:22:43 -0700969 .get_tune_settings = lgdt330x_get_tune_settings,
970 .read_status = lgdt3303_read_status,
Michael Krufky1963c902005-08-08 09:22:43 -0700971 .read_signal_strength = lgdt330x_read_signal_strength,
Mauro Carvalho Chehab19bdd0d2018-03-09 10:53:34 -0500972 .read_snr = lgdt330x_read_snr,
Michael Krufky1963c902005-08-08 09:22:43 -0700973 .read_ucblocks = lgdt330x_read_ucblocks,
974 .release = lgdt330x_release,
975};
976
Mauro Carvalho Chehab23ba6352018-03-09 10:53:30 -0500977static int lgdt330x_remove(struct i2c_client *client)
978{
979 struct lgdt330x_state *state = i2c_get_clientdata(client);
980
981 dev_dbg(&client->dev, "\n");
982
983 kfree(state);
984
985 return 0;
986}
987
988static const struct i2c_device_id lgdt330x_id_table[] = {
989 {"lgdt330x", 0},
990 {}
991};
992MODULE_DEVICE_TABLE(i2c, lgdt330x_id_table);
993
994static struct i2c_driver lgdt330x_driver = {
995 .driver = {
996 .name = "lgdt330x",
997 .suppress_bind_attrs = true,
998 },
999 .probe = lgdt330x_probe,
1000 .remove = lgdt330x_remove,
1001 .id_table = lgdt330x_id_table,
1002};
1003
1004module_i2c_driver(lgdt330x_driver);
1005
1006
Michael Krufky1963c902005-08-08 09:22:43 -07001007MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
Mac Michaelsd8667cb2005-07-07 17:58:29 -07001008MODULE_AUTHOR("Wilson Michaels");
1009MODULE_LICENSE("GPL");