1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Realtek RTL2832 DVB-T demodulator driver |
4 | * |
5 | * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com> |
6 | * Copyright (C) 2012-2014 Antti Palosaari <crope@iki.fi> |
7 | */ |
8 | |
9 | #include "rtl2832_priv.h" |
10 | |
11 | #define REG_MASK(b) (BIT(b + 1) - 1) |
12 | |
13 | static const struct rtl2832_reg_entry registers[] = { |
14 | [DVBT_SOFT_RST] = {0x101, 2, 2}, |
15 | [DVBT_IIC_REPEAT] = {.start_address: 0x101, .msb: 3, .lsb: 3}, |
16 | [DVBT_TR_WAIT_MIN_8K] = {.start_address: 0x188, .msb: 11, .lsb: 2}, |
17 | [DVBT_RSD_BER_FAIL_VAL] = {.start_address: 0x18f, .msb: 15, .lsb: 0}, |
18 | [DVBT_EN_BK_TRK] = {.start_address: 0x1a6, .msb: 7, .lsb: 7}, |
19 | [DVBT_AD_EN_REG] = {.start_address: 0x008, .msb: 7, .lsb: 7}, |
20 | [DVBT_AD_EN_REG1] = {.start_address: 0x008, .msb: 6, .lsb: 6}, |
21 | [DVBT_EN_BBIN] = {.start_address: 0x1b1, .msb: 0, .lsb: 0}, |
22 | [DVBT_MGD_THD0] = {.start_address: 0x195, .msb: 7, .lsb: 0}, |
23 | [DVBT_MGD_THD1] = {.start_address: 0x196, .msb: 7, .lsb: 0}, |
24 | [DVBT_MGD_THD2] = {.start_address: 0x197, .msb: 7, .lsb: 0}, |
25 | [DVBT_MGD_THD3] = {.start_address: 0x198, .msb: 7, .lsb: 0}, |
26 | [DVBT_MGD_THD4] = {.start_address: 0x199, .msb: 7, .lsb: 0}, |
27 | [DVBT_MGD_THD5] = {.start_address: 0x19a, .msb: 7, .lsb: 0}, |
28 | [DVBT_MGD_THD6] = {.start_address: 0x19b, .msb: 7, .lsb: 0}, |
29 | [DVBT_MGD_THD7] = {.start_address: 0x19c, .msb: 7, .lsb: 0}, |
30 | [DVBT_EN_CACQ_NOTCH] = {.start_address: 0x161, .msb: 4, .lsb: 4}, |
31 | [DVBT_AD_AV_REF] = {.start_address: 0x009, .msb: 6, .lsb: 0}, |
32 | [DVBT_REG_PI] = {.start_address: 0x00a, .msb: 2, .lsb: 0}, |
33 | [DVBT_PIP_ON] = {.start_address: 0x021, .msb: 3, .lsb: 3}, |
34 | [DVBT_SCALE1_B92] = {.start_address: 0x292, .msb: 7, .lsb: 0}, |
35 | [DVBT_SCALE1_B93] = {.start_address: 0x293, .msb: 7, .lsb: 0}, |
36 | [DVBT_SCALE1_BA7] = {.start_address: 0x2a7, .msb: 7, .lsb: 0}, |
37 | [DVBT_SCALE1_BA9] = {.start_address: 0x2a9, .msb: 7, .lsb: 0}, |
38 | [DVBT_SCALE1_BAA] = {.start_address: 0x2aa, .msb: 7, .lsb: 0}, |
39 | [DVBT_SCALE1_BAB] = {.start_address: 0x2ab, .msb: 7, .lsb: 0}, |
40 | [DVBT_SCALE1_BAC] = {.start_address: 0x2ac, .msb: 7, .lsb: 0}, |
41 | [DVBT_SCALE1_BB0] = {.start_address: 0x2b0, .msb: 7, .lsb: 0}, |
42 | [DVBT_SCALE1_BB1] = {.start_address: 0x2b1, .msb: 7, .lsb: 0}, |
43 | [DVBT_KB_P1] = {.start_address: 0x164, .msb: 3, .lsb: 1}, |
44 | [DVBT_KB_P2] = {.start_address: 0x164, .msb: 6, .lsb: 4}, |
45 | [DVBT_KB_P3] = {.start_address: 0x165, .msb: 2, .lsb: 0}, |
46 | [DVBT_OPT_ADC_IQ] = {.start_address: 0x006, .msb: 5, .lsb: 4}, |
47 | [DVBT_AD_AVI] = {.start_address: 0x009, .msb: 1, .lsb: 0}, |
48 | [DVBT_AD_AVQ] = {.start_address: 0x009, .msb: 3, .lsb: 2}, |
49 | [DVBT_K1_CR_STEP12] = {.start_address: 0x2ad, .msb: 9, .lsb: 4}, |
50 | [DVBT_TRK_KS_P2] = {.start_address: 0x16f, .msb: 2, .lsb: 0}, |
51 | [DVBT_TRK_KS_I2] = {.start_address: 0x170, .msb: 5, .lsb: 3}, |
52 | [DVBT_TR_THD_SET2] = {.start_address: 0x172, .msb: 3, .lsb: 0}, |
53 | [DVBT_TRK_KC_P2] = {.start_address: 0x173, .msb: 5, .lsb: 3}, |
54 | [DVBT_TRK_KC_I2] = {.start_address: 0x175, .msb: 2, .lsb: 0}, |
55 | [DVBT_CR_THD_SET2] = {.start_address: 0x176, .msb: 7, .lsb: 6}, |
56 | [DVBT_PSET_IFFREQ] = {.start_address: 0x119, .msb: 21, .lsb: 0}, |
57 | [DVBT_SPEC_INV] = {.start_address: 0x115, .msb: 0, .lsb: 0}, |
58 | [DVBT_RSAMP_RATIO] = {.start_address: 0x19f, .msb: 27, .lsb: 2}, |
59 | [DVBT_CFREQ_OFF_RATIO] = {.start_address: 0x19d, .msb: 23, .lsb: 4}, |
60 | [DVBT_FSM_STAGE] = {.start_address: 0x351, .msb: 6, .lsb: 3}, |
61 | [DVBT_RX_CONSTEL] = {.start_address: 0x33c, .msb: 3, .lsb: 2}, |
62 | [DVBT_RX_HIER] = {.start_address: 0x33c, .msb: 6, .lsb: 4}, |
63 | [DVBT_RX_C_RATE_LP] = {.start_address: 0x33d, .msb: 2, .lsb: 0}, |
64 | [DVBT_RX_C_RATE_HP] = {.start_address: 0x33d, .msb: 5, .lsb: 3}, |
65 | [DVBT_GI_IDX] = {.start_address: 0x351, .msb: 1, .lsb: 0}, |
66 | [DVBT_FFT_MODE_IDX] = {.start_address: 0x351, .msb: 2, .lsb: 2}, |
67 | [DVBT_RSD_BER_EST] = {.start_address: 0x34e, .msb: 15, .lsb: 0}, |
68 | [DVBT_CE_EST_EVM] = {.start_address: 0x40c, .msb: 15, .lsb: 0}, |
69 | [DVBT_RF_AGC_VAL] = {.start_address: 0x35b, .msb: 13, .lsb: 0}, |
70 | [DVBT_IF_AGC_VAL] = {.start_address: 0x359, .msb: 13, .lsb: 0}, |
71 | [DVBT_DAGC_VAL] = {.start_address: 0x305, .msb: 7, .lsb: 0}, |
72 | [DVBT_SFREQ_OFF] = {.start_address: 0x318, .msb: 13, .lsb: 0}, |
73 | [DVBT_CFREQ_OFF] = {.start_address: 0x35f, .msb: 17, .lsb: 0}, |
74 | [DVBT_POLAR_RF_AGC] = {.start_address: 0x00e, .msb: 1, .lsb: 1}, |
75 | [DVBT_POLAR_IF_AGC] = {.start_address: 0x00e, .msb: 0, .lsb: 0}, |
76 | [DVBT_AAGC_HOLD] = {.start_address: 0x104, .msb: 5, .lsb: 5}, |
77 | [DVBT_EN_RF_AGC] = {.start_address: 0x104, .msb: 6, .lsb: 6}, |
78 | [DVBT_EN_IF_AGC] = {.start_address: 0x104, .msb: 7, .lsb: 7}, |
79 | [DVBT_IF_AGC_MIN] = {.start_address: 0x108, .msb: 7, .lsb: 0}, |
80 | [DVBT_IF_AGC_MAX] = {.start_address: 0x109, .msb: 7, .lsb: 0}, |
81 | [DVBT_RF_AGC_MIN] = {.start_address: 0x10a, .msb: 7, .lsb: 0}, |
82 | [DVBT_RF_AGC_MAX] = {.start_address: 0x10b, .msb: 7, .lsb: 0}, |
83 | [DVBT_IF_AGC_MAN] = {.start_address: 0x10c, .msb: 6, .lsb: 6}, |
84 | [DVBT_IF_AGC_MAN_VAL] = {.start_address: 0x10c, .msb: 13, .lsb: 0}, |
85 | [DVBT_RF_AGC_MAN] = {.start_address: 0x10e, .msb: 6, .lsb: 6}, |
86 | [DVBT_RF_AGC_MAN_VAL] = {.start_address: 0x10e, .msb: 13, .lsb: 0}, |
87 | [DVBT_DAGC_TRG_VAL] = {.start_address: 0x112, .msb: 7, .lsb: 0}, |
88 | [DVBT_AGC_TARG_VAL_0] = {.start_address: 0x102, .msb: 0, .lsb: 0}, |
89 | [DVBT_AGC_TARG_VAL_8_1] = {.start_address: 0x103, .msb: 7, .lsb: 0}, |
90 | [DVBT_AAGC_LOOP_GAIN] = {.start_address: 0x1c7, .msb: 5, .lsb: 1}, |
91 | [DVBT_LOOP_GAIN2_3_0] = {.start_address: 0x104, .msb: 4, .lsb: 1}, |
92 | [DVBT_LOOP_GAIN2_4] = {.start_address: 0x105, .msb: 7, .lsb: 7}, |
93 | [DVBT_LOOP_GAIN3] = {.start_address: 0x1c8, .msb: 4, .lsb: 0}, |
94 | [DVBT_VTOP1] = {.start_address: 0x106, .msb: 5, .lsb: 0}, |
95 | [DVBT_VTOP2] = {.start_address: 0x1c9, .msb: 5, .lsb: 0}, |
96 | [DVBT_VTOP3] = {.start_address: 0x1ca, .msb: 5, .lsb: 0}, |
97 | [DVBT_KRF1] = {.start_address: 0x1cb, .msb: 7, .lsb: 0}, |
98 | [DVBT_KRF2] = {.start_address: 0x107, .msb: 7, .lsb: 0}, |
99 | [DVBT_KRF3] = {.start_address: 0x1cd, .msb: 7, .lsb: 0}, |
100 | [DVBT_KRF4] = {.start_address: 0x1ce, .msb: 7, .lsb: 0}, |
101 | [DVBT_EN_GI_PGA] = {.start_address: 0x1e5, .msb: 0, .lsb: 0}, |
102 | [DVBT_THD_LOCK_UP] = {.start_address: 0x1d9, .msb: 8, .lsb: 0}, |
103 | [DVBT_THD_LOCK_DW] = {.start_address: 0x1db, .msb: 8, .lsb: 0}, |
104 | [DVBT_THD_UP1] = {.start_address: 0x1dd, .msb: 7, .lsb: 0}, |
105 | [DVBT_THD_DW1] = {.start_address: 0x1de, .msb: 7, .lsb: 0}, |
106 | [DVBT_INTER_CNT_LEN] = {.start_address: 0x1d8, .msb: 3, .lsb: 0}, |
107 | [DVBT_GI_PGA_STATE] = {.start_address: 0x1e6, .msb: 3, .lsb: 3}, |
108 | [DVBT_EN_AGC_PGA] = {.start_address: 0x1d7, .msb: 0, .lsb: 0}, |
109 | [DVBT_CKOUTPAR] = {.start_address: 0x17b, .msb: 5, .lsb: 5}, |
110 | [DVBT_CKOUT_PWR] = {.start_address: 0x17b, .msb: 6, .lsb: 6}, |
111 | [DVBT_SYNC_DUR] = {.start_address: 0x17b, .msb: 7, .lsb: 7}, |
112 | [DVBT_ERR_DUR] = {.start_address: 0x17c, .msb: 0, .lsb: 0}, |
113 | [DVBT_SYNC_LVL] = {.start_address: 0x17c, .msb: 1, .lsb: 1}, |
114 | [DVBT_ERR_LVL] = {.start_address: 0x17c, .msb: 2, .lsb: 2}, |
115 | [DVBT_VAL_LVL] = {.start_address: 0x17c, .msb: 3, .lsb: 3}, |
116 | [DVBT_SERIAL] = {.start_address: 0x17c, .msb: 4, .lsb: 4}, |
117 | [DVBT_SER_LSB] = {.start_address: 0x17c, .msb: 5, .lsb: 5}, |
118 | [DVBT_CDIV_PH0] = {.start_address: 0x17d, .msb: 3, .lsb: 0}, |
119 | [DVBT_CDIV_PH1] = {.start_address: 0x17d, .msb: 7, .lsb: 4}, |
120 | [DVBT_MPEG_IO_OPT_2_2] = {.start_address: 0x006, .msb: 7, .lsb: 7}, |
121 | [DVBT_MPEG_IO_OPT_1_0] = {.start_address: 0x007, .msb: 7, .lsb: 6}, |
122 | [DVBT_CKOUTPAR_PIP] = {.start_address: 0x0b7, .msb: 4, .lsb: 4}, |
123 | [DVBT_CKOUT_PWR_PIP] = {.start_address: 0x0b7, .msb: 3, .lsb: 3}, |
124 | [DVBT_SYNC_LVL_PIP] = {.start_address: 0x0b7, .msb: 2, .lsb: 2}, |
125 | [DVBT_ERR_LVL_PIP] = {.start_address: 0x0b7, .msb: 1, .lsb: 1}, |
126 | [DVBT_VAL_LVL_PIP] = {.start_address: 0x0b7, .msb: 0, .lsb: 0}, |
127 | [DVBT_CKOUTPAR_PID] = {.start_address: 0x0b9, .msb: 4, .lsb: 4}, |
128 | [DVBT_CKOUT_PWR_PID] = {.start_address: 0x0b9, .msb: 3, .lsb: 3}, |
129 | [DVBT_SYNC_LVL_PID] = {.start_address: 0x0b9, .msb: 2, .lsb: 2}, |
130 | [DVBT_ERR_LVL_PID] = {.start_address: 0x0b9, .msb: 1, .lsb: 1}, |
131 | [DVBT_VAL_LVL_PID] = {.start_address: 0x0b9, .msb: 0, .lsb: 0}, |
132 | [DVBT_SM_PASS] = {.start_address: 0x193, .msb: 11, .lsb: 0}, |
133 | [DVBT_AD7_SETTING] = {.start_address: 0x011, .msb: 15, .lsb: 0}, |
134 | [DVBT_RSSI_R] = {.start_address: 0x301, .msb: 6, .lsb: 0}, |
135 | [DVBT_ACI_DET_IND] = {.start_address: 0x312, .msb: 0, .lsb: 0}, |
136 | [DVBT_REG_MON] = {.start_address: 0x00d, .msb: 1, .lsb: 0}, |
137 | [DVBT_REG_MONSEL] = {.start_address: 0x00d, .msb: 2, .lsb: 2}, |
138 | [DVBT_REG_GPE] = {.start_address: 0x00d, .msb: 7, .lsb: 7}, |
139 | [DVBT_REG_GPO] = {.start_address: 0x010, .msb: 0, .lsb: 0}, |
140 | [DVBT_REG_4MSEL] = {.start_address: 0x013, .msb: 0, .lsb: 0}, |
141 | }; |
142 | |
143 | static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val) |
144 | { |
145 | struct i2c_client *client = dev->client; |
146 | int ret, i; |
147 | u16 reg_start_addr; |
148 | u8 msb, lsb, reading[4], len; |
149 | u32 reading_tmp, mask; |
150 | |
151 | reg_start_addr = registers[reg].start_address; |
152 | msb = registers[reg].msb; |
153 | lsb = registers[reg].lsb; |
154 | len = (msb >> 3) + 1; |
155 | mask = REG_MASK(msb - lsb); |
156 | |
157 | ret = regmap_bulk_read(map: dev->regmap, reg: reg_start_addr, val: reading, val_count: len); |
158 | 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 | |
167 | return 0; |
168 | err: |
169 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
170 | return ret; |
171 | } |
172 | |
173 | static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, int reg, u32 val) |
174 | { |
175 | struct i2c_client *client = dev->client; |
176 | int ret, i; |
177 | u16 reg_start_addr; |
178 | u8 msb, lsb, reading[4], writing[4], len; |
179 | u32 reading_tmp, writing_tmp, mask; |
180 | |
181 | reg_start_addr = registers[reg].start_address; |
182 | msb = registers[reg].msb; |
183 | lsb = registers[reg].lsb; |
184 | len = (msb >> 3) + 1; |
185 | mask = REG_MASK(msb - lsb); |
186 | |
187 | ret = regmap_bulk_read(map: dev->regmap, reg: reg_start_addr, val: reading, val_count: len); |
188 | 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 | |
198 | for (i = 0; i < len; i++) |
199 | writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff; |
200 | |
201 | ret = regmap_bulk_write(map: dev->regmap, reg: reg_start_addr, val: writing, val_count: len); |
202 | if (ret) |
203 | goto err; |
204 | |
205 | return 0; |
206 | err: |
207 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
208 | return ret; |
209 | } |
210 | |
211 | static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq) |
212 | { |
213 | struct rtl2832_dev *dev = fe->demodulator_priv; |
214 | struct i2c_client *client = dev->client; |
215 | 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 | */ |
223 | pset_iffreq = if_freq % dev->pdata->clk; |
224 | pset_iffreq *= 0x400000; |
225 | pset_iffreq = div_u64(dividend: pset_iffreq, divisor: dev->pdata->clk); |
226 | pset_iffreq = -pset_iffreq; |
227 | pset_iffreq = pset_iffreq & 0x3fffff; |
228 | dev_dbg(&client->dev, "if_frequency=%d pset_iffreq=%08x\n" , |
229 | if_freq, (unsigned)pset_iffreq); |
230 | |
231 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_EN_BBIN, val: en_bbin); |
232 | if (ret) |
233 | goto err; |
234 | |
235 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_PSET_IFFREQ, val: pset_iffreq); |
236 | if (ret) |
237 | goto err; |
238 | |
239 | return 0; |
240 | err: |
241 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
242 | return ret; |
243 | } |
244 | |
245 | static int rtl2832_init(struct dvb_frontend *fe) |
246 | { |
247 | struct rtl2832_dev *dev = fe->demodulator_priv; |
248 | struct i2c_client *client = dev->client; |
249 | struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; |
250 | const struct rtl2832_reg_value *init; |
251 | int i, ret, len; |
252 | /* initialization values for the demodulator registers */ |
253 | struct rtl2832_reg_value rtl2832_initial_regs[] = { |
254 | {.reg: DVBT_AD_EN_REG, .value: 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}, |
296 | }; |
297 | |
298 | dev_dbg(&client->dev, "\n" ); |
299 | |
300 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_SOFT_RST, val: 0x0); |
301 | if (ret) |
302 | goto err; |
303 | |
304 | for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) { |
305 | ret = rtl2832_wr_demod_reg(dev, reg: rtl2832_initial_regs[i].reg, |
306 | val: rtl2832_initial_regs[i].value); |
307 | if (ret) |
308 | goto err; |
309 | } |
310 | |
311 | /* load tuner specific settings */ |
312 | dev_dbg(&client->dev, "load settings for tuner=%02x\n" , |
313 | dev->pdata->tuner); |
314 | switch (dev->pdata->tuner) { |
315 | case RTL2832_TUNER_FC2580: |
316 | len = ARRAY_SIZE(rtl2832_tuner_init_fc2580); |
317 | init = rtl2832_tuner_init_fc2580; |
318 | break; |
319 | 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; |
324 | case RTL2832_TUNER_TUA9001: |
325 | len = ARRAY_SIZE(rtl2832_tuner_init_tua9001); |
326 | init = rtl2832_tuner_init_tua9001; |
327 | break; |
328 | case RTL2832_TUNER_E4000: |
329 | len = ARRAY_SIZE(rtl2832_tuner_init_e4000); |
330 | init = rtl2832_tuner_init_e4000; |
331 | break; |
332 | case RTL2832_TUNER_R820T: |
333 | case RTL2832_TUNER_R828D: |
334 | len = ARRAY_SIZE(rtl2832_tuner_init_r820t); |
335 | init = rtl2832_tuner_init_r820t; |
336 | break; |
337 | case RTL2832_TUNER_SI2157: |
338 | len = ARRAY_SIZE(rtl2832_tuner_init_si2157); |
339 | init = rtl2832_tuner_init_si2157; |
340 | break; |
341 | default: |
342 | ret = -EINVAL; |
343 | goto err; |
344 | } |
345 | |
346 | for (i = 0; i < len; i++) { |
347 | ret = rtl2832_wr_demod_reg(dev, reg: init[i].reg, val: init[i].value); |
348 | if (ret) |
349 | goto err; |
350 | } |
351 | |
352 | /* init stats here in order signal app which stats are supported */ |
353 | c->strength.len = 1; |
354 | c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
355 | c->cnr.len = 1; |
356 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
357 | 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; |
361 | dev->sleeping = false; |
362 | |
363 | return 0; |
364 | err: |
365 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
366 | return ret; |
367 | } |
368 | |
369 | static int rtl2832_sleep(struct dvb_frontend *fe) |
370 | { |
371 | struct rtl2832_dev *dev = fe->demodulator_priv; |
372 | struct i2c_client *client = dev->client; |
373 | int ret; |
374 | |
375 | dev_dbg(&client->dev, "\n" ); |
376 | |
377 | dev->sleeping = true; |
378 | dev->fe_status = 0; |
379 | |
380 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_SOFT_RST, val: 0x1); |
381 | if (ret) |
382 | goto err; |
383 | |
384 | return 0; |
385 | err: |
386 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
387 | return ret; |
388 | } |
389 | |
390 | static int rtl2832_get_tune_settings(struct dvb_frontend *fe, |
391 | struct dvb_frontend_tune_settings *s) |
392 | { |
393 | struct rtl2832_dev *dev = fe->demodulator_priv; |
394 | struct i2c_client *client = dev->client; |
395 | |
396 | dev_dbg(&client->dev, "\n" ); |
397 | s->min_delay_ms = 1000; |
398 | s->step_size = fe->ops.info.frequency_stepsize_hz * 2; |
399 | s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1; |
400 | return 0; |
401 | } |
402 | |
403 | static int rtl2832_set_frontend(struct dvb_frontend *fe) |
404 | { |
405 | struct rtl2832_dev *dev = fe->demodulator_priv; |
406 | struct i2c_client *client = dev->client; |
407 | 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; |
411 | 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 | |
437 | dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n" , |
438 | c->frequency, c->bandwidth_hz, c->inversion); |
439 | |
440 | /* program tuner */ |
441 | if (fe->ops.tuner_ops.set_params) |
442 | fe->ops.tuner_ops.set_params(fe); |
443 | |
444 | /* If the frontend has get_if_frequency(), use it */ |
445 | if (fe->ops.tuner_ops.get_if_frequency) { |
446 | u32 if_freq; |
447 | |
448 | ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); |
449 | if (ret) |
450 | goto err; |
451 | |
452 | ret = rtl2832_set_if(fe, if_freq); |
453 | if (ret) |
454 | goto err; |
455 | } |
456 | |
457 | 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: |
471 | dev_err(&client->dev, "invalid bandwidth_hz %u\n" , |
472 | c->bandwidth_hz); |
473 | ret = -EINVAL; |
474 | goto err; |
475 | } |
476 | |
477 | for (j = 0; j < sizeof(bw_params[0]); j++) { |
478 | ret = regmap_bulk_write(map: dev->regmap, |
479 | reg: 0x11c + j, val: &bw_params[i][j], val_count: 1); |
480 | 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 | */ |
488 | num = dev->pdata->clk * 7ULL; |
489 | num *= 0x400000; |
490 | num = div_u64(dividend: num, divisor: bw_mode); |
491 | resamp_ratio = num & 0x3ffffff; |
492 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_RSAMP_RATIO, val: resamp_ratio); |
493 | 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; |
501 | num2 = dev->pdata->clk * 7ULL; |
502 | num = div_u64(dividend: num, divisor: num2); |
503 | num = -num; |
504 | cfreq_off_ratio = num & 0xfffff; |
505 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_CFREQ_OFF_RATIO, val: cfreq_off_ratio); |
506 | if (ret) |
507 | goto err; |
508 | |
509 | /* soft reset */ |
510 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_SOFT_RST, val: 0x1); |
511 | if (ret) |
512 | goto err; |
513 | |
514 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_SOFT_RST, val: 0x0); |
515 | if (ret) |
516 | goto err; |
517 | |
518 | return 0; |
519 | err: |
520 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
521 | return ret; |
522 | } |
523 | |
524 | static int rtl2832_get_frontend(struct dvb_frontend *fe, |
525 | struct dtv_frontend_properties *c) |
526 | { |
527 | struct rtl2832_dev *dev = fe->demodulator_priv; |
528 | struct i2c_client *client = dev->client; |
529 | int ret; |
530 | u8 buf[3]; |
531 | |
532 | if (dev->sleeping) |
533 | return 0; |
534 | |
535 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x33c, val: buf, val_count: 2); |
536 | if (ret) |
537 | goto err; |
538 | |
539 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x351, val: &buf[2], val_count: 1); |
540 | if (ret) |
541 | goto err; |
542 | |
543 | dev_dbg(&client->dev, "TPS=%*ph\n" , 3, buf); |
544 | |
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; |
632 | err: |
633 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
634 | return ret; |
635 | } |
636 | |
637 | static int rtl2832_read_status(struct dvb_frontend *fe, enum fe_status *status) |
638 | { |
639 | struct rtl2832_dev *dev = fe->demodulator_priv; |
640 | struct i2c_client *client = dev->client; |
641 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
642 | int ret; |
643 | u32 tmp; |
644 | u8 u8tmp, buf[2]; |
645 | u16 u16tmp; |
646 | |
647 | dev_dbg(&client->dev, "\n" ); |
648 | |
649 | *status = 0; |
650 | if (dev->sleeping) |
651 | return 0; |
652 | |
653 | ret = rtl2832_rd_demod_reg(dev, reg: DVBT_FSM_STAGE, val: &tmp); |
654 | 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; |
660 | } else if (tmp == 10) { |
661 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | |
662 | FE_HAS_VITERBI; |
663 | } |
664 | |
665 | dev->fe_status = *status; |
666 | |
667 | /* signal strength */ |
668 | if (dev->fe_status & FE_HAS_SIGNAL) { |
669 | /* read digital AGC */ |
670 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x305, val: &u8tmp, val_count: 1); |
671 | 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 | |
685 | /* 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 | |
696 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x33c, val: &u8tmp, val_count: 1); |
697 | if (ret) |
698 | goto err; |
699 | |
700 | constellation = (u8tmp >> 2) & 0x03; /* [3:2] */ |
701 | ret = -EINVAL; |
702 | if (constellation > CONSTELLATION_NUM - 1) |
703 | goto err; |
704 | |
705 | hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */ |
706 | if (hierarchy > HIERARCHY_NUM - 1) |
707 | goto err; |
708 | |
709 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x40c, val: buf, val_count: 2); |
710 | if (ret) |
711 | goto err; |
712 | |
713 | u16tmp = buf[0] << 8 | buf[1] << 0; |
714 | if (u16tmp) |
715 | tmp = (constant[constellation][hierarchy] - |
716 | intlog10(value: u16tmp)) / ((1 << 24) / 10000); |
717 | else |
718 | tmp = 0; |
719 | |
720 | dev_dbg(&client->dev, "cnr raw=%u\n" , u16tmp); |
721 | |
722 | c->cnr.stat[0].scale = FE_SCALE_DECIBEL; |
723 | c->cnr.stat[0].svalue = tmp; |
724 | } else { |
725 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
726 | } |
727 | |
728 | /* BER */ |
729 | if (dev->fe_status & FE_HAS_LOCK) { |
730 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x34e, val: buf, val_count: 2); |
731 | if (ret) |
732 | goto err; |
733 | |
734 | u16tmp = buf[0] << 8 | buf[1] << 0; |
735 | dev->post_bit_error += u16tmp; |
736 | dev->post_bit_count += 1000000; |
737 | |
738 | dev_dbg(&client->dev, "ber errors=%u total=1000000\n" , u16tmp); |
739 | |
740 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; |
741 | c->post_bit_error.stat[0].uvalue = dev->post_bit_error; |
742 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
743 | c->post_bit_count.stat[0].uvalue = dev->post_bit_count; |
744 | } else { |
745 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
746 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
747 | } |
748 | |
749 | return 0; |
750 | err: |
751 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
752 | return ret; |
753 | } |
754 | |
755 | static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) |
756 | { |
757 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
758 | |
759 | /* report SNR in resolution of 0.1 dB */ |
760 | if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) |
761 | *snr = div_s64(dividend: c->cnr.stat[0].svalue, divisor: 100); |
762 | else |
763 | *snr = 0; |
764 | |
765 | return 0; |
766 | } |
767 | |
768 | static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) |
769 | { |
770 | struct rtl2832_dev *dev = fe->demodulator_priv; |
771 | |
772 | *ber = (dev->post_bit_error - dev->post_bit_error_prev); |
773 | dev->post_bit_error_prev = dev->post_bit_error; |
774 | |
775 | return 0; |
776 | } |
777 | |
778 | /* |
779 | * I2C gate/mux/repeater logic |
780 | * There is delay mechanism to avoid unneeded I2C gate open / close. Gate close |
781 | * is delayed here a little bit in order to see if there is sequence of I2C |
782 | * messages sent to same I2C bus. |
783 | */ |
784 | static void rtl2832_i2c_gate_work(struct work_struct *work) |
785 | { |
786 | struct rtl2832_dev *dev = container_of(work, struct rtl2832_dev, i2c_gate_work.work); |
787 | struct i2c_client *client = dev->client; |
788 | int ret; |
789 | |
790 | /* close gate */ |
791 | ret = regmap_update_bits(map: dev->regmap, reg: 0x101, mask: 0x08, val: 0x00); |
792 | if (ret) |
793 | goto err; |
794 | |
795 | return; |
796 | err: |
797 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
798 | } |
799 | |
800 | static int rtl2832_select(struct i2c_mux_core *muxc, u32 chan_id) |
801 | { |
802 | struct rtl2832_dev *dev = i2c_mux_priv(muxc); |
803 | struct i2c_client *client = dev->client; |
804 | int ret; |
805 | |
806 | /* terminate possible gate closing */ |
807 | cancel_delayed_work(dwork: &dev->i2c_gate_work); |
808 | |
809 | /* open gate */ |
810 | ret = regmap_update_bits(map: dev->regmap, reg: 0x101, mask: 0x08, val: 0x08); |
811 | if (ret) |
812 | goto err; |
813 | |
814 | return 0; |
815 | err: |
816 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
817 | return ret; |
818 | } |
819 | |
820 | static int rtl2832_deselect(struct i2c_mux_core *muxc, u32 chan_id) |
821 | { |
822 | struct rtl2832_dev *dev = i2c_mux_priv(muxc); |
823 | |
824 | schedule_delayed_work(dwork: &dev->i2c_gate_work, delay: usecs_to_jiffies(u: 100)); |
825 | return 0; |
826 | } |
827 | |
828 | static const struct dvb_frontend_ops rtl2832_ops = { |
829 | .delsys = { SYS_DVBT }, |
830 | .info = { |
831 | .name = "Realtek RTL2832 (DVB-T)" , |
832 | .frequency_min_hz = 174 * MHz, |
833 | .frequency_max_hz = 862 * MHz, |
834 | .frequency_stepsize_hz = 166667, |
835 | .caps = FE_CAN_FEC_1_2 | |
836 | FE_CAN_FEC_2_3 | |
837 | FE_CAN_FEC_3_4 | |
838 | FE_CAN_FEC_5_6 | |
839 | FE_CAN_FEC_7_8 | |
840 | FE_CAN_FEC_AUTO | |
841 | FE_CAN_QPSK | |
842 | FE_CAN_QAM_16 | |
843 | FE_CAN_QAM_64 | |
844 | FE_CAN_QAM_AUTO | |
845 | FE_CAN_TRANSMISSION_MODE_AUTO | |
846 | FE_CAN_GUARD_INTERVAL_AUTO | |
847 | FE_CAN_HIERARCHY_AUTO | |
848 | FE_CAN_RECOVER | |
849 | FE_CAN_MUTE_TS |
850 | }, |
851 | |
852 | .init = rtl2832_init, |
853 | .sleep = rtl2832_sleep, |
854 | |
855 | .get_tune_settings = rtl2832_get_tune_settings, |
856 | |
857 | .set_frontend = rtl2832_set_frontend, |
858 | .get_frontend = rtl2832_get_frontend, |
859 | |
860 | .read_status = rtl2832_read_status, |
861 | .read_snr = rtl2832_read_snr, |
862 | .read_ber = rtl2832_read_ber, |
863 | }; |
864 | |
865 | static bool rtl2832_volatile_reg(struct device *dev, unsigned int reg) |
866 | { |
867 | switch (reg) { |
868 | case 0x305: |
869 | case 0x33c: |
870 | case 0x34e: |
871 | case 0x351: |
872 | case 0x40c ... 0x40d: |
873 | return true; |
874 | default: |
875 | break; |
876 | } |
877 | |
878 | return false; |
879 | } |
880 | |
881 | static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client) |
882 | { |
883 | struct rtl2832_dev *dev = i2c_get_clientdata(client); |
884 | |
885 | dev_dbg(&client->dev, "\n" ); |
886 | return &dev->fe; |
887 | } |
888 | |
889 | static struct i2c_adapter *rtl2832_get_i2c_adapter(struct i2c_client *client) |
890 | { |
891 | struct rtl2832_dev *dev = i2c_get_clientdata(client); |
892 | |
893 | dev_dbg(&client->dev, "\n" ); |
894 | return dev->muxc->adapter[0]; |
895 | } |
896 | |
897 | static int rtl2832_slave_ts_ctrl(struct i2c_client *client, bool enable) |
898 | { |
899 | struct rtl2832_dev *dev = i2c_get_clientdata(client); |
900 | int ret; |
901 | |
902 | dev_dbg(&client->dev, "enable=%d\n" , enable); |
903 | |
904 | if (enable) { |
905 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_SOFT_RST, val: 0x0); |
906 | if (ret) |
907 | goto err; |
908 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x10c, val: "\x5f\xff" , val_count: 2); |
909 | if (ret) |
910 | goto err; |
911 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_PIP_ON, val: 0x1); |
912 | if (ret) |
913 | goto err; |
914 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x0bc, val: "\x18" , val_count: 1); |
915 | if (ret) |
916 | goto err; |
917 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x192, val: "\x7f\xf7\xff" , val_count: 3); |
918 | if (ret) |
919 | goto err; |
920 | } else { |
921 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x192, val: "\x00\x0f\xff" , val_count: 3); |
922 | if (ret) |
923 | goto err; |
924 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x0bc, val: "\x08" , val_count: 1); |
925 | if (ret) |
926 | goto err; |
927 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_PIP_ON, val: 0x0); |
928 | if (ret) |
929 | goto err; |
930 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x10c, val: "\x00\x00" , val_count: 2); |
931 | if (ret) |
932 | goto err; |
933 | ret = rtl2832_wr_demod_reg(dev, reg: DVBT_SOFT_RST, val: 0x1); |
934 | if (ret) |
935 | goto err; |
936 | } |
937 | |
938 | dev->slave_ts = enable; |
939 | |
940 | return 0; |
941 | err: |
942 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
943 | return ret; |
944 | } |
945 | |
946 | static int rtl2832_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) |
947 | { |
948 | struct rtl2832_dev *dev = fe->demodulator_priv; |
949 | struct i2c_client *client = dev->client; |
950 | int ret; |
951 | u8 u8tmp; |
952 | |
953 | dev_dbg(&client->dev, "onoff=%d, slave_ts=%d\n" , onoff, dev->slave_ts); |
954 | |
955 | /* enable / disable PID filter */ |
956 | if (onoff) |
957 | u8tmp = 0x80; |
958 | else |
959 | u8tmp = 0x00; |
960 | |
961 | if (dev->slave_ts) |
962 | ret = regmap_update_bits(map: dev->regmap, reg: 0x021, mask: 0xc0, val: u8tmp); |
963 | else |
964 | ret = regmap_update_bits(map: dev->regmap, reg: 0x061, mask: 0xc0, val: u8tmp); |
965 | if (ret) |
966 | goto err; |
967 | |
968 | return 0; |
969 | err: |
970 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
971 | return ret; |
972 | } |
973 | |
974 | static int rtl2832_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, |
975 | int onoff) |
976 | { |
977 | struct rtl2832_dev *dev = fe->demodulator_priv; |
978 | struct i2c_client *client = dev->client; |
979 | int ret; |
980 | u8 buf[4]; |
981 | |
982 | dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d slave_ts=%d\n" , |
983 | index, pid, onoff, dev->slave_ts); |
984 | |
985 | /* skip invalid PIDs (0x2000) */ |
986 | if (pid > 0x1fff || index > 32) |
987 | return 0; |
988 | |
989 | if (onoff) |
990 | set_bit(nr: index, addr: &dev->filters); |
991 | else |
992 | clear_bit(nr: index, addr: &dev->filters); |
993 | |
994 | /* enable / disable PIDs */ |
995 | buf[0] = (dev->filters >> 0) & 0xff; |
996 | buf[1] = (dev->filters >> 8) & 0xff; |
997 | buf[2] = (dev->filters >> 16) & 0xff; |
998 | buf[3] = (dev->filters >> 24) & 0xff; |
999 | |
1000 | if (dev->slave_ts) |
1001 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x022, val: buf, val_count: 4); |
1002 | else |
1003 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x062, val: buf, val_count: 4); |
1004 | if (ret) |
1005 | goto err; |
1006 | |
1007 | /* add PID */ |
1008 | buf[0] = (pid >> 8) & 0xff; |
1009 | buf[1] = (pid >> 0) & 0xff; |
1010 | |
1011 | if (dev->slave_ts) |
1012 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x026 + 2 * index, val: buf, val_count: 2); |
1013 | else |
1014 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x066 + 2 * index, val: buf, val_count: 2); |
1015 | if (ret) |
1016 | goto err; |
1017 | |
1018 | return 0; |
1019 | err: |
1020 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1021 | return ret; |
1022 | } |
1023 | |
1024 | static int rtl2832_probe(struct i2c_client *client) |
1025 | { |
1026 | struct rtl2832_platform_data *pdata = client->dev.platform_data; |
1027 | struct i2c_adapter *i2c = client->adapter; |
1028 | struct rtl2832_dev *dev; |
1029 | int ret; |
1030 | u8 tmp; |
1031 | 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 | }; |
1042 | |
1043 | dev_dbg(&client->dev, "\n" ); |
1044 | |
1045 | /* allocate memory for the internal state */ |
1046 | dev = kzalloc(size: sizeof(struct rtl2832_dev), GFP_KERNEL); |
1047 | if (dev == NULL) { |
1048 | ret = -ENOMEM; |
1049 | goto err; |
1050 | } |
1051 | |
1052 | /* setup the state */ |
1053 | i2c_set_clientdata(client, data: dev); |
1054 | dev->client = client; |
1055 | dev->pdata = client->dev.platform_data; |
1056 | dev->sleeping = true; |
1057 | INIT_DELAYED_WORK(&dev->i2c_gate_work, rtl2832_i2c_gate_work); |
1058 | /* create regmap */ |
1059 | dev->regmap_config.reg_bits = 8; |
1060 | dev->regmap_config.val_bits = 8; |
1061 | 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); |
1065 | dev->regmap_config.cache_type = REGCACHE_NONE; |
1066 | dev->regmap = regmap_init_i2c(client, &dev->regmap_config); |
1067 | if (IS_ERR(ptr: dev->regmap)) { |
1068 | ret = PTR_ERR(ptr: dev->regmap); |
1069 | goto err_kfree; |
1070 | } |
1071 | |
1072 | /* check if the demod is there */ |
1073 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x000, val: &tmp, val_count: 1); |
1074 | if (ret) |
1075 | goto err_regmap_exit; |
1076 | |
1077 | /* create muxed i2c adapter for demod tuner bus */ |
1078 | dev->muxc = i2c_mux_alloc(parent: i2c, dev: &i2c->dev, max_adapters: 1, sizeof_priv: 0, I2C_MUX_LOCKED, |
1079 | select: rtl2832_select, deselect: rtl2832_deselect); |
1080 | if (!dev->muxc) { |
1081 | ret = -ENOMEM; |
1082 | goto err_regmap_exit; |
1083 | } |
1084 | dev->muxc->priv = dev; |
1085 | ret = i2c_mux_add_adapter(muxc: dev->muxc, force_nr: 0, chan_id: 0, class: 0); |
1086 | if (ret) |
1087 | goto err_regmap_exit; |
1088 | |
1089 | /* create dvb_frontend */ |
1090 | memcpy(&dev->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops)); |
1091 | dev->fe.demodulator_priv = dev; |
1092 | |
1093 | /* setup callbacks */ |
1094 | pdata->get_dvb_frontend = rtl2832_get_dvb_frontend; |
1095 | pdata->get_i2c_adapter = rtl2832_get_i2c_adapter; |
1096 | pdata->slave_ts_ctrl = rtl2832_slave_ts_ctrl; |
1097 | pdata->pid_filter = rtl2832_pid_filter; |
1098 | pdata->pid_filter_ctrl = rtl2832_pid_filter_ctrl; |
1099 | pdata->regmap = dev->regmap; |
1100 | |
1101 | dev_info(&client->dev, "Realtek RTL2832 successfully attached\n" ); |
1102 | return 0; |
1103 | err_regmap_exit: |
1104 | regmap_exit(map: dev->regmap); |
1105 | err_kfree: |
1106 | kfree(objp: dev); |
1107 | err: |
1108 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1109 | return ret; |
1110 | } |
1111 | |
1112 | static void rtl2832_remove(struct i2c_client *client) |
1113 | { |
1114 | struct rtl2832_dev *dev = i2c_get_clientdata(client); |
1115 | |
1116 | dev_dbg(&client->dev, "\n" ); |
1117 | |
1118 | cancel_delayed_work_sync(dwork: &dev->i2c_gate_work); |
1119 | |
1120 | i2c_mux_del_adapters(muxc: dev->muxc); |
1121 | |
1122 | regmap_exit(map: dev->regmap); |
1123 | |
1124 | kfree(objp: dev); |
1125 | } |
1126 | |
1127 | static const struct i2c_device_id rtl2832_id_table[] = { |
1128 | {"rtl2832" , 0}, |
1129 | {} |
1130 | }; |
1131 | MODULE_DEVICE_TABLE(i2c, rtl2832_id_table); |
1132 | |
1133 | static struct i2c_driver rtl2832_driver = { |
1134 | .driver = { |
1135 | .name = "rtl2832" , |
1136 | .suppress_bind_attrs = true, |
1137 | }, |
1138 | .probe = rtl2832_probe, |
1139 | .remove = rtl2832_remove, |
1140 | .id_table = rtl2832_id_table, |
1141 | }; |
1142 | |
1143 | module_i2c_driver(rtl2832_driver); |
1144 | |
1145 | MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>" ); |
1146 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>" ); |
1147 | MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver" ); |
1148 | MODULE_LICENSE("GPL" ); |
1149 | |