1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Driver for the MaxLinear MxL5xx family of tuners/demods |
4 | * |
5 | * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de> |
6 | * Marcus Metzler <mocm@metzlerbros.de> |
7 | * developed for Digital Devices GmbH |
8 | * |
9 | * based on code: |
10 | * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved |
11 | * which was released under GPL V2 |
12 | */ |
13 | |
14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> |
17 | #include <linux/init.h> |
18 | #include <linux/delay.h> |
19 | #include <linux/firmware.h> |
20 | #include <linux/i2c.h> |
21 | #include <linux/mutex.h> |
22 | #include <linux/vmalloc.h> |
23 | #include <asm/div64.h> |
24 | #include <asm/unaligned.h> |
25 | |
26 | #include <media/dvb_frontend.h> |
27 | #include "mxl5xx.h" |
28 | #include "mxl5xx_regs.h" |
29 | #include "mxl5xx_defs.h" |
30 | |
31 | #define BYTE0(v) ((v >> 0) & 0xff) |
32 | #define BYTE1(v) ((v >> 8) & 0xff) |
33 | #define BYTE2(v) ((v >> 16) & 0xff) |
34 | #define BYTE3(v) ((v >> 24) & 0xff) |
35 | |
36 | static LIST_HEAD(mxllist); |
37 | |
38 | struct mxl_base { |
39 | struct list_head mxllist; |
40 | struct list_head mxls; |
41 | |
42 | u8 adr; |
43 | struct i2c_adapter *i2c; |
44 | |
45 | u32 count; |
46 | u32 type; |
47 | u32 sku_type; |
48 | u32 chipversion; |
49 | u32 clock; |
50 | u32 fwversion; |
51 | |
52 | u8 *ts_map; |
53 | u8 can_clkout; |
54 | u8 chan_bond; |
55 | u8 demod_num; |
56 | u8 tuner_num; |
57 | |
58 | unsigned long next_tune; |
59 | |
60 | struct mutex i2c_lock; |
61 | struct mutex status_lock; |
62 | struct mutex tune_lock; |
63 | |
64 | u8 buf[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; |
65 | |
66 | u32 cmd_size; |
67 | u8 cmd_data[MAX_CMD_DATA]; |
68 | }; |
69 | |
70 | struct mxl { |
71 | struct list_head mxl; |
72 | |
73 | struct mxl_base *base; |
74 | struct dvb_frontend fe; |
75 | struct device *i2cdev; |
76 | u32 demod; |
77 | u32 tuner; |
78 | u32 tuner_in_use; |
79 | u8 xbar[3]; |
80 | |
81 | unsigned long tune_time; |
82 | }; |
83 | |
84 | static void convert_endian(u8 flag, u32 size, u8 *d) |
85 | { |
86 | u32 i; |
87 | |
88 | if (!flag) |
89 | return; |
90 | for (i = 0; i < (size & ~3); i += 4) { |
91 | d[i + 0] ^= d[i + 3]; |
92 | d[i + 3] ^= d[i + 0]; |
93 | d[i + 0] ^= d[i + 3]; |
94 | |
95 | d[i + 1] ^= d[i + 2]; |
96 | d[i + 2] ^= d[i + 1]; |
97 | d[i + 1] ^= d[i + 2]; |
98 | } |
99 | |
100 | switch (size & 3) { |
101 | case 0: |
102 | case 1: |
103 | /* do nothing */ |
104 | break; |
105 | case 2: |
106 | d[i + 0] ^= d[i + 1]; |
107 | d[i + 1] ^= d[i + 0]; |
108 | d[i + 0] ^= d[i + 1]; |
109 | break; |
110 | |
111 | case 3: |
112 | d[i + 0] ^= d[i + 2]; |
113 | d[i + 2] ^= d[i + 0]; |
114 | d[i + 0] ^= d[i + 2]; |
115 | break; |
116 | } |
117 | |
118 | } |
119 | |
120 | static int i2c_write(struct i2c_adapter *adap, u8 adr, |
121 | u8 *data, u32 len) |
122 | { |
123 | struct i2c_msg msg = {.addr = adr, .flags = 0, |
124 | .buf = data, .len = len}; |
125 | |
126 | return (i2c_transfer(adap, msgs: &msg, num: 1) == 1) ? 0 : -1; |
127 | } |
128 | |
129 | static int i2c_read(struct i2c_adapter *adap, u8 adr, |
130 | u8 *data, u32 len) |
131 | { |
132 | struct i2c_msg msg = {.addr = adr, .flags = I2C_M_RD, |
133 | .buf = data, .len = len}; |
134 | |
135 | return (i2c_transfer(adap, msgs: &msg, num: 1) == 1) ? 0 : -1; |
136 | } |
137 | |
138 | static int i2cread(struct mxl *state, u8 *data, int len) |
139 | { |
140 | return i2c_read(adap: state->base->i2c, adr: state->base->adr, data, len); |
141 | } |
142 | |
143 | static int i2cwrite(struct mxl *state, u8 *data, int len) |
144 | { |
145 | return i2c_write(adap: state->base->i2c, adr: state->base->adr, data, len); |
146 | } |
147 | |
148 | static int read_register_unlocked(struct mxl *state, u32 reg, u32 *val) |
149 | { |
150 | int stat; |
151 | u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = { |
152 | MXL_HYDRA_PLID_REG_READ, 0x04, |
153 | GET_BYTE(reg, 0), GET_BYTE(reg, 1), |
154 | GET_BYTE(reg, 2), GET_BYTE(reg, 3), |
155 | }; |
156 | |
157 | stat = i2cwrite(state, data, |
158 | MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE); |
159 | if (stat) |
160 | dev_err(state->i2cdev, "i2c read error 1\n" ); |
161 | if (!stat) |
162 | stat = i2cread(state, data: (u8 *) val, |
163 | MXL_HYDRA_REG_SIZE_IN_BYTES); |
164 | le32_to_cpus(val); |
165 | if (stat) |
166 | dev_err(state->i2cdev, "i2c read error 2\n" ); |
167 | return stat; |
168 | } |
169 | |
170 | #define DMA_I2C_INTERRUPT_ADDR 0x8000011C |
171 | #define DMA_INTR_PROT_WR_CMP 0x08 |
172 | |
173 | static int send_command(struct mxl *state, u32 size, u8 *buf) |
174 | { |
175 | int stat; |
176 | u32 val, count = 10; |
177 | |
178 | mutex_lock(&state->base->i2c_lock); |
179 | if (state->base->fwversion > 0x02010109) { |
180 | read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, val: &val); |
181 | if (DMA_INTR_PROT_WR_CMP & val) |
182 | dev_info(state->i2cdev, "%s busy\n" , __func__); |
183 | while ((DMA_INTR_PROT_WR_CMP & val) && --count) { |
184 | mutex_unlock(lock: &state->base->i2c_lock); |
185 | usleep_range(min: 1000, max: 2000); |
186 | mutex_lock(&state->base->i2c_lock); |
187 | read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, |
188 | val: &val); |
189 | } |
190 | if (!count) { |
191 | dev_info(state->i2cdev, "%s busy\n" , __func__); |
192 | mutex_unlock(lock: &state->base->i2c_lock); |
193 | return -EBUSY; |
194 | } |
195 | } |
196 | stat = i2cwrite(state, data: buf, len: size); |
197 | mutex_unlock(lock: &state->base->i2c_lock); |
198 | return stat; |
199 | } |
200 | |
201 | static int write_register(struct mxl *state, u32 reg, u32 val) |
202 | { |
203 | int stat; |
204 | u8 data[MXL_HYDRA_REG_WRITE_LEN] = { |
205 | MXL_HYDRA_PLID_REG_WRITE, 0x08, |
206 | BYTE0(reg), BYTE1(reg), BYTE2(reg), BYTE3(reg), |
207 | BYTE0(val), BYTE1(val), BYTE2(val), BYTE3(val), |
208 | }; |
209 | mutex_lock(&state->base->i2c_lock); |
210 | stat = i2cwrite(state, data, len: sizeof(data)); |
211 | mutex_unlock(lock: &state->base->i2c_lock); |
212 | if (stat) |
213 | dev_err(state->i2cdev, "i2c write error\n" ); |
214 | return stat; |
215 | } |
216 | |
217 | static int write_firmware_block(struct mxl *state, |
218 | u32 reg, u32 size, u8 *reg_data_ptr) |
219 | { |
220 | int stat; |
221 | u8 *buf = state->base->buf; |
222 | |
223 | mutex_lock(&state->base->i2c_lock); |
224 | buf[0] = MXL_HYDRA_PLID_REG_WRITE; |
225 | buf[1] = size + 4; |
226 | buf[2] = GET_BYTE(reg, 0); |
227 | buf[3] = GET_BYTE(reg, 1); |
228 | buf[4] = GET_BYTE(reg, 2); |
229 | buf[5] = GET_BYTE(reg, 3); |
230 | memcpy(&buf[6], reg_data_ptr, size); |
231 | stat = i2cwrite(state, data: buf, |
232 | MXL_HYDRA_I2C_HDR_SIZE + |
233 | MXL_HYDRA_REG_SIZE_IN_BYTES + size); |
234 | mutex_unlock(lock: &state->base->i2c_lock); |
235 | if (stat) |
236 | dev_err(state->i2cdev, "fw block write failed\n" ); |
237 | return stat; |
238 | } |
239 | |
240 | static int read_register(struct mxl *state, u32 reg, u32 *val) |
241 | { |
242 | int stat; |
243 | u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = { |
244 | MXL_HYDRA_PLID_REG_READ, 0x04, |
245 | GET_BYTE(reg, 0), GET_BYTE(reg, 1), |
246 | GET_BYTE(reg, 2), GET_BYTE(reg, 3), |
247 | }; |
248 | |
249 | mutex_lock(&state->base->i2c_lock); |
250 | stat = i2cwrite(state, data, |
251 | MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE); |
252 | if (stat) |
253 | dev_err(state->i2cdev, "i2c read error 1\n" ); |
254 | if (!stat) |
255 | stat = i2cread(state, data: (u8 *) val, |
256 | MXL_HYDRA_REG_SIZE_IN_BYTES); |
257 | mutex_unlock(lock: &state->base->i2c_lock); |
258 | le32_to_cpus(val); |
259 | if (stat) |
260 | dev_err(state->i2cdev, "i2c read error 2\n" ); |
261 | return stat; |
262 | } |
263 | |
264 | static int read_register_block(struct mxl *state, u32 reg, u32 size, u8 *data) |
265 | { |
266 | int stat; |
267 | u8 *buf = state->base->buf; |
268 | |
269 | mutex_lock(&state->base->i2c_lock); |
270 | |
271 | buf[0] = MXL_HYDRA_PLID_REG_READ; |
272 | buf[1] = size + 4; |
273 | buf[2] = GET_BYTE(reg, 0); |
274 | buf[3] = GET_BYTE(reg, 1); |
275 | buf[4] = GET_BYTE(reg, 2); |
276 | buf[5] = GET_BYTE(reg, 3); |
277 | stat = i2cwrite(state, data: buf, |
278 | MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES); |
279 | if (!stat) { |
280 | stat = i2cread(state, data, len: size); |
281 | convert_endian(MXL_ENABLE_BIG_ENDIAN, size, d: data); |
282 | } |
283 | mutex_unlock(lock: &state->base->i2c_lock); |
284 | return stat; |
285 | } |
286 | |
287 | static int read_by_mnemonic(struct mxl *state, |
288 | u32 reg, u8 lsbloc, u8 numofbits, u32 *val) |
289 | { |
290 | u32 data = 0, mask = 0; |
291 | int stat; |
292 | |
293 | stat = read_register(state, reg, val: &data); |
294 | if (stat) |
295 | return stat; |
296 | mask = MXL_GET_REG_MASK_32(lsbloc, numofbits); |
297 | data &= mask; |
298 | data >>= lsbloc; |
299 | *val = data; |
300 | return 0; |
301 | } |
302 | |
303 | |
304 | static int update_by_mnemonic(struct mxl *state, |
305 | u32 reg, u8 lsbloc, u8 numofbits, u32 val) |
306 | { |
307 | u32 data, mask; |
308 | int stat; |
309 | |
310 | stat = read_register(state, reg, val: &data); |
311 | if (stat) |
312 | return stat; |
313 | mask = MXL_GET_REG_MASK_32(lsbloc, numofbits); |
314 | data = (data & ~mask) | ((val << lsbloc) & mask); |
315 | stat = write_register(state, reg, val: data); |
316 | return stat; |
317 | } |
318 | |
319 | static int firmware_is_alive(struct mxl *state) |
320 | { |
321 | u32 hb0, hb1; |
322 | |
323 | if (read_register(state, HYDRA_HEAR_BEAT, val: &hb0)) |
324 | return 0; |
325 | msleep(msecs: 20); |
326 | if (read_register(state, HYDRA_HEAR_BEAT, val: &hb1)) |
327 | return 0; |
328 | if (hb1 == hb0) |
329 | return 0; |
330 | return 1; |
331 | } |
332 | |
333 | static int init(struct dvb_frontend *fe) |
334 | { |
335 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
336 | |
337 | /* init fe stats */ |
338 | p->strength.len = 1; |
339 | p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
340 | p->cnr.len = 1; |
341 | p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
342 | p->pre_bit_error.len = 1; |
343 | p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
344 | p->pre_bit_count.len = 1; |
345 | p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
346 | p->post_bit_error.len = 1; |
347 | p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
348 | p->post_bit_count.len = 1; |
349 | p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
350 | |
351 | return 0; |
352 | } |
353 | |
354 | static void release(struct dvb_frontend *fe) |
355 | { |
356 | struct mxl *state = fe->demodulator_priv; |
357 | |
358 | list_del(entry: &state->mxl); |
359 | /* Release one frontend, two more shall take its place! */ |
360 | state->base->count--; |
361 | if (state->base->count == 0) { |
362 | list_del(entry: &state->base->mxllist); |
363 | kfree(objp: state->base); |
364 | } |
365 | kfree(objp: state); |
366 | } |
367 | |
368 | static enum dvbfe_algo get_algo(struct dvb_frontend *fe) |
369 | { |
370 | return DVBFE_ALGO_HW; |
371 | } |
372 | |
373 | static u32 gold2root(u32 gold) |
374 | { |
375 | u32 x, g, tmp = gold; |
376 | |
377 | if (tmp >= 0x3ffff) |
378 | tmp = 0; |
379 | for (g = 0, x = 1; g < tmp; g++) |
380 | x = (((x ^ (x >> 7)) & 1) << 17) | (x >> 1); |
381 | return x; |
382 | } |
383 | |
384 | static int cfg_scrambler(struct mxl *state, u32 gold) |
385 | { |
386 | u32 root; |
387 | u8 buf[26] = { |
388 | MXL_HYDRA_PLID_CMD_WRITE, 24, |
389 | 0, MXL_HYDRA_DEMOD_SCRAMBLE_CODE_CMD, 0, 0, |
390 | state->demod, 0, 0, 0, |
391 | 0, 0, 0, 0, 0, 0, 0, 0, |
392 | 0, 0, 0, 0, 1, 0, 0, 0, |
393 | }; |
394 | |
395 | root = gold2root(gold); |
396 | |
397 | buf[25] = (root >> 24) & 0xff; |
398 | buf[24] = (root >> 16) & 0xff; |
399 | buf[23] = (root >> 8) & 0xff; |
400 | buf[22] = root & 0xff; |
401 | |
402 | return send_command(state, size: sizeof(buf), buf); |
403 | } |
404 | |
405 | static int cfg_demod_abort_tune(struct mxl *state) |
406 | { |
407 | struct MXL_HYDRA_DEMOD_ABORT_TUNE_T abort_tune_cmd; |
408 | u8 cmd_size = sizeof(abort_tune_cmd); |
409 | u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; |
410 | |
411 | abort_tune_cmd.demod_id = state->demod; |
412 | BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE, |
413 | cmd_size, &abort_tune_cmd, cmd_buff); |
414 | return send_command(state, size: cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, |
415 | buf: &cmd_buff[0]); |
416 | } |
417 | |
418 | static int send_master_cmd(struct dvb_frontend *fe, |
419 | struct dvb_diseqc_master_cmd *cmd) |
420 | { |
421 | /*struct mxl *state = fe->demodulator_priv;*/ |
422 | |
423 | return 0; /*CfgDemodAbortTune(state);*/ |
424 | } |
425 | |
426 | static int set_parameters(struct dvb_frontend *fe) |
427 | { |
428 | struct mxl *state = fe->demodulator_priv; |
429 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
430 | struct MXL_HYDRA_DEMOD_PARAM_T demod_chan_cfg; |
431 | u8 cmd_size = sizeof(demod_chan_cfg); |
432 | u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; |
433 | u32 srange = 10; |
434 | int stat; |
435 | |
436 | if (p->frequency < 950000 || p->frequency > 2150000) |
437 | return -EINVAL; |
438 | if (p->symbol_rate < 1000000 || p->symbol_rate > 45000000) |
439 | return -EINVAL; |
440 | |
441 | /* CfgDemodAbortTune(state); */ |
442 | |
443 | switch (p->delivery_system) { |
444 | case SYS_DSS: |
445 | demod_chan_cfg.standard = MXL_HYDRA_DSS; |
446 | demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_AUTO; |
447 | break; |
448 | case SYS_DVBS: |
449 | srange = p->symbol_rate / 1000000; |
450 | if (srange > 10) |
451 | srange = 10; |
452 | demod_chan_cfg.standard = MXL_HYDRA_DVBS; |
453 | demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_0_35; |
454 | demod_chan_cfg.modulation_scheme = MXL_HYDRA_MOD_QPSK; |
455 | demod_chan_cfg.pilots = MXL_HYDRA_PILOTS_OFF; |
456 | break; |
457 | case SYS_DVBS2: |
458 | demod_chan_cfg.standard = MXL_HYDRA_DVBS2; |
459 | demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_AUTO; |
460 | demod_chan_cfg.modulation_scheme = MXL_HYDRA_MOD_AUTO; |
461 | demod_chan_cfg.pilots = MXL_HYDRA_PILOTS_AUTO; |
462 | cfg_scrambler(state, gold: p->scrambling_sequence_index); |
463 | break; |
464 | default: |
465 | return -EINVAL; |
466 | } |
467 | demod_chan_cfg.tuner_index = state->tuner; |
468 | demod_chan_cfg.demod_index = state->demod; |
469 | demod_chan_cfg.frequency_in_hz = p->frequency * 1000; |
470 | demod_chan_cfg.symbol_rate_in_hz = p->symbol_rate; |
471 | demod_chan_cfg.max_carrier_offset_in_mhz = srange; |
472 | demod_chan_cfg.spectrum_inversion = MXL_HYDRA_SPECTRUM_AUTO; |
473 | demod_chan_cfg.fec_code_rate = MXL_HYDRA_FEC_AUTO; |
474 | |
475 | mutex_lock(&state->base->tune_lock); |
476 | if (time_after(jiffies + msecs_to_jiffies(200), |
477 | state->base->next_tune)) |
478 | while (time_before(jiffies, state->base->next_tune)) |
479 | usleep_range(min: 10000, max: 11000); |
480 | state->base->next_tune = jiffies + msecs_to_jiffies(m: 100); |
481 | state->tuner_in_use = state->tuner; |
482 | BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_SET_PARAM_CMD, MXL_CMD_WRITE, |
483 | cmd_size, &demod_chan_cfg, cmd_buff); |
484 | stat = send_command(state, size: cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, |
485 | buf: &cmd_buff[0]); |
486 | mutex_unlock(lock: &state->base->tune_lock); |
487 | return stat; |
488 | } |
489 | |
490 | static int enable_tuner(struct mxl *state, u32 tuner, u32 enable); |
491 | |
492 | static int sleep(struct dvb_frontend *fe) |
493 | { |
494 | struct mxl *state = fe->demodulator_priv; |
495 | struct mxl *p; |
496 | |
497 | cfg_demod_abort_tune(state); |
498 | if (state->tuner_in_use != 0xffffffff) { |
499 | mutex_lock(&state->base->tune_lock); |
500 | state->tuner_in_use = 0xffffffff; |
501 | list_for_each_entry(p, &state->base->mxls, mxl) { |
502 | if (p->tuner_in_use == state->tuner) |
503 | break; |
504 | } |
505 | if (&p->mxl == &state->base->mxls) |
506 | enable_tuner(state, tuner: state->tuner, enable: 0); |
507 | mutex_unlock(lock: &state->base->tune_lock); |
508 | } |
509 | return 0; |
510 | } |
511 | |
512 | static int read_snr(struct dvb_frontend *fe) |
513 | { |
514 | struct mxl *state = fe->demodulator_priv; |
515 | int stat; |
516 | u32 reg_data = 0; |
517 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
518 | |
519 | mutex_lock(&state->base->status_lock); |
520 | HYDRA_DEMOD_STATUS_LOCK(state, state->demod); |
521 | stat = read_register(state, reg: (HYDRA_DMD_SNR_ADDR_OFFSET + |
522 | HYDRA_DMD_STATUS_OFFSET(state->demod)), |
523 | val: ®_data); |
524 | HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); |
525 | mutex_unlock(lock: &state->base->status_lock); |
526 | |
527 | p->cnr.stat[0].scale = FE_SCALE_DECIBEL; |
528 | p->cnr.stat[0].svalue = (s16)reg_data * 10; |
529 | |
530 | return stat; |
531 | } |
532 | |
533 | static int read_ber(struct dvb_frontend *fe) |
534 | { |
535 | struct mxl *state = fe->demodulator_priv; |
536 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
537 | u32 reg[8]; |
538 | |
539 | mutex_lock(&state->base->status_lock); |
540 | HYDRA_DEMOD_STATUS_LOCK(state, state->demod); |
541 | read_register_block(state, |
542 | reg: (HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET + |
543 | HYDRA_DMD_STATUS_OFFSET(state->demod)), |
544 | size: (4 * sizeof(u32)), |
545 | data: (u8 *) ®[0]); |
546 | HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); |
547 | |
548 | switch (p->delivery_system) { |
549 | case SYS_DSS: |
550 | case SYS_DVBS: |
551 | p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; |
552 | p->pre_bit_error.stat[0].uvalue = reg[2]; |
553 | p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
554 | p->pre_bit_count.stat[0].uvalue = reg[3]; |
555 | break; |
556 | default: |
557 | break; |
558 | } |
559 | |
560 | read_register_block(state, |
561 | reg: (HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET + |
562 | HYDRA_DMD_STATUS_OFFSET(state->demod)), |
563 | size: (7 * sizeof(u32)), |
564 | data: (u8 *) ®[0]); |
565 | |
566 | switch (p->delivery_system) { |
567 | case SYS_DSS: |
568 | case SYS_DVBS: |
569 | p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; |
570 | p->post_bit_error.stat[0].uvalue = reg[5]; |
571 | p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
572 | p->post_bit_count.stat[0].uvalue = reg[6]; |
573 | break; |
574 | case SYS_DVBS2: |
575 | p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; |
576 | p->post_bit_error.stat[0].uvalue = reg[1]; |
577 | p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
578 | p->post_bit_count.stat[0].uvalue = reg[2]; |
579 | break; |
580 | default: |
581 | break; |
582 | } |
583 | |
584 | mutex_unlock(lock: &state->base->status_lock); |
585 | |
586 | return 0; |
587 | } |
588 | |
589 | static int read_signal_strength(struct dvb_frontend *fe) |
590 | { |
591 | struct mxl *state = fe->demodulator_priv; |
592 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
593 | int stat; |
594 | u32 reg_data = 0; |
595 | |
596 | mutex_lock(&state->base->status_lock); |
597 | HYDRA_DEMOD_STATUS_LOCK(state, state->demod); |
598 | stat = read_register(state, reg: (HYDRA_DMD_STATUS_INPUT_POWER_ADDR + |
599 | HYDRA_DMD_STATUS_OFFSET(state->demod)), |
600 | val: ®_data); |
601 | HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); |
602 | mutex_unlock(lock: &state->base->status_lock); |
603 | |
604 | p->strength.stat[0].scale = FE_SCALE_DECIBEL; |
605 | p->strength.stat[0].svalue = (s16) reg_data * 10; /* fix scale */ |
606 | |
607 | return stat; |
608 | } |
609 | |
610 | static int read_status(struct dvb_frontend *fe, enum fe_status *status) |
611 | { |
612 | struct mxl *state = fe->demodulator_priv; |
613 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
614 | u32 reg_data = 0; |
615 | |
616 | mutex_lock(&state->base->status_lock); |
617 | HYDRA_DEMOD_STATUS_LOCK(state, state->demod); |
618 | read_register(state, reg: (HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET + |
619 | HYDRA_DMD_STATUS_OFFSET(state->demod)), |
620 | val: ®_data); |
621 | HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); |
622 | mutex_unlock(lock: &state->base->status_lock); |
623 | |
624 | *status = (reg_data == 1) ? 0x1f : 0; |
625 | |
626 | /* signal statistics */ |
627 | |
628 | /* signal strength is always available */ |
629 | read_signal_strength(fe); |
630 | |
631 | if (*status & FE_HAS_CARRIER) |
632 | read_snr(fe); |
633 | else |
634 | p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
635 | |
636 | if (*status & FE_HAS_SYNC) |
637 | read_ber(fe); |
638 | else { |
639 | p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
640 | p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
641 | p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
642 | p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
643 | } |
644 | |
645 | return 0; |
646 | } |
647 | |
648 | static int tune(struct dvb_frontend *fe, bool re_tune, |
649 | unsigned int mode_flags, |
650 | unsigned int *delay, enum fe_status *status) |
651 | { |
652 | struct mxl *state = fe->demodulator_priv; |
653 | int r = 0; |
654 | |
655 | *delay = HZ / 2; |
656 | if (re_tune) { |
657 | r = set_parameters(fe); |
658 | if (r) |
659 | return r; |
660 | state->tune_time = jiffies; |
661 | } |
662 | |
663 | return read_status(fe, status); |
664 | } |
665 | |
666 | static enum fe_code_rate conv_fec(enum MXL_HYDRA_FEC_E fec) |
667 | { |
668 | enum fe_code_rate fec2fec[11] = { |
669 | FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3, |
670 | FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, |
671 | FEC_7_8, FEC_8_9, FEC_9_10 |
672 | }; |
673 | |
674 | if (fec > MXL_HYDRA_FEC_9_10) |
675 | return FEC_NONE; |
676 | return fec2fec[fec]; |
677 | } |
678 | |
679 | static int get_frontend(struct dvb_frontend *fe, |
680 | struct dtv_frontend_properties *p) |
681 | { |
682 | struct mxl *state = fe->demodulator_priv; |
683 | u32 reg_data[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE]; |
684 | u32 freq; |
685 | |
686 | mutex_lock(&state->base->status_lock); |
687 | HYDRA_DEMOD_STATUS_LOCK(state, state->demod); |
688 | read_register_block(state, |
689 | reg: (HYDRA_DMD_STANDARD_ADDR_OFFSET + |
690 | HYDRA_DMD_STATUS_OFFSET(state->demod)), |
691 | size: (MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), /* 25 * 4 bytes */ |
692 | data: (u8 *) ®_data[0]); |
693 | /* read demod channel parameters */ |
694 | read_register_block(state, |
695 | reg: (HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR + |
696 | HYDRA_DMD_STATUS_OFFSET(state->demod)), |
697 | size: (4), /* 4 bytes */ |
698 | data: (u8 *) &freq); |
699 | HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); |
700 | mutex_unlock(lock: &state->base->status_lock); |
701 | |
702 | dev_dbg(state->i2cdev, "freq=%u delsys=%u srate=%u\n" , |
703 | freq * 1000, reg_data[DMD_STANDARD_ADDR], |
704 | reg_data[DMD_SYMBOL_RATE_ADDR]); |
705 | p->symbol_rate = reg_data[DMD_SYMBOL_RATE_ADDR]; |
706 | p->frequency = freq; |
707 | /* |
708 | * p->delivery_system = |
709 | * (MXL_HYDRA_BCAST_STD_E) regData[DMD_STANDARD_ADDR]; |
710 | * p->inversion = |
711 | * (MXL_HYDRA_SPECTRUM_E) regData[DMD_SPECTRUM_INVERSION_ADDR]; |
712 | * freqSearchRangeKHz = |
713 | * (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]); |
714 | */ |
715 | |
716 | p->fec_inner = conv_fec(fec: reg_data[DMD_FEC_CODE_RATE_ADDR]); |
717 | switch (p->delivery_system) { |
718 | case SYS_DSS: |
719 | break; |
720 | case SYS_DVBS2: |
721 | switch ((enum MXL_HYDRA_PILOTS_E) |
722 | reg_data[DMD_DVBS2_PILOT_ON_OFF_ADDR]) { |
723 | case MXL_HYDRA_PILOTS_OFF: |
724 | p->pilot = PILOT_OFF; |
725 | break; |
726 | case MXL_HYDRA_PILOTS_ON: |
727 | p->pilot = PILOT_ON; |
728 | break; |
729 | default: |
730 | break; |
731 | } |
732 | fallthrough; |
733 | case SYS_DVBS: |
734 | switch ((enum MXL_HYDRA_MODULATION_E) |
735 | reg_data[DMD_MODULATION_SCHEME_ADDR]) { |
736 | case MXL_HYDRA_MOD_QPSK: |
737 | p->modulation = QPSK; |
738 | break; |
739 | case MXL_HYDRA_MOD_8PSK: |
740 | p->modulation = PSK_8; |
741 | break; |
742 | default: |
743 | break; |
744 | } |
745 | switch ((enum MXL_HYDRA_ROLLOFF_E) |
746 | reg_data[DMD_SPECTRUM_ROLL_OFF_ADDR]) { |
747 | case MXL_HYDRA_ROLLOFF_0_20: |
748 | p->rolloff = ROLLOFF_20; |
749 | break; |
750 | case MXL_HYDRA_ROLLOFF_0_35: |
751 | p->rolloff = ROLLOFF_35; |
752 | break; |
753 | case MXL_HYDRA_ROLLOFF_0_25: |
754 | p->rolloff = ROLLOFF_25; |
755 | break; |
756 | default: |
757 | break; |
758 | } |
759 | break; |
760 | default: |
761 | return -EINVAL; |
762 | } |
763 | return 0; |
764 | } |
765 | |
766 | static int set_input(struct dvb_frontend *fe, int input) |
767 | { |
768 | struct mxl *state = fe->demodulator_priv; |
769 | |
770 | state->tuner = input; |
771 | return 0; |
772 | } |
773 | |
774 | static const struct dvb_frontend_ops mxl_ops = { |
775 | .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, |
776 | .info = { |
777 | .name = "MaxLinear MxL5xx DVB-S/S2 tuner-demodulator" , |
778 | .frequency_min_hz = 300 * MHz, |
779 | .frequency_max_hz = 2350 * MHz, |
780 | .symbol_rate_min = 1000000, |
781 | .symbol_rate_max = 45000000, |
782 | .caps = FE_CAN_INVERSION_AUTO | |
783 | FE_CAN_FEC_AUTO | |
784 | FE_CAN_QPSK | |
785 | FE_CAN_2G_MODULATION |
786 | }, |
787 | .init = init, |
788 | .release = release, |
789 | .get_frontend_algo = get_algo, |
790 | .tune = tune, |
791 | .read_status = read_status, |
792 | .sleep = sleep, |
793 | .get_frontend = get_frontend, |
794 | .diseqc_send_master_cmd = send_master_cmd, |
795 | }; |
796 | |
797 | static struct mxl_base *match_base(struct i2c_adapter *i2c, u8 adr) |
798 | { |
799 | struct mxl_base *p; |
800 | |
801 | list_for_each_entry(p, &mxllist, mxllist) |
802 | if (p->i2c == i2c && p->adr == adr) |
803 | return p; |
804 | return NULL; |
805 | } |
806 | |
807 | static void cfg_dev_xtal(struct mxl *state, u32 freq, u32 cap, u32 enable) |
808 | { |
809 | if (state->base->can_clkout || !enable) |
810 | update_by_mnemonic(state, reg: 0x90200054, lsbloc: 23, numofbits: 1, val: enable); |
811 | |
812 | if (freq == 24000000) |
813 | write_register(state, HYDRA_CRYSTAL_SETTING, val: 0); |
814 | else |
815 | write_register(state, HYDRA_CRYSTAL_SETTING, val: 1); |
816 | |
817 | write_register(state, HYDRA_CRYSTAL_CAP, val: cap); |
818 | } |
819 | |
820 | static u32 get_big_endian(u8 num_of_bits, const u8 buf[]) |
821 | { |
822 | u32 ret_value = 0; |
823 | |
824 | switch (num_of_bits) { |
825 | case 24: |
826 | ret_value = (((u32) buf[0]) << 16) | |
827 | (((u32) buf[1]) << 8) | buf[2]; |
828 | break; |
829 | case 32: |
830 | ret_value = (((u32) buf[0]) << 24) | |
831 | (((u32) buf[1]) << 16) | |
832 | (((u32) buf[2]) << 8) | buf[3]; |
833 | break; |
834 | default: |
835 | break; |
836 | } |
837 | |
838 | return ret_value; |
839 | } |
840 | |
841 | static int write_fw_segment(struct mxl *state, |
842 | u32 mem_addr, u32 total_size, u8 *data_ptr) |
843 | { |
844 | int status; |
845 | u32 data_count = 0; |
846 | u32 size = 0; |
847 | u32 orig_size = 0; |
848 | u8 *w_buf_ptr = NULL; |
849 | u32 block_size = ((MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH - |
850 | (MXL_HYDRA_I2C_HDR_SIZE + |
851 | MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4; |
852 | u8 w_msg_buffer[MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH - |
853 | (MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)]; |
854 | |
855 | do { |
856 | size = orig_size = (((u32)(data_count + block_size)) > total_size) ? |
857 | (total_size - data_count) : block_size; |
858 | |
859 | if (orig_size & 3) |
860 | size = (orig_size + 4) & ~3; |
861 | w_buf_ptr = &w_msg_buffer[0]; |
862 | memset((void *) w_buf_ptr, 0, size); |
863 | memcpy((void *) w_buf_ptr, (void *) data_ptr, orig_size); |
864 | convert_endian(flag: 1, size, d: w_buf_ptr); |
865 | status = write_firmware_block(state, reg: mem_addr, size, reg_data_ptr: w_buf_ptr); |
866 | if (status) |
867 | return status; |
868 | data_count += size; |
869 | mem_addr += size; |
870 | data_ptr += size; |
871 | } while (data_count < total_size); |
872 | |
873 | return status; |
874 | } |
875 | |
876 | static int do_firmware_download(struct mxl *state, u8 *mbin_buffer_ptr, |
877 | u32 mbin_buffer_size) |
878 | |
879 | { |
880 | int status; |
881 | u32 index = 0; |
882 | u32 seg_length = 0; |
883 | u32 seg_address = 0; |
884 | struct MBIN_FILE_T *mbin_ptr = (struct MBIN_FILE_T *)mbin_buffer_ptr; |
885 | struct MBIN_SEGMENT_T *segment_ptr; |
886 | enum MXL_BOOL_E xcpu_fw_flag = MXL_FALSE; |
887 | |
888 | if (mbin_ptr->header.id != MBIN_FILE_HEADER_ID) { |
889 | dev_err(state->i2cdev, "%s: Invalid file header ID (%c)\n" , |
890 | __func__, mbin_ptr->header.id); |
891 | return -EINVAL; |
892 | } |
893 | status = write_register(state, FW_DL_SIGN_ADDR, val: 0); |
894 | if (status) |
895 | return status; |
896 | segment_ptr = (struct MBIN_SEGMENT_T *) (&mbin_ptr->data[0]); |
897 | for (index = 0; index < mbin_ptr->header.num_segments; index++) { |
898 | if (segment_ptr->header.id != MBIN_SEGMENT_HEADER_ID) { |
899 | dev_err(state->i2cdev, "%s: Invalid segment header ID (%c)\n" , |
900 | __func__, segment_ptr->header.id); |
901 | return -EINVAL; |
902 | } |
903 | seg_length = get_big_endian(num_of_bits: 24, |
904 | buf: &(segment_ptr->header.len24[0])); |
905 | seg_address = get_big_endian(num_of_bits: 32, |
906 | buf: &(segment_ptr->header.address[0])); |
907 | |
908 | if (state->base->type == MXL_HYDRA_DEVICE_568) { |
909 | if ((((seg_address & 0x90760000) == 0x90760000) || |
910 | ((seg_address & 0x90740000) == 0x90740000)) && |
911 | (xcpu_fw_flag == MXL_FALSE)) { |
912 | update_by_mnemonic(state, reg: 0x8003003C, lsbloc: 0, numofbits: 1, val: 1); |
913 | msleep(msecs: 200); |
914 | write_register(state, reg: 0x90720000, val: 0); |
915 | usleep_range(min: 10000, max: 11000); |
916 | xcpu_fw_flag = MXL_TRUE; |
917 | } |
918 | status = write_fw_segment(state, mem_addr: seg_address, |
919 | total_size: seg_length, |
920 | data_ptr: (u8 *) segment_ptr->data); |
921 | } else { |
922 | if (((seg_address & 0x90760000) != 0x90760000) && |
923 | ((seg_address & 0x90740000) != 0x90740000)) |
924 | status = write_fw_segment(state, mem_addr: seg_address, |
925 | total_size: seg_length, data_ptr: (u8 *) segment_ptr->data); |
926 | } |
927 | if (status) |
928 | return status; |
929 | segment_ptr = (struct MBIN_SEGMENT_T *) |
930 | &(segment_ptr->data[((seg_length + 3) / 4) * 4]); |
931 | } |
932 | return status; |
933 | } |
934 | |
935 | static int check_fw(struct mxl *state, u8 *mbin, u32 mbin_len) |
936 | { |
937 | struct MBIN_FILE_HEADER_T *fh = (struct MBIN_FILE_HEADER_T *) mbin; |
938 | u32 flen = (fh->image_size24[0] << 16) | |
939 | (fh->image_size24[1] << 8) | fh->image_size24[2]; |
940 | u8 *fw, cs = 0; |
941 | u32 i; |
942 | |
943 | if (fh->id != 'M' || fh->fmt_version != '1' || flen > 0x3FFF0) { |
944 | dev_info(state->i2cdev, "Invalid FW Header\n" ); |
945 | return -1; |
946 | } |
947 | fw = mbin + sizeof(struct MBIN_FILE_HEADER_T); |
948 | for (i = 0; i < flen; i += 1) |
949 | cs += fw[i]; |
950 | if (cs != fh->image_checksum) { |
951 | dev_info(state->i2cdev, "Invalid FW Checksum\n" ); |
952 | return -1; |
953 | } |
954 | return 0; |
955 | } |
956 | |
957 | static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len) |
958 | { |
959 | int status; |
960 | u32 reg_data = 0; |
961 | struct MXL_HYDRA_SKU_COMMAND_T dev_sku_cfg; |
962 | u8 cmd_size = sizeof(struct MXL_HYDRA_SKU_COMMAND_T); |
963 | u8 cmd_buff[sizeof(struct MXL_HYDRA_SKU_COMMAND_T) + 6]; |
964 | |
965 | if (check_fw(state, mbin, mbin_len)) |
966 | return -1; |
967 | |
968 | /* put CPU into reset */ |
969 | status = update_by_mnemonic(state, reg: 0x8003003C, lsbloc: 0, numofbits: 1, val: 0); |
970 | if (status) |
971 | return status; |
972 | usleep_range(min: 1000, max: 2000); |
973 | |
974 | /* Reset TX FIFO's, BBAND, XBAR */ |
975 | status = write_register(state, HYDRA_RESET_TRANSPORT_FIFO_REG, |
976 | HYDRA_RESET_TRANSPORT_FIFO_DATA); |
977 | if (status) |
978 | return status; |
979 | status = write_register(state, HYDRA_RESET_BBAND_REG, |
980 | HYDRA_RESET_BBAND_DATA); |
981 | if (status) |
982 | return status; |
983 | status = write_register(state, HYDRA_RESET_XBAR_REG, |
984 | HYDRA_RESET_XBAR_DATA); |
985 | if (status) |
986 | return status; |
987 | |
988 | /* Disable clock to Baseband, Wideband, SerDes, |
989 | * Alias ext & Transport modules |
990 | */ |
991 | status = write_register(state, HYDRA_MODULES_CLK_2_REG, |
992 | HYDRA_DISABLE_CLK_2); |
993 | if (status) |
994 | return status; |
995 | /* Clear Software & Host interrupt status - (Clear on read) */ |
996 | status = read_register(state, HYDRA_PRCM_ROOT_CLK_REG, val: ®_data); |
997 | if (status) |
998 | return status; |
999 | status = do_firmware_download(state, mbin_buffer_ptr: mbin, mbin_buffer_size: mbin_len); |
1000 | if (status) |
1001 | return status; |
1002 | |
1003 | if (state->base->type == MXL_HYDRA_DEVICE_568) { |
1004 | usleep_range(min: 10000, max: 11000); |
1005 | |
1006 | /* bring XCPU out of reset */ |
1007 | status = write_register(state, reg: 0x90720000, val: 1); |
1008 | if (status) |
1009 | return status; |
1010 | msleep(msecs: 500); |
1011 | |
1012 | /* Enable XCPU UART message processing in MCPU */ |
1013 | status = write_register(state, reg: 0x9076B510, val: 1); |
1014 | if (status) |
1015 | return status; |
1016 | } else { |
1017 | /* Bring CPU out of reset */ |
1018 | status = update_by_mnemonic(state, reg: 0x8003003C, lsbloc: 0, numofbits: 1, val: 1); |
1019 | if (status) |
1020 | return status; |
1021 | /* Wait until FW boots */ |
1022 | msleep(msecs: 150); |
1023 | } |
1024 | |
1025 | /* Initialize XPT XBAR */ |
1026 | status = write_register(state, XPT_DMD0_BASEADDR, val: 0x76543210); |
1027 | if (status) |
1028 | return status; |
1029 | |
1030 | if (!firmware_is_alive(state)) |
1031 | return -1; |
1032 | |
1033 | dev_info(state->i2cdev, "Hydra FW alive. Hail!\n" ); |
1034 | |
1035 | /* sometimes register values are wrong shortly |
1036 | * after first heart beats |
1037 | */ |
1038 | msleep(msecs: 50); |
1039 | |
1040 | dev_sku_cfg.sku_type = state->base->sku_type; |
1041 | BUILD_HYDRA_CMD(MXL_HYDRA_DEV_CFG_SKU_CMD, MXL_CMD_WRITE, |
1042 | cmd_size, &dev_sku_cfg, cmd_buff); |
1043 | status = send_command(state, size: cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, |
1044 | buf: &cmd_buff[0]); |
1045 | |
1046 | return status; |
1047 | } |
1048 | |
1049 | static int cfg_ts_pad_mux(struct mxl *state, enum MXL_BOOL_E enable_serial_ts) |
1050 | { |
1051 | int status = 0; |
1052 | u32 pad_mux_value = 0; |
1053 | |
1054 | if (enable_serial_ts == MXL_TRUE) { |
1055 | pad_mux_value = 0; |
1056 | if ((state->base->type == MXL_HYDRA_DEVICE_541) || |
1057 | (state->base->type == MXL_HYDRA_DEVICE_541S)) |
1058 | pad_mux_value = 2; |
1059 | } else { |
1060 | if ((state->base->type == MXL_HYDRA_DEVICE_581) || |
1061 | (state->base->type == MXL_HYDRA_DEVICE_581S)) |
1062 | pad_mux_value = 2; |
1063 | else |
1064 | pad_mux_value = 3; |
1065 | } |
1066 | |
1067 | switch (state->base->type) { |
1068 | case MXL_HYDRA_DEVICE_561: |
1069 | case MXL_HYDRA_DEVICE_581: |
1070 | case MXL_HYDRA_DEVICE_541: |
1071 | case MXL_HYDRA_DEVICE_541S: |
1072 | case MXL_HYDRA_DEVICE_561S: |
1073 | case MXL_HYDRA_DEVICE_581S: |
1074 | status |= update_by_mnemonic(state, reg: 0x90000170, lsbloc: 24, numofbits: 3, |
1075 | val: pad_mux_value); |
1076 | status |= update_by_mnemonic(state, reg: 0x90000170, lsbloc: 28, numofbits: 3, |
1077 | val: pad_mux_value); |
1078 | status |= update_by_mnemonic(state, reg: 0x90000174, lsbloc: 0, numofbits: 3, |
1079 | val: pad_mux_value); |
1080 | status |= update_by_mnemonic(state, reg: 0x90000174, lsbloc: 4, numofbits: 3, |
1081 | val: pad_mux_value); |
1082 | status |= update_by_mnemonic(state, reg: 0x90000174, lsbloc: 8, numofbits: 3, |
1083 | val: pad_mux_value); |
1084 | status |= update_by_mnemonic(state, reg: 0x90000174, lsbloc: 12, numofbits: 3, |
1085 | val: pad_mux_value); |
1086 | status |= update_by_mnemonic(state, reg: 0x90000174, lsbloc: 16, numofbits: 3, |
1087 | val: pad_mux_value); |
1088 | status |= update_by_mnemonic(state, reg: 0x90000174, lsbloc: 20, numofbits: 3, |
1089 | val: pad_mux_value); |
1090 | status |= update_by_mnemonic(state, reg: 0x90000174, lsbloc: 24, numofbits: 3, |
1091 | val: pad_mux_value); |
1092 | status |= update_by_mnemonic(state, reg: 0x90000174, lsbloc: 28, numofbits: 3, |
1093 | val: pad_mux_value); |
1094 | status |= update_by_mnemonic(state, reg: 0x90000178, lsbloc: 0, numofbits: 3, |
1095 | val: pad_mux_value); |
1096 | status |= update_by_mnemonic(state, reg: 0x90000178, lsbloc: 4, numofbits: 3, |
1097 | val: pad_mux_value); |
1098 | status |= update_by_mnemonic(state, reg: 0x90000178, lsbloc: 8, numofbits: 3, |
1099 | val: pad_mux_value); |
1100 | break; |
1101 | |
1102 | case MXL_HYDRA_DEVICE_544: |
1103 | case MXL_HYDRA_DEVICE_542: |
1104 | status |= update_by_mnemonic(state, reg: 0x9000016C, lsbloc: 4, numofbits: 3, val: 1); |
1105 | status |= update_by_mnemonic(state, reg: 0x9000016C, lsbloc: 8, numofbits: 3, val: 0); |
1106 | status |= update_by_mnemonic(state, reg: 0x9000016C, lsbloc: 12, numofbits: 3, val: 0); |
1107 | status |= update_by_mnemonic(state, reg: 0x9000016C, lsbloc: 16, numofbits: 3, val: 0); |
1108 | status |= update_by_mnemonic(state, reg: 0x90000170, lsbloc: 0, numofbits: 3, val: 0); |
1109 | status |= update_by_mnemonic(state, reg: 0x90000178, lsbloc: 12, numofbits: 3, val: 1); |
1110 | status |= update_by_mnemonic(state, reg: 0x90000178, lsbloc: 16, numofbits: 3, val: 1); |
1111 | status |= update_by_mnemonic(state, reg: 0x90000178, lsbloc: 20, numofbits: 3, val: 1); |
1112 | status |= update_by_mnemonic(state, reg: 0x90000178, lsbloc: 24, numofbits: 3, val: 1); |
1113 | status |= update_by_mnemonic(state, reg: 0x9000017C, lsbloc: 0, numofbits: 3, val: 1); |
1114 | status |= update_by_mnemonic(state, reg: 0x9000017C, lsbloc: 4, numofbits: 3, val: 1); |
1115 | if (enable_serial_ts == MXL_ENABLE) { |
1116 | status |= update_by_mnemonic(state, |
1117 | reg: 0x90000170, lsbloc: 4, numofbits: 3, val: 0); |
1118 | status |= update_by_mnemonic(state, |
1119 | reg: 0x90000170, lsbloc: 8, numofbits: 3, val: 0); |
1120 | status |= update_by_mnemonic(state, |
1121 | reg: 0x90000170, lsbloc: 12, numofbits: 3, val: 0); |
1122 | status |= update_by_mnemonic(state, |
1123 | reg: 0x90000170, lsbloc: 16, numofbits: 3, val: 0); |
1124 | status |= update_by_mnemonic(state, |
1125 | reg: 0x90000170, lsbloc: 20, numofbits: 3, val: 1); |
1126 | status |= update_by_mnemonic(state, |
1127 | reg: 0x90000170, lsbloc: 24, numofbits: 3, val: 1); |
1128 | status |= update_by_mnemonic(state, |
1129 | reg: 0x90000170, lsbloc: 28, numofbits: 3, val: 2); |
1130 | status |= update_by_mnemonic(state, |
1131 | reg: 0x90000174, lsbloc: 0, numofbits: 3, val: 2); |
1132 | status |= update_by_mnemonic(state, |
1133 | reg: 0x90000174, lsbloc: 4, numofbits: 3, val: 2); |
1134 | status |= update_by_mnemonic(state, |
1135 | reg: 0x90000174, lsbloc: 8, numofbits: 3, val: 2); |
1136 | status |= update_by_mnemonic(state, |
1137 | reg: 0x90000174, lsbloc: 12, numofbits: 3, val: 2); |
1138 | status |= update_by_mnemonic(state, |
1139 | reg: 0x90000174, lsbloc: 16, numofbits: 3, val: 2); |
1140 | status |= update_by_mnemonic(state, |
1141 | reg: 0x90000174, lsbloc: 20, numofbits: 3, val: 2); |
1142 | status |= update_by_mnemonic(state, |
1143 | reg: 0x90000174, lsbloc: 24, numofbits: 3, val: 2); |
1144 | status |= update_by_mnemonic(state, |
1145 | reg: 0x90000174, lsbloc: 28, numofbits: 3, val: 2); |
1146 | status |= update_by_mnemonic(state, |
1147 | reg: 0x90000178, lsbloc: 0, numofbits: 3, val: 2); |
1148 | status |= update_by_mnemonic(state, |
1149 | reg: 0x90000178, lsbloc: 4, numofbits: 3, val: 2); |
1150 | status |= update_by_mnemonic(state, |
1151 | reg: 0x90000178, lsbloc: 8, numofbits: 3, val: 2); |
1152 | } else { |
1153 | status |= update_by_mnemonic(state, |
1154 | reg: 0x90000170, lsbloc: 4, numofbits: 3, val: 3); |
1155 | status |= update_by_mnemonic(state, |
1156 | reg: 0x90000170, lsbloc: 8, numofbits: 3, val: 3); |
1157 | status |= update_by_mnemonic(state, |
1158 | reg: 0x90000170, lsbloc: 12, numofbits: 3, val: 3); |
1159 | status |= update_by_mnemonic(state, |
1160 | reg: 0x90000170, lsbloc: 16, numofbits: 3, val: 3); |
1161 | status |= update_by_mnemonic(state, |
1162 | reg: 0x90000170, lsbloc: 20, numofbits: 3, val: 3); |
1163 | status |= update_by_mnemonic(state, |
1164 | reg: 0x90000170, lsbloc: 24, numofbits: 3, val: 3); |
1165 | status |= update_by_mnemonic(state, |
1166 | reg: 0x90000170, lsbloc: 28, numofbits: 3, val: 3); |
1167 | status |= update_by_mnemonic(state, |
1168 | reg: 0x90000174, lsbloc: 0, numofbits: 3, val: 3); |
1169 | status |= update_by_mnemonic(state, |
1170 | reg: 0x90000174, lsbloc: 4, numofbits: 3, val: 3); |
1171 | status |= update_by_mnemonic(state, |
1172 | reg: 0x90000174, lsbloc: 8, numofbits: 3, val: 3); |
1173 | status |= update_by_mnemonic(state, |
1174 | reg: 0x90000174, lsbloc: 12, numofbits: 3, val: 3); |
1175 | status |= update_by_mnemonic(state, |
1176 | reg: 0x90000174, lsbloc: 16, numofbits: 3, val: 3); |
1177 | status |= update_by_mnemonic(state, |
1178 | reg: 0x90000174, lsbloc: 20, numofbits: 3, val: 1); |
1179 | status |= update_by_mnemonic(state, |
1180 | reg: 0x90000174, lsbloc: 24, numofbits: 3, val: 1); |
1181 | status |= update_by_mnemonic(state, |
1182 | reg: 0x90000174, lsbloc: 28, numofbits: 3, val: 1); |
1183 | status |= update_by_mnemonic(state, |
1184 | reg: 0x90000178, lsbloc: 0, numofbits: 3, val: 1); |
1185 | status |= update_by_mnemonic(state, |
1186 | reg: 0x90000178, lsbloc: 4, numofbits: 3, val: 1); |
1187 | status |= update_by_mnemonic(state, |
1188 | reg: 0x90000178, lsbloc: 8, numofbits: 3, val: 1); |
1189 | } |
1190 | break; |
1191 | |
1192 | case MXL_HYDRA_DEVICE_568: |
1193 | if (enable_serial_ts == MXL_FALSE) { |
1194 | status |= update_by_mnemonic(state, |
1195 | reg: 0x9000016C, lsbloc: 8, numofbits: 3, val: 5); |
1196 | status |= update_by_mnemonic(state, |
1197 | reg: 0x9000016C, lsbloc: 12, numofbits: 3, val: 5); |
1198 | status |= update_by_mnemonic(state, |
1199 | reg: 0x9000016C, lsbloc: 16, numofbits: 3, val: 5); |
1200 | status |= update_by_mnemonic(state, |
1201 | reg: 0x9000016C, lsbloc: 20, numofbits: 3, val: 5); |
1202 | status |= update_by_mnemonic(state, |
1203 | reg: 0x9000016C, lsbloc: 24, numofbits: 3, val: 5); |
1204 | status |= update_by_mnemonic(state, |
1205 | reg: 0x9000016C, lsbloc: 28, numofbits: 3, val: 5); |
1206 | status |= update_by_mnemonic(state, |
1207 | reg: 0x90000170, lsbloc: 0, numofbits: 3, val: 5); |
1208 | status |= update_by_mnemonic(state, |
1209 | reg: 0x90000170, lsbloc: 4, numofbits: 3, val: 5); |
1210 | status |= update_by_mnemonic(state, |
1211 | reg: 0x90000170, lsbloc: 8, numofbits: 3, val: 5); |
1212 | status |= update_by_mnemonic(state, |
1213 | reg: 0x90000170, lsbloc: 12, numofbits: 3, val: 5); |
1214 | status |= update_by_mnemonic(state, |
1215 | reg: 0x90000170, lsbloc: 16, numofbits: 3, val: 5); |
1216 | status |= update_by_mnemonic(state, |
1217 | reg: 0x90000170, lsbloc: 20, numofbits: 3, val: 5); |
1218 | |
1219 | status |= update_by_mnemonic(state, |
1220 | reg: 0x90000170, lsbloc: 24, numofbits: 3, val: pad_mux_value); |
1221 | status |= update_by_mnemonic(state, |
1222 | reg: 0x90000174, lsbloc: 0, numofbits: 3, val: pad_mux_value); |
1223 | status |= update_by_mnemonic(state, |
1224 | reg: 0x90000174, lsbloc: 4, numofbits: 3, val: pad_mux_value); |
1225 | status |= update_by_mnemonic(state, |
1226 | reg: 0x90000174, lsbloc: 8, numofbits: 3, val: pad_mux_value); |
1227 | status |= update_by_mnemonic(state, |
1228 | reg: 0x90000174, lsbloc: 12, numofbits: 3, val: pad_mux_value); |
1229 | status |= update_by_mnemonic(state, |
1230 | reg: 0x90000174, lsbloc: 16, numofbits: 3, val: pad_mux_value); |
1231 | status |= update_by_mnemonic(state, |
1232 | reg: 0x90000174, lsbloc: 20, numofbits: 3, val: pad_mux_value); |
1233 | status |= update_by_mnemonic(state, |
1234 | reg: 0x90000174, lsbloc: 24, numofbits: 3, val: pad_mux_value); |
1235 | status |= update_by_mnemonic(state, |
1236 | reg: 0x90000174, lsbloc: 28, numofbits: 3, val: pad_mux_value); |
1237 | status |= update_by_mnemonic(state, |
1238 | reg: 0x90000178, lsbloc: 0, numofbits: 3, val: pad_mux_value); |
1239 | status |= update_by_mnemonic(state, |
1240 | reg: 0x90000178, lsbloc: 4, numofbits: 3, val: pad_mux_value); |
1241 | |
1242 | status |= update_by_mnemonic(state, |
1243 | reg: 0x90000178, lsbloc: 8, numofbits: 3, val: 5); |
1244 | status |= update_by_mnemonic(state, |
1245 | reg: 0x90000178, lsbloc: 12, numofbits: 3, val: 5); |
1246 | status |= update_by_mnemonic(state, |
1247 | reg: 0x90000178, lsbloc: 16, numofbits: 3, val: 5); |
1248 | status |= update_by_mnemonic(state, |
1249 | reg: 0x90000178, lsbloc: 20, numofbits: 3, val: 5); |
1250 | status |= update_by_mnemonic(state, |
1251 | reg: 0x90000178, lsbloc: 24, numofbits: 3, val: 5); |
1252 | status |= update_by_mnemonic(state, |
1253 | reg: 0x90000178, lsbloc: 28, numofbits: 3, val: 5); |
1254 | status |= update_by_mnemonic(state, |
1255 | reg: 0x9000017C, lsbloc: 0, numofbits: 3, val: 5); |
1256 | status |= update_by_mnemonic(state, |
1257 | reg: 0x9000017C, lsbloc: 4, numofbits: 3, val: 5); |
1258 | } else { |
1259 | status |= update_by_mnemonic(state, |
1260 | reg: 0x90000170, lsbloc: 4, numofbits: 3, val: pad_mux_value); |
1261 | status |= update_by_mnemonic(state, |
1262 | reg: 0x90000170, lsbloc: 8, numofbits: 3, val: pad_mux_value); |
1263 | status |= update_by_mnemonic(state, |
1264 | reg: 0x90000170, lsbloc: 12, numofbits: 3, val: pad_mux_value); |
1265 | status |= update_by_mnemonic(state, |
1266 | reg: 0x90000170, lsbloc: 16, numofbits: 3, val: pad_mux_value); |
1267 | status |= update_by_mnemonic(state, |
1268 | reg: 0x90000170, lsbloc: 20, numofbits: 3, val: pad_mux_value); |
1269 | status |= update_by_mnemonic(state, |
1270 | reg: 0x90000170, lsbloc: 24, numofbits: 3, val: pad_mux_value); |
1271 | status |= update_by_mnemonic(state, |
1272 | reg: 0x90000170, lsbloc: 28, numofbits: 3, val: pad_mux_value); |
1273 | status |= update_by_mnemonic(state, |
1274 | reg: 0x90000174, lsbloc: 0, numofbits: 3, val: pad_mux_value); |
1275 | status |= update_by_mnemonic(state, |
1276 | reg: 0x90000174, lsbloc: 4, numofbits: 3, val: pad_mux_value); |
1277 | status |= update_by_mnemonic(state, |
1278 | reg: 0x90000174, lsbloc: 8, numofbits: 3, val: pad_mux_value); |
1279 | status |= update_by_mnemonic(state, |
1280 | reg: 0x90000174, lsbloc: 12, numofbits: 3, val: pad_mux_value); |
1281 | } |
1282 | break; |
1283 | |
1284 | |
1285 | case MXL_HYDRA_DEVICE_584: |
1286 | default: |
1287 | status |= update_by_mnemonic(state, |
1288 | reg: 0x90000170, lsbloc: 4, numofbits: 3, val: pad_mux_value); |
1289 | status |= update_by_mnemonic(state, |
1290 | reg: 0x90000170, lsbloc: 8, numofbits: 3, val: pad_mux_value); |
1291 | status |= update_by_mnemonic(state, |
1292 | reg: 0x90000170, lsbloc: 12, numofbits: 3, val: pad_mux_value); |
1293 | status |= update_by_mnemonic(state, |
1294 | reg: 0x90000170, lsbloc: 16, numofbits: 3, val: pad_mux_value); |
1295 | status |= update_by_mnemonic(state, |
1296 | reg: 0x90000170, lsbloc: 20, numofbits: 3, val: pad_mux_value); |
1297 | status |= update_by_mnemonic(state, |
1298 | reg: 0x90000170, lsbloc: 24, numofbits: 3, val: pad_mux_value); |
1299 | status |= update_by_mnemonic(state, |
1300 | reg: 0x90000170, lsbloc: 28, numofbits: 3, val: pad_mux_value); |
1301 | status |= update_by_mnemonic(state, |
1302 | reg: 0x90000174, lsbloc: 0, numofbits: 3, val: pad_mux_value); |
1303 | status |= update_by_mnemonic(state, |
1304 | reg: 0x90000174, lsbloc: 4, numofbits: 3, val: pad_mux_value); |
1305 | status |= update_by_mnemonic(state, |
1306 | reg: 0x90000174, lsbloc: 8, numofbits: 3, val: pad_mux_value); |
1307 | status |= update_by_mnemonic(state, |
1308 | reg: 0x90000174, lsbloc: 12, numofbits: 3, val: pad_mux_value); |
1309 | break; |
1310 | } |
1311 | return status; |
1312 | } |
1313 | |
1314 | static int set_drive_strength(struct mxl *state, |
1315 | enum MXL_HYDRA_TS_DRIVE_STRENGTH_E ts_drive_strength) |
1316 | { |
1317 | int stat = 0; |
1318 | u32 val; |
1319 | |
1320 | read_register(state, reg: 0x90000194, val: &val); |
1321 | dev_info(state->i2cdev, "DIGIO = %08x\n" , val); |
1322 | dev_info(state->i2cdev, "set drive_strength = %u\n" , ts_drive_strength); |
1323 | |
1324 | |
1325 | stat |= update_by_mnemonic(state, reg: 0x90000194, lsbloc: 0, numofbits: 3, val: ts_drive_strength); |
1326 | stat |= update_by_mnemonic(state, reg: 0x90000194, lsbloc: 20, numofbits: 3, val: ts_drive_strength); |
1327 | stat |= update_by_mnemonic(state, reg: 0x90000194, lsbloc: 24, numofbits: 3, val: ts_drive_strength); |
1328 | stat |= update_by_mnemonic(state, reg: 0x90000198, lsbloc: 12, numofbits: 3, val: ts_drive_strength); |
1329 | stat |= update_by_mnemonic(state, reg: 0x90000198, lsbloc: 16, numofbits: 3, val: ts_drive_strength); |
1330 | stat |= update_by_mnemonic(state, reg: 0x90000198, lsbloc: 20, numofbits: 3, val: ts_drive_strength); |
1331 | stat |= update_by_mnemonic(state, reg: 0x90000198, lsbloc: 24, numofbits: 3, val: ts_drive_strength); |
1332 | stat |= update_by_mnemonic(state, reg: 0x9000019C, lsbloc: 0, numofbits: 3, val: ts_drive_strength); |
1333 | stat |= update_by_mnemonic(state, reg: 0x9000019C, lsbloc: 4, numofbits: 3, val: ts_drive_strength); |
1334 | stat |= update_by_mnemonic(state, reg: 0x9000019C, lsbloc: 8, numofbits: 3, val: ts_drive_strength); |
1335 | stat |= update_by_mnemonic(state, reg: 0x9000019C, lsbloc: 24, numofbits: 3, val: ts_drive_strength); |
1336 | stat |= update_by_mnemonic(state, reg: 0x9000019C, lsbloc: 28, numofbits: 3, val: ts_drive_strength); |
1337 | stat |= update_by_mnemonic(state, reg: 0x900001A0, lsbloc: 0, numofbits: 3, val: ts_drive_strength); |
1338 | stat |= update_by_mnemonic(state, reg: 0x900001A0, lsbloc: 4, numofbits: 3, val: ts_drive_strength); |
1339 | stat |= update_by_mnemonic(state, reg: 0x900001A0, lsbloc: 20, numofbits: 3, val: ts_drive_strength); |
1340 | stat |= update_by_mnemonic(state, reg: 0x900001A0, lsbloc: 24, numofbits: 3, val: ts_drive_strength); |
1341 | stat |= update_by_mnemonic(state, reg: 0x900001A0, lsbloc: 28, numofbits: 3, val: ts_drive_strength); |
1342 | |
1343 | return stat; |
1344 | } |
1345 | |
1346 | static int enable_tuner(struct mxl *state, u32 tuner, u32 enable) |
1347 | { |
1348 | int stat = 0; |
1349 | struct MXL_HYDRA_TUNER_CMD ctrl_tuner_cmd; |
1350 | u8 cmd_size = sizeof(ctrl_tuner_cmd); |
1351 | u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; |
1352 | u32 val, count = 10; |
1353 | |
1354 | ctrl_tuner_cmd.tuner_id = tuner; |
1355 | ctrl_tuner_cmd.enable = enable; |
1356 | BUILD_HYDRA_CMD(MXL_HYDRA_TUNER_ACTIVATE_CMD, MXL_CMD_WRITE, |
1357 | cmd_size, &ctrl_tuner_cmd, cmd_buff); |
1358 | stat = send_command(state, size: cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, |
1359 | buf: &cmd_buff[0]); |
1360 | if (stat) |
1361 | return stat; |
1362 | read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, val: &val); |
1363 | while (--count && ((val >> tuner) & 1) != enable) { |
1364 | msleep(msecs: 20); |
1365 | read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, val: &val); |
1366 | } |
1367 | if (!count) |
1368 | return -1; |
1369 | read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, val: &val); |
1370 | dev_dbg(state->i2cdev, "tuner %u ready = %u\n" , |
1371 | tuner, (val >> tuner) & 1); |
1372 | |
1373 | return 0; |
1374 | } |
1375 | |
1376 | |
1377 | static int config_ts(struct mxl *state, enum MXL_HYDRA_DEMOD_ID_E demod_id, |
1378 | struct MXL_HYDRA_MPEGOUT_PARAM_T *mpeg_out_param_ptr) |
1379 | { |
1380 | int status = 0; |
1381 | u32 nco_count_min = 0; |
1382 | u32 clk_type = 0; |
1383 | |
1384 | struct MXL_REG_FIELD_T xpt_sync_polarity[MXL_HYDRA_DEMOD_MAX] = { |
1385 | {0x90700010, 8, 1}, {0x90700010, 9, 1}, |
1386 | {0x90700010, 10, 1}, {0x90700010, 11, 1}, |
1387 | {0x90700010, 12, 1}, {0x90700010, 13, 1}, |
1388 | {0x90700010, 14, 1}, {0x90700010, 15, 1} }; |
1389 | struct MXL_REG_FIELD_T xpt_clock_polarity[MXL_HYDRA_DEMOD_MAX] = { |
1390 | {0x90700010, 16, 1}, {0x90700010, 17, 1}, |
1391 | {0x90700010, 18, 1}, {0x90700010, 19, 1}, |
1392 | {0x90700010, 20, 1}, {0x90700010, 21, 1}, |
1393 | {0x90700010, 22, 1}, {0x90700010, 23, 1} }; |
1394 | struct MXL_REG_FIELD_T xpt_valid_polarity[MXL_HYDRA_DEMOD_MAX] = { |
1395 | {0x90700014, 0, 1}, {0x90700014, 1, 1}, |
1396 | {0x90700014, 2, 1}, {0x90700014, 3, 1}, |
1397 | {0x90700014, 4, 1}, {0x90700014, 5, 1}, |
1398 | {0x90700014, 6, 1}, {0x90700014, 7, 1} }; |
1399 | struct MXL_REG_FIELD_T xpt_ts_clock_phase[MXL_HYDRA_DEMOD_MAX] = { |
1400 | {0x90700018, 0, 3}, {0x90700018, 4, 3}, |
1401 | {0x90700018, 8, 3}, {0x90700018, 12, 3}, |
1402 | {0x90700018, 16, 3}, {0x90700018, 20, 3}, |
1403 | {0x90700018, 24, 3}, {0x90700018, 28, 3} }; |
1404 | struct MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = { |
1405 | {0x9070000C, 16, 1}, {0x9070000C, 17, 1}, |
1406 | {0x9070000C, 18, 1}, {0x9070000C, 19, 1}, |
1407 | {0x9070000C, 20, 1}, {0x9070000C, 21, 1}, |
1408 | {0x9070000C, 22, 1}, {0x9070000C, 23, 1} }; |
1409 | struct MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = { |
1410 | {0x90700010, 0, 1}, {0x90700010, 1, 1}, |
1411 | {0x90700010, 2, 1}, {0x90700010, 3, 1}, |
1412 | {0x90700010, 4, 1}, {0x90700010, 5, 1}, |
1413 | {0x90700010, 6, 1}, {0x90700010, 7, 1} }; |
1414 | struct MXL_REG_FIELD_T xpt_enable_output[MXL_HYDRA_DEMOD_MAX] = { |
1415 | {0x9070000C, 0, 1}, {0x9070000C, 1, 1}, |
1416 | {0x9070000C, 2, 1}, {0x9070000C, 3, 1}, |
1417 | {0x9070000C, 4, 1}, {0x9070000C, 5, 1}, |
1418 | {0x9070000C, 6, 1}, {0x9070000C, 7, 1} }; |
1419 | struct MXL_REG_FIELD_T xpt_err_replace_sync[MXL_HYDRA_DEMOD_MAX] = { |
1420 | {0x9070000C, 24, 1}, {0x9070000C, 25, 1}, |
1421 | {0x9070000C, 26, 1}, {0x9070000C, 27, 1}, |
1422 | {0x9070000C, 28, 1}, {0x9070000C, 29, 1}, |
1423 | {0x9070000C, 30, 1}, {0x9070000C, 31, 1} }; |
1424 | struct MXL_REG_FIELD_T xpt_err_replace_valid[MXL_HYDRA_DEMOD_MAX] = { |
1425 | {0x90700014, 8, 1}, {0x90700014, 9, 1}, |
1426 | {0x90700014, 10, 1}, {0x90700014, 11, 1}, |
1427 | {0x90700014, 12, 1}, {0x90700014, 13, 1}, |
1428 | {0x90700014, 14, 1}, {0x90700014, 15, 1} }; |
1429 | struct MXL_REG_FIELD_T xpt_continuous_clock[MXL_HYDRA_DEMOD_MAX] = { |
1430 | {0x907001D4, 0, 1}, {0x907001D4, 1, 1}, |
1431 | {0x907001D4, 2, 1}, {0x907001D4, 3, 1}, |
1432 | {0x907001D4, 4, 1}, {0x907001D4, 5, 1}, |
1433 | {0x907001D4, 6, 1}, {0x907001D4, 7, 1} }; |
1434 | struct MXL_REG_FIELD_T xpt_nco_clock_rate[MXL_HYDRA_DEMOD_MAX] = { |
1435 | {0x90700044, 16, 80}, {0x90700044, 16, 81}, |
1436 | {0x90700044, 16, 82}, {0x90700044, 16, 83}, |
1437 | {0x90700044, 16, 84}, {0x90700044, 16, 85}, |
1438 | {0x90700044, 16, 86}, {0x90700044, 16, 87} }; |
1439 | |
1440 | demod_id = state->base->ts_map[demod_id]; |
1441 | |
1442 | if (mpeg_out_param_ptr->enable == MXL_ENABLE) { |
1443 | if (mpeg_out_param_ptr->mpeg_mode == |
1444 | MXL_HYDRA_MPEG_MODE_PARALLEL) { |
1445 | } else { |
1446 | cfg_ts_pad_mux(state, enable_serial_ts: MXL_TRUE); |
1447 | update_by_mnemonic(state, |
1448 | reg: 0x90700010, lsbloc: 27, numofbits: 1, val: MXL_FALSE); |
1449 | } |
1450 | } |
1451 | |
1452 | nco_count_min = |
1453 | (u32)(MXL_HYDRA_NCO_CLK / mpeg_out_param_ptr->max_mpeg_clk_rate); |
1454 | |
1455 | if (state->base->chipversion >= 2) { |
1456 | status |= update_by_mnemonic(state, |
1457 | reg: xpt_nco_clock_rate[demod_id].reg_addr, /* Reg Addr */ |
1458 | lsbloc: xpt_nco_clock_rate[demod_id].lsb_pos, /* LSB pos */ |
1459 | numofbits: xpt_nco_clock_rate[demod_id].num_of_bits, /* Num of bits */ |
1460 | val: nco_count_min); /* Data */ |
1461 | } else |
1462 | update_by_mnemonic(state, reg: 0x90700044, lsbloc: 16, numofbits: 8, val: nco_count_min); |
1463 | |
1464 | if (mpeg_out_param_ptr->mpeg_clk_type == MXL_HYDRA_MPEG_CLK_CONTINUOUS) |
1465 | clk_type = 1; |
1466 | |
1467 | if (mpeg_out_param_ptr->mpeg_mode < MXL_HYDRA_MPEG_MODE_PARALLEL) { |
1468 | status |= update_by_mnemonic(state, |
1469 | reg: xpt_continuous_clock[demod_id].reg_addr, |
1470 | lsbloc: xpt_continuous_clock[demod_id].lsb_pos, |
1471 | numofbits: xpt_continuous_clock[demod_id].num_of_bits, |
1472 | val: clk_type); |
1473 | } else |
1474 | update_by_mnemonic(state, reg: 0x907001D4, lsbloc: 8, numofbits: 1, val: clk_type); |
1475 | |
1476 | status |= update_by_mnemonic(state, |
1477 | reg: xpt_sync_polarity[demod_id].reg_addr, |
1478 | lsbloc: xpt_sync_polarity[demod_id].lsb_pos, |
1479 | numofbits: xpt_sync_polarity[demod_id].num_of_bits, |
1480 | val: mpeg_out_param_ptr->mpeg_sync_pol); |
1481 | |
1482 | status |= update_by_mnemonic(state, |
1483 | reg: xpt_valid_polarity[demod_id].reg_addr, |
1484 | lsbloc: xpt_valid_polarity[demod_id].lsb_pos, |
1485 | numofbits: xpt_valid_polarity[demod_id].num_of_bits, |
1486 | val: mpeg_out_param_ptr->mpeg_valid_pol); |
1487 | |
1488 | status |= update_by_mnemonic(state, |
1489 | reg: xpt_clock_polarity[demod_id].reg_addr, |
1490 | lsbloc: xpt_clock_polarity[demod_id].lsb_pos, |
1491 | numofbits: xpt_clock_polarity[demod_id].num_of_bits, |
1492 | val: mpeg_out_param_ptr->mpeg_clk_pol); |
1493 | |
1494 | status |= update_by_mnemonic(state, |
1495 | reg: xpt_sync_byte[demod_id].reg_addr, |
1496 | lsbloc: xpt_sync_byte[demod_id].lsb_pos, |
1497 | numofbits: xpt_sync_byte[demod_id].num_of_bits, |
1498 | val: mpeg_out_param_ptr->mpeg_sync_pulse_width); |
1499 | |
1500 | status |= update_by_mnemonic(state, |
1501 | reg: xpt_ts_clock_phase[demod_id].reg_addr, |
1502 | lsbloc: xpt_ts_clock_phase[demod_id].lsb_pos, |
1503 | numofbits: xpt_ts_clock_phase[demod_id].num_of_bits, |
1504 | val: mpeg_out_param_ptr->mpeg_clk_phase); |
1505 | |
1506 | status |= update_by_mnemonic(state, |
1507 | reg: xpt_lsb_first[demod_id].reg_addr, |
1508 | lsbloc: xpt_lsb_first[demod_id].lsb_pos, |
1509 | numofbits: xpt_lsb_first[demod_id].num_of_bits, |
1510 | val: mpeg_out_param_ptr->lsb_or_msb_first); |
1511 | |
1512 | switch (mpeg_out_param_ptr->mpeg_error_indication) { |
1513 | case MXL_HYDRA_MPEG_ERR_REPLACE_SYNC: |
1514 | status |= update_by_mnemonic(state, |
1515 | reg: xpt_err_replace_sync[demod_id].reg_addr, |
1516 | lsbloc: xpt_err_replace_sync[demod_id].lsb_pos, |
1517 | numofbits: xpt_err_replace_sync[demod_id].num_of_bits, |
1518 | val: MXL_TRUE); |
1519 | status |= update_by_mnemonic(state, |
1520 | reg: xpt_err_replace_valid[demod_id].reg_addr, |
1521 | lsbloc: xpt_err_replace_valid[demod_id].lsb_pos, |
1522 | numofbits: xpt_err_replace_valid[demod_id].num_of_bits, |
1523 | val: MXL_FALSE); |
1524 | break; |
1525 | |
1526 | case MXL_HYDRA_MPEG_ERR_REPLACE_VALID: |
1527 | status |= update_by_mnemonic(state, |
1528 | reg: xpt_err_replace_sync[demod_id].reg_addr, |
1529 | lsbloc: xpt_err_replace_sync[demod_id].lsb_pos, |
1530 | numofbits: xpt_err_replace_sync[demod_id].num_of_bits, |
1531 | val: MXL_FALSE); |
1532 | |
1533 | status |= update_by_mnemonic(state, |
1534 | reg: xpt_err_replace_valid[demod_id].reg_addr, |
1535 | lsbloc: xpt_err_replace_valid[demod_id].lsb_pos, |
1536 | numofbits: xpt_err_replace_valid[demod_id].num_of_bits, |
1537 | val: MXL_TRUE); |
1538 | break; |
1539 | |
1540 | case MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED: |
1541 | default: |
1542 | status |= update_by_mnemonic(state, |
1543 | reg: xpt_err_replace_sync[demod_id].reg_addr, |
1544 | lsbloc: xpt_err_replace_sync[demod_id].lsb_pos, |
1545 | numofbits: xpt_err_replace_sync[demod_id].num_of_bits, |
1546 | val: MXL_FALSE); |
1547 | |
1548 | status |= update_by_mnemonic(state, |
1549 | reg: xpt_err_replace_valid[demod_id].reg_addr, |
1550 | lsbloc: xpt_err_replace_valid[demod_id].lsb_pos, |
1551 | numofbits: xpt_err_replace_valid[demod_id].num_of_bits, |
1552 | val: MXL_FALSE); |
1553 | |
1554 | break; |
1555 | |
1556 | } |
1557 | |
1558 | if (mpeg_out_param_ptr->mpeg_mode != MXL_HYDRA_MPEG_MODE_PARALLEL) { |
1559 | status |= update_by_mnemonic(state, |
1560 | reg: xpt_enable_output[demod_id].reg_addr, |
1561 | lsbloc: xpt_enable_output[demod_id].lsb_pos, |
1562 | numofbits: xpt_enable_output[demod_id].num_of_bits, |
1563 | val: mpeg_out_param_ptr->enable); |
1564 | } |
1565 | return status; |
1566 | } |
1567 | |
1568 | static int config_mux(struct mxl *state) |
1569 | { |
1570 | update_by_mnemonic(state, reg: 0x9070000C, lsbloc: 0, numofbits: 1, val: 0); |
1571 | update_by_mnemonic(state, reg: 0x9070000C, lsbloc: 1, numofbits: 1, val: 0); |
1572 | update_by_mnemonic(state, reg: 0x9070000C, lsbloc: 2, numofbits: 1, val: 0); |
1573 | update_by_mnemonic(state, reg: 0x9070000C, lsbloc: 3, numofbits: 1, val: 0); |
1574 | update_by_mnemonic(state, reg: 0x9070000C, lsbloc: 4, numofbits: 1, val: 0); |
1575 | update_by_mnemonic(state, reg: 0x9070000C, lsbloc: 5, numofbits: 1, val: 0); |
1576 | update_by_mnemonic(state, reg: 0x9070000C, lsbloc: 6, numofbits: 1, val: 0); |
1577 | update_by_mnemonic(state, reg: 0x9070000C, lsbloc: 7, numofbits: 1, val: 0); |
1578 | update_by_mnemonic(state, reg: 0x90700008, lsbloc: 0, numofbits: 2, val: 1); |
1579 | update_by_mnemonic(state, reg: 0x90700008, lsbloc: 2, numofbits: 2, val: 1); |
1580 | return 0; |
1581 | } |
1582 | |
1583 | static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg) |
1584 | { |
1585 | int stat = 0; |
1586 | u8 *buf; |
1587 | |
1588 | if (cfg->fw) |
1589 | return firmware_download(state, mbin: cfg->fw, mbin_len: cfg->fw_len); |
1590 | |
1591 | if (!cfg->fw_read) |
1592 | return -1; |
1593 | |
1594 | buf = vmalloc(size: 0x40000); |
1595 | if (!buf) |
1596 | return -ENOMEM; |
1597 | |
1598 | cfg->fw_read(cfg->fw_priv, buf, 0x40000); |
1599 | stat = firmware_download(state, mbin: buf, mbin_len: 0x40000); |
1600 | vfree(addr: buf); |
1601 | |
1602 | return stat; |
1603 | } |
1604 | |
1605 | static int validate_sku(struct mxl *state) |
1606 | { |
1607 | u32 pad_mux_bond = 0, prcm_chip_id = 0, prcm_so_cid = 0; |
1608 | int status; |
1609 | u32 type = state->base->type; |
1610 | |
1611 | status = read_by_mnemonic(state, reg: 0x90000190, lsbloc: 0, numofbits: 3, val: &pad_mux_bond); |
1612 | status |= read_by_mnemonic(state, reg: 0x80030000, lsbloc: 0, numofbits: 12, val: &prcm_chip_id); |
1613 | status |= read_by_mnemonic(state, reg: 0x80030004, lsbloc: 24, numofbits: 8, val: &prcm_so_cid); |
1614 | if (status) |
1615 | return -1; |
1616 | |
1617 | dev_info(state->i2cdev, "padMuxBond=%08x, prcmChipId=%08x, prcmSoCId=%08x\n" , |
1618 | pad_mux_bond, prcm_chip_id, prcm_so_cid); |
1619 | |
1620 | if (prcm_chip_id != 0x560) { |
1621 | switch (pad_mux_bond) { |
1622 | case MXL_HYDRA_SKU_ID_581: |
1623 | if (type == MXL_HYDRA_DEVICE_581) |
1624 | return 0; |
1625 | if (type == MXL_HYDRA_DEVICE_581S) { |
1626 | state->base->type = MXL_HYDRA_DEVICE_581; |
1627 | return 0; |
1628 | } |
1629 | break; |
1630 | case MXL_HYDRA_SKU_ID_584: |
1631 | if (type == MXL_HYDRA_DEVICE_584) |
1632 | return 0; |
1633 | break; |
1634 | case MXL_HYDRA_SKU_ID_544: |
1635 | if (type == MXL_HYDRA_DEVICE_544) |
1636 | return 0; |
1637 | if (type == MXL_HYDRA_DEVICE_542) |
1638 | return 0; |
1639 | break; |
1640 | case MXL_HYDRA_SKU_ID_582: |
1641 | if (type == MXL_HYDRA_DEVICE_582) |
1642 | return 0; |
1643 | break; |
1644 | default: |
1645 | return -1; |
1646 | } |
1647 | } |
1648 | return -1; |
1649 | } |
1650 | |
1651 | static int get_fwinfo(struct mxl *state) |
1652 | { |
1653 | int status; |
1654 | u32 val = 0; |
1655 | |
1656 | status = read_by_mnemonic(state, reg: 0x90000190, lsbloc: 0, numofbits: 3, val: &val); |
1657 | if (status) |
1658 | return status; |
1659 | dev_info(state->i2cdev, "chipID=%08x\n" , val); |
1660 | |
1661 | status = read_by_mnemonic(state, reg: 0x80030004, lsbloc: 8, numofbits: 8, val: &val); |
1662 | if (status) |
1663 | return status; |
1664 | dev_info(state->i2cdev, "chipVer=%08x\n" , val); |
1665 | |
1666 | status = read_register(state, HYDRA_FIRMWARE_VERSION, val: &val); |
1667 | if (status) |
1668 | return status; |
1669 | dev_info(state->i2cdev, "FWVer=%08x\n" , val); |
1670 | |
1671 | state->base->fwversion = val; |
1672 | return status; |
1673 | } |
1674 | |
1675 | |
1676 | static u8 ts_map1_to_1[MXL_HYDRA_DEMOD_MAX] = { |
1677 | MXL_HYDRA_DEMOD_ID_0, |
1678 | MXL_HYDRA_DEMOD_ID_1, |
1679 | MXL_HYDRA_DEMOD_ID_2, |
1680 | MXL_HYDRA_DEMOD_ID_3, |
1681 | MXL_HYDRA_DEMOD_ID_4, |
1682 | MXL_HYDRA_DEMOD_ID_5, |
1683 | MXL_HYDRA_DEMOD_ID_6, |
1684 | MXL_HYDRA_DEMOD_ID_7, |
1685 | }; |
1686 | |
1687 | static u8 ts_map54x[MXL_HYDRA_DEMOD_MAX] = { |
1688 | MXL_HYDRA_DEMOD_ID_2, |
1689 | MXL_HYDRA_DEMOD_ID_3, |
1690 | MXL_HYDRA_DEMOD_ID_4, |
1691 | MXL_HYDRA_DEMOD_ID_5, |
1692 | MXL_HYDRA_DEMOD_MAX, |
1693 | MXL_HYDRA_DEMOD_MAX, |
1694 | MXL_HYDRA_DEMOD_MAX, |
1695 | MXL_HYDRA_DEMOD_MAX, |
1696 | }; |
1697 | |
1698 | static int probe(struct mxl *state, struct mxl5xx_cfg *cfg) |
1699 | { |
1700 | u32 chipver; |
1701 | int fw, status, j; |
1702 | struct MXL_HYDRA_MPEGOUT_PARAM_T mpeg_interface_cfg; |
1703 | |
1704 | state->base->ts_map = ts_map1_to_1; |
1705 | |
1706 | switch (state->base->type) { |
1707 | case MXL_HYDRA_DEVICE_581: |
1708 | case MXL_HYDRA_DEVICE_581S: |
1709 | state->base->can_clkout = 1; |
1710 | state->base->demod_num = 8; |
1711 | state->base->tuner_num = 1; |
1712 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_581; |
1713 | break; |
1714 | case MXL_HYDRA_DEVICE_582: |
1715 | state->base->can_clkout = 1; |
1716 | state->base->demod_num = 8; |
1717 | state->base->tuner_num = 3; |
1718 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_582; |
1719 | break; |
1720 | case MXL_HYDRA_DEVICE_585: |
1721 | state->base->can_clkout = 0; |
1722 | state->base->demod_num = 8; |
1723 | state->base->tuner_num = 4; |
1724 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_585; |
1725 | break; |
1726 | case MXL_HYDRA_DEVICE_544: |
1727 | state->base->can_clkout = 0; |
1728 | state->base->demod_num = 4; |
1729 | state->base->tuner_num = 4; |
1730 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_544; |
1731 | state->base->ts_map = ts_map54x; |
1732 | break; |
1733 | case MXL_HYDRA_DEVICE_541: |
1734 | case MXL_HYDRA_DEVICE_541S: |
1735 | state->base->can_clkout = 0; |
1736 | state->base->demod_num = 4; |
1737 | state->base->tuner_num = 1; |
1738 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_541; |
1739 | state->base->ts_map = ts_map54x; |
1740 | break; |
1741 | case MXL_HYDRA_DEVICE_561: |
1742 | case MXL_HYDRA_DEVICE_561S: |
1743 | state->base->can_clkout = 0; |
1744 | state->base->demod_num = 6; |
1745 | state->base->tuner_num = 1; |
1746 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_561; |
1747 | break; |
1748 | case MXL_HYDRA_DEVICE_568: |
1749 | state->base->can_clkout = 0; |
1750 | state->base->demod_num = 8; |
1751 | state->base->tuner_num = 1; |
1752 | state->base->chan_bond = 1; |
1753 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_568; |
1754 | break; |
1755 | case MXL_HYDRA_DEVICE_542: |
1756 | state->base->can_clkout = 1; |
1757 | state->base->demod_num = 4; |
1758 | state->base->tuner_num = 3; |
1759 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_542; |
1760 | state->base->ts_map = ts_map54x; |
1761 | break; |
1762 | case MXL_HYDRA_DEVICE_TEST: |
1763 | case MXL_HYDRA_DEVICE_584: |
1764 | default: |
1765 | state->base->can_clkout = 0; |
1766 | state->base->demod_num = 8; |
1767 | state->base->tuner_num = 4; |
1768 | state->base->sku_type = MXL_HYDRA_SKU_TYPE_584; |
1769 | break; |
1770 | } |
1771 | |
1772 | status = validate_sku(state); |
1773 | if (status) |
1774 | return status; |
1775 | |
1776 | update_by_mnemonic(state, reg: 0x80030014, lsbloc: 9, numofbits: 1, val: 1); |
1777 | update_by_mnemonic(state, reg: 0x8003003C, lsbloc: 12, numofbits: 1, val: 1); |
1778 | status = read_by_mnemonic(state, reg: 0x80030000, lsbloc: 12, numofbits: 4, val: &chipver); |
1779 | if (status) |
1780 | state->base->chipversion = 0; |
1781 | else |
1782 | state->base->chipversion = (chipver == 2) ? 2 : 1; |
1783 | dev_info(state->i2cdev, "Hydra chip version %u\n" , |
1784 | state->base->chipversion); |
1785 | |
1786 | cfg_dev_xtal(state, freq: cfg->clk, cap: cfg->cap, enable: 0); |
1787 | |
1788 | fw = firmware_is_alive(state); |
1789 | if (!fw) { |
1790 | status = load_fw(state, cfg); |
1791 | if (status) |
1792 | return status; |
1793 | } |
1794 | get_fwinfo(state); |
1795 | |
1796 | config_mux(state); |
1797 | mpeg_interface_cfg.enable = MXL_ENABLE; |
1798 | mpeg_interface_cfg.lsb_or_msb_first = MXL_HYDRA_MPEG_SERIAL_MSB_1ST; |
1799 | /* supports only (0-104&139)MHz */ |
1800 | if (cfg->ts_clk) |
1801 | mpeg_interface_cfg.max_mpeg_clk_rate = cfg->ts_clk; |
1802 | else |
1803 | mpeg_interface_cfg.max_mpeg_clk_rate = 69; /* 139; */ |
1804 | mpeg_interface_cfg.mpeg_clk_phase = MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG; |
1805 | mpeg_interface_cfg.mpeg_clk_pol = MXL_HYDRA_MPEG_CLK_IN_PHASE; |
1806 | /* MXL_HYDRA_MPEG_CLK_GAPPED; */ |
1807 | mpeg_interface_cfg.mpeg_clk_type = MXL_HYDRA_MPEG_CLK_CONTINUOUS; |
1808 | mpeg_interface_cfg.mpeg_error_indication = |
1809 | MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED; |
1810 | mpeg_interface_cfg.mpeg_mode = MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE; |
1811 | mpeg_interface_cfg.mpeg_sync_pol = MXL_HYDRA_MPEG_ACTIVE_HIGH; |
1812 | mpeg_interface_cfg.mpeg_sync_pulse_width = MXL_HYDRA_MPEG_SYNC_WIDTH_BIT; |
1813 | mpeg_interface_cfg.mpeg_valid_pol = MXL_HYDRA_MPEG_ACTIVE_HIGH; |
1814 | |
1815 | for (j = 0; j < state->base->demod_num; j++) { |
1816 | status = config_ts(state, demod_id: (enum MXL_HYDRA_DEMOD_ID_E) j, |
1817 | mpeg_out_param_ptr: &mpeg_interface_cfg); |
1818 | if (status) |
1819 | return status; |
1820 | } |
1821 | set_drive_strength(state, ts_drive_strength: 1); |
1822 | return 0; |
1823 | } |
1824 | |
1825 | struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, |
1826 | struct mxl5xx_cfg *cfg, u32 demod, u32 tuner, |
1827 | int (**fn_set_input)(struct dvb_frontend *, int)) |
1828 | { |
1829 | struct mxl *state; |
1830 | struct mxl_base *base; |
1831 | |
1832 | state = kzalloc(size: sizeof(struct mxl), GFP_KERNEL); |
1833 | if (!state) |
1834 | return NULL; |
1835 | |
1836 | state->demod = demod; |
1837 | state->tuner = tuner; |
1838 | state->tuner_in_use = 0xffffffff; |
1839 | state->i2cdev = &i2c->dev; |
1840 | |
1841 | base = match_base(i2c, adr: cfg->adr); |
1842 | if (base) { |
1843 | base->count++; |
1844 | if (base->count > base->demod_num) |
1845 | goto fail; |
1846 | state->base = base; |
1847 | } else { |
1848 | base = kzalloc(size: sizeof(struct mxl_base), GFP_KERNEL); |
1849 | if (!base) |
1850 | goto fail; |
1851 | base->i2c = i2c; |
1852 | base->adr = cfg->adr; |
1853 | base->type = cfg->type; |
1854 | base->count = 1; |
1855 | mutex_init(&base->i2c_lock); |
1856 | mutex_init(&base->status_lock); |
1857 | mutex_init(&base->tune_lock); |
1858 | INIT_LIST_HEAD(list: &base->mxls); |
1859 | |
1860 | state->base = base; |
1861 | if (probe(state, cfg) < 0) { |
1862 | kfree(objp: base); |
1863 | goto fail; |
1864 | } |
1865 | list_add(new: &base->mxllist, head: &mxllist); |
1866 | } |
1867 | state->fe.ops = mxl_ops; |
1868 | state->xbar[0] = 4; |
1869 | state->xbar[1] = demod; |
1870 | state->xbar[2] = 8; |
1871 | state->fe.demodulator_priv = state; |
1872 | *fn_set_input = set_input; |
1873 | |
1874 | list_add(new: &state->mxl, head: &base->mxls); |
1875 | return &state->fe; |
1876 | |
1877 | fail: |
1878 | kfree(objp: state); |
1879 | return NULL; |
1880 | } |
1881 | EXPORT_SYMBOL_GPL(mxl5xx_attach); |
1882 | |
1883 | MODULE_DESCRIPTION("MaxLinear MxL5xx DVB-S/S2 tuner-demodulator driver" ); |
1884 | MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR" ); |
1885 | MODULE_LICENSE("GPL v2" ); |
1886 | |