1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/clk.h>
21#include <linux/delay.h>
22#include <linux/errno.h>
23#include <linux/i2c.h>
24#include <linux/kernel.h>
25#include <linux/math64.h>
26#include <linux/max2175.h>
27#include <linux/module.h>
28#include <linux/of.h>
29#include <linux/regmap.h>
30#include <linux/slab.h>
31#include <media/v4l2-ctrls.h>
32#include <media/v4l2-device.h>
33
34#include "max2175.h"
35
36#define DRIVER_NAME "max2175"
37
38#define mxm_dbg(ctx, fmt, arg...) dev_dbg(&ctx->client->dev, fmt, ## arg)
39#define mxm_err(ctx, fmt, arg...) dev_err(&ctx->client->dev, fmt, ## arg)
40
41
42struct max2175_rxmode {
43 enum max2175_band band;
44 u32 freq;
45 u8 i2s_word_size;
46};
47
48
49struct max2175_reg_map {
50 u8 idx;
51 u8 val;
52};
53
54static const struct max2175_rxmode eu_rx_modes[] = {
55
56 [MAX2175_EU_FM_1_2] = { MAX2175_BAND_FM, 98256000, 1 },
57 [MAX2175_DAB_1_2] = { MAX2175_BAND_VHF, 182640000, 0 },
58};
59
60static const struct max2175_rxmode na_rx_modes[] = {
61
62 [MAX2175_NA_FM_1_0] = { MAX2175_BAND_FM, 98255520, 1 },
63 [MAX2175_NA_FM_2_0] = { MAX2175_BAND_FM, 98255520, 6 },
64};
65
66
67
68
69
70static const u8 full_fm_eu_1p0[] = {
71 0x15, 0x04, 0xb8, 0xe3, 0x35, 0x18, 0x7c, 0x00,
72 0x00, 0x7d, 0x40, 0x08, 0x70, 0x7a, 0x88, 0x91,
73 0x61, 0x61, 0x61, 0x61, 0x5a, 0x0f, 0x34, 0x1c,
74 0x14, 0x88, 0x33, 0x02, 0x00, 0x09, 0x00, 0x65,
75 0x9f, 0x2b, 0x80, 0x00, 0x95, 0x05, 0x2c, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
77 0x4a, 0x08, 0xa8, 0x0e, 0x0e, 0x2f, 0x7e, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5e, 0xa9,
80 0xae, 0xbb, 0x57, 0x18, 0x3b, 0x03, 0x3b, 0x64,
81 0x40, 0x60, 0x00, 0x2a, 0xbf, 0x3f, 0xff, 0x9f,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
83 0xff, 0xfc, 0xef, 0x1c, 0x40, 0x00, 0x00, 0x02,
84 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x40, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00,
87 0x00, 0x47, 0x00, 0x00, 0x11, 0x3f, 0x22, 0x00,
88 0xf1, 0x00, 0x41, 0x03, 0xb0, 0x00, 0x00, 0x00,
89 0x1b,
90};
91
92static const u8 full_fm_na_1p0[] = {
93 0x13, 0x08, 0x8d, 0xc0, 0x35, 0x18, 0x7d, 0x3f,
94 0x7d, 0x75, 0x40, 0x08, 0x70, 0x7a, 0x88, 0x91,
95 0x61, 0x61, 0x61, 0x61, 0x5c, 0x0f, 0x34, 0x1c,
96 0x14, 0x88, 0x33, 0x02, 0x00, 0x01, 0x00, 0x65,
97 0x9f, 0x2b, 0x80, 0x00, 0x95, 0x05, 0x2c, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
99 0x4a, 0x08, 0xa8, 0x0e, 0x0e, 0xaf, 0x7e, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5e, 0xa9,
102 0xae, 0xbb, 0x57, 0x18, 0x3b, 0x03, 0x3b, 0x64,
103 0x40, 0x60, 0x00, 0x2a, 0xbf, 0x3f, 0xff, 0x9f,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
105 0xff, 0xfc, 0xef, 0x1c, 0x40, 0x00, 0x00, 0x02,
106 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x40, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00,
109 0x00, 0x35, 0x00, 0x00, 0x11, 0x3f, 0x22, 0x00,
110 0xf1, 0x00, 0x41, 0x03, 0xb0, 0x00, 0x00, 0x00,
111 0x1b,
112};
113
114
115static const struct max2175_reg_map dab12_map[] = {
116 { 0x01, 0x13 }, { 0x02, 0x0d }, { 0x03, 0x15 }, { 0x04, 0x55 },
117 { 0x05, 0x0a }, { 0x06, 0xa0 }, { 0x07, 0x40 }, { 0x08, 0x00 },
118 { 0x09, 0x00 }, { 0x0a, 0x7d }, { 0x0b, 0x4a }, { 0x0c, 0x28 },
119 { 0x0e, 0x43 }, { 0x0f, 0xb5 }, { 0x10, 0x31 }, { 0x11, 0x9e },
120 { 0x12, 0x68 }, { 0x13, 0x9e }, { 0x14, 0x68 }, { 0x15, 0x58 },
121 { 0x16, 0x2f }, { 0x17, 0x3f }, { 0x18, 0x40 }, { 0x1a, 0x88 },
122 { 0x1b, 0xaa }, { 0x1c, 0x9a }, { 0x1d, 0x00 }, { 0x1e, 0x00 },
123 { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x00 }, { 0x26, 0x00 },
124 { 0x27, 0x00 }, { 0x32, 0x08 }, { 0x33, 0xf8 }, { 0x36, 0x2d },
125 { 0x37, 0x7e }, { 0x55, 0xaf }, { 0x56, 0x3f }, { 0x57, 0xf8 },
126 { 0x58, 0x99 }, { 0x76, 0x00 }, { 0x77, 0x00 }, { 0x78, 0x02 },
127 { 0x79, 0x40 }, { 0x82, 0x00 }, { 0x83, 0x00 }, { 0x85, 0x00 },
128 { 0x86, 0x20 },
129};
130
131
132static const struct max2175_reg_map fmeu1p2_map[] = {
133 { 0x01, 0x15 }, { 0x02, 0x04 }, { 0x03, 0xb8 }, { 0x04, 0xe3 },
134 { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7c }, { 0x08, 0x00 },
135 { 0x09, 0x00 }, { 0x0a, 0x73 }, { 0x0b, 0x40 }, { 0x0c, 0x08 },
136 { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
137 { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5a },
138 { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
139 { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
140 { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
141 { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0x2f },
142 { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
143 { 0x58, 0x9f }, { 0x76, 0xac }, { 0x77, 0x40 }, { 0x78, 0x00 },
144 { 0x79, 0x00 }, { 0x82, 0x47 }, { 0x83, 0x00 }, { 0x85, 0x11 },
145 { 0x86, 0x3f },
146};
147
148
149static const struct max2175_reg_map fmna1p0_map[] = {
150 { 0x01, 0x13 }, { 0x02, 0x08 }, { 0x03, 0x8d }, { 0x04, 0xc0 },
151 { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7d }, { 0x08, 0x3f },
152 { 0x09, 0x7d }, { 0x0a, 0x75 }, { 0x0b, 0x40 }, { 0x0c, 0x08 },
153 { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
154 { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5c },
155 { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
156 { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
157 { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
158 { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0xaf },
159 { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
160 { 0x58, 0x9f }, { 0x76, 0xa6 }, { 0x77, 0x40 }, { 0x78, 0x00 },
161 { 0x79, 0x00 }, { 0x82, 0x35 }, { 0x83, 0x00 }, { 0x85, 0x11 },
162 { 0x86, 0x3f },
163};
164
165
166static const struct max2175_reg_map fmna2p0_map[] = {
167 { 0x01, 0x13 }, { 0x02, 0x08 }, { 0x03, 0x8d }, { 0x04, 0xc0 },
168 { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7c }, { 0x08, 0x54 },
169 { 0x09, 0xa7 }, { 0x0a, 0x55 }, { 0x0b, 0x42 }, { 0x0c, 0x48 },
170 { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
171 { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5c },
172 { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
173 { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
174 { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
175 { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0xaf },
176 { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
177 { 0x58, 0x9f }, { 0x76, 0xac }, { 0x77, 0xc0 }, { 0x78, 0x00 },
178 { 0x79, 0x00 }, { 0x82, 0x6b }, { 0x83, 0x00 }, { 0x85, 0x11 },
179 { 0x86, 0x3f },
180};
181
182static const u16 ch_coeff_dab1[] = {
183 0x001c, 0x0007, 0xffcd, 0x0056, 0xffa4, 0x0033, 0x0027, 0xff61,
184 0x010e, 0xfec0, 0x0106, 0xffb8, 0xff1c, 0x023c, 0xfcb2, 0x039b,
185 0xfd4e, 0x0055, 0x036a, 0xf7de, 0x0d21, 0xee72, 0x1499, 0x6a51,
186};
187
188static const u16 ch_coeff_fmeu[] = {
189 0x0000, 0xffff, 0x0001, 0x0002, 0xfffa, 0xffff, 0x0015, 0xffec,
190 0xffde, 0x0054, 0xfff9, 0xff52, 0x00b8, 0x00a2, 0xfe0a, 0x00af,
191 0x02e3, 0xfc14, 0xfe89, 0x089d, 0xfa2e, 0xf30f, 0x25be, 0x4eb6,
192};
193
194static const u16 eq_coeff_fmeu1_ra02_m6db[] = {
195 0x0040, 0xffc6, 0xfffa, 0x002c, 0x000d, 0xff90, 0x0037, 0x006e,
196 0xffc0, 0xff5b, 0x006a, 0x00f0, 0xff57, 0xfe94, 0x0112, 0x0252,
197 0xfe0c, 0xfc6a, 0x0385, 0x0553, 0xfa49, 0xf789, 0x0b91, 0x1a10,
198};
199
200static const u16 ch_coeff_fmna[] = {
201 0x0001, 0x0003, 0xfffe, 0xfff4, 0x0000, 0x001f, 0x000c, 0xffbc,
202 0xffd3, 0x007d, 0x0075, 0xff33, 0xff01, 0x0131, 0x01ef, 0xfe60,
203 0xfc7a, 0x020e, 0x0656, 0xfd94, 0xf395, 0x02ab, 0x2857, 0x3d3f,
204};
205
206static const u16 eq_coeff_fmna1_ra02_m6db[] = {
207 0xfff1, 0xffe1, 0xffef, 0x000e, 0x0030, 0x002f, 0xfff6, 0xffa7,
208 0xff9d, 0x000a, 0x00a2, 0x00b5, 0xffea, 0xfed9, 0xfec5, 0x003d,
209 0x0217, 0x021b, 0xff5a, 0xfc2b, 0xfcbd, 0x02c4, 0x0ac3, 0x0e85,
210};
211
212static const u8 adc_presets[2][23] = {
213 {
214 0x83, 0x00, 0xcf, 0xb4, 0x0f, 0x2c, 0x0c, 0x49,
215 0x00, 0x00, 0x00, 0x8c, 0x02, 0x02, 0x00, 0x04,
216 0xec, 0x82, 0x4b, 0xcc, 0x01, 0x88, 0x0c,
217 },
218 {
219 0x83, 0x00, 0xcf, 0xb4, 0x0f, 0x2c, 0x0c, 0x49,
220 0x00, 0x00, 0x00, 0x8c, 0x02, 0x20, 0x33, 0x8c,
221 0x57, 0xd7, 0x59, 0xb7, 0x65, 0x0e, 0x0c,
222 },
223};
224
225
226static const struct v4l2_frequency_band eu_bands_rf = {
227 .tuner = 0,
228 .type = V4L2_TUNER_RF,
229 .index = 0,
230 .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
231 .rangelow = 65000000,
232 .rangehigh = 240000000,
233};
234
235static const struct v4l2_frequency_band na_bands_rf = {
236 .tuner = 0,
237 .type = V4L2_TUNER_RF,
238 .index = 0,
239 .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
240 .rangelow = 65000000,
241 .rangehigh = 108000000,
242};
243
244
245static const struct regmap_range max2175_regmap_volatile_range[] = {
246 regmap_reg_range(0x30, 0x35),
247 regmap_reg_range(0x3a, 0x45),
248 regmap_reg_range(0x59, 0x5e),
249 regmap_reg_range(0x73, 0x75),
250};
251
252static const struct regmap_access_table max2175_volatile_regs = {
253 .yes_ranges = max2175_regmap_volatile_range,
254 .n_yes_ranges = ARRAY_SIZE(max2175_regmap_volatile_range),
255};
256
257static const struct reg_default max2175_reg_defaults[] = {
258 { 0x00, 0x07},
259};
260
261static const struct regmap_config max2175_regmap_config = {
262 .reg_bits = 8,
263 .val_bits = 8,
264 .max_register = 0xff,
265 .reg_defaults = max2175_reg_defaults,
266 .num_reg_defaults = ARRAY_SIZE(max2175_reg_defaults),
267 .volatile_table = &max2175_volatile_regs,
268 .cache_type = REGCACHE_FLAT,
269};
270
271struct max2175 {
272 struct v4l2_subdev sd;
273 struct i2c_client *client;
274
275
276 struct v4l2_ctrl_handler ctrl_hdl;
277 struct v4l2_ctrl *lna_gain;
278 struct v4l2_ctrl *if_gain;
279 struct v4l2_ctrl *pll_lock;
280 struct v4l2_ctrl *i2s_en;
281 struct v4l2_ctrl *hsls;
282 struct v4l2_ctrl *rx_mode;
283
284
285 struct regmap *regmap;
286
287
288 u32 freq;
289 const struct max2175_rxmode *rx_modes;
290 const struct v4l2_frequency_band *bands_rf;
291
292
293 unsigned long xtal_freq;
294 u32 decim_ratio;
295 bool master;
296 bool am_hiz;
297
298
299 u8 rom_bbf_bw_am;
300 u8 rom_bbf_bw_fm;
301 u8 rom_bbf_bw_dab;
302
303
304 bool mode_resolved;
305};
306
307static inline struct max2175 *max2175_from_sd(struct v4l2_subdev *sd)
308{
309 return container_of(sd, struct max2175, sd);
310}
311
312static inline struct max2175 *max2175_from_ctrl_hdl(struct v4l2_ctrl_handler *h)
313{
314 return container_of(h, struct max2175, ctrl_hdl);
315}
316
317
318static inline u8 max2175_get_bitval(u8 val, u8 msb, u8 lsb)
319{
320 return (val & GENMASK(msb, lsb)) >> lsb;
321}
322
323
324static int max2175_read(struct max2175 *ctx, u8 idx, u8 *val)
325{
326 u32 regval;
327 int ret;
328
329 ret = regmap_read(ctx->regmap, idx, ®val);
330 if (ret)
331 mxm_err(ctx, "read ret(%d): idx 0x%02x\n", ret, idx);
332 else
333 *val = regval;
334
335 return ret;
336}
337
338static int max2175_write(struct max2175 *ctx, u8 idx, u8 val)
339{
340 int ret;
341
342 ret = regmap_write(ctx->regmap, idx, val);
343 if (ret)
344 mxm_err(ctx, "write ret(%d): idx 0x%02x val 0x%02x\n",
345 ret, idx, val);
346
347 return ret;
348}
349
350static u8 max2175_read_bits(struct max2175 *ctx, u8 idx, u8 msb, u8 lsb)
351{
352 u8 val;
353
354 if (max2175_read(ctx, idx, &val))
355 return 0;
356
357 return max2175_get_bitval(val, msb, lsb);
358}
359
360static int max2175_write_bits(struct max2175 *ctx, u8 idx,
361 u8 msb, u8 lsb, u8 newval)
362{
363 int ret = regmap_update_bits(ctx->regmap, idx, GENMASK(msb, lsb),
364 newval << lsb);
365
366 if (ret)
367 mxm_err(ctx, "wbits ret(%d): idx 0x%02x\n", ret, idx);
368
369 return ret;
370}
371
372static int max2175_write_bit(struct max2175 *ctx, u8 idx, u8 bit, u8 newval)
373{
374 return max2175_write_bits(ctx, idx, bit, bit, newval);
375}
376
377
378static int max2175_poll_timeout(struct max2175 *ctx, u8 idx, u8 msb, u8 lsb,
379 u8 exp_bitval, u32 timeout_us)
380{
381 unsigned int val;
382
383 return regmap_read_poll_timeout(ctx->regmap, idx, val,
384 (max2175_get_bitval(val, msb, lsb) == exp_bitval),
385 1000, timeout_us);
386}
387
388static int max2175_poll_csm_ready(struct max2175 *ctx)
389{
390 int ret;
391
392 ret = max2175_poll_timeout(ctx, 69, 1, 1, 0, 50000);
393 if (ret)
394 mxm_err(ctx, "csm not ready\n");
395
396 return ret;
397}
398
399#define MAX2175_IS_BAND_AM(ctx) \
400 (max2175_read_bits(ctx, 5, 1, 0) == MAX2175_BAND_AM)
401
402#define MAX2175_IS_BAND_VHF(ctx) \
403 (max2175_read_bits(ctx, 5, 1, 0) == MAX2175_BAND_VHF)
404
405#define MAX2175_IS_FM_MODE(ctx) \
406 (max2175_read_bits(ctx, 12, 5, 4) == 0)
407
408#define MAX2175_IS_FMHD_MODE(ctx) \
409 (max2175_read_bits(ctx, 12, 5, 4) == 1)
410
411#define MAX2175_IS_DAB_MODE(ctx) \
412 (max2175_read_bits(ctx, 12, 5, 4) == 2)
413
414static int max2175_band_from_freq(u32 freq)
415{
416 if (freq >= 144000 && freq <= 26100000)
417 return MAX2175_BAND_AM;
418 else if (freq >= 65000000 && freq <= 108000000)
419 return MAX2175_BAND_FM;
420
421 return MAX2175_BAND_VHF;
422}
423
424static void max2175_i2s_enable(struct max2175 *ctx, bool enable)
425{
426 if (enable)
427
428 max2175_write_bits(ctx, 104, 3, 0, 2);
429 else
430
431 max2175_write_bits(ctx, 104, 3, 0, 9);
432 mxm_dbg(ctx, "i2s %sabled\n", enable ? "en" : "dis");
433}
434
435static void max2175_set_filter_coeffs(struct max2175 *ctx, u8 m_sel,
436 u8 bank, const u16 *coeffs)
437{
438 unsigned int i;
439 u8 coeff_addr, upper_address = 24;
440
441 mxm_dbg(ctx, "set_filter_coeffs: m_sel %d bank %d\n", m_sel, bank);
442 max2175_write_bits(ctx, 114, 5, 4, m_sel);
443
444 if (m_sel == 2)
445 upper_address = 12;
446
447 for (i = 0; i < upper_address; i++) {
448 coeff_addr = i + bank * 24;
449 max2175_write(ctx, 115, coeffs[i] >> 8);
450 max2175_write(ctx, 116, coeffs[i]);
451 max2175_write(ctx, 117, coeff_addr | 1 << 7);
452 }
453 max2175_write_bit(ctx, 117, 7, 0);
454}
455
456static void max2175_load_fmeu_1p2(struct max2175 *ctx)
457{
458 unsigned int i;
459
460 for (i = 0; i < ARRAY_SIZE(fmeu1p2_map); i++)
461 max2175_write(ctx, fmeu1p2_map[i].idx, fmeu1p2_map[i].val);
462
463 ctx->decim_ratio = 36;
464
465
466 max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0, ch_coeff_fmeu);
467 max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
468 eq_coeff_fmeu1_ra02_m6db);
469}
470
471static void max2175_load_dab_1p2(struct max2175 *ctx)
472{
473 unsigned int i;
474
475 for (i = 0; i < ARRAY_SIZE(dab12_map); i++)
476 max2175_write(ctx, dab12_map[i].idx, dab12_map[i].val);
477
478 ctx->decim_ratio = 1;
479
480
481 max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 2, ch_coeff_dab1);
482}
483
484static void max2175_load_fmna_1p0(struct max2175 *ctx)
485{
486 unsigned int i;
487
488 for (i = 0; i < ARRAY_SIZE(fmna1p0_map); i++)
489 max2175_write(ctx, fmna1p0_map[i].idx, fmna1p0_map[i].val);
490}
491
492static void max2175_load_fmna_2p0(struct max2175 *ctx)
493{
494 unsigned int i;
495
496 for (i = 0; i < ARRAY_SIZE(fmna2p0_map); i++)
497 max2175_write(ctx, fmna2p0_map[i].idx, fmna2p0_map[i].val);
498}
499
500static void max2175_set_bbfilter(struct max2175 *ctx)
501{
502 if (MAX2175_IS_BAND_AM(ctx)) {
503 max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_am);
504 mxm_dbg(ctx, "set_bbfilter AM: rom %d\n", ctx->rom_bbf_bw_am);
505 } else if (MAX2175_IS_DAB_MODE(ctx)) {
506 max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_dab);
507 mxm_dbg(ctx, "set_bbfilter DAB: rom %d\n", ctx->rom_bbf_bw_dab);
508 } else {
509 max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_fm);
510 mxm_dbg(ctx, "set_bbfilter FM: rom %d\n", ctx->rom_bbf_bw_fm);
511 }
512}
513
514static bool max2175_set_csm_mode(struct max2175 *ctx,
515 enum max2175_csm_mode new_mode)
516{
517 int ret = max2175_poll_csm_ready(ctx);
518
519 if (ret)
520 return ret;
521
522 max2175_write_bits(ctx, 0, 2, 0, new_mode);
523 mxm_dbg(ctx, "set csm new mode %d\n", new_mode);
524
525
526 switch (new_mode) {
527 case MAX2175_PRESET_TUNE:
528 usleep_range(51100, 51500);
529 break;
530
531
532
533
534 default:
535 break;
536 }
537
538 return max2175_poll_csm_ready(ctx);
539}
540
541static int max2175_csm_action(struct max2175 *ctx,
542 enum max2175_csm_mode action)
543{
544 int ret;
545
546 mxm_dbg(ctx, "csm_action: %d\n", action);
547
548
549 ret = max2175_set_csm_mode(ctx, MAX2175_LOAD_TO_BUFFER);
550 if (ret)
551 return ret;
552
553 return max2175_set_csm_mode(ctx, MAX2175_PRESET_TUNE);
554}
555
556static int max2175_set_lo_freq(struct max2175 *ctx, u32 lo_freq)
557{
558 u8 lo_mult, loband_bits = 0, vcodiv_bits = 0;
559 u32 int_desired, frac_desired;
560 enum max2175_band band;
561 int ret;
562
563 band = max2175_read_bits(ctx, 5, 1, 0);
564 switch (band) {
565 case MAX2175_BAND_AM:
566 lo_mult = 16;
567 break;
568 case MAX2175_BAND_FM:
569 if (lo_freq <= 74700000) {
570 lo_mult = 16;
571 } else if (lo_freq > 74700000 && lo_freq <= 110000000) {
572 loband_bits = 1;
573 lo_mult = 8;
574 } else {
575 loband_bits = 1;
576 vcodiv_bits = 3;
577 lo_mult = 8;
578 }
579 break;
580 case MAX2175_BAND_VHF:
581 if (lo_freq <= 210000000)
582 vcodiv_bits = 2;
583 else
584 vcodiv_bits = 1;
585
586 loband_bits = 2;
587 lo_mult = 4;
588 break;
589 default:
590 loband_bits = 3;
591 vcodiv_bits = 2;
592 lo_mult = 2;
593 break;
594 }
595
596 if (band == MAX2175_BAND_L)
597 lo_freq /= lo_mult;
598 else
599 lo_freq *= lo_mult;
600
601 int_desired = lo_freq / ctx->xtal_freq;
602 frac_desired = div_u64((u64)(lo_freq % ctx->xtal_freq) << 20,
603 ctx->xtal_freq);
604
605
606 ret = max2175_poll_csm_ready(ctx);
607 if (ret)
608 return ret;
609
610 mxm_dbg(ctx, "lo_mult %u int %u frac %u\n",
611 lo_mult, int_desired, frac_desired);
612
613
614 max2175_write(ctx, 1, int_desired);
615 max2175_write_bits(ctx, 2, 3, 0, (frac_desired >> 16) & 0xf);
616 max2175_write(ctx, 3, frac_desired >> 8);
617 max2175_write(ctx, 4, frac_desired);
618 max2175_write_bits(ctx, 5, 3, 2, loband_bits);
619 max2175_write_bits(ctx, 6, 7, 6, vcodiv_bits);
620
621 return ret;
622}
623
624
625
626
627
628static inline s64 max2175_round_closest(s64 dividend, s32 divisor)
629{
630 if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0))
631 return div_s64(dividend + divisor / 2, divisor);
632
633 return div_s64(dividend - divisor / 2, divisor);
634}
635
636static int max2175_set_nco_freq(struct max2175 *ctx, s32 nco_freq)
637{
638 s32 clock_rate = ctx->xtal_freq / ctx->decim_ratio;
639 u32 nco_reg, abs_nco_freq = abs(nco_freq);
640 s64 nco_val_desired;
641 int ret;
642
643 if (abs_nco_freq < clock_rate / 2) {
644 nco_val_desired = 2 * nco_freq;
645 } else {
646 nco_val_desired = 2LL * (clock_rate - abs_nco_freq);
647 if (nco_freq < 0)
648 nco_val_desired = -nco_val_desired;
649 }
650
651 nco_reg = max2175_round_closest(nco_val_desired << 20, clock_rate);
652
653 if (nco_freq < 0)
654 nco_reg += 0x200000;
655
656
657 ret = max2175_poll_csm_ready(ctx);
658 if (ret)
659 return ret;
660
661 mxm_dbg(ctx, "freq %d desired %lld reg %u\n",
662 nco_freq, nco_val_desired, nco_reg);
663
664
665 max2175_write_bits(ctx, 7, 4, 0, (nco_reg >> 16) & 0x1f);
666 max2175_write(ctx, 8, nco_reg >> 8);
667 max2175_write(ctx, 9, nco_reg);
668
669 return ret;
670}
671
672static int max2175_set_rf_freq_non_am_bands(struct max2175 *ctx, u64 freq,
673 u32 lo_pos)
674{
675 s64 adj_freq, low_if_freq;
676 int ret;
677
678 mxm_dbg(ctx, "rf_freq: non AM bands\n");
679
680 if (MAX2175_IS_FM_MODE(ctx))
681 low_if_freq = 128000;
682 else if (MAX2175_IS_FMHD_MODE(ctx))
683 low_if_freq = 228000;
684 else
685 return max2175_set_lo_freq(ctx, freq);
686
687 if (MAX2175_IS_BAND_VHF(ctx) == (lo_pos == MAX2175_LO_ABOVE_DESIRED))
688 adj_freq = freq + low_if_freq;
689 else
690 adj_freq = freq - low_if_freq;
691
692 ret = max2175_set_lo_freq(ctx, adj_freq);
693 if (ret)
694 return ret;
695
696 return max2175_set_nco_freq(ctx, -low_if_freq);
697}
698
699static int max2175_set_rf_freq(struct max2175 *ctx, u64 freq, u32 lo_pos)
700{
701 int ret;
702
703 if (MAX2175_IS_BAND_AM(ctx))
704 ret = max2175_set_nco_freq(ctx, freq);
705 else
706 ret = max2175_set_rf_freq_non_am_bands(ctx, freq, lo_pos);
707
708 mxm_dbg(ctx, "set_rf_freq: ret %d freq %llu\n", ret, freq);
709
710 return ret;
711}
712
713static int max2175_tune_rf_freq(struct max2175 *ctx, u64 freq, u32 hsls)
714{
715 int ret;
716
717 ret = max2175_set_rf_freq(ctx, freq, hsls);
718 if (ret)
719 return ret;
720
721 ret = max2175_csm_action(ctx, MAX2175_BUFFER_PLUS_PRESET_TUNE);
722 if (ret)
723 return ret;
724
725 mxm_dbg(ctx, "tune_rf_freq: old %u new %llu\n", ctx->freq, freq);
726 ctx->freq = freq;
727
728 return ret;
729}
730
731static void max2175_set_hsls(struct max2175 *ctx, u32 lo_pos)
732{
733 mxm_dbg(ctx, "set_hsls: lo_pos %u\n", lo_pos);
734
735 if ((lo_pos == MAX2175_LO_BELOW_DESIRED) == MAX2175_IS_BAND_VHF(ctx))
736 max2175_write_bit(ctx, 5, 4, 1);
737 else
738 max2175_write_bit(ctx, 5, 4, 0);
739}
740
741static void max2175_set_eu_rx_mode(struct max2175 *ctx, u32 rx_mode)
742{
743 switch (rx_mode) {
744 case MAX2175_EU_FM_1_2:
745 max2175_load_fmeu_1p2(ctx);
746 break;
747
748 case MAX2175_DAB_1_2:
749 max2175_load_dab_1p2(ctx);
750 break;
751 }
752
753 if (!ctx->master)
754 max2175_write_bit(ctx, 30, 7, 1);
755}
756
757static void max2175_set_na_rx_mode(struct max2175 *ctx, u32 rx_mode)
758{
759 switch (rx_mode) {
760 case MAX2175_NA_FM_1_0:
761 max2175_load_fmna_1p0(ctx);
762 break;
763 case MAX2175_NA_FM_2_0:
764 max2175_load_fmna_2p0(ctx);
765 break;
766 }
767
768 if (!ctx->master)
769 max2175_write_bit(ctx, 30, 7, 1);
770
771 ctx->decim_ratio = 27;
772
773
774 max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0, ch_coeff_fmna);
775 max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
776 eq_coeff_fmna1_ra02_m6db);
777}
778
779static int max2175_set_rx_mode(struct max2175 *ctx, u32 rx_mode)
780{
781 mxm_dbg(ctx, "set_rx_mode: %u am_hiz %u\n", rx_mode, ctx->am_hiz);
782 if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ)
783 max2175_set_eu_rx_mode(ctx, rx_mode);
784 else
785 max2175_set_na_rx_mode(ctx, rx_mode);
786
787 if (ctx->am_hiz) {
788 mxm_dbg(ctx, "setting AM HiZ related config\n");
789 max2175_write_bit(ctx, 50, 5, 1);
790 max2175_write_bit(ctx, 90, 7, 1);
791 max2175_write_bits(ctx, 73, 1, 0, 2);
792 max2175_write_bits(ctx, 80, 5, 0, 33);
793 }
794
795
796 max2175_set_bbfilter(ctx);
797
798
799 max2175_set_hsls(ctx, ctx->hsls->cur.val);
800
801
802 max2175_i2s_enable(ctx, ctx->i2s_en->cur.val);
803
804 ctx->mode_resolved = true;
805
806 return 0;
807}
808
809static int max2175_rx_mode_from_freq(struct max2175 *ctx, u32 freq, u32 *mode)
810{
811 unsigned int i;
812 int band = max2175_band_from_freq(freq);
813
814
815 for (i = 0; i <= ctx->rx_mode->maximum; i++) {
816 if (ctx->rx_modes[i].band == band) {
817 *mode = i;
818 mxm_dbg(ctx, "rx_mode_from_freq: freq %u mode %d\n",
819 freq, *mode);
820 return 0;
821 }
822 }
823
824 return -EINVAL;
825}
826
827static bool max2175_freq_rx_mode_valid(struct max2175 *ctx,
828 u32 mode, u32 freq)
829{
830 int band = max2175_band_from_freq(freq);
831
832 return (ctx->rx_modes[mode].band == band);
833}
834
835static void max2175_load_adc_presets(struct max2175 *ctx)
836{
837 unsigned int i, j;
838
839 for (i = 0; i < ARRAY_SIZE(adc_presets); i++)
840 for (j = 0; j < ARRAY_SIZE(adc_presets[0]); j++)
841 max2175_write(ctx, 146 + j + i * 55, adc_presets[i][j]);
842}
843
844static int max2175_init_power_manager(struct max2175 *ctx)
845{
846 int ret;
847
848
849 max2175_write_bit(ctx, 99, 2, 0);
850 usleep_range(1000, 1500);
851 max2175_write_bit(ctx, 99, 2, 1);
852
853
854 ret = max2175_poll_timeout(ctx, 69, 7, 7, 1, 50000);
855 if (ret)
856 mxm_err(ctx, "init pm failed\n");
857
858 return ret;
859}
860
861static int max2175_recalibrate_adc(struct max2175 *ctx)
862{
863 int ret;
864
865
866 max2175_write(ctx, 150, 0xff);
867 max2175_write(ctx, 205, 0xff);
868 max2175_write(ctx, 147, 0x20);
869 max2175_write(ctx, 147, 0x00);
870 max2175_write(ctx, 202, 0x20);
871 max2175_write(ctx, 202, 0x00);
872
873 ret = max2175_poll_timeout(ctx, 69, 4, 3, 3, 50000);
874 if (ret)
875 mxm_err(ctx, "adc recalibration failed\n");
876
877 return ret;
878}
879
880static u8 max2175_read_rom(struct max2175 *ctx, u8 row)
881{
882 u8 data = 0;
883
884 max2175_write_bit(ctx, 56, 4, 0);
885 max2175_write_bits(ctx, 56, 3, 0, row);
886
887 usleep_range(2000, 2500);
888 max2175_read(ctx, 58, &data);
889
890 max2175_write_bits(ctx, 56, 3, 0, 0);
891
892 mxm_dbg(ctx, "read_rom: row %d data 0x%02x\n", row, data);
893
894 return data;
895}
896
897static void max2175_load_from_rom(struct max2175 *ctx)
898{
899 u8 data = 0;
900
901 data = max2175_read_rom(ctx, 0);
902 ctx->rom_bbf_bw_am = data & 0x0f;
903 max2175_write_bits(ctx, 81, 3, 0, data >> 4);
904
905 data = max2175_read_rom(ctx, 1);
906 ctx->rom_bbf_bw_fm = data & 0x0f;
907 ctx->rom_bbf_bw_dab = data >> 4;
908
909 data = max2175_read_rom(ctx, 2);
910 max2175_write_bits(ctx, 82, 4, 0, data & 0x1f);
911 max2175_write_bits(ctx, 82, 7, 5, data >> 5);
912
913 data = max2175_read_rom(ctx, 3);
914 if (ctx->am_hiz) {
915 data &= 0x0f;
916 data |= (max2175_read_rom(ctx, 7) & 0x40) >> 2;
917 if (!data)
918 data |= 2;
919 } else {
920 data = (data & 0xf0) >> 4;
921 data |= (max2175_read_rom(ctx, 7) & 0x80) >> 3;
922 if (!data)
923 data |= 30;
924 }
925 max2175_write_bits(ctx, 80, 5, 0, data + 31);
926
927 data = max2175_read_rom(ctx, 6);
928 max2175_write_bits(ctx, 81, 7, 6, data >> 6);
929}
930
931static void max2175_load_full_fm_eu_1p0(struct max2175 *ctx)
932{
933 unsigned int i;
934
935 for (i = 0; i < ARRAY_SIZE(full_fm_eu_1p0); i++)
936 max2175_write(ctx, i + 1, full_fm_eu_1p0[i]);
937
938 usleep_range(5000, 5500);
939 ctx->decim_ratio = 36;
940}
941
942static void max2175_load_full_fm_na_1p0(struct max2175 *ctx)
943{
944 unsigned int i;
945
946 for (i = 0; i < ARRAY_SIZE(full_fm_na_1p0); i++)
947 max2175_write(ctx, i + 1, full_fm_na_1p0[i]);
948
949 usleep_range(5000, 5500);
950 ctx->decim_ratio = 27;
951}
952
953static int max2175_core_init(struct max2175 *ctx, u32 refout_bits)
954{
955 int ret;
956
957
958 if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ)
959 max2175_load_full_fm_eu_1p0(ctx);
960 else
961 max2175_load_full_fm_na_1p0(ctx);
962
963
964 if (!ctx->master)
965 max2175_write_bit(ctx, 30, 7, 1);
966
967 mxm_dbg(ctx, "refout_bits %u\n", refout_bits);
968
969
970 max2175_write_bits(ctx, 56, 7, 5, refout_bits);
971
972
973 max2175_write_bit(ctx, 99, 1, 0);
974 usleep_range(1000, 1500);
975 max2175_write_bit(ctx, 99, 1, 1);
976
977
978 max2175_load_adc_presets(ctx);
979
980
981 ret = max2175_init_power_manager(ctx);
982 if (ret)
983 return ret;
984
985
986 ret = max2175_recalibrate_adc(ctx);
987 if (ret)
988 return ret;
989
990
991 max2175_load_from_rom(ctx);
992
993 if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ) {
994
995 max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0,
996 ch_coeff_fmeu);
997 max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
998 eq_coeff_fmeu1_ra02_m6db);
999 } else {
1000
1001 max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0,
1002 ch_coeff_fmna);
1003 max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
1004 eq_coeff_fmna1_ra02_m6db);
1005 }
1006 mxm_dbg(ctx, "core initialized\n");
1007
1008 return 0;
1009}
1010
1011static void max2175_s_ctrl_rx_mode(struct max2175 *ctx, u32 rx_mode)
1012{
1013
1014 max2175_set_rx_mode(ctx, rx_mode);
1015
1016 mxm_dbg(ctx, "s_ctrl_rx_mode: %u curr freq %u\n", rx_mode, ctx->freq);
1017
1018
1019 if (max2175_freq_rx_mode_valid(ctx, rx_mode, ctx->freq))
1020 max2175_tune_rf_freq(ctx, ctx->freq, ctx->hsls->cur.val);
1021 else
1022
1023 max2175_tune_rf_freq(ctx, ctx->rx_modes[rx_mode].freq,
1024 ctx->hsls->cur.val);
1025}
1026
1027static int max2175_s_ctrl(struct v4l2_ctrl *ctrl)
1028{
1029 struct max2175 *ctx = max2175_from_ctrl_hdl(ctrl->handler);
1030
1031 mxm_dbg(ctx, "s_ctrl: id 0x%x, val %u\n", ctrl->id, ctrl->val);
1032 switch (ctrl->id) {
1033 case V4L2_CID_MAX2175_I2S_ENABLE:
1034 max2175_i2s_enable(ctx, ctrl->val);
1035 break;
1036 case V4L2_CID_MAX2175_HSLS:
1037 max2175_set_hsls(ctx, ctrl->val);
1038 break;
1039 case V4L2_CID_MAX2175_RX_MODE:
1040 max2175_s_ctrl_rx_mode(ctx, ctrl->val);
1041 break;
1042 }
1043
1044 return 0;
1045}
1046
1047static u32 max2175_get_lna_gain(struct max2175 *ctx)
1048{
1049 enum max2175_band band = max2175_read_bits(ctx, 5, 1, 0);
1050
1051 switch (band) {
1052 case MAX2175_BAND_AM:
1053 return max2175_read_bits(ctx, 51, 3, 0);
1054 case MAX2175_BAND_FM:
1055 return max2175_read_bits(ctx, 50, 3, 0);
1056 case MAX2175_BAND_VHF:
1057 return max2175_read_bits(ctx, 52, 5, 0);
1058 default:
1059 return 0;
1060 }
1061}
1062
1063static int max2175_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1064{
1065 struct max2175 *ctx = max2175_from_ctrl_hdl(ctrl->handler);
1066
1067 switch (ctrl->id) {
1068 case V4L2_CID_RF_TUNER_LNA_GAIN:
1069 ctrl->val = max2175_get_lna_gain(ctx);
1070 break;
1071 case V4L2_CID_RF_TUNER_IF_GAIN:
1072 ctrl->val = max2175_read_bits(ctx, 49, 4, 0);
1073 break;
1074 case V4L2_CID_RF_TUNER_PLL_LOCK:
1075 ctrl->val = (max2175_read_bits(ctx, 60, 7, 6) == 3);
1076 break;
1077 }
1078
1079 return 0;
1080};
1081
1082static int max2175_set_freq_and_mode(struct max2175 *ctx, u32 freq)
1083{
1084 u32 rx_mode;
1085 int ret;
1086
1087
1088 ret = max2175_rx_mode_from_freq(ctx, freq, &rx_mode);
1089 if (ret)
1090 return ret;
1091
1092 mxm_dbg(ctx, "set_freq_and_mode: freq %u rx_mode %d\n", freq, rx_mode);
1093
1094
1095 max2175_set_rx_mode(ctx, rx_mode);
1096 ctx->rx_mode->cur.val = rx_mode;
1097
1098
1099 return max2175_tune_rf_freq(ctx, freq, ctx->hsls->cur.val);
1100}
1101
1102static int max2175_s_frequency(struct v4l2_subdev *sd,
1103 const struct v4l2_frequency *vf)
1104{
1105 struct max2175 *ctx = max2175_from_sd(sd);
1106 u32 freq;
1107 int ret = 0;
1108
1109 mxm_dbg(ctx, "s_freq: new %u curr %u, mode_resolved %d\n",
1110 vf->frequency, ctx->freq, ctx->mode_resolved);
1111
1112 if (vf->tuner != 0)
1113 return -EINVAL;
1114
1115 freq = clamp(vf->frequency, ctx->bands_rf->rangelow,
1116 ctx->bands_rf->rangehigh);
1117
1118
1119 if (ctx->mode_resolved &&
1120 max2175_freq_rx_mode_valid(ctx, ctx->rx_mode->cur.val, freq))
1121 ret = max2175_tune_rf_freq(ctx, freq, ctx->hsls->cur.val);
1122 else
1123
1124 ret = max2175_set_freq_and_mode(ctx, freq);
1125
1126 mxm_dbg(ctx, "s_freq: ret %d curr %u mode_resolved %d mode %u\n",
1127 ret, ctx->freq, ctx->mode_resolved, ctx->rx_mode->cur.val);
1128
1129 return ret;
1130}
1131
1132static int max2175_g_frequency(struct v4l2_subdev *sd,
1133 struct v4l2_frequency *vf)
1134{
1135 struct max2175 *ctx = max2175_from_sd(sd);
1136 int ret = 0;
1137
1138 if (vf->tuner != 0)
1139 return -EINVAL;
1140
1141
1142 vf->type = V4L2_TUNER_RF;
1143 vf->frequency = ctx->freq;
1144
1145 return ret;
1146}
1147
1148static int max2175_enum_freq_bands(struct v4l2_subdev *sd,
1149 struct v4l2_frequency_band *band)
1150{
1151 struct max2175 *ctx = max2175_from_sd(sd);
1152
1153 if (band->tuner != 0 || band->index != 0)
1154 return -EINVAL;
1155
1156 *band = *ctx->bands_rf;
1157
1158 return 0;
1159}
1160
1161static int max2175_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1162{
1163 struct max2175 *ctx = max2175_from_sd(sd);
1164
1165 if (vt->index > 0)
1166 return -EINVAL;
1167
1168 strlcpy(vt->name, "RF", sizeof(vt->name));
1169 vt->type = V4L2_TUNER_RF;
1170 vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
1171 vt->rangelow = ctx->bands_rf->rangelow;
1172 vt->rangehigh = ctx->bands_rf->rangehigh;
1173
1174 return 0;
1175}
1176
1177static int max2175_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
1178{
1179
1180 if (vt->index > 0)
1181 return -EINVAL;
1182
1183 return 0;
1184}
1185
1186static const struct v4l2_subdev_tuner_ops max2175_tuner_ops = {
1187 .s_frequency = max2175_s_frequency,
1188 .g_frequency = max2175_g_frequency,
1189 .enum_freq_bands = max2175_enum_freq_bands,
1190 .g_tuner = max2175_g_tuner,
1191 .s_tuner = max2175_s_tuner,
1192};
1193
1194static const struct v4l2_subdev_ops max2175_ops = {
1195 .tuner = &max2175_tuner_ops,
1196};
1197
1198static const struct v4l2_ctrl_ops max2175_ctrl_ops = {
1199 .s_ctrl = max2175_s_ctrl,
1200 .g_volatile_ctrl = max2175_g_volatile_ctrl,
1201};
1202
1203
1204
1205
1206
1207static const struct v4l2_ctrl_config max2175_i2s_en = {
1208 .ops = &max2175_ctrl_ops,
1209 .id = V4L2_CID_MAX2175_I2S_ENABLE,
1210 .name = "I2S Enable",
1211 .type = V4L2_CTRL_TYPE_BOOLEAN,
1212 .min = 0,
1213 .max = 1,
1214 .step = 1,
1215 .def = 1,
1216 .is_private = 1,
1217};
1218
1219
1220
1221
1222
1223static const struct v4l2_ctrl_config max2175_hsls = {
1224 .ops = &max2175_ctrl_ops,
1225 .id = V4L2_CID_MAX2175_HSLS,
1226 .name = "HSLS Above/Below Desired",
1227 .type = V4L2_CTRL_TYPE_BOOLEAN,
1228 .min = 0,
1229 .max = 1,
1230 .step = 1,
1231 .def = 1,
1232};
1233
1234
1235
1236
1237
1238
1239static const char * const max2175_ctrl_eu_rx_modes[] = {
1240 [MAX2175_EU_FM_1_2] = "EU FM 1.2",
1241 [MAX2175_DAB_1_2] = "DAB 1.2",
1242};
1243
1244static const char * const max2175_ctrl_na_rx_modes[] = {
1245 [MAX2175_NA_FM_1_0] = "NA FM 1.0",
1246 [MAX2175_NA_FM_2_0] = "NA FM 2.0",
1247};
1248
1249static const struct v4l2_ctrl_config max2175_eu_rx_mode = {
1250 .ops = &max2175_ctrl_ops,
1251 .id = V4L2_CID_MAX2175_RX_MODE,
1252 .name = "RX Mode",
1253 .type = V4L2_CTRL_TYPE_MENU,
1254 .max = ARRAY_SIZE(max2175_ctrl_eu_rx_modes) - 1,
1255 .def = 0,
1256 .qmenu = max2175_ctrl_eu_rx_modes,
1257};
1258
1259static const struct v4l2_ctrl_config max2175_na_rx_mode = {
1260 .ops = &max2175_ctrl_ops,
1261 .id = V4L2_CID_MAX2175_RX_MODE,
1262 .name = "RX Mode",
1263 .type = V4L2_CTRL_TYPE_MENU,
1264 .max = ARRAY_SIZE(max2175_ctrl_na_rx_modes) - 1,
1265 .def = 0,
1266 .qmenu = max2175_ctrl_na_rx_modes,
1267};
1268
1269static int max2175_refout_load_to_bits(struct i2c_client *client, u32 load,
1270 u32 *bits)
1271{
1272 if (load <= 40)
1273 *bits = load / 10;
1274 else if (load >= 60 && load <= 70)
1275 *bits = load / 10 - 1;
1276 else
1277 return -EINVAL;
1278
1279 return 0;
1280}
1281
1282static int max2175_probe(struct i2c_client *client,
1283 const struct i2c_device_id *id)
1284{
1285 bool master = true, am_hiz = false;
1286 u32 refout_load, refout_bits = 0;
1287 struct v4l2_ctrl_handler *hdl;
1288 struct fwnode_handle *fwnode;
1289 struct device_node *np;
1290 struct v4l2_subdev *sd;
1291 struct regmap *regmap;
1292 struct max2175 *ctx;
1293 struct clk *clk;
1294 int ret;
1295
1296
1297 np = of_parse_phandle(client->dev.of_node, "maxim,master", 0);
1298 if (np) {
1299 master = false;
1300 of_node_put(np);
1301 }
1302
1303 fwnode = of_fwnode_handle(client->dev.of_node);
1304 if (fwnode_property_present(fwnode, "maxim,am-hiz-filter"))
1305 am_hiz = true;
1306
1307 if (!fwnode_property_read_u32(fwnode, "maxim,refout-load",
1308 &refout_load)) {
1309 ret = max2175_refout_load_to_bits(client, refout_load,
1310 &refout_bits);
1311 if (ret) {
1312 dev_err(&client->dev, "invalid refout_load %u\n",
1313 refout_load);
1314 return -EINVAL;
1315 }
1316 }
1317
1318 clk = devm_clk_get(&client->dev, NULL);
1319 if (IS_ERR(clk)) {
1320 ret = PTR_ERR(clk);
1321 dev_err(&client->dev, "cannot get clock %d\n", ret);
1322 return ret;
1323 }
1324
1325 regmap = devm_regmap_init_i2c(client, &max2175_regmap_config);
1326 if (IS_ERR(regmap)) {
1327 ret = PTR_ERR(regmap);
1328 dev_err(&client->dev, "regmap init failed %d\n", ret);
1329 return -ENODEV;
1330 }
1331
1332
1333 ctx = devm_kzalloc(&client->dev, sizeof(*ctx), GFP_KERNEL);
1334 if (ctx == NULL)
1335 return -ENOMEM;
1336
1337 sd = &ctx->sd;
1338 ctx->master = master;
1339 ctx->am_hiz = am_hiz;
1340 ctx->mode_resolved = false;
1341 ctx->regmap = regmap;
1342 ctx->xtal_freq = clk_get_rate(clk);
1343 dev_info(&client->dev, "xtal freq %luHz\n", ctx->xtal_freq);
1344
1345 v4l2_i2c_subdev_init(sd, client, &max2175_ops);
1346 ctx->client = client;
1347
1348 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1349
1350
1351 hdl = &ctx->ctrl_hdl;
1352 ret = v4l2_ctrl_handler_init(hdl, 7);
1353 if (ret)
1354 return ret;
1355
1356 ctx->lna_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
1357 V4L2_CID_RF_TUNER_LNA_GAIN,
1358 0, 63, 1, 0);
1359 ctx->lna_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
1360 V4L2_CTRL_FLAG_READ_ONLY);
1361 ctx->if_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
1362 V4L2_CID_RF_TUNER_IF_GAIN,
1363 0, 31, 1, 0);
1364 ctx->if_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
1365 V4L2_CTRL_FLAG_READ_ONLY);
1366 ctx->pll_lock = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
1367 V4L2_CID_RF_TUNER_PLL_LOCK,
1368 0, 1, 1, 0);
1369 ctx->pll_lock->flags |= (V4L2_CTRL_FLAG_VOLATILE |
1370 V4L2_CTRL_FLAG_READ_ONLY);
1371 ctx->i2s_en = v4l2_ctrl_new_custom(hdl, &max2175_i2s_en, NULL);
1372 ctx->hsls = v4l2_ctrl_new_custom(hdl, &max2175_hsls, NULL);
1373
1374 if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ) {
1375 ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
1376 &max2175_eu_rx_mode, NULL);
1377 ctx->rx_modes = eu_rx_modes;
1378 ctx->bands_rf = &eu_bands_rf;
1379 } else {
1380 ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
1381 &max2175_na_rx_mode, NULL);
1382 ctx->rx_modes = na_rx_modes;
1383 ctx->bands_rf = &na_bands_rf;
1384 }
1385 ctx->sd.ctrl_handler = &ctx->ctrl_hdl;
1386
1387
1388 ctx->freq = ctx->bands_rf->rangelow;
1389
1390
1391 ret = v4l2_async_register_subdev(sd);
1392 if (ret) {
1393 dev_err(&client->dev, "register subdev failed\n");
1394 goto err_reg;
1395 }
1396
1397
1398 ret = max2175_core_init(ctx, refout_bits);
1399 if (ret)
1400 goto err_init;
1401
1402 ret = v4l2_ctrl_handler_setup(hdl);
1403 if (ret)
1404 goto err_init;
1405
1406 return 0;
1407
1408err_init:
1409 v4l2_async_unregister_subdev(sd);
1410err_reg:
1411 v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
1412
1413 return ret;
1414}
1415
1416static int max2175_remove(struct i2c_client *client)
1417{
1418 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1419 struct max2175 *ctx = max2175_from_sd(sd);
1420
1421 v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
1422 v4l2_async_unregister_subdev(sd);
1423
1424 return 0;
1425}
1426
1427static const struct i2c_device_id max2175_id[] = {
1428 { DRIVER_NAME, 0},
1429 {},
1430};
1431MODULE_DEVICE_TABLE(i2c, max2175_id);
1432
1433static const struct of_device_id max2175_of_ids[] = {
1434 { .compatible = "maxim,max2175", },
1435 { }
1436};
1437MODULE_DEVICE_TABLE(of, max2175_of_ids);
1438
1439static struct i2c_driver max2175_driver = {
1440 .driver = {
1441 .name = DRIVER_NAME,
1442 .of_match_table = max2175_of_ids,
1443 },
1444 .probe = max2175_probe,
1445 .remove = max2175_remove,
1446 .id_table = max2175_id,
1447};
1448
1449module_i2c_driver(max2175_driver);
1450
1451MODULE_DESCRIPTION("Maxim MAX2175 RF to Bits tuner driver");
1452MODULE_LICENSE("GPL v2");
1453MODULE_AUTHOR("Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>");
1454