blob: 6ec2774213909d8ffe653438ddf4db41a0c16f03 [file] [log] [blame]
Thomas Gleixner16216332019-05-19 15:51:31 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Thomas Mair82041c02012-05-18 14:47:40 -03002/*
3 * Realtek RTL2832 DVB-T demodulator driver
4 *
5 * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
Antti Palosaari75c24002014-12-16 13:54:23 -03006 * Copyright (C) 2012-2014 Antti Palosaari <crope@iki.fi>
Thomas Mair82041c02012-05-18 14:47:40 -03007 */
8
9#include "rtl2832_priv.h"
Thomas Mair82041c02012-05-18 14:47:40 -030010
Mauro Carvalho Chehab298f18a2012-07-05 12:16:26 -030011#define REG_MASK(b) (BIT(b + 1) - 1)
Thomas Mair82041c02012-05-18 14:47:40 -030012
13static const struct rtl2832_reg_entry registers[] = {
Antti Palosaarieec21be2014-12-15 01:17:25 -030014 [DVBT_SOFT_RST] = {0x101, 2, 2},
15 [DVBT_IIC_REPEAT] = {0x101, 3, 3},
16 [DVBT_TR_WAIT_MIN_8K] = {0x188, 11, 2},
17 [DVBT_RSD_BER_FAIL_VAL] = {0x18f, 15, 0},
18 [DVBT_EN_BK_TRK] = {0x1a6, 7, 7},
19 [DVBT_AD_EN_REG] = {0x008, 7, 7},
20 [DVBT_AD_EN_REG1] = {0x008, 6, 6},
21 [DVBT_EN_BBIN] = {0x1b1, 0, 0},
22 [DVBT_MGD_THD0] = {0x195, 7, 0},
23 [DVBT_MGD_THD1] = {0x196, 7, 0},
24 [DVBT_MGD_THD2] = {0x197, 7, 0},
25 [DVBT_MGD_THD3] = {0x198, 7, 0},
26 [DVBT_MGD_THD4] = {0x199, 7, 0},
27 [DVBT_MGD_THD5] = {0x19a, 7, 0},
28 [DVBT_MGD_THD6] = {0x19b, 7, 0},
29 [DVBT_MGD_THD7] = {0x19c, 7, 0},
30 [DVBT_EN_CACQ_NOTCH] = {0x161, 4, 4},
31 [DVBT_AD_AV_REF] = {0x009, 6, 0},
32 [DVBT_REG_PI] = {0x00a, 2, 0},
33 [DVBT_PIP_ON] = {0x021, 3, 3},
34 [DVBT_SCALE1_B92] = {0x292, 7, 0},
35 [DVBT_SCALE1_B93] = {0x293, 7, 0},
36 [DVBT_SCALE1_BA7] = {0x2a7, 7, 0},
37 [DVBT_SCALE1_BA9] = {0x2a9, 7, 0},
38 [DVBT_SCALE1_BAA] = {0x2aa, 7, 0},
39 [DVBT_SCALE1_BAB] = {0x2ab, 7, 0},
40 [DVBT_SCALE1_BAC] = {0x2ac, 7, 0},
41 [DVBT_SCALE1_BB0] = {0x2b0, 7, 0},
42 [DVBT_SCALE1_BB1] = {0x2b1, 7, 0},
43 [DVBT_KB_P1] = {0x164, 3, 1},
44 [DVBT_KB_P2] = {0x164, 6, 4},
45 [DVBT_KB_P3] = {0x165, 2, 0},
46 [DVBT_OPT_ADC_IQ] = {0x006, 5, 4},
47 [DVBT_AD_AVI] = {0x009, 1, 0},
48 [DVBT_AD_AVQ] = {0x009, 3, 2},
49 [DVBT_K1_CR_STEP12] = {0x2ad, 9, 4},
50 [DVBT_TRK_KS_P2] = {0x16f, 2, 0},
51 [DVBT_TRK_KS_I2] = {0x170, 5, 3},
52 [DVBT_TR_THD_SET2] = {0x172, 3, 0},
53 [DVBT_TRK_KC_P2] = {0x173, 5, 3},
54 [DVBT_TRK_KC_I2] = {0x175, 2, 0},
55 [DVBT_CR_THD_SET2] = {0x176, 7, 6},
56 [DVBT_PSET_IFFREQ] = {0x119, 21, 0},
57 [DVBT_SPEC_INV] = {0x115, 0, 0},
58 [DVBT_RSAMP_RATIO] = {0x19f, 27, 2},
59 [DVBT_CFREQ_OFF_RATIO] = {0x19d, 23, 4},
60 [DVBT_FSM_STAGE] = {0x351, 6, 3},
61 [DVBT_RX_CONSTEL] = {0x33c, 3, 2},
62 [DVBT_RX_HIER] = {0x33c, 6, 4},
63 [DVBT_RX_C_RATE_LP] = {0x33d, 2, 0},
64 [DVBT_RX_C_RATE_HP] = {0x33d, 5, 3},
65 [DVBT_GI_IDX] = {0x351, 1, 0},
66 [DVBT_FFT_MODE_IDX] = {0x351, 2, 2},
67 [DVBT_RSD_BER_EST] = {0x34e, 15, 0},
68 [DVBT_CE_EST_EVM] = {0x40c, 15, 0},
69 [DVBT_RF_AGC_VAL] = {0x35b, 13, 0},
70 [DVBT_IF_AGC_VAL] = {0x359, 13, 0},
71 [DVBT_DAGC_VAL] = {0x305, 7, 0},
72 [DVBT_SFREQ_OFF] = {0x318, 13, 0},
73 [DVBT_CFREQ_OFF] = {0x35f, 17, 0},
74 [DVBT_POLAR_RF_AGC] = {0x00e, 1, 1},
75 [DVBT_POLAR_IF_AGC] = {0x00e, 0, 0},
76 [DVBT_AAGC_HOLD] = {0x104, 5, 5},
77 [DVBT_EN_RF_AGC] = {0x104, 6, 6},
78 [DVBT_EN_IF_AGC] = {0x104, 7, 7},
79 [DVBT_IF_AGC_MIN] = {0x108, 7, 0},
80 [DVBT_IF_AGC_MAX] = {0x109, 7, 0},
81 [DVBT_RF_AGC_MIN] = {0x10a, 7, 0},
82 [DVBT_RF_AGC_MAX] = {0x10b, 7, 0},
83 [DVBT_IF_AGC_MAN] = {0x10c, 6, 6},
84 [DVBT_IF_AGC_MAN_VAL] = {0x10c, 13, 0},
85 [DVBT_RF_AGC_MAN] = {0x10e, 6, 6},
86 [DVBT_RF_AGC_MAN_VAL] = {0x10e, 13, 0},
87 [DVBT_DAGC_TRG_VAL] = {0x112, 7, 0},
88 [DVBT_AGC_TARG_VAL_0] = {0x102, 0, 0},
89 [DVBT_AGC_TARG_VAL_8_1] = {0x103, 7, 0},
90 [DVBT_AAGC_LOOP_GAIN] = {0x1c7, 5, 1},
91 [DVBT_LOOP_GAIN2_3_0] = {0x104, 4, 1},
92 [DVBT_LOOP_GAIN2_4] = {0x105, 7, 7},
93 [DVBT_LOOP_GAIN3] = {0x1c8, 4, 0},
94 [DVBT_VTOP1] = {0x106, 5, 0},
95 [DVBT_VTOP2] = {0x1c9, 5, 0},
96 [DVBT_VTOP3] = {0x1ca, 5, 0},
97 [DVBT_KRF1] = {0x1cb, 7, 0},
98 [DVBT_KRF2] = {0x107, 7, 0},
99 [DVBT_KRF3] = {0x1cd, 7, 0},
100 [DVBT_KRF4] = {0x1ce, 7, 0},
101 [DVBT_EN_GI_PGA] = {0x1e5, 0, 0},
102 [DVBT_THD_LOCK_UP] = {0x1d9, 8, 0},
103 [DVBT_THD_LOCK_DW] = {0x1db, 8, 0},
104 [DVBT_THD_UP1] = {0x1dd, 7, 0},
105 [DVBT_THD_DW1] = {0x1de, 7, 0},
106 [DVBT_INTER_CNT_LEN] = {0x1d8, 3, 0},
107 [DVBT_GI_PGA_STATE] = {0x1e6, 3, 3},
108 [DVBT_EN_AGC_PGA] = {0x1d7, 0, 0},
109 [DVBT_CKOUTPAR] = {0x17b, 5, 5},
110 [DVBT_CKOUT_PWR] = {0x17b, 6, 6},
111 [DVBT_SYNC_DUR] = {0x17b, 7, 7},
112 [DVBT_ERR_DUR] = {0x17c, 0, 0},
113 [DVBT_SYNC_LVL] = {0x17c, 1, 1},
114 [DVBT_ERR_LVL] = {0x17c, 2, 2},
115 [DVBT_VAL_LVL] = {0x17c, 3, 3},
116 [DVBT_SERIAL] = {0x17c, 4, 4},
117 [DVBT_SER_LSB] = {0x17c, 5, 5},
118 [DVBT_CDIV_PH0] = {0x17d, 3, 0},
119 [DVBT_CDIV_PH1] = {0x17d, 7, 4},
120 [DVBT_MPEG_IO_OPT_2_2] = {0x006, 7, 7},
121 [DVBT_MPEG_IO_OPT_1_0] = {0x007, 7, 6},
122 [DVBT_CKOUTPAR_PIP] = {0x0b7, 4, 4},
123 [DVBT_CKOUT_PWR_PIP] = {0x0b7, 3, 3},
124 [DVBT_SYNC_LVL_PIP] = {0x0b7, 2, 2},
125 [DVBT_ERR_LVL_PIP] = {0x0b7, 1, 1},
126 [DVBT_VAL_LVL_PIP] = {0x0b7, 0, 0},
127 [DVBT_CKOUTPAR_PID] = {0x0b9, 4, 4},
128 [DVBT_CKOUT_PWR_PID] = {0x0b9, 3, 3},
129 [DVBT_SYNC_LVL_PID] = {0x0b9, 2, 2},
130 [DVBT_ERR_LVL_PID] = {0x0b9, 1, 1},
131 [DVBT_VAL_LVL_PID] = {0x0b9, 0, 0},
132 [DVBT_SM_PASS] = {0x193, 11, 0},
133 [DVBT_AD7_SETTING] = {0x011, 15, 0},
134 [DVBT_RSSI_R] = {0x301, 6, 0},
135 [DVBT_ACI_DET_IND] = {0x312, 0, 0},
136 [DVBT_REG_MON] = {0x00d, 1, 0},
137 [DVBT_REG_MONSEL] = {0x00d, 2, 2},
138 [DVBT_REG_GPE] = {0x00d, 7, 7},
139 [DVBT_REG_GPO] = {0x010, 0, 0},
140 [DVBT_REG_4MSEL] = {0x013, 0, 0},
Thomas Mair82041c02012-05-18 14:47:40 -0300141};
142
Antti Palosaari038c6f22014-12-13 00:37:43 -0300143static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val)
Thomas Mair82041c02012-05-18 14:47:40 -0300144{
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300145 struct i2c_client *client = dev->client;
Antti Palosaaricd559e02014-12-16 13:37:18 -0300146 int ret, i;
Antti Palosaarieec21be2014-12-15 01:17:25 -0300147 u16 reg_start_addr;
Antti Palosaaricd559e02014-12-16 13:37:18 -0300148 u8 msb, lsb, reading[4], len;
149 u32 reading_tmp, mask;
Thomas Mair82041c02012-05-18 14:47:40 -0300150
151 reg_start_addr = registers[reg].start_address;
152 msb = registers[reg].msb;
153 lsb = registers[reg].lsb;
Thomas Mair82041c02012-05-18 14:47:40 -0300154 len = (msb >> 3) + 1;
Mauro Carvalho Chehab298f18a2012-07-05 12:16:26 -0300155 mask = REG_MASK(msb - lsb);
Thomas Mair82041c02012-05-18 14:47:40 -0300156
Peter Rosin1cf79db2016-05-04 22:15:33 +0200157 ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
Thomas Mair82041c02012-05-18 14:47:40 -0300158 if (ret)
159 goto err;
160
161 reading_tmp = 0;
162 for (i = 0; i < len; i++)
163 reading_tmp |= reading[i] << ((len - 1 - i) * 8);
164
165 *val = (reading_tmp >> lsb) & mask;
166
Antti Palosaaricd559e02014-12-16 13:37:18 -0300167 return 0;
Thomas Mair82041c02012-05-18 14:47:40 -0300168err:
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300169 dev_dbg(&client->dev, "failed=%d\n", ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300170 return ret;
Thomas Mair82041c02012-05-18 14:47:40 -0300171}
172
Antti Palosaari038c6f22014-12-13 00:37:43 -0300173static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val)
Thomas Mair82041c02012-05-18 14:47:40 -0300174{
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300175 struct i2c_client *client = dev->client;
Thomas Mair82041c02012-05-18 14:47:40 -0300176 int ret, i;
Antti Palosaarieec21be2014-12-15 01:17:25 -0300177 u16 reg_start_addr;
Antti Palosaaricd559e02014-12-16 13:37:18 -0300178 u8 msb, lsb, reading[4], writing[4], len;
179 u32 reading_tmp, writing_tmp, mask;
Thomas Mair82041c02012-05-18 14:47:40 -0300180
181 reg_start_addr = registers[reg].start_address;
182 msb = registers[reg].msb;
183 lsb = registers[reg].lsb;
Thomas Mair82041c02012-05-18 14:47:40 -0300184 len = (msb >> 3) + 1;
Mauro Carvalho Chehab298f18a2012-07-05 12:16:26 -0300185 mask = REG_MASK(msb - lsb);
Thomas Mair82041c02012-05-18 14:47:40 -0300186
Peter Rosin1cf79db2016-05-04 22:15:33 +0200187 ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
Thomas Mair82041c02012-05-18 14:47:40 -0300188 if (ret)
189 goto err;
190
191 reading_tmp = 0;
192 for (i = 0; i < len; i++)
193 reading_tmp |= reading[i] << ((len - 1 - i) * 8);
194
195 writing_tmp = reading_tmp & ~(mask << lsb);
196 writing_tmp |= ((val & mask) << lsb);
197
Thomas Mair82041c02012-05-18 14:47:40 -0300198 for (i = 0; i < len; i++)
199 writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
200
Peter Rosin1cf79db2016-05-04 22:15:33 +0200201 ret = regmap_bulk_write(dev->regmap, reg_start_addr, writing, len);
Thomas Mair82041c02012-05-18 14:47:40 -0300202 if (ret)
203 goto err;
204
Antti Palosaaricd559e02014-12-16 13:37:18 -0300205 return 0;
Thomas Mair82041c02012-05-18 14:47:40 -0300206err:
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300207 dev_dbg(&client->dev, "failed=%d\n", ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300208 return ret;
Thomas Mair82041c02012-05-18 14:47:40 -0300209}
210
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300211static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq)
212{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300213 struct rtl2832_dev *dev = fe->demodulator_priv;
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300214 struct i2c_client *client = dev->client;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300215 int ret;
216 u64 pset_iffreq;
217 u8 en_bbin = (if_freq == 0 ? 0x1 : 0x0);
218
219 /*
220 * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22)
221 * / CrystalFreqHz)
222 */
Antti Palosaarie1174d72014-12-13 05:26:27 -0300223 pset_iffreq = if_freq % dev->pdata->clk;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300224 pset_iffreq *= 0x400000;
Antti Palosaarie1174d72014-12-13 05:26:27 -0300225 pset_iffreq = div_u64(pset_iffreq, dev->pdata->clk);
Mauro Carvalho Chehabc8832e82013-04-15 19:44:39 -0300226 pset_iffreq = -pset_iffreq;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300227 pset_iffreq = pset_iffreq & 0x3fffff;
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300228 dev_dbg(&client->dev, "if_frequency=%d pset_iffreq=%08x\n",
229 if_freq, (unsigned)pset_iffreq);
Mauro Carvalho Chehabc8832e82013-04-15 19:44:39 -0300230
Antti Palosaari038c6f22014-12-13 00:37:43 -0300231 ret = rtl2832_wr_demod_reg(dev, DVBT_EN_BBIN, en_bbin);
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300232 if (ret)
Antti Palosaaricd559e02014-12-16 13:37:18 -0300233 goto err;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300234
Antti Palosaari038c6f22014-12-13 00:37:43 -0300235 ret = rtl2832_wr_demod_reg(dev, DVBT_PSET_IFFREQ, pset_iffreq);
Antti Palosaaricd559e02014-12-16 13:37:18 -0300236 if (ret)
237 goto err;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300238
Antti Palosaaricd559e02014-12-16 13:37:18 -0300239 return 0;
240err:
241 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari3ca24182013-10-13 00:06:44 -0300242 return ret;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300243}
244
Thomas Mair82041c02012-05-18 14:47:40 -0300245static int rtl2832_init(struct dvb_frontend *fe)
246{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300247 struct rtl2832_dev *dev = fe->demodulator_priv;
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300248 struct i2c_client *client = dev->client;
Antti Palosaari19d273d2014-12-14 06:55:43 -0300249 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300250 const struct rtl2832_reg_value *init;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300251 int i, ret, len;
Thomas Mair82041c02012-05-18 14:47:40 -0300252 /* initialization values for the demodulator registers */
253 struct rtl2832_reg_value rtl2832_initial_regs[] = {
254 {DVBT_AD_EN_REG, 0x1},
255 {DVBT_AD_EN_REG1, 0x1},
256 {DVBT_RSD_BER_FAIL_VAL, 0x2800},
257 {DVBT_MGD_THD0, 0x10},
258 {DVBT_MGD_THD1, 0x20},
259 {DVBT_MGD_THD2, 0x20},
260 {DVBT_MGD_THD3, 0x40},
261 {DVBT_MGD_THD4, 0x22},
262 {DVBT_MGD_THD5, 0x32},
263 {DVBT_MGD_THD6, 0x37},
264 {DVBT_MGD_THD7, 0x39},
265 {DVBT_EN_BK_TRK, 0x0},
266 {DVBT_EN_CACQ_NOTCH, 0x0},
267 {DVBT_AD_AV_REF, 0x2a},
268 {DVBT_REG_PI, 0x6},
269 {DVBT_PIP_ON, 0x0},
270 {DVBT_CDIV_PH0, 0x8},
271 {DVBT_CDIV_PH1, 0x8},
272 {DVBT_SCALE1_B92, 0x4},
273 {DVBT_SCALE1_B93, 0xb0},
274 {DVBT_SCALE1_BA7, 0x78},
275 {DVBT_SCALE1_BA9, 0x28},
276 {DVBT_SCALE1_BAA, 0x59},
277 {DVBT_SCALE1_BAB, 0x83},
278 {DVBT_SCALE1_BAC, 0xd4},
279 {DVBT_SCALE1_BB0, 0x65},
280 {DVBT_SCALE1_BB1, 0x43},
281 {DVBT_KB_P1, 0x1},
282 {DVBT_KB_P2, 0x4},
283 {DVBT_KB_P3, 0x7},
284 {DVBT_K1_CR_STEP12, 0xa},
285 {DVBT_REG_GPE, 0x1},
286 {DVBT_SERIAL, 0x0},
287 {DVBT_CDIV_PH0, 0x9},
288 {DVBT_CDIV_PH1, 0x9},
289 {DVBT_MPEG_IO_OPT_2_2, 0x0},
290 {DVBT_MPEG_IO_OPT_1_0, 0x0},
291 {DVBT_TRK_KS_P2, 0x4},
292 {DVBT_TRK_KS_I2, 0x7},
293 {DVBT_TR_THD_SET2, 0x6},
294 {DVBT_TRK_KC_I2, 0x5},
295 {DVBT_CR_THD_SET2, 0x1},
Thomas Mair82041c02012-05-18 14:47:40 -0300296 };
297
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300298 dev_dbg(&client->dev, "\n");
Thomas Mair82041c02012-05-18 14:47:40 -0300299
Antti Palosaarid884aca2016-02-05 18:26:30 -0200300 ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0);
301 if (ret)
302 goto err;
303
Thomas Mair82041c02012-05-18 14:47:40 -0300304 for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) {
Antti Palosaari038c6f22014-12-13 00:37:43 -0300305 ret = rtl2832_wr_demod_reg(dev, rtl2832_initial_regs[i].reg,
Thomas Mair82041c02012-05-18 14:47:40 -0300306 rtl2832_initial_regs[i].value);
307 if (ret)
308 goto err;
309 }
310
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300311 /* load tuner specific settings */
Antti Palosaarie1174d72014-12-13 05:26:27 -0300312 dev_dbg(&client->dev, "load settings for tuner=%02x\n",
313 dev->pdata->tuner);
314 switch (dev->pdata->tuner) {
Antti Palosaarif88aae92015-04-23 22:52:07 -0300315 case RTL2832_TUNER_FC2580:
316 len = ARRAY_SIZE(rtl2832_tuner_init_fc2580);
317 init = rtl2832_tuner_init_fc2580;
318 break;
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300319 case RTL2832_TUNER_FC0012:
320 case RTL2832_TUNER_FC0013:
321 len = ARRAY_SIZE(rtl2832_tuner_init_fc0012);
322 init = rtl2832_tuner_init_fc0012;
323 break;
Antti Palosaari5db41872012-09-11 22:27:08 -0300324 case RTL2832_TUNER_TUA9001:
325 len = ARRAY_SIZE(rtl2832_tuner_init_tua9001);
326 init = rtl2832_tuner_init_tua9001;
327 break;
Antti Palosaari7e688de2012-09-17 17:53:04 -0300328 case RTL2832_TUNER_E4000:
329 len = ARRAY_SIZE(rtl2832_tuner_init_e4000);
330 init = rtl2832_tuner_init_e4000;
331 break;
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300332 case RTL2832_TUNER_R820T:
Antti Palosaaria26758e2013-10-30 00:36:38 -0300333 case RTL2832_TUNER_R828D:
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300334 len = ARRAY_SIZE(rtl2832_tuner_init_r820t);
335 init = rtl2832_tuner_init_r820t;
336 break;
Olli Salonen699dcff2015-05-05 13:54:19 -0300337 case RTL2832_TUNER_SI2157:
338 len = ARRAY_SIZE(rtl2832_tuner_init_si2157);
339 init = rtl2832_tuner_init_si2157;
340 break;
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300341 default:
342 ret = -EINVAL;
343 goto err;
344 }
345
346 for (i = 0; i < len; i++) {
Antti Palosaari038c6f22014-12-13 00:37:43 -0300347 ret = rtl2832_wr_demod_reg(dev, init[i].reg, init[i].value);
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300348 if (ret)
349 goto err;
350 }
351
Antti Palosaari19d273d2014-12-14 06:55:43 -0300352 /* init stats here in order signal app which stats are supported */
Antti Palosaari25ef9f52014-12-14 11:00:50 -0300353 c->strength.len = 1;
354 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari19d273d2014-12-14 06:55:43 -0300355 c->cnr.len = 1;
356 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari6b4fd012014-12-14 09:59:20 -0300357 c->post_bit_error.len = 1;
358 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
359 c->post_bit_count.len = 1;
360 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari038c6f22014-12-13 00:37:43 -0300361 dev->sleeping = false;
Thomas Mair82041c02012-05-18 14:47:40 -0300362
Antti Palosaaricd559e02014-12-16 13:37:18 -0300363 return 0;
Thomas Mair82041c02012-05-18 14:47:40 -0300364err:
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300365 dev_dbg(&client->dev, "failed=%d\n", ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300366 return ret;
367}
368
369static int rtl2832_sleep(struct dvb_frontend *fe)
370{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300371 struct rtl2832_dev *dev = fe->demodulator_priv;
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300372 struct i2c_client *client = dev->client;
Antti Palosaaria08c3782014-12-16 14:51:33 -0300373 int ret;
Thomas Mair82041c02012-05-18 14:47:40 -0300374
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300375 dev_dbg(&client->dev, "\n");
Antti Palosaaria08c3782014-12-16 14:51:33 -0300376
Antti Palosaari038c6f22014-12-13 00:37:43 -0300377 dev->sleeping = true;
Antti Palosaari19d273d2014-12-14 06:55:43 -0300378 dev->fe_status = 0;
Antti Palosaaria08c3782014-12-16 14:51:33 -0300379
380 ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1);
381 if (ret)
382 goto err;
383
Thomas Mair82041c02012-05-18 14:47:40 -0300384 return 0;
Antti Palosaaria08c3782014-12-16 14:51:33 -0300385err:
386 dev_dbg(&client->dev, "failed=%d\n", ret);
387 return ret;
Thomas Mair82041c02012-05-18 14:47:40 -0300388}
389
Mauro Carvalho Chehabb0944ea2012-10-27 11:24:37 -0300390static int rtl2832_get_tune_settings(struct dvb_frontend *fe,
Thomas Mair82041c02012-05-18 14:47:40 -0300391 struct dvb_frontend_tune_settings *s)
392{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300393 struct rtl2832_dev *dev = fe->demodulator_priv;
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300394 struct i2c_client *client = dev->client;
Antti Palosaari298efdd2012-09-11 22:27:11 -0300395
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300396 dev_dbg(&client->dev, "\n");
Thomas Mair82041c02012-05-18 14:47:40 -0300397 s->min_delay_ms = 1000;
Mauro Carvalho Chehabf1b1eab2018-07-05 18:59:36 -0400398 s->step_size = fe->ops.info.frequency_stepsize_hz * 2;
399 s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1;
Thomas Mair82041c02012-05-18 14:47:40 -0300400 return 0;
401}
402
403static int rtl2832_set_frontend(struct dvb_frontend *fe)
404{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300405 struct rtl2832_dev *dev = fe->demodulator_priv;
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300406 struct i2c_client *client = dev->client;
Thomas Mair82041c02012-05-18 14:47:40 -0300407 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
408 int ret, i, j;
409 u64 bw_mode, num, num2;
410 u32 resamp_ratio, cfreq_off_ratio;
Thomas Mair82041c02012-05-18 14:47:40 -0300411 static u8 bw_params[3][32] = {
412 /* 6 MHz bandwidth */
413 {
414 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f,
415 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2,
416 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67,
417 0x19, 0xe0,
418 },
419
420 /* 7 MHz bandwidth */
421 {
422 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf,
423 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30,
424 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22,
425 0x19, 0x10,
426 },
427
428 /* 8 MHz bandwidth */
429 {
430 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf,
431 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7,
432 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8,
433 0x19, 0xe0,
434 },
435 };
436
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300437 dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n",
438 c->frequency, c->bandwidth_hz, c->inversion);
Thomas Mair82041c02012-05-18 14:47:40 -0300439
440 /* program tuner */
441 if (fe->ops.tuner_ops.set_params)
442 fe->ops.tuner_ops.set_params(fe);
443
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300444 /* If the frontend has get_if_frequency(), use it */
445 if (fe->ops.tuner_ops.get_if_frequency) {
446 u32 if_freq;
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300447
448 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
449 if (ret)
450 goto err;
451
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300452 ret = rtl2832_set_if(fe, if_freq);
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300453 if (ret)
454 goto err;
455 }
456
Thomas Mair82041c02012-05-18 14:47:40 -0300457 switch (c->bandwidth_hz) {
458 case 6000000:
459 i = 0;
460 bw_mode = 48000000;
461 break;
462 case 7000000:
463 i = 1;
464 bw_mode = 56000000;
465 break;
466 case 8000000:
467 i = 2;
468 bw_mode = 64000000;
469 break;
470 default:
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300471 dev_err(&client->dev, "invalid bandwidth_hz %u\n",
472 c->bandwidth_hz);
473 ret = -EINVAL;
474 goto err;
Thomas Mair82041c02012-05-18 14:47:40 -0300475 }
476
Hans-Frieder Vogtfc4b3fa2012-07-15 13:56:47 -0300477 for (j = 0; j < sizeof(bw_params[0]); j++) {
Peter Rosin1cf79db2016-05-04 22:15:33 +0200478 ret = regmap_bulk_write(dev->regmap,
479 0x11c + j, &bw_params[i][j], 1);
Thomas Mair82041c02012-05-18 14:47:40 -0300480 if (ret)
481 goto err;
482 }
483
484 /* calculate and set resample ratio
485 * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22)
486 * / ConstWithBandwidthMode)
487 */
Gustavo A. R. Silva1ae207f2018-02-06 11:46:59 -0500488 num = dev->pdata->clk * 7ULL;
Thomas Mair82041c02012-05-18 14:47:40 -0300489 num *= 0x400000;
490 num = div_u64(num, bw_mode);
491 resamp_ratio = num & 0x3ffffff;
Antti Palosaari038c6f22014-12-13 00:37:43 -0300492 ret = rtl2832_wr_demod_reg(dev, DVBT_RSAMP_RATIO, resamp_ratio);
Thomas Mair82041c02012-05-18 14:47:40 -0300493 if (ret)
494 goto err;
495
496 /* calculate and set cfreq off ratio
497 * CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20)
498 * / (CrystalFreqHz * 7))
499 */
500 num = bw_mode << 20;
Gustavo A. R. Silva1ae207f2018-02-06 11:46:59 -0500501 num2 = dev->pdata->clk * 7ULL;
Thomas Mair82041c02012-05-18 14:47:40 -0300502 num = div_u64(num, num2);
503 num = -num;
504 cfreq_off_ratio = num & 0xfffff;
Antti Palosaari038c6f22014-12-13 00:37:43 -0300505 ret = rtl2832_wr_demod_reg(dev, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio);
Thomas Mair82041c02012-05-18 14:47:40 -0300506 if (ret)
507 goto err;
508
Thomas Mair82041c02012-05-18 14:47:40 -0300509 /* soft reset */
Antti Palosaari038c6f22014-12-13 00:37:43 -0300510 ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1);
Thomas Mair82041c02012-05-18 14:47:40 -0300511 if (ret)
512 goto err;
513
Antti Palosaari038c6f22014-12-13 00:37:43 -0300514 ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0);
Thomas Mair82041c02012-05-18 14:47:40 -0300515 if (ret)
516 goto err;
517
Antti Palosaaricd559e02014-12-16 13:37:18 -0300518 return 0;
Thomas Mair82041c02012-05-18 14:47:40 -0300519err:
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300520 dev_dbg(&client->dev, "failed=%d\n", ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300521 return ret;
522}
523
Mauro Carvalho Chehab7e3e68b2016-02-04 12:58:30 -0200524static int rtl2832_get_frontend(struct dvb_frontend *fe,
525 struct dtv_frontend_properties *c)
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300526{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300527 struct rtl2832_dev *dev = fe->demodulator_priv;
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300528 struct i2c_client *client = dev->client;
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300529 int ret;
530 u8 buf[3];
531
Antti Palosaari038c6f22014-12-13 00:37:43 -0300532 if (dev->sleeping)
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300533 return 0;
534
Peter Rosin1cf79db2016-05-04 22:15:33 +0200535 ret = regmap_bulk_read(dev->regmap, 0x33c, buf, 2);
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300536 if (ret)
537 goto err;
538
Peter Rosin1cf79db2016-05-04 22:15:33 +0200539 ret = regmap_bulk_read(dev->regmap, 0x351, &buf[2], 1);
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300540 if (ret)
541 goto err;
542
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300543 dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf);
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300544
545 switch ((buf[0] >> 2) & 3) {
546 case 0:
547 c->modulation = QPSK;
548 break;
549 case 1:
550 c->modulation = QAM_16;
551 break;
552 case 2:
553 c->modulation = QAM_64;
554 break;
555 }
556
557 switch ((buf[2] >> 2) & 1) {
558 case 0:
559 c->transmission_mode = TRANSMISSION_MODE_2K;
560 break;
561 case 1:
562 c->transmission_mode = TRANSMISSION_MODE_8K;
563 }
564
565 switch ((buf[2] >> 0) & 3) {
566 case 0:
567 c->guard_interval = GUARD_INTERVAL_1_32;
568 break;
569 case 1:
570 c->guard_interval = GUARD_INTERVAL_1_16;
571 break;
572 case 2:
573 c->guard_interval = GUARD_INTERVAL_1_8;
574 break;
575 case 3:
576 c->guard_interval = GUARD_INTERVAL_1_4;
577 break;
578 }
579
580 switch ((buf[0] >> 4) & 7) {
581 case 0:
582 c->hierarchy = HIERARCHY_NONE;
583 break;
584 case 1:
585 c->hierarchy = HIERARCHY_1;
586 break;
587 case 2:
588 c->hierarchy = HIERARCHY_2;
589 break;
590 case 3:
591 c->hierarchy = HIERARCHY_4;
592 break;
593 }
594
595 switch ((buf[1] >> 3) & 7) {
596 case 0:
597 c->code_rate_HP = FEC_1_2;
598 break;
599 case 1:
600 c->code_rate_HP = FEC_2_3;
601 break;
602 case 2:
603 c->code_rate_HP = FEC_3_4;
604 break;
605 case 3:
606 c->code_rate_HP = FEC_5_6;
607 break;
608 case 4:
609 c->code_rate_HP = FEC_7_8;
610 break;
611 }
612
613 switch ((buf[1] >> 0) & 7) {
614 case 0:
615 c->code_rate_LP = FEC_1_2;
616 break;
617 case 1:
618 c->code_rate_LP = FEC_2_3;
619 break;
620 case 2:
621 c->code_rate_LP = FEC_3_4;
622 break;
623 case 3:
624 c->code_rate_LP = FEC_5_6;
625 break;
626 case 4:
627 c->code_rate_LP = FEC_7_8;
628 break;
629 }
630
631 return 0;
632err:
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300633 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300634 return ret;
635}
636
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300637static int rtl2832_read_status(struct dvb_frontend *fe, enum fe_status *status)
Thomas Mair82041c02012-05-18 14:47:40 -0300638{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300639 struct rtl2832_dev *dev = fe->demodulator_priv;
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300640 struct i2c_client *client = dev->client;
Antti Palosaari426508e2016-02-06 20:12:05 -0200641 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Thomas Mair82041c02012-05-18 14:47:40 -0300642 int ret;
Luis de Bethencourt20357752015-02-11 08:08:51 -0300643 u32 uninitialized_var(tmp);
Antti Palosaari426508e2016-02-06 20:12:05 -0200644 u8 u8tmp, buf[2];
645 u16 u16tmp;
Thomas Mair82041c02012-05-18 14:47:40 -0300646
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300647 dev_dbg(&client->dev, "\n");
648
649 *status = 0;
Antti Palosaari038c6f22014-12-13 00:37:43 -0300650 if (dev->sleeping)
Thomas Mair82041c02012-05-18 14:47:40 -0300651 return 0;
652
Antti Palosaari038c6f22014-12-13 00:37:43 -0300653 ret = rtl2832_rd_demod_reg(dev, DVBT_FSM_STAGE, &tmp);
Thomas Mair82041c02012-05-18 14:47:40 -0300654 if (ret)
655 goto err;
656
657 if (tmp == 11) {
658 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
659 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
Antti Palosaari1c7da402014-12-14 12:15:55 -0300660 } else if (tmp == 10) {
Thomas Mair82041c02012-05-18 14:47:40 -0300661 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
662 FE_HAS_VITERBI;
Antti Palosaari1c7da402014-12-14 12:15:55 -0300663 }
Thomas Mair82041c02012-05-18 14:47:40 -0300664
Antti Palosaari19d273d2014-12-14 06:55:43 -0300665 dev->fe_status = *status;
Antti Palosaari19d273d2014-12-14 06:55:43 -0300666
Antti Palosaari25ef9f52014-12-14 11:00:50 -0300667 /* signal strength */
668 if (dev->fe_status & FE_HAS_SIGNAL) {
669 /* read digital AGC */
Peter Rosin1cf79db2016-05-04 22:15:33 +0200670 ret = regmap_bulk_read(dev->regmap, 0x305, &u8tmp, 1);
Antti Palosaari25ef9f52014-12-14 11:00:50 -0300671 if (ret)
672 goto err;
673
674 dev_dbg(&client->dev, "digital agc=%02x", u8tmp);
675
676 u8tmp = ~u8tmp;
677 u16tmp = u8tmp << 8 | u8tmp << 0;
678
679 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
680 c->strength.stat[0].uvalue = u16tmp;
681 } else {
682 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
683 }
684
Antti Palosaari19d273d2014-12-14 06:55:43 -0300685 /* CNR */
686 if (dev->fe_status & FE_HAS_VITERBI) {
687 unsigned hierarchy, constellation;
688 #define CONSTELLATION_NUM 3
689 #define HIERARCHY_NUM 4
690 static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
691 {85387325, 85387325, 85387325, 85387325},
692 {86676178, 86676178, 87167949, 87795660},
693 {87659938, 87659938, 87885178, 88241743},
694 };
695
Peter Rosin1cf79db2016-05-04 22:15:33 +0200696 ret = regmap_bulk_read(dev->regmap, 0x33c, &u8tmp, 1);
Antti Palosaari19d273d2014-12-14 06:55:43 -0300697 if (ret)
698 goto err;
699
700 constellation = (u8tmp >> 2) & 0x03; /* [3:2] */
701 if (constellation > CONSTELLATION_NUM - 1)
Antti Palosaari426508e2016-02-06 20:12:05 -0200702 goto err;
Antti Palosaari19d273d2014-12-14 06:55:43 -0300703
704 hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */
705 if (hierarchy > HIERARCHY_NUM - 1)
Antti Palosaari426508e2016-02-06 20:12:05 -0200706 goto err;
Antti Palosaari19d273d2014-12-14 06:55:43 -0300707
Peter Rosin1cf79db2016-05-04 22:15:33 +0200708 ret = regmap_bulk_read(dev->regmap, 0x40c, buf, 2);
Antti Palosaari19d273d2014-12-14 06:55:43 -0300709 if (ret)
710 goto err;
711
712 u16tmp = buf[0] << 8 | buf[1] << 0;
713 if (u16tmp)
714 tmp = (constant[constellation][hierarchy] -
715 intlog10(u16tmp)) / ((1 << 24) / 10000);
716 else
717 tmp = 0;
718
719 dev_dbg(&client->dev, "cnr raw=%u\n", u16tmp);
720
721 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
722 c->cnr.stat[0].svalue = tmp;
723 } else {
724 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
725 }
726
Antti Palosaari6b4fd012014-12-14 09:59:20 -0300727 /* BER */
728 if (dev->fe_status & FE_HAS_LOCK) {
Peter Rosin1cf79db2016-05-04 22:15:33 +0200729 ret = regmap_bulk_read(dev->regmap, 0x34e, buf, 2);
Antti Palosaari6b4fd012014-12-14 09:59:20 -0300730 if (ret)
731 goto err;
732
733 u16tmp = buf[0] << 8 | buf[1] << 0;
734 dev->post_bit_error += u16tmp;
735 dev->post_bit_count += 1000000;
736
737 dev_dbg(&client->dev, "ber errors=%u total=1000000\n", u16tmp);
738
739 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
740 c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
741 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
742 c->post_bit_count.stat[0].uvalue = dev->post_bit_count;
743 } else {
744 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
745 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
746 }
747
Antti Palosaari426508e2016-02-06 20:12:05 -0200748 return 0;
Antti Palosaari19d273d2014-12-14 06:55:43 -0300749err:
750 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari426508e2016-02-06 20:12:05 -0200751 return ret;
752}
753
754static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr)
755{
756 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
757
758 /* report SNR in resolution of 0.1 dB */
759 if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
760 *snr = div_s64(c->cnr.stat[0].svalue, 100);
761 else
762 *snr = 0;
763
764 return 0;
765}
766
767static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber)
768{
769 struct rtl2832_dev *dev = fe->demodulator_priv;
770
771 *ber = (dev->post_bit_error - dev->post_bit_error_prev);
772 dev->post_bit_error_prev = dev->post_bit_error;
773
774 return 0;
Antti Palosaari19d273d2014-12-14 06:55:43 -0300775}
776
Antti Palosaari92d20d92014-02-08 03:50:04 -0300777/*
Antti Palosaarid1016582014-12-14 04:45:57 -0300778 * I2C gate/mux/repeater logic
Antti Palosaarid1016582014-12-14 04:45:57 -0300779 * There is delay mechanism to avoid unneeded I2C gate open / close. Gate close
780 * is delayed here a little bit in order to see if there is sequence of I2C
Antti Palosaari92d20d92014-02-08 03:50:04 -0300781 * messages sent to same I2C bus.
Antti Palosaari92d20d92014-02-08 03:50:04 -0300782 */
783static void rtl2832_i2c_gate_work(struct work_struct *work)
Antti Palosaari8823f022013-11-26 12:53:46 -0300784{
Antti Palosaarid1016582014-12-14 04:45:57 -0300785 struct rtl2832_dev *dev = container_of(work, struct rtl2832_dev, i2c_gate_work.work);
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300786 struct i2c_client *client = dev->client;
Antti Palosaari0ea872d2013-12-03 18:19:39 -0300787 int ret;
Antti Palosaari8823f022013-11-26 12:53:46 -0300788
Antti Palosaarid1016582014-12-14 04:45:57 -0300789 /* close gate */
Peter Rosin1cf79db2016-05-04 22:15:33 +0200790 ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x00);
Antti Palosaarid1016582014-12-14 04:45:57 -0300791 if (ret)
Antti Palosaari92d20d92014-02-08 03:50:04 -0300792 goto err;
793
Antti Palosaari92d20d92014-02-08 03:50:04 -0300794 return;
795err:
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300796 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari92d20d92014-02-08 03:50:04 -0300797}
798
Peter Rosincddcc402016-04-20 08:41:25 +0200799static int rtl2832_select(struct i2c_mux_core *muxc, u32 chan_id)
Antti Palosaari92d20d92014-02-08 03:50:04 -0300800{
Peter Rosincddcc402016-04-20 08:41:25 +0200801 struct rtl2832_dev *dev = i2c_mux_priv(muxc);
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300802 struct i2c_client *client = dev->client;
Antti Palosaari92d20d92014-02-08 03:50:04 -0300803 int ret;
Antti Palosaari92d20d92014-02-08 03:50:04 -0300804
805 /* terminate possible gate closing */
Antti Palosaarid1016582014-12-14 04:45:57 -0300806 cancel_delayed_work(&dev->i2c_gate_work);
Antti Palosaari92d20d92014-02-08 03:50:04 -0300807
Peter Rosin1cf79db2016-05-04 22:15:33 +0200808 /* open gate */
Antti Palosaari0d117902014-12-18 06:30:32 -0300809 ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08);
Antti Palosaarid1016582014-12-14 04:45:57 -0300810 if (ret)
Antti Palosaari0ea872d2013-12-03 18:19:39 -0300811 goto err;
812
Antti Palosaari0ea872d2013-12-03 18:19:39 -0300813 return 0;
814err:
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300815 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaarid1016582014-12-14 04:45:57 -0300816 return ret;
Antti Palosaari8823f022013-11-26 12:53:46 -0300817}
818
Peter Rosincddcc402016-04-20 08:41:25 +0200819static int rtl2832_deselect(struct i2c_mux_core *muxc, u32 chan_id)
Antti Palosaari92d20d92014-02-08 03:50:04 -0300820{
Peter Rosincddcc402016-04-20 08:41:25 +0200821 struct rtl2832_dev *dev = i2c_mux_priv(muxc);
Antti Palosaari6e6aac62014-12-13 02:28:33 -0300822
Antti Palosaari038c6f22014-12-13 00:37:43 -0300823 schedule_delayed_work(&dev->i2c_gate_work, usecs_to_jiffies(100));
Antti Palosaari92d20d92014-02-08 03:50:04 -0300824 return 0;
825}
826
Max Kellermannbd336e62016-08-09 18:32:21 -0300827static const struct dvb_frontend_ops rtl2832_ops = {
Thomas Mair82041c02012-05-18 14:47:40 -0300828 .delsys = { SYS_DVBT },
829 .info = {
830 .name = "Realtek RTL2832 (DVB-T)",
Mauro Carvalho Chehabf1b1eab2018-07-05 18:59:36 -0400831 .frequency_min_hz = 174 * MHz,
832 .frequency_max_hz = 862 * MHz,
833 .frequency_stepsize_hz = 166667,
Thomas Mair82041c02012-05-18 14:47:40 -0300834 .caps = FE_CAN_FEC_1_2 |
835 FE_CAN_FEC_2_3 |
836 FE_CAN_FEC_3_4 |
837 FE_CAN_FEC_5_6 |
838 FE_CAN_FEC_7_8 |
839 FE_CAN_FEC_AUTO |
840 FE_CAN_QPSK |
841 FE_CAN_QAM_16 |
842 FE_CAN_QAM_64 |
843 FE_CAN_QAM_AUTO |
844 FE_CAN_TRANSMISSION_MODE_AUTO |
845 FE_CAN_GUARD_INTERVAL_AUTO |
846 FE_CAN_HIERARCHY_AUTO |
847 FE_CAN_RECOVER |
848 FE_CAN_MUTE_TS
849 },
850
Thomas Mair82041c02012-05-18 14:47:40 -0300851 .init = rtl2832_init,
852 .sleep = rtl2832_sleep,
853
854 .get_tune_settings = rtl2832_get_tune_settings,
855
856 .set_frontend = rtl2832_set_frontend,
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300857 .get_frontend = rtl2832_get_frontend,
Thomas Mair82041c02012-05-18 14:47:40 -0300858
859 .read_status = rtl2832_read_status,
Antti Palosaari73983492012-08-21 19:56:21 -0300860 .read_snr = rtl2832_read_snr,
Antti Palosaaridb32d742012-08-21 19:56:22 -0300861 .read_ber = rtl2832_read_ber,
Thomas Mair82041c02012-05-18 14:47:40 -0300862};
863
Antti Palosaaridcadb822014-12-14 16:23:28 -0300864static bool rtl2832_volatile_reg(struct device *dev, unsigned int reg)
865{
866 switch (reg) {
867 case 0x305:
868 case 0x33c:
869 case 0x34e:
870 case 0x351:
871 case 0x40c ... 0x40d:
872 return true;
873 default:
874 break;
875 }
876
877 return false;
878}
879
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300880static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client)
881{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300882 struct rtl2832_dev *dev = i2c_get_clientdata(client);
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300883
884 dev_dbg(&client->dev, "\n");
885 return &dev->fe;
886}
887
Antti Palosaaricd559e02014-12-16 13:37:18 -0300888static struct i2c_adapter *rtl2832_get_i2c_adapter(struct i2c_client *client)
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300889{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300890 struct rtl2832_dev *dev = i2c_get_clientdata(client);
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300891
892 dev_dbg(&client->dev, "\n");
Peter Rosincddcc402016-04-20 08:41:25 +0200893 return dev->muxc->adapter[0];
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300894}
895
Antti Palosaarid884aca2016-02-05 18:26:30 -0200896static int rtl2832_slave_ts_ctrl(struct i2c_client *client, bool enable)
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300897{
Antti Palosaari038c6f22014-12-13 00:37:43 -0300898 struct rtl2832_dev *dev = i2c_get_clientdata(client);
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300899 int ret;
900
Antti Palosaarid884aca2016-02-05 18:26:30 -0200901 dev_dbg(&client->dev, "enable=%d\n", enable);
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300902
Antti Palosaarid884aca2016-02-05 18:26:30 -0200903 if (enable) {
904 ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x0);
905 if (ret)
906 goto err;
Peter Rosin1cf79db2016-05-04 22:15:33 +0200907 ret = regmap_bulk_write(dev->regmap, 0x10c, "\x5f\xff", 2);
Antti Palosaarid884aca2016-02-05 18:26:30 -0200908 if (ret)
909 goto err;
910 ret = rtl2832_wr_demod_reg(dev, DVBT_PIP_ON, 0x1);
911 if (ret)
912 goto err;
Peter Rosin1cf79db2016-05-04 22:15:33 +0200913 ret = regmap_bulk_write(dev->regmap, 0x0bc, "\x18", 1);
Antti Palosaarid884aca2016-02-05 18:26:30 -0200914 if (ret)
915 goto err;
Peter Rosin1cf79db2016-05-04 22:15:33 +0200916 ret = regmap_bulk_write(dev->regmap, 0x192, "\x7f\xf7\xff", 3);
Antti Palosaarid884aca2016-02-05 18:26:30 -0200917 if (ret)
918 goto err;
919 } else {
Peter Rosin1cf79db2016-05-04 22:15:33 +0200920 ret = regmap_bulk_write(dev->regmap, 0x192, "\x00\x0f\xff", 3);
Antti Palosaarid884aca2016-02-05 18:26:30 -0200921 if (ret)
922 goto err;
Peter Rosin1cf79db2016-05-04 22:15:33 +0200923 ret = regmap_bulk_write(dev->regmap, 0x0bc, "\x08", 1);
Antti Palosaarid884aca2016-02-05 18:26:30 -0200924 if (ret)
925 goto err;
926 ret = rtl2832_wr_demod_reg(dev, DVBT_PIP_ON, 0x0);
927 if (ret)
928 goto err;
Peter Rosin1cf79db2016-05-04 22:15:33 +0200929 ret = regmap_bulk_write(dev->regmap, 0x10c, "\x00\x00", 2);
Antti Palosaarid884aca2016-02-05 18:26:30 -0200930 if (ret)
931 goto err;
932 ret = rtl2832_wr_demod_reg(dev, DVBT_SOFT_RST, 0x1);
933 if (ret)
934 goto err;
935 }
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300936
Martin Blumenstingld10f89c2016-06-07 18:31:47 -0300937 dev->slave_ts = enable;
938
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -0300939 return 0;
940err:
941 dev_dbg(&client->dev, "failed=%d\n", ret);
942 return ret;
943}
944
Antti Palosaari4b01e012014-12-14 14:07:35 -0300945static int rtl2832_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
946{
947 struct rtl2832_dev *dev = fe->demodulator_priv;
948 struct i2c_client *client = dev->client;
949 int ret;
950 u8 u8tmp;
951
Martin Blumenstingld10f89c2016-06-07 18:31:47 -0300952 dev_dbg(&client->dev, "onoff=%d, slave_ts=%d\n", onoff, dev->slave_ts);
Antti Palosaari4b01e012014-12-14 14:07:35 -0300953
954 /* enable / disable PID filter */
955 if (onoff)
956 u8tmp = 0x80;
957 else
958 u8tmp = 0x00;
959
Martin Blumenstingld10f89c2016-06-07 18:31:47 -0300960 if (dev->slave_ts)
961 ret = regmap_update_bits(dev->regmap, 0x021, 0xc0, u8tmp);
962 else
963 ret = regmap_update_bits(dev->regmap, 0x061, 0xc0, u8tmp);
Antti Palosaari4b01e012014-12-14 14:07:35 -0300964 if (ret)
965 goto err;
966
967 return 0;
968err:
969 dev_dbg(&client->dev, "failed=%d\n", ret);
970 return ret;
971}
972
973static int rtl2832_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid,
974 int onoff)
975{
976 struct rtl2832_dev *dev = fe->demodulator_priv;
977 struct i2c_client *client = dev->client;
978 int ret;
979 u8 buf[4];
980
Martin Blumenstingld10f89c2016-06-07 18:31:47 -0300981 dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d slave_ts=%d\n",
982 index, pid, onoff, dev->slave_ts);
Antti Palosaari4b01e012014-12-14 14:07:35 -0300983
984 /* skip invalid PIDs (0x2000) */
985 if (pid > 0x1fff || index > 32)
986 return 0;
987
988 if (onoff)
989 set_bit(index, &dev->filters);
990 else
991 clear_bit(index, &dev->filters);
992
993 /* enable / disable PIDs */
994 buf[0] = (dev->filters >> 0) & 0xff;
995 buf[1] = (dev->filters >> 8) & 0xff;
996 buf[2] = (dev->filters >> 16) & 0xff;
997 buf[3] = (dev->filters >> 24) & 0xff;
Martin Blumenstingld10f89c2016-06-07 18:31:47 -0300998
999 if (dev->slave_ts)
1000 ret = regmap_bulk_write(dev->regmap, 0x022, buf, 4);
1001 else
1002 ret = regmap_bulk_write(dev->regmap, 0x062, buf, 4);
Antti Palosaari4b01e012014-12-14 14:07:35 -03001003 if (ret)
1004 goto err;
1005
1006 /* add PID */
1007 buf[0] = (pid >> 8) & 0xff;
1008 buf[1] = (pid >> 0) & 0xff;
Martin Blumenstingld10f89c2016-06-07 18:31:47 -03001009
1010 if (dev->slave_ts)
1011 ret = regmap_bulk_write(dev->regmap, 0x026 + 2 * index, buf, 2);
1012 else
1013 ret = regmap_bulk_write(dev->regmap, 0x066 + 2 * index, buf, 2);
Antti Palosaari4b01e012014-12-14 14:07:35 -03001014 if (ret)
1015 goto err;
1016
1017 return 0;
1018err:
1019 dev_dbg(&client->dev, "failed=%d\n", ret);
1020 return ret;
1021}
1022
Antti Palosaaric2c83862014-12-02 10:55:17 -03001023static int rtl2832_probe(struct i2c_client *client,
1024 const struct i2c_device_id *id)
1025{
1026 struct rtl2832_platform_data *pdata = client->dev.platform_data;
Antti Palosaaric2c83862014-12-02 10:55:17 -03001027 struct i2c_adapter *i2c = client->adapter;
Antti Palosaari038c6f22014-12-13 00:37:43 -03001028 struct rtl2832_dev *dev;
Antti Palosaaric2c83862014-12-02 10:55:17 -03001029 int ret;
1030 u8 tmp;
Antti Palosaarid1016582014-12-14 04:45:57 -03001031 static const struct regmap_range_cfg regmap_range_cfg[] = {
1032 {
1033 .selector_reg = 0x00,
1034 .selector_mask = 0xff,
1035 .selector_shift = 0,
1036 .window_start = 0,
1037 .window_len = 0x100,
1038 .range_min = 0 * 0x100,
1039 .range_max = 5 * 0x100,
1040 },
1041 };
Antti Palosaaric2c83862014-12-02 10:55:17 -03001042
1043 dev_dbg(&client->dev, "\n");
1044
Antti Palosaaric2c83862014-12-02 10:55:17 -03001045 /* allocate memory for the internal state */
Antti Palosaari038c6f22014-12-13 00:37:43 -03001046 dev = kzalloc(sizeof(struct rtl2832_dev), GFP_KERNEL);
1047 if (dev == NULL) {
Antti Palosaaric2c83862014-12-02 10:55:17 -03001048 ret = -ENOMEM;
1049 goto err;
1050 }
1051
Antti Palosaari038c6f22014-12-13 00:37:43 -03001052 /* setup the state */
Antti Palosaarid1016582014-12-14 04:45:57 -03001053 i2c_set_clientdata(client, dev);
Antti Palosaari038c6f22014-12-13 00:37:43 -03001054 dev->client = client;
Antti Palosaarie1174d72014-12-13 05:26:27 -03001055 dev->pdata = client->dev.platform_data;
Antti Palosaari038c6f22014-12-13 00:37:43 -03001056 dev->sleeping = true;
Antti Palosaari038c6f22014-12-13 00:37:43 -03001057 INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work);
Antti Palosaarid1016582014-12-14 04:45:57 -03001058 /* create regmap */
Antti Palosaarib410dae2014-12-18 07:22:46 -03001059 dev->regmap_config.reg_bits = 8,
1060 dev->regmap_config.val_bits = 8,
Antti Palosaarib410dae2014-12-18 07:22:46 -03001061 dev->regmap_config.volatile_reg = rtl2832_volatile_reg,
1062 dev->regmap_config.max_register = 5 * 0x100,
1063 dev->regmap_config.ranges = regmap_range_cfg,
1064 dev->regmap_config.num_ranges = ARRAY_SIZE(regmap_range_cfg),
Antti Palosaarib3b2bf82015-03-14 11:13:07 -03001065 dev->regmap_config.cache_type = REGCACHE_NONE,
Peter Rosin1cf79db2016-05-04 22:15:33 +02001066 dev->regmap = regmap_init_i2c(client, &dev->regmap_config);
Antti Palosaarid1016582014-12-14 04:45:57 -03001067 if (IS_ERR(dev->regmap)) {
1068 ret = PTR_ERR(dev->regmap);
1069 goto err_kfree;
1070 }
Antti Palosaaric2c83862014-12-02 10:55:17 -03001071
1072 /* check if the demod is there */
Peter Rosin1cf79db2016-05-04 22:15:33 +02001073 ret = regmap_bulk_read(dev->regmap, 0x000, &tmp, 1);
Antti Palosaaric2c83862014-12-02 10:55:17 -03001074 if (ret)
Antti Palosaari0d117902014-12-18 06:30:32 -03001075 goto err_regmap_exit;
Antti Palosaaric2c83862014-12-02 10:55:17 -03001076
1077 /* create muxed i2c adapter for demod tuner bus */
Peter Rosin1cf79db2016-05-04 22:15:33 +02001078 dev->muxc = i2c_mux_alloc(i2c, &i2c->dev, 1, 0, I2C_MUX_LOCKED,
Peter Rosincddcc402016-04-20 08:41:25 +02001079 rtl2832_select, rtl2832_deselect);
1080 if (!dev->muxc) {
1081 ret = -ENOMEM;
Antti Palosaari0d117902014-12-18 06:30:32 -03001082 goto err_regmap_exit;
Antti Palosaaric2c83862014-12-02 10:55:17 -03001083 }
Peter Rosincddcc402016-04-20 08:41:25 +02001084 dev->muxc->priv = dev;
1085 ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
1086 if (ret)
1087 goto err_regmap_exit;
Antti Palosaaric2c83862014-12-02 10:55:17 -03001088
1089 /* create dvb_frontend */
Antti Palosaari038c6f22014-12-13 00:37:43 -03001090 memcpy(&dev->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
1091 dev->fe.demodulator_priv = dev;
Antti Palosaari6f5f6ee2014-12-12 23:16:19 -03001092
1093 /* setup callbacks */
1094 pdata->get_dvb_frontend = rtl2832_get_dvb_frontend;
Antti Palosaaricd559e02014-12-16 13:37:18 -03001095 pdata->get_i2c_adapter = rtl2832_get_i2c_adapter;
Antti Palosaarid884aca2016-02-05 18:26:30 -02001096 pdata->slave_ts_ctrl = rtl2832_slave_ts_ctrl;
Antti Palosaari4b01e012014-12-14 14:07:35 -03001097 pdata->pid_filter = rtl2832_pid_filter;
1098 pdata->pid_filter_ctrl = rtl2832_pid_filter_ctrl;
Peter Rosin1cf79db2016-05-04 22:15:33 +02001099 pdata->regmap = dev->regmap;
Antti Palosaaric2c83862014-12-02 10:55:17 -03001100
1101 dev_info(&client->dev, "Realtek RTL2832 successfully attached\n");
1102 return 0;
Antti Palosaarid1016582014-12-14 04:45:57 -03001103err_regmap_exit:
1104 regmap_exit(dev->regmap);
Antti Palosaaric2c83862014-12-02 10:55:17 -03001105err_kfree:
Antti Palosaari038c6f22014-12-13 00:37:43 -03001106 kfree(dev);
Antti Palosaaric2c83862014-12-02 10:55:17 -03001107err:
1108 dev_dbg(&client->dev, "failed=%d\n", ret);
1109 return ret;
1110}
1111
1112static int rtl2832_remove(struct i2c_client *client)
1113{
Antti Palosaari038c6f22014-12-13 00:37:43 -03001114 struct rtl2832_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric2c83862014-12-02 10:55:17 -03001115
1116 dev_dbg(&client->dev, "\n");
1117
Antti Palosaari038c6f22014-12-13 00:37:43 -03001118 cancel_delayed_work_sync(&dev->i2c_gate_work);
Antti Palosaaric2c83862014-12-02 10:55:17 -03001119
Peter Rosincddcc402016-04-20 08:41:25 +02001120 i2c_mux_del_adapters(dev->muxc);
Antti Palosaaric2c83862014-12-02 10:55:17 -03001121
Antti Palosaarid1016582014-12-14 04:45:57 -03001122 regmap_exit(dev->regmap);
1123
Antti Palosaari038c6f22014-12-13 00:37:43 -03001124 kfree(dev);
Antti Palosaaric2c83862014-12-02 10:55:17 -03001125
1126 return 0;
1127}
1128
1129static const struct i2c_device_id rtl2832_id_table[] = {
1130 {"rtl2832", 0},
1131 {}
1132};
1133MODULE_DEVICE_TABLE(i2c, rtl2832_id_table);
1134
1135static struct i2c_driver rtl2832_driver = {
1136 .driver = {
Antti Palosaaric2c83862014-12-02 10:55:17 -03001137 .name = "rtl2832",
Antti Palosaari678fdb62016-06-29 20:40:57 -03001138 .suppress_bind_attrs = true,
Antti Palosaaric2c83862014-12-02 10:55:17 -03001139 },
1140 .probe = rtl2832_probe,
1141 .remove = rtl2832_remove,
1142 .id_table = rtl2832_id_table,
1143};
1144
1145module_i2c_driver(rtl2832_driver);
1146
Thomas Mair82041c02012-05-18 14:47:40 -03001147MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>");
Antti Palosaari75c24002014-12-16 13:54:23 -03001148MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
Thomas Mair82041c02012-05-18 14:47:40 -03001149MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver");
1150MODULE_LICENSE("GPL");