1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * ddbridge-max.c: Digital Devices bridge MAX card support |
4 | * |
5 | * Copyright (C) 2010-2017 Digital Devices GmbH |
6 | * Ralph Metzler <rjkm@metzlerbros.de> |
7 | * Marcus Metzler <mocm@metzlerbros.de> |
8 | */ |
9 | |
10 | #include <linux/module.h> |
11 | #include <linux/init.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/poll.h> |
16 | #include <linux/io.h> |
17 | #include <linux/pci.h> |
18 | #include <linux/pci_ids.h> |
19 | #include <linux/timer.h> |
20 | #include <linux/i2c.h> |
21 | #include <linux/swab.h> |
22 | #include <linux/vmalloc.h> |
23 | |
24 | #include "ddbridge.h" |
25 | #include "ddbridge-regs.h" |
26 | #include "ddbridge-io.h" |
27 | #include "ddbridge-mci.h" |
28 | |
29 | #include "ddbridge-max.h" |
30 | #include "mxl5xx.h" |
31 | |
32 | /******************************************************************************/ |
33 | |
34 | /* MaxS4/8 related modparams */ |
35 | static int fmode; |
36 | module_param(fmode, int, 0444); |
37 | MODULE_PARM_DESC(fmode, "frontend emulation mode" ); |
38 | |
39 | static int fmode_sat = -1; |
40 | module_param(fmode_sat, int, 0444); |
41 | MODULE_PARM_DESC(fmode_sat, "set frontend emulation mode sat" ); |
42 | |
43 | static int old_quattro; |
44 | module_param(old_quattro, int, 0444); |
45 | MODULE_PARM_DESC(old_quattro, "old quattro LNB input order " ); |
46 | |
47 | /******************************************************************************/ |
48 | |
49 | static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) |
50 | { |
51 | u32 c, v = 0, tag = DDB_LINK_TAG(link); |
52 | |
53 | v = LNB_TONE & (dev->link[link].lnb.tone << (15 - lnb)); |
54 | ddbwritel(dev, val: cmd | v, adr: tag | LNB_CONTROL(lnb)); |
55 | for (c = 0; c < 10; c++) { |
56 | v = ddbreadl(dev, adr: tag | LNB_CONTROL(lnb)); |
57 | if ((v & LNB_BUSY) == 0) |
58 | break; |
59 | msleep(msecs: 20); |
60 | } |
61 | if (c == 10) |
62 | dev_info(dev->dev, "%s lnb = %08x cmd = %08x\n" , |
63 | __func__, lnb, cmd); |
64 | return 0; |
65 | } |
66 | |
67 | static int max_send_master_cmd(struct dvb_frontend *fe, |
68 | struct dvb_diseqc_master_cmd *cmd) |
69 | { |
70 | struct ddb_input *input = fe->sec_priv; |
71 | struct ddb_port *port = input->port; |
72 | struct ddb *dev = port->dev; |
73 | struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; |
74 | u32 tag = DDB_LINK_TAG(port->lnr); |
75 | int i; |
76 | u32 fmode = dev->link[port->lnr].lnb.fmode; |
77 | |
78 | if (fmode == 2 || fmode == 1) |
79 | return 0; |
80 | if (dvb->diseqc_send_master_cmd) |
81 | dvb->diseqc_send_master_cmd(fe, cmd); |
82 | |
83 | mutex_lock(&dev->link[port->lnr].lnb.lock); |
84 | ddbwritel(dev, val: 0, adr: tag | LNB_BUF_LEVEL(dvb->input)); |
85 | for (i = 0; i < cmd->msg_len; i++) |
86 | ddbwritel(dev, val: cmd->msg[i], adr: tag | LNB_BUF_WRITE(dvb->input)); |
87 | lnb_command(dev, link: port->lnr, lnb: dvb->input, LNB_CMD_DISEQC); |
88 | mutex_unlock(lock: &dev->link[port->lnr].lnb.lock); |
89 | return 0; |
90 | } |
91 | |
92 | static int lnb_send_diseqc(struct ddb *dev, u32 link, u32 input, |
93 | struct dvb_diseqc_master_cmd *cmd) |
94 | { |
95 | u32 tag = DDB_LINK_TAG(link); |
96 | int i; |
97 | |
98 | ddbwritel(dev, val: 0, adr: tag | LNB_BUF_LEVEL(input)); |
99 | for (i = 0; i < cmd->msg_len; i++) |
100 | ddbwritel(dev, val: cmd->msg[i], adr: tag | LNB_BUF_WRITE(input)); |
101 | lnb_command(dev, link, lnb: input, LNB_CMD_DISEQC); |
102 | return 0; |
103 | } |
104 | |
105 | static int lnb_set_sat(struct ddb *dev, u32 link, u32 input, u32 sat, u32 band, |
106 | u32 hor) |
107 | { |
108 | struct dvb_diseqc_master_cmd cmd = { |
109 | .msg = {0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, |
110 | .msg_len = 4 |
111 | }; |
112 | cmd.msg[3] = 0xf0 | (((sat << 2) & 0x0c) | (band ? 1 : 0) | |
113 | (hor ? 2 : 0)); |
114 | return lnb_send_diseqc(dev, link, input, cmd: &cmd); |
115 | } |
116 | |
117 | static int lnb_set_tone(struct ddb *dev, u32 link, u32 input, |
118 | enum fe_sec_tone_mode tone) |
119 | { |
120 | int s = 0; |
121 | u32 mask = (1ULL << input); |
122 | |
123 | switch (tone) { |
124 | case SEC_TONE_OFF: |
125 | if (!(dev->link[link].lnb.tone & mask)) |
126 | return 0; |
127 | dev->link[link].lnb.tone &= ~(1ULL << input); |
128 | break; |
129 | case SEC_TONE_ON: |
130 | if (dev->link[link].lnb.tone & mask) |
131 | return 0; |
132 | dev->link[link].lnb.tone |= (1ULL << input); |
133 | break; |
134 | default: |
135 | s = -EINVAL; |
136 | break; |
137 | } |
138 | if (!s) |
139 | s = lnb_command(dev, link, lnb: input, LNB_CMD_NOP); |
140 | return s; |
141 | } |
142 | |
143 | static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input, |
144 | enum fe_sec_voltage voltage) |
145 | { |
146 | int s = 0; |
147 | |
148 | if (dev->link[link].lnb.oldvoltage[input] == voltage) |
149 | return 0; |
150 | switch (voltage) { |
151 | case SEC_VOLTAGE_OFF: |
152 | if (dev->link[link].lnb.voltage[input]) |
153 | return 0; |
154 | lnb_command(dev, link, lnb: input, LNB_CMD_OFF); |
155 | break; |
156 | case SEC_VOLTAGE_13: |
157 | lnb_command(dev, link, lnb: input, LNB_CMD_LOW); |
158 | break; |
159 | case SEC_VOLTAGE_18: |
160 | lnb_command(dev, link, lnb: input, LNB_CMD_HIGH); |
161 | break; |
162 | default: |
163 | s = -EINVAL; |
164 | break; |
165 | } |
166 | dev->link[link].lnb.oldvoltage[input] = voltage; |
167 | return s; |
168 | } |
169 | |
170 | static int max_set_input_unlocked(struct dvb_frontend *fe, int in) |
171 | { |
172 | struct ddb_input *input = fe->sec_priv; |
173 | struct ddb_port *port = input->port; |
174 | struct ddb *dev = port->dev; |
175 | struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; |
176 | int res = 0; |
177 | |
178 | if (in > 3) |
179 | return -EINVAL; |
180 | if (dvb->input != in) { |
181 | u32 bit = (1ULL << input->nr); |
182 | u32 obit = |
183 | dev->link[port->lnr].lnb.voltage[dvb->input & 3] & bit; |
184 | |
185 | dev->link[port->lnr].lnb.voltage[dvb->input & 3] &= ~bit; |
186 | dvb->input = in; |
187 | dev->link[port->lnr].lnb.voltage[dvb->input & 3] |= obit; |
188 | } |
189 | res = dvb->set_input(fe, in); |
190 | return res; |
191 | } |
192 | |
193 | static int max_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) |
194 | { |
195 | struct ddb_input *input = fe->sec_priv; |
196 | struct ddb_port *port = input->port; |
197 | struct ddb *dev = port->dev; |
198 | struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; |
199 | int tuner = 0; |
200 | int res = 0; |
201 | u32 fmode = dev->link[port->lnr].lnb.fmode; |
202 | |
203 | mutex_lock(&dev->link[port->lnr].lnb.lock); |
204 | dvb->tone = tone; |
205 | switch (fmode) { |
206 | default: |
207 | case 0: |
208 | case 3: |
209 | res = lnb_set_tone(dev, link: port->lnr, input: dvb->input, tone); |
210 | break; |
211 | case 1: |
212 | case 2: |
213 | if (old_quattro) { |
214 | if (dvb->tone == SEC_TONE_ON) |
215 | tuner |= 2; |
216 | if (dvb->voltage == SEC_VOLTAGE_18) |
217 | tuner |= 1; |
218 | } else { |
219 | if (dvb->tone == SEC_TONE_ON) |
220 | tuner |= 1; |
221 | if (dvb->voltage == SEC_VOLTAGE_18) |
222 | tuner |= 2; |
223 | } |
224 | res = max_set_input_unlocked(fe, in: tuner); |
225 | break; |
226 | } |
227 | mutex_unlock(lock: &dev->link[port->lnr].lnb.lock); |
228 | return res; |
229 | } |
230 | |
231 | static int max_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) |
232 | { |
233 | struct ddb_input *input = fe->sec_priv; |
234 | struct ddb_port *port = input->port; |
235 | struct ddb *dev = port->dev; |
236 | struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; |
237 | int tuner = 0; |
238 | u32 nv, ov = dev->link[port->lnr].lnb.voltages; |
239 | int res = 0; |
240 | u32 fmode = dev->link[port->lnr].lnb.fmode; |
241 | |
242 | mutex_lock(&dev->link[port->lnr].lnb.lock); |
243 | dvb->voltage = voltage; |
244 | |
245 | switch (fmode) { |
246 | case 3: |
247 | default: |
248 | case 0: |
249 | if (fmode == 3) |
250 | max_set_input_unlocked(fe, in: 0); |
251 | if (voltage == SEC_VOLTAGE_OFF) |
252 | dev->link[port->lnr].lnb.voltage[dvb->input] &= |
253 | ~(1ULL << input->nr); |
254 | else |
255 | dev->link[port->lnr].lnb.voltage[dvb->input] |= |
256 | (1ULL << input->nr); |
257 | |
258 | res = lnb_set_voltage(dev, link: port->lnr, input: dvb->input, voltage); |
259 | break; |
260 | case 1: |
261 | case 2: |
262 | if (voltage == SEC_VOLTAGE_OFF) |
263 | dev->link[port->lnr].lnb.voltages &= |
264 | ~(1ULL << input->nr); |
265 | else |
266 | dev->link[port->lnr].lnb.voltages |= |
267 | (1ULL << input->nr); |
268 | |
269 | nv = dev->link[port->lnr].lnb.voltages; |
270 | |
271 | if (old_quattro) { |
272 | if (dvb->tone == SEC_TONE_ON) |
273 | tuner |= 2; |
274 | if (dvb->voltage == SEC_VOLTAGE_18) |
275 | tuner |= 1; |
276 | } else { |
277 | if (dvb->tone == SEC_TONE_ON) |
278 | tuner |= 1; |
279 | if (dvb->voltage == SEC_VOLTAGE_18) |
280 | tuner |= 2; |
281 | } |
282 | res = max_set_input_unlocked(fe, in: tuner); |
283 | |
284 | if (nv != ov) { |
285 | if (nv) { |
286 | lnb_set_voltage( |
287 | dev, link: port->lnr, |
288 | input: 0, voltage: SEC_VOLTAGE_13); |
289 | if (fmode == 1) { |
290 | lnb_set_voltage( |
291 | dev, link: port->lnr, |
292 | input: 0, voltage: SEC_VOLTAGE_13); |
293 | if (old_quattro) { |
294 | lnb_set_voltage( |
295 | dev, link: port->lnr, |
296 | input: 1, voltage: SEC_VOLTAGE_18); |
297 | lnb_set_voltage( |
298 | dev, link: port->lnr, |
299 | input: 2, voltage: SEC_VOLTAGE_13); |
300 | } else { |
301 | lnb_set_voltage( |
302 | dev, link: port->lnr, |
303 | input: 1, voltage: SEC_VOLTAGE_13); |
304 | lnb_set_voltage( |
305 | dev, link: port->lnr, |
306 | input: 2, voltage: SEC_VOLTAGE_18); |
307 | } |
308 | lnb_set_voltage( |
309 | dev, link: port->lnr, |
310 | input: 3, voltage: SEC_VOLTAGE_18); |
311 | } |
312 | } else { |
313 | lnb_set_voltage( |
314 | dev, link: port->lnr, |
315 | input: 0, voltage: SEC_VOLTAGE_OFF); |
316 | if (fmode == 1) { |
317 | lnb_set_voltage( |
318 | dev, link: port->lnr, |
319 | input: 1, voltage: SEC_VOLTAGE_OFF); |
320 | lnb_set_voltage( |
321 | dev, link: port->lnr, |
322 | input: 2, voltage: SEC_VOLTAGE_OFF); |
323 | lnb_set_voltage( |
324 | dev, link: port->lnr, |
325 | input: 3, voltage: SEC_VOLTAGE_OFF); |
326 | } |
327 | } |
328 | } |
329 | break; |
330 | } |
331 | mutex_unlock(lock: &dev->link[port->lnr].lnb.lock); |
332 | return res; |
333 | } |
334 | |
335 | static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) |
336 | { |
337 | return 0; |
338 | } |
339 | |
340 | static int max_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) |
341 | { |
342 | return 0; |
343 | } |
344 | |
345 | static int mxl_fw_read(void *priv, u8 *buf, u32 len) |
346 | { |
347 | struct ddb_link *link = priv; |
348 | struct ddb *dev = link->dev; |
349 | |
350 | dev_info(dev->dev, "Read mxl_fw from link %u\n" , link->nr); |
351 | |
352 | return ddbridge_flashread(dev, link: link->nr, buf, addr: 0xc0000, len); |
353 | } |
354 | |
355 | int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm) |
356 | { |
357 | u32 l = link->nr; |
358 | |
359 | if (link->lnb.fmode == fm) |
360 | return 0; |
361 | dev_info(dev->dev, "Set fmode link %u = %u\n" , l, fm); |
362 | mutex_lock(&link->lnb.lock); |
363 | if (fm == 2 || fm == 1) { |
364 | if (fmode_sat >= 0) { |
365 | lnb_set_sat(dev, link: l, input: 0, sat: fmode_sat, band: 0, hor: 0); |
366 | if (old_quattro) { |
367 | lnb_set_sat(dev, link: l, input: 1, sat: fmode_sat, band: 0, hor: 1); |
368 | lnb_set_sat(dev, link: l, input: 2, sat: fmode_sat, band: 1, hor: 0); |
369 | } else { |
370 | lnb_set_sat(dev, link: l, input: 1, sat: fmode_sat, band: 1, hor: 0); |
371 | lnb_set_sat(dev, link: l, input: 2, sat: fmode_sat, band: 0, hor: 1); |
372 | } |
373 | lnb_set_sat(dev, link: l, input: 3, sat: fmode_sat, band: 1, hor: 1); |
374 | } |
375 | lnb_set_tone(dev, link: l, input: 0, tone: SEC_TONE_OFF); |
376 | if (old_quattro) { |
377 | lnb_set_tone(dev, link: l, input: 1, tone: SEC_TONE_OFF); |
378 | lnb_set_tone(dev, link: l, input: 2, tone: SEC_TONE_ON); |
379 | } else { |
380 | lnb_set_tone(dev, link: l, input: 1, tone: SEC_TONE_ON); |
381 | lnb_set_tone(dev, link: l, input: 2, tone: SEC_TONE_OFF); |
382 | } |
383 | lnb_set_tone(dev, link: l, input: 3, tone: SEC_TONE_ON); |
384 | } |
385 | link->lnb.fmode = fm; |
386 | mutex_unlock(lock: &link->lnb.lock); |
387 | return 0; |
388 | } |
389 | |
390 | static struct mxl5xx_cfg mxl5xx = { |
391 | .adr = 0x60, |
392 | .type = 0x01, |
393 | .clk = 27000000, |
394 | .ts_clk = 139, |
395 | .cap = 12, |
396 | .fw_read = mxl_fw_read, |
397 | }; |
398 | |
399 | int ddb_fe_attach_mxl5xx(struct ddb_input *input) |
400 | { |
401 | struct ddb *dev = input->port->dev; |
402 | struct i2c_adapter *i2c = &input->port->i2c->adap; |
403 | struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; |
404 | struct ddb_port *port = input->port; |
405 | struct ddb_link *link = &dev->link[port->lnr]; |
406 | struct mxl5xx_cfg cfg; |
407 | int demod, tuner; |
408 | |
409 | cfg = mxl5xx; |
410 | cfg.fw_priv = link; |
411 | dvb->set_input = NULL; |
412 | |
413 | demod = input->nr; |
414 | tuner = demod & 3; |
415 | if (fmode == 3) |
416 | tuner = 0; |
417 | |
418 | dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, |
419 | demod, tuner, &dvb->set_input); |
420 | |
421 | if (!dvb->fe) { |
422 | dev_err(dev->dev, "No MXL5XX found!\n" ); |
423 | return -ENODEV; |
424 | } |
425 | |
426 | if (!dvb->set_input) { |
427 | dev_err(dev->dev, "No mxl5xx_set_input function pointer!\n" ); |
428 | return -ENODEV; |
429 | } |
430 | |
431 | if (input->nr < 4) { |
432 | lnb_command(dev, link: port->lnr, lnb: input->nr, LNB_CMD_INIT); |
433 | lnb_set_voltage(dev, link: port->lnr, input: input->nr, voltage: SEC_VOLTAGE_OFF); |
434 | } |
435 | ddb_lnb_init_fmode(dev, link, fm: fmode); |
436 | |
437 | dvb->fe->ops.set_voltage = max_set_voltage; |
438 | dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage; |
439 | dvb->fe->ops.set_tone = max_set_tone; |
440 | dvb->diseqc_send_master_cmd = dvb->fe->ops.diseqc_send_master_cmd; |
441 | dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd; |
442 | dvb->fe->ops.diseqc_send_burst = max_send_burst; |
443 | dvb->fe->sec_priv = input; |
444 | dvb->input = tuner; |
445 | return 0; |
446 | } |
447 | |
448 | /******************************************************************************/ |
449 | /* MAX MCI related functions */ |
450 | |
451 | int ddb_fe_attach_mci(struct ddb_input *input, u32 type) |
452 | { |
453 | struct ddb *dev = input->port->dev; |
454 | struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; |
455 | struct ddb_port *port = input->port; |
456 | struct ddb_link *link = &dev->link[port->lnr]; |
457 | int demod, tuner; |
458 | struct mci_cfg cfg; |
459 | |
460 | demod = input->nr; |
461 | tuner = demod & 3; |
462 | switch (type) { |
463 | case DDB_TUNER_MCI_SX8: |
464 | cfg = ddb_max_sx8_cfg; |
465 | if (fmode == 3) |
466 | tuner = 0; |
467 | break; |
468 | default: |
469 | return -EINVAL; |
470 | } |
471 | dvb->fe = ddb_mci_attach(input, cfg: &cfg, nr: demod, fn_set_input: &dvb->set_input); |
472 | if (!dvb->fe) { |
473 | dev_err(dev->dev, "No MCI card found!\n" ); |
474 | return -ENODEV; |
475 | } |
476 | if (!dvb->set_input) { |
477 | dev_err(dev->dev, "No MCI set_input function pointer!\n" ); |
478 | return -ENODEV; |
479 | } |
480 | if (input->nr < 4) { |
481 | lnb_command(dev, link: port->lnr, lnb: input->nr, LNB_CMD_INIT); |
482 | lnb_set_voltage(dev, link: port->lnr, input: input->nr, voltage: SEC_VOLTAGE_OFF); |
483 | } |
484 | ddb_lnb_init_fmode(dev, link, fm: fmode); |
485 | |
486 | dvb->fe->ops.set_voltage = max_set_voltage; |
487 | dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage; |
488 | dvb->fe->ops.set_tone = max_set_tone; |
489 | dvb->diseqc_send_master_cmd = dvb->fe->ops.diseqc_send_master_cmd; |
490 | dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd; |
491 | dvb->fe->ops.diseqc_send_burst = max_send_burst; |
492 | dvb->fe->sec_priv = input; |
493 | dvb->input = tuner; |
494 | return 0; |
495 | } |
496 | |